GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_subtheory_core.cpp Lines: 263 308 85.4 %
Date: 2021-05-22 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
127
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
127
  if (d_equalityEngine == nullptr)
41
  {
42
127
    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
174
bool CoreSolverExtTheoryCallback::getReduction(int effort,
72
                                               Node n,
73
                                               Node& nr,
74
                                               bool& satDep)
75
{
76
174
  Trace("bv-ext") << "TheoryBV::checkExt : non-reduced : " << n << std::endl;
77
174
  if (n.getKind() == kind::BITVECTOR_TO_NAT)
78
  {
79
93
    nr = utils::eliminateBv2Nat(n);
80
93
    satDep = false;
81
93
    return true;
82
  }
83
81
  else if (n.getKind() == kind::INT_TO_BITVECTOR)
84
  {
85
81
    nr = utils::eliminateInt2Bv(n);
86
81
    satDep = false;
87
81
    return true;
88
  }
89
  return false;
90
}
91
92
9403
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
9403
                                bv->d_bv.getSatContext(),
103
9403
                                bv->d_bv.getUserContext(),
104
18806
                                bv->d_bv.getOutputChannel())),
105
      d_reasons(c),
106
      d_needsLastCallCheck(false),
107
9403
      d_extf_range_infer(bv->d_bv.getUserContext()),
108
37612
      d_extf_collapse_infer(bv->d_bv.getUserContext())
109
{
110
9403
  d_extTheory->addFunctionKind(kind::BITVECTOR_TO_NAT);
111
9403
  d_extTheory->addFunctionKind(kind::INT_TO_BITVECTOR);
112
9403
}
113
114
18806
CoreSolver::~CoreSolver() {}
115
116
9403
bool CoreSolver::needsEqualityEngine(EeSetupInfo& esi)
117
{
118
9403
  esi.d_notify = &d_notify;
119
9403
  esi.d_name = "theory::bv::ee";
120
9403
  return true;
121
}
122
123
9403
void CoreSolver::finishInit()
124
{
125
  // use the parent's equality engine, which may be the one we allocated above
126
9403
  d_equalityEngine = d_bv->d_bv.getEqualityEngine();
127
128
  // The kinds we are treating as function application in congruence
129
9403
  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
9403
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_MULT, true);
139
9403
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_ADD, true);
140
9403
  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
9403
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_TO_NAT);
160
9403
  d_equalityEngine->addFunctionKind(kind::INT_TO_BITVECTOR);
161
9403
}
162
163
221279
void CoreSolver::preRegister(TNode node) {
164
221279
  d_preregisterCalled = true;
165
221279
  if (node.getKind() == kind::EQUAL) {
166
54604
    d_equalityEngine->addTriggerPredicate(node);
167
  } else {
168
166675
    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
166675
    d_extTheory->registerTerm(node);
174
  }
175
221279
}
176
177
178
3551
void CoreSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
179
3551
  bool polarity = literal.getKind() != kind::NOT;
180
7102
  TNode atom = polarity ? literal : literal[0];
181
3551
  if (atom.getKind() == kind::EQUAL) {
182
3551
    d_equalityEngine->explainEquality(atom[0], atom[1], polarity, assumptions);
183
  } else {
184
    d_equalityEngine->explainPredicate(atom, polarity, assumptions);
185
  }
186
3551
}
187
188
238193
bool CoreSolver::check(Theory::Effort e) {
189
238193
  Trace("bitvector::core") << "CoreSolver::check \n";
190
191
238193
  d_bv->d_im.spendResource(Resource::TheoryCheckStep);
192
193
238193
  d_checkCalled = true;
194
238193
  Assert(!d_bv->inConflict());
195
238193
  ++(d_statistics.d_numCallstoCheck);
196
238193
  bool ok = true;
197
476386
  std::vector<Node> core_eqs;
198
476386
  TNodeBoolMap seen;
199
3032703
  while (! done()) {
200
2794732
    TNode fact = get();
201
1397477
    if (d_isComplete && !isCompleteForTerm(fact, seen)) {
202
2724
      d_isComplete = false;
203
    }
204
205
    // only reason about equalities
206
1397477
    if (fact.getKind() == kind::EQUAL || (fact.getKind() == kind::NOT && fact[0].getKind() == kind::EQUAL)) {
207
836283
      ok = assertFactToEqualityEngine(fact, fact);
208
    } else {
209
561194
      ok = assertFactToEqualityEngine(fact, fact);
210
    }
211
1397477
    if (!ok)
212
222
      return false;
213
  }
214
215
237971
  if (Theory::fullEffort(e) && isComplete()) {
216
20828
    buildModel();
217
  }
218
219
237971
  return true;
220
}
221
222
20828
void CoreSolver::buildModel()
223
{
224
20828
  Debug("bv-core") << "CoreSolver::buildModel() \n";
225
20828
  NodeManager* nm = NodeManager::currentNM();
226
20828
  d_modelValues.clear();
227
41379
  TNodeSet constants;
228
41379
  TNodeSet constants_in_eq_engine;
229
  // collect constants in equality engine
230
20828
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
231
123478
  while (!eqcs_i.isFinished())
232
  {
233
102650
    TNode repr = *eqcs_i;
234
51325
    if (repr.getKind() == kind::CONST_BITVECTOR)
235
    {
236
      // must check if it's just the constant
237
3570
      eq::EqClassIterator it(repr, d_equalityEngine);
238
3570
      if (!(++it).isFinished() || true)
239
      {
240
3570
        constants.insert(repr);
241
3570
        constants_in_eq_engine.insert(repr);
242
      }
243
    }
244
51325
    ++eqcs_i;
245
  }
246
247
  // build repr to value map
248
249
20828
  eqcs_i = eq::EqClassesIterator(d_equalityEngine);
250
121524
  while (!eqcs_i.isFinished())
251
  {
252
58015
    TNode repr = *eqcs_i;
253
50625
    ++eqcs_i;
254
255
149251
    if (!repr.isVar() && repr.getKind() != kind::CONST_BITVECTOR
256
145709
        && !d_bv->isSharedTerm(repr))
257
    {
258
42958
      continue;
259
    }
260
261
15057
    TypeNode type = repr.getType();
262
7667
    if (type.isBitVector() && repr.getKind() != kind::CONST_BITVECTOR)
263
    {
264
4053
      Debug("bv-core-model") << "   processing " << repr << "\n";
265
      // we need to assign a value for it
266
7829
      TypeEnumerator te(type);
267
7829
      Node val;
268
6047
      do
269
      {
270
10100
        val = *te;
271
10100
        ++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
10100
      } while (constants.count(val) != 0 && !(te.isFinished()));
277
278
4053
      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
554
        std::vector<TNode> representatives;
283
277
        representatives.push_back(repr);
284
285
341
        for (TNodeSet::const_iterator it = constants_in_eq_engine.begin();
286
341
             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
930
        for (ModelValue::const_iterator it = d_modelValues.begin();
296
930
             it != d_modelValues.end();
297
             ++it)
298
        {
299
653
          representatives.push_back(it->first);
300
        }
301
554
        std::vector<Node> equalities;
302
1243
        for (unsigned i = 0; i < representatives.size(); ++i)
303
        {
304
2272
          for (unsigned j = i + 1; j < representatives.size(); ++j)
305
          {
306
2579
            TNode a = representatives[i];
307
2579
            TNode b = representatives[j];
308
2645
            if (a.getKind() == kind::CONST_BITVECTOR
309
1306
                && b.getKind() == kind::CONST_BITVECTOR)
310
            {
311
33
              Assert(a != b);
312
33
              continue;
313
            }
314
1273
            if (utils::getSize(a) == utils::getSize(b))
315
            {
316
1202
              equalities.push_back(nm->mkNode(kind::EQUAL, a, b));
317
            }
318
          }
319
        }
320
        // better off letting the SAT solver split on values
321
277
        if (equalities.size() > d_lemmaThreshold)
322
        {
323
          d_isComplete = false;
324
          return;
325
        }
326
327
277
        if (equalities.size() == 0)
328
        {
329
          Debug("bv-core") << "  lemma: true (no equalities)" << std::endl;
330
        }
331
        else
332
        {
333
554
          Node lemma = utils::mkOr(equalities);
334
277
          d_bv->lemma(lemma);
335
277
          Debug("bv-core") << "  lemma: " << lemma << std::endl;
336
        }
337
277
        return;
338
      }
339
340
3776
      Debug("bv-core-model") << "   " << repr << " => " << val << "\n";
341
3776
      constants.insert(val);
342
3776
      d_modelValues[repr] = val;
343
    }
344
  }
345
}
346
347
1397477
bool CoreSolver::assertFactToEqualityEngine(TNode fact, TNode reason) {
348
  // Notify the equality engine
349
2794954
  if (!d_bv->inConflict()
350
5347200
      && (!d_bv->wasPropagatedBySubtheory(fact)
351
2025640
          || d_bv->getPropagatingSubtheory(fact) != SUB_CORE))
352
  {
353
1154769
    Debug("bv-slicer-eq") << "CoreSolver::assertFactToEqualityEngine fact=" << fact << endl;
354
    // Debug("bv-slicer-eq") << "                     reason=" << reason << endl;
355
1154769
    bool negated = fact.getKind() == kind::NOT;
356
2309538
    TNode predicate = negated ? fact[0] : fact;
357
1154769
    if (predicate.getKind() == kind::EQUAL) {
358
593575
      if (negated) {
359
        // dis-equality
360
198403
        d_equalityEngine->assertEquality(predicate, false, reason);
361
      } else {
362
        // equality
363
395172
        d_equalityEngine->assertEquality(predicate, true, reason);
364
      }
365
    } else {
366
      // Adding predicate if the congruence over it is turned on
367
561194
      if (d_equalityEngine->isFunctionKind(predicate.getKind()))
368
      {
369
        d_equalityEngine->assertPredicate(predicate, !negated, reason);
370
      }
371
    }
372
  }
373
374
  // checking for a conflict
375
1397477
  if (d_bv->inConflict())
376
  {
377
222
    return false;
378
  }
379
1397255
  return true;
380
}
381
382
1212547
bool CoreSolver::NotifyClass::eqNotifyTriggerPredicate(TNode predicate, bool value) {
383
1212547
  Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
384
1212547
  if (value) {
385
792322
    return d_solver.storePropagation(predicate);
386
  }
387
420225
  return d_solver.storePropagation(predicate.notNode());
388
}
389
390
127942
bool CoreSolver::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
391
127942
  Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
392
127942
  if (value) {
393
96667
    return d_solver.storePropagation(t1.eqNode(t2));
394
  } else {
395
31275
    return d_solver.storePropagation(t1.eqNode(t2).notNode());
396
  }
397
}
398
399
222
void CoreSolver::NotifyClass::eqNotifyConstantTermMerge(TNode t1, TNode t2) {
400
222
  d_solver.conflict(t1, t2);
401
222
}
402
403
1340489
bool CoreSolver::storePropagation(TNode literal) {
404
1340489
  return d_bv->storePropagation(literal, SUB_CORE);
405
}
406
407
222
void CoreSolver::conflict(TNode a, TNode b) {
408
444
  std::vector<TNode> assumptions;
409
222
  d_equalityEngine->explainEquality(a, b, true, assumptions);
410
444
  Node conflict = flattenAnd(assumptions);
411
222
  d_bv->setConflict(conflict);
412
222
}
413
414
51144
bool CoreSolver::isCompleteForTerm(TNode term, TNodeBoolMap& seen) {
415
51144
  return utils::isEqualityTerm(term, seen);
416
}
417
418
3932
bool CoreSolver::collectModelValues(TheoryModel* m,
419
                                    const std::set<Node>& termSet)
420
{
421
3932
  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
3932
  if (isComplete()) {
429
3932
    Debug("bitvector-model") << "CoreSolver::collectModelValues complete.";
430
4236
    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
3932
  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
9403
CoreSolver::Statistics::Statistics()
487
9403
    : d_numCallstoCheck(smtStatisticsRegistry().registerInt(
488
9403
        "theory::bv::CoreSolver::NumCallsToCheck"))
489
{
490
9403
}
491
492
25782
void CoreSolver::checkExtf(Theory::Effort e)
493
{
494
25782
  if (e == Theory::EFFORT_LAST_CALL)
495
  {
496
    std::vector<Node> nred = d_extTheory->getActive();
497
    doExtfReductions(nred);
498
  }
499
25782
  Assert(e == Theory::EFFORT_FULL);
500
  // do inferences (adds external lemmas)  TODO: this can be improved to add
501
  // internal inferences
502
51437
  std::vector<Node> nred;
503
25782
  if (d_extTheory->doInferences(0, nred))
504
  {
505
    return;
506
  }
507
25782
  d_needsLastCallCheck = false;
508
25782
  if (!nred.empty())
509
  {
510
    // other inferences involving bv2nat, int2bv
511
254
    if (options::bvAlgExtf())
512
    {
513
127
      if (doExtfInferences(nred))
514
      {
515
70
        return;
516
      }
517
    }
518
57
    if (!options::bvLazyReduceExtf())
519
    {
520
57
      if (doExtfReductions(nred))
521
      {
522
57
        return;
523
      }
524
    }
525
    else
526
    {
527
      d_needsLastCallCheck = true;
528
    }
529
  }
530
}
531
532
8438
bool CoreSolver::needsCheckLastEffort() const { return d_needsLastCallCheck; }
533
534
127
bool CoreSolver::doExtfInferences(std::vector<Node>& terms)
535
{
536
127
  NodeManager* nm = NodeManager::currentNM();
537
127
  SkolemManager* sm = nm->getSkolemManager();
538
127
  bool sentLemma = false;
539
127
  eq::EqualityEngine* ee = d_equalityEngine;
540
254
  std::map<Node, Node> op_map;
541
502
  for (unsigned j = 0; j < terms.size(); j++)
542
  {
543
750
    TNode n = terms[j];
544
375
    Assert(n.getKind() == kind::BITVECTOR_TO_NAT
545
           || n.getKind() == kind::INT_TO_BITVECTOR);
546
375
    if (n.getKind() == kind::BITVECTOR_TO_NAT)
547
    {
548
      // range lemmas
549
201
      if (d_extf_range_infer.find(n) == d_extf_range_infer.end())
550
      {
551
105
        d_extf_range_infer.insert(n);
552
105
        unsigned bvs = n[0].getType().getBitVectorSize();
553
210
        Node min = nm->mkConst(Rational(0));
554
210
        Node max = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
555
        Node lem = nm->mkNode(kind::AND,
556
210
                              nm->mkNode(kind::GEQ, n, min),
557
420
                              nm->mkNode(kind::LT, n, max));
558
210
        Trace("bv-extf-lemma")
559
105
            << "BV extf lemma (range) : " << lem << std::endl;
560
105
        d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_LEMMA);
561
105
        sentLemma = true;
562
      }
563
    }
564
750
    Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n[0]) : n[0];
565
375
    op_map[r] = n;
566
  }
567
502
  for (unsigned j = 0; j < terms.size(); j++)
568
  {
569
750
    TNode n = terms[j];
570
750
    Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n) : n;
571
375
    std::map<Node, Node>::iterator it = op_map.find(r);
572
375
    if (it != op_map.end())
573
    {
574
332
      Node parent = it->second;
575
      // Node cterm = parent[0]==n ? parent : nm->mkNode( parent.getOperator(),
576
      // n );
577
332
      Node cterm = parent[0].eqNode(n);
578
332
      Trace("bv-extf-lemma-debug")
579
166
          << "BV extf collapse based on : " << cterm << std::endl;
580
166
      if (d_extf_collapse_infer.find(cterm) == d_extf_collapse_infer.end())
581
      {
582
86
        d_extf_collapse_infer.insert(cterm);
583
584
172
        Node t = n[0];
585
86
        if (t.getType() == parent.getType())
586
        {
587
84
          if (n.getKind() == kind::INT_TO_BITVECTOR)
588
          {
589
64
            Assert(t.getType().isInteger());
590
            // congruent modulo 2^( bv width )
591
64
            unsigned bvs = n.getType().getBitVectorSize();
592
128
            Node coeff = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
593
            Node k = sm->mkDummySkolem(
594
128
                "int_bv_cong", t.getType(), "for int2bv/bv2nat congruence");
595
64
            t = nm->mkNode(kind::PLUS, t, nm->mkNode(kind::MULT, coeff, k));
596
          }
597
168
          Node lem = parent.eqNode(t);
598
599
84
          if (parent[0] != n)
600
          {
601
22
            Assert(ee->areEqual(parent[0], n));
602
22
            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
168
          Trace("bv-extf-lemma")
608
84
              << "BV extf lemma (collapse) : " << lem << std::endl;
609
84
          d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_COLLAPSE);
610
84
          sentLemma = true;
611
        }
612
      }
613
332
      Trace("bv-extf-lemma-debug")
614
166
          << "BV extf f collapse based on : " << cterm << std::endl;
615
    }
616
  }
617
254
  return sentLemma;
618
}
619
620
57
bool CoreSolver::doExtfReductions(std::vector<Node>& terms)
621
{
622
114
  std::vector<Node> nredr;
623
57
  if (d_extTheory->doReductions(0, terms, nredr))
624
  {
625
57
    return true;
626
  }
627
  Assert(nredr.empty());
628
  return false;
629
28318
}