GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_solver_lazy.cpp Lines: 295 333 88.6 %
Date: 2021-05-21 Branches: 611 1360 44.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Mathias Preiner, Liana Hadarean, Andrew Reynolds
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
 * Lazy bit-vector solver.
14
 */
15
16
#include "theory/bv/bv_solver_lazy.h"
17
18
#include "expr/node_algorithm.h"
19
#include "options/bv_options.h"
20
#include "options/smt_options.h"
21
#include "smt/smt_statistics_registry.h"
22
#include "theory/bv/abstraction.h"
23
#include "theory/bv/bv_eager_solver.h"
24
#include "theory/bv/bv_subtheory_algebraic.h"
25
#include "theory/bv/bv_subtheory_bitblast.h"
26
#include "theory/bv/bv_subtheory_core.h"
27
#include "theory/bv/bv_subtheory_inequality.h"
28
#include "theory/bv/theory_bv_rewrite_rules_normalization.h"
29
#include "theory/bv/theory_bv_rewrite_rules_simplification.h"
30
#include "theory/bv/theory_bv_rewriter.h"
31
#include "theory/bv/theory_bv_utils.h"
32
#include "theory/theory_model.h"
33
34
using namespace cvc5::theory::bv::utils;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace bv {
39
40
8941
BVSolverLazy::BVSolverLazy(TheoryBV& bv,
41
                           context::Context* c,
42
                           context::UserContext* u,
43
                           ProofNodeManager* pnm,
44
8941
                           std::string name)
45
    : BVSolver(bv.d_state, bv.d_im),
46
      d_bv(bv),
47
      d_context(c),
48
      d_alreadyPropagatedSet(c),
49
      d_sharedTermsSet(c),
50
      d_subtheories(),
51
      d_subtheoryMap(),
52
      d_statistics(),
53
      d_staticLearnCache(),
54
      d_lemmasAdded(c, false),
55
      d_conflict(c, false),
56
      d_invalidateModelCache(c, true),
57
      d_literalsToPropagate(c),
58
      d_literalsToPropagateIndex(c, 0),
59
      d_propagatedBy(c),
60
      d_eagerSolver(),
61
26823
      d_abstractionModule(new AbstractionModule(getStatsPrefix(THEORY_BV))),
62
35764
      d_calledPreregister(false)
63
{
64
8941
  if (options::bitblastMode() == options::BitblastMode::EAGER)
65
  {
66
29
    d_eagerSolver.reset(new EagerBitblastSolver(c, this));
67
29
    return;
68
  }
69
70
8912
  if (options::bitvectorEqualitySolver())
71
  {
72
8910
    d_subtheories.emplace_back(new CoreSolver(c, this));
73
8910
    d_subtheoryMap[SUB_CORE] = d_subtheories.back().get();
74
  }
75
76
17824
  if (options::bitvectorInequalitySolver())
77
  {
78
8912
    d_subtheories.emplace_back(new InequalitySolver(c, u, this));
79
8912
    d_subtheoryMap[SUB_INEQUALITY] = d_subtheories.back().get();
80
  }
81
82
8912
  if (options::bitvectorAlgebraicSolver())
83
  {
84
    d_subtheories.emplace_back(new AlgebraicSolver(c, this));
85
    d_subtheoryMap[SUB_ALGEBRAIC] = d_subtheories.back().get();
86
  }
87
88
8912
  BitblastSolver* bb_solver = new BitblastSolver(c, this);
89
8912
  if (options::bvAbstraction())
90
  {
91
2
    bb_solver->setAbstraction(d_abstractionModule.get());
92
  }
93
8912
  d_subtheories.emplace_back(bb_solver);
94
8912
  d_subtheoryMap[SUB_BITBLAST] = bb_solver;
95
}
96
97
17882
BVSolverLazy::~BVSolverLazy() {}
98
99
8941
bool BVSolverLazy::needsEqualityEngine(EeSetupInfo& esi)
100
{
101
8941
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
102
8941
  if (core)
103
  {
104
8910
    return core->needsEqualityEngine(esi);
105
  }
106
  // otherwise we don't use an equality engine
107
31
  return false;
108
}
109
110
8941
void BVSolverLazy::finishInit()
111
{
112
8941
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
113
8941
  if (core)
114
  {
115
    // must finish initialization in the core solver
116
8910
    core->finishInit();
117
  }
118
8941
}
119
120
481517
void BVSolverLazy::spendResource(Resource r)
121
{
122
481517
  d_im.spendResource(r);
123
481517
}
124
125
8941
BVSolverLazy::Statistics::Statistics()
126
8941
    : d_avgConflictSize(smtStatisticsRegistry().registerAverage(
127
17882
        "theory::bv::lazy::AvgBVConflictSize")),
128
8941
      d_solveTimer(smtStatisticsRegistry().registerTimer(
129
17882
          "theory::bv::lazy::solveTimer")),
130
8941
      d_numCallsToCheckFullEffort(smtStatisticsRegistry().registerInt(
131
17882
          "theory::bv::lazy::NumFullCheckCalls")),
132
8941
      d_numCallsToCheckStandardEffort(smtStatisticsRegistry().registerInt(
133
17882
          "theory::bv::lazy::NumStandardCheckCalls")),
134
8941
      d_weightComputationTimer(smtStatisticsRegistry().registerTimer(
135
17882
          "theory::bv::lazy::weightComputationTimer")),
136
8941
      d_numMultSlice(smtStatisticsRegistry().registerInt(
137
53646
          "theory::bv::lazy::NumMultSliceApplied"))
138
{
139
8941
}
140
141
219997
void BVSolverLazy::preRegisterTerm(TNode node)
142
{
143
219997
  d_calledPreregister = true;
144
439994
  Debug("bitvector-preregister")
145
219997
      << "BVSolverLazy::preRegister(" << node << ")" << std::endl;
146
147
219997
  if (options::bitblastMode() == options::BitblastMode::EAGER)
148
  {
149
    // the aig bit-blaster option is set heuristically
150
    // if bv abstraction is used
151
1818
    if (!d_eagerSolver->isInitialized())
152
    {
153
17
      d_eagerSolver->initialize();
154
    }
155
156
1818
    if (node.getKind() == kind::BITVECTOR_EAGER_ATOM)
157
    {
158
528
      Node formula = node[0];
159
264
      d_eagerSolver->assertFormula(formula);
160
    }
161
1818
    return;
162
  }
163
164
872702
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
165
  {
166
654523
    d_subtheories[i]->preRegister(node);
167
  }
168
169
  // AJR : equality solver currently registers all terms to ExtTheory, if we
170
  // want a lazy reduction without the bv equality solver, need to call this
171
  // d_bv.d_extTheory->registerTermRec( node );
172
}
173
174
15193
void BVSolverLazy::sendConflict()
175
{
176
15193
  Assert(d_conflict);
177
15193
  if (d_conflictNode.isNull())
178
  {
179
    return;
180
  }
181
  else
182
  {
183
30386
    Debug("bitvector") << indent() << "BVSolverLazy::check(): conflict "
184
15193
                       << d_conflictNode << std::endl;
185
15193
    d_im.conflict(d_conflictNode, InferenceId::BV_LAZY_CONFLICT);
186
15193
    d_statistics.d_avgConflictSize << d_conflictNode.getNumChildren();
187
15193
    d_conflictNode = Node::null();
188
  }
189
}
190
191
1372255
void BVSolverLazy::checkForLemma(TNode fact)
192
{
193
1372255
  if (fact.getKind() == kind::EQUAL)
194
  {
195
442818
    NodeManager* nm = NodeManager::currentNM();
196
442818
    if (fact[0].getKind() == kind::BITVECTOR_UREM)
197
    {
198
1894
      TNode urem = fact[0];
199
1894
      TNode result = fact[1];
200
1894
      TNode divisor = urem[1];
201
1894
      Node result_ult_div = nm->mkNode(kind::BITVECTOR_ULT, result, divisor);
202
      Node divisor_eq_0 =
203
1894
          nm->mkNode(kind::EQUAL, divisor, mkZero(getSize(divisor)));
204
      Node split = nm->mkNode(
205
1894
          kind::OR, divisor_eq_0, nm->mkNode(kind::NOT, fact), result_ult_div);
206
947
      lemma(split);
207
    }
208
442818
    if (fact[1].getKind() == kind::BITVECTOR_UREM)
209
    {
210
124
      TNode urem = fact[1];
211
124
      TNode result = fact[0];
212
124
      TNode divisor = urem[1];
213
124
      Node result_ult_div = nm->mkNode(kind::BITVECTOR_ULT, result, divisor);
214
      Node divisor_eq_0 =
215
124
          nm->mkNode(kind::EQUAL, divisor, mkZero(getSize(divisor)));
216
      Node split = nm->mkNode(
217
124
          kind::OR, divisor_eq_0, nm->mkNode(kind::NOT, fact), result_ult_div);
218
62
      lemma(split);
219
    }
220
  }
221
1372255
}
222
223
228459
bool BVSolverLazy::preCheck(Theory::Effort e)
224
{
225
228459
  check(e);
226
228459
  return true;
227
}
228
229
228459
void BVSolverLazy::check(Theory::Effort e)
230
{
231
228459
  if (done() && e < Theory::EFFORT_FULL)
232
  {
233
15371
    return;
234
  }
235
236
  // last call : do reductions on extended bitvector functions
237
228459
  if (e == Theory::EFFORT_LAST_CALL)
238
  {
239
    CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
240
    if (core)
241
    {
242
      // check extended functions at last call effort
243
      core->checkExtf(e);
244
    }
245
    return;
246
  }
247
248
228459
  Debug("bitvector") << "BVSolverLazy::check(" << e << ")" << std::endl;
249
441547
  TimerStat::CodeTimer codeTimer(d_statistics.d_solveTimer);
250
  // we may be getting new assertions so the model cache may not be sound
251
228459
  d_invalidateModelCache.set(true);
252
  // if we are using the eager solver
253
228459
  if (options::bitblastMode() == options::BitblastMode::EAGER)
254
  {
255
    // this can only happen on an empty benchmark
256
178
    if (!d_eagerSolver->isInitialized())
257
    {
258
2
      d_eagerSolver->initialize();
259
    }
260
178
    if (!Theory::fullEffort(e)) return;
261
262
74
    std::vector<TNode> assertions;
263
565
    while (!done())
264
    {
265
528
      TNode fact = get().d_assertion;
266
264
      Assert(fact.getKind() == kind::BITVECTOR_EAGER_ATOM);
267
264
      assertions.push_back(fact);
268
264
      d_eagerSolver->assertFormula(fact[0]);
269
    }
270
271
37
    bool ok = d_eagerSolver->checkSat();
272
37
    if (!ok)
273
    {
274
10
      if (assertions.size() == 1)
275
      {
276
6
        d_im.conflict(assertions[0], InferenceId::BV_LAZY_CONFLICT);
277
6
        return;
278
      }
279
8
      Node conflict = utils::mkAnd(assertions);
280
4
      d_im.conflict(conflict, InferenceId::BV_LAZY_CONFLICT);
281
4
      return;
282
    }
283
27
    return;
284
  }
285
286
228281
  if (Theory::fullEffort(e))
287
  {
288
30437
    ++(d_statistics.d_numCallsToCheckFullEffort);
289
  }
290
  else
291
  {
292
197844
    ++(d_statistics.d_numCallsToCheckStandardEffort);
293
  }
294
  // if we are already in conflict just return the conflict
295
228281
  if (inConflict())
296
  {
297
    sendConflict();
298
    return;
299
  }
300
301
2972791
  while (!done())
302
  {
303
2744510
    TNode fact = get().d_assertion;
304
305
1372255
    checkForLemma(fact);
306
307
5489012
    for (unsigned i = 0; i < d_subtheories.size(); ++i)
308
    {
309
4116757
      d_subtheories[i]->assertFact(fact);
310
    }
311
  }
312
313
228281
  bool ok = true;
314
228281
  bool complete = false;
315
621795
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
316
  {
317
621795
    Assert(!inConflict());
318
621795
    ok = d_subtheories[i]->check(e);
319
621795
    complete = d_subtheories[i]->isComplete();
320
321
621795
    if (!ok)
322
    {
323
      // if we are in a conflict no need to check with other theories
324
15193
      Assert(inConflict());
325
15193
      sendConflict();
326
15193
      return;
327
    }
328
606602
    if (complete)
329
    {
330
      // if the last subtheory was complete we stop
331
213088
      break;
332
    }
333
  }
334
335
  // check extended functions
336
213088
  if (Theory::fullEffort(e))
337
  {
338
25285
    CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
339
25285
    if (core)
340
    {
341
      // check extended functions at full effort
342
25283
      core->checkExtf(e);
343
    }
344
  }
345
}
346
347
8351
bool BVSolverLazy::needsCheckLastEffort()
348
{
349
8351
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
350
8351
  if (core)
351
  {
352
8322
    return core->needsCheckLastEffort();
353
  }
354
29
  return false;
355
}
356
357
7130
bool BVSolverLazy::collectModelValues(TheoryModel* m,
358
                                      const std::set<Node>& termSet)
359
{
360
7130
  Assert(!inConflict());
361
7130
  if (options::bitblastMode() == options::BitblastMode::EAGER)
362
  {
363
9
    if (!d_eagerSolver->collectModelInfo(m, true))
364
    {
365
      return false;
366
    }
367
  }
368
13520
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
369
  {
370
13511
    if (d_subtheories[i]->isComplete())
371
    {
372
7121
      return d_subtheories[i]->collectModelValues(m, termSet);
373
    }
374
  }
375
9
  return true;
376
}
377
378
Node BVSolverLazy::getModelValue(TNode var)
379
{
380
  Assert(!inConflict());
381
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
382
  {
383
    if (d_subtheories[i]->isComplete())
384
    {
385
      return d_subtheories[i]->getModelValue(var);
386
    }
387
  }
388
  Unreachable();
389
}
390
391
802646
void BVSolverLazy::propagate(Theory::Effort e)
392
{
393
802646
  Debug("bitvector") << indent() << "BVSolverLazy::propagate()" << std::endl;
394
802646
  if (options::bitblastMode() == options::BitblastMode::EAGER)
395
  {
396
168
    return;
397
  }
398
399
802478
  if (inConflict())
400
  {
401
    return;
402
  }
403
404
  // go through stored propagations
405
802478
  bool ok = true;
406
2504837
  for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok;
407
1134906
       d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1)
408
  {
409
1134906
    TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
410
    // temporary fix for incremental bit-blasting
411
567453
    if (d_state.isSatLiteral(literal))
412
    {
413
1059704
      Debug("bitvector::propagate")
414
529852
          << "BVSolverLazy:: propagating " << literal << "\n";
415
529852
      ok = d_im.propagateLit(literal);
416
    }
417
  }
418
419
802478
  if (!ok)
420
  {
421
    Debug("bitvector::propagate")
422
        << indent() << "BVSolverLazy::propagate(): conflict from theory engine"
423
        << std::endl;
424
    setConflict();
425
  }
426
}
427
428
311678
TrustNode BVSolverLazy::ppRewrite(TNode t)
429
{
430
311678
  Debug("bv-pp-rewrite") << "BVSolverLazy::ppRewrite " << t << "\n";
431
623356
  Node res = t;
432
623356
  if (options::bitwiseEq() && RewriteRule<BitwiseEq>::applies(t))
433
  {
434
840
    Node result = RewriteRule<BitwiseEq>::run<false>(t);
435
420
    res = Rewriter::rewrite(result);
436
  }
437
311258
  else if (RewriteRule<UltAddOne>::applies(t))
438
  {
439
108
    Node result = RewriteRule<UltAddOne>::run<false>(t);
440
54
    res = Rewriter::rewrite(result);
441
  }
442
622408
  else if (res.getKind() == kind::EQUAL
443
933616
           && ((res[0].getKind() == kind::BITVECTOR_ADD
444
312000
                && RewriteRule<ConcatToMult>::applies(res[1]))
445
328165
               || (res[1].getKind() == kind::BITVECTOR_ADD
446
311630
                   && RewriteRule<ConcatToMult>::applies(res[0]))))
447
  {
448
8
    Node mult = RewriteRule<ConcatToMult>::applies(res[0])
449
                    ? RewriteRule<ConcatToMult>::run<false>(res[0])
450
8
                    : RewriteRule<ConcatToMult>::run<true>(res[1]);
451
8
    Node factor = mult[0];
452
8
    Node sum = RewriteRule<ConcatToMult>::applies(res[0]) ? res[1] : res[0];
453
8
    Node new_eq = NodeManager::currentNM()->mkNode(kind::EQUAL, sum, mult);
454
8
    Node rewr_eq = RewriteRule<SolveEq>::run<true>(new_eq);
455
4
    if (rewr_eq[0].isVar() || rewr_eq[1].isVar())
456
    {
457
4
      res = Rewriter::rewrite(rewr_eq);
458
    }
459
    else
460
    {
461
      res = t;
462
    }
463
  }
464
311200
  else if (RewriteRule<SignExtendEqConst>::applies(t))
465
  {
466
346
    res = RewriteRule<SignExtendEqConst>::run<false>(t);
467
  }
468
310854
  else if (RewriteRule<ZeroExtendEqConst>::applies(t))
469
  {
470
    res = RewriteRule<ZeroExtendEqConst>::run<false>(t);
471
  }
472
310854
  else if (RewriteRule<NormalizeEqAddNeg>::applies(t))
473
  {
474
1212
    res = RewriteRule<NormalizeEqAddNeg>::run<false>(t);
475
  }
476
477
  // if(t.getKind() == kind::EQUAL &&
478
  //    ((t[0].getKind() == kind::BITVECTOR_MULT && t[1].getKind() ==
479
  //    kind::BITVECTOR_ADD) ||
480
  //     (t[1].getKind() == kind::BITVECTOR_MULT && t[0].getKind() ==
481
  //     kind::BITVECTOR_ADD))) {
482
  //   // if we have an equality between a multiplication and addition
483
  //   // try to express multiplication in terms of addition
484
  //   Node mult = t[0].getKind() == kind::BITVECTOR_MULT? t[0] : t[1];
485
  //   Node add = t[0].getKind() == kind::BITVECTOR_ADD? t[0] : t[1];
486
  //   if (RewriteRule<MultSlice>::applies(mult)) {
487
  //     Node new_mult = RewriteRule<MultSlice>::run<false>(mult);
488
  //     Node new_eq =
489
  //     Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::EQUAL,
490
  //     new_mult, add));
491
492
  //     // the simplification can cause the formula to blow up
493
  //     // only apply if formula reduced
494
  //     if (d_subtheoryMap.find(SUB_BITBLAST) != d_subtheoryMap.end()) {
495
  //       BitblastSolver* bv = (BitblastSolver*)d_subtheoryMap[SUB_BITBLAST];
496
  //       uint64_t old_size = bv->computeAtomWeight(t);
497
  //       Assert (old_size);
498
  //       uint64_t new_size = bv->computeAtomWeight(new_eq);
499
  //       double ratio = ((double)new_size)/old_size;
500
  //       if (ratio <= 0.4) {
501
  //         ++(d_statistics.d_numMultSlice);
502
  //         return new_eq;
503
  //       }
504
  //     }
505
506
  //     if (new_eq.getKind() == kind::CONST_BOOLEAN) {
507
  //       ++(d_statistics.d_numMultSlice);
508
  //       return new_eq;
509
  //     }
510
  //   }
511
  // }
512
513
311678
  if (options::bvAbstraction() && t.getType().isBoolean())
514
  {
515
12
    d_abstractionModule->addInputAtom(res);
516
  }
517
311678
  Debug("bv-pp-rewrite") << "to   " << res << "\n";
518
311678
  if (res != t)
519
  {
520
1138
    return TrustNode::mkTrustRewrite(t, res, nullptr);
521
  }
522
310540
  return TrustNode::null();
523
}
524
525
12727
void BVSolverLazy::presolve()
526
{
527
12727
  Debug("bitvector") << "BVSolverLazy::presolve" << std::endl;
528
12727
}
529
530
static int prop_count = 0;
531
532
2386196
bool BVSolverLazy::storePropagation(TNode literal, SubTheory subtheory)
533
{
534
4772392
  Debug("bitvector::propagate") << indent() << d_context->getLevel() << " "
535
2386196
                                << "BVSolverLazy::storePropagation(" << literal
536
2386196
                                << ", " << subtheory << ")" << std::endl;
537
2386196
  prop_count++;
538
539
  // If already in conflict, no more propagation
540
2386196
  if (d_conflict)
541
  {
542
    Debug("bitvector::propagate")
543
        << indent() << "BVSolverLazy::storePropagation(" << literal << ", "
544
        << subtheory << "): already in conflict" << std::endl;
545
    return false;
546
  }
547
548
  // If propagated already, just skip
549
2386196
  PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
550
2386196
  if (find != d_propagatedBy.end())
551
  {
552
866368
    return true;
553
  }
554
  else
555
  {
556
1519828
    bool polarity = literal.getKind() != kind::NOT;
557
3037629
    Node negatedLiteral = polarity ? literal.notNode() : (Node)literal[0];
558
1519828
    find = d_propagatedBy.find(negatedLiteral);
559
1519828
    if (find != d_propagatedBy.end() && (*find).second != subtheory)
560
    {
561
      // Safe to ignore this one, subtheory should produce a conflict
562
2027
      return true;
563
    }
564
565
1517801
    d_propagatedBy[literal] = subtheory;
566
  }
567
568
  // Propagate differs depending on the subtheory
569
  // * bitblaster needs to be left alone until it's done, otherwise it doesn't
570
  //   know how to explain
571
  // * equality engine can propagate eagerly
572
  // TODO(2348): Determine if ok should be set by propagate. If not, remove ok.
573
1517801
  constexpr bool ok = true;
574
1517801
  if (subtheory == SUB_CORE)
575
  {
576
754385
    d_im.propagateLit(literal);
577
    if (!ok)
578
    {
579
      setConflict();
580
    }
581
  }
582
  else
583
  {
584
763416
    d_literalsToPropagate.push_back(literal);
585
  }
586
1517801
  return ok;
587
588
} /* BVSolverLazy::propagate(TNode) */
589
590
23436
void BVSolverLazy::explain(TNode literal, std::vector<TNode>& assumptions)
591
{
592
23436
  Assert(wasPropagatedBySubtheory(literal));
593
23436
  SubTheory sub = getPropagatingSubtheory(literal);
594
23436
  d_subtheoryMap[sub]->explain(literal, assumptions);
595
23436
}
596
597
23436
TrustNode BVSolverLazy::explain(TNode node)
598
{
599
46872
  Debug("bitvector::explain")
600
23436
      << "BVSolverLazy::explain(" << node << ")" << std::endl;
601
46872
  std::vector<TNode> assumptions;
602
603
  // Ask for the explanation
604
23436
  explain(node, assumptions);
605
  // this means that it is something true at level 0
606
46872
  Node explanation;
607
23436
  if (assumptions.size() == 0)
608
  {
609
132
    explanation = utils::mkTrue();
610
  }
611
  else
612
  {
613
    // return the explanation
614
23304
    explanation = utils::mkAnd(assumptions);
615
  }
616
46872
  Debug("bitvector::explain") << "BVSolverLazy::explain(" << node << ") => "
617
23436
                              << explanation << std::endl;
618
23436
  Debug("bitvector::explain") << "BVSolverLazy::explain done. \n";
619
46872
  return TrustNode::mkTrustPropExp(node, explanation, nullptr);
620
}
621
622
48471
void BVSolverLazy::notifySharedTerm(TNode t)
623
{
624
96942
  Debug("bitvector::sharing")
625
48471
      << indent() << "BVSolverLazy::notifySharedTerm(" << t << ")" << std::endl;
626
48471
  d_sharedTermsSet.insert(t);
627
48471
}
628
629
55014
EqualityStatus BVSolverLazy::getEqualityStatus(TNode a, TNode b)
630
{
631
55014
  if (options::bitblastMode() == options::BitblastMode::EAGER)
632
    return EQUALITY_UNKNOWN;
633
55014
  Assert(options::bitblastMode() == options::BitblastMode::LAZY);
634
113914
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
635
  {
636
113812
    EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b);
637
113812
    if (status != EQUALITY_UNKNOWN)
638
    {
639
54912
      return status;
640
    }
641
  }
642
102
  return EQUALITY_UNKNOWN;
643
  ;
644
}
645
646
518462
void BVSolverLazy::ppStaticLearn(TNode in, NodeBuilder& learned)
647
{
648
518462
  if (d_staticLearnCache.find(in) != d_staticLearnCache.end())
649
  {
650
59586
    return;
651
  }
652
458876
  d_staticLearnCache.insert(in);
653
654
458876
  if (in.getKind() == kind::EQUAL)
655
  {
656
66996
    if ((in[0].getKind() == kind::BITVECTOR_ADD
657
22346
         && in[1].getKind() == kind::BITVECTOR_SHL)
658
111660
        || (in[1].getKind() == kind::BITVECTOR_ADD
659
22334
            && in[0].getKind() == kind::BITVECTOR_SHL))
660
    {
661
4
      TNode p = in[0].getKind() == kind::BITVECTOR_ADD ? in[0] : in[1];
662
4
      TNode s = in[0].getKind() == kind::BITVECTOR_ADD ? in[1] : in[0];
663
664
6
      if (p.getNumChildren() == 2 && p[0].getKind() == kind::BITVECTOR_SHL
665
6
          && p[1].getKind() == kind::BITVECTOR_SHL)
666
      {
667
2
        unsigned size = utils::getSize(s);
668
4
        Node one = utils::mkConst(size, 1u);
669
2
        if (s[0] == one && p[0][0] == one && p[1][0] == one)
670
        {
671
4
          Node zero = utils::mkConst(size, 0u);
672
4
          TNode b = p[0];
673
4
          TNode c = p[1];
674
          // (s : 1 << S) = (b : 1 << B) + (c : 1 << C)
675
4
          Node b_eq_0 = b.eqNode(zero);
676
4
          Node c_eq_0 = c.eqNode(zero);
677
4
          Node b_eq_c = b.eqNode(c);
678
679
          Node dis = NodeManager::currentNM()->mkNode(
680
4
              kind::OR, b_eq_0, c_eq_0, b_eq_c);
681
4
          Node imp = in.impNode(dis);
682
2
          learned << imp;
683
        }
684
      }
685
    }
686
  }
687
436544
  else if (in.getKind() == kind::AND)
688
  {
689
423918
    for (size_t i = 0, N = in.getNumChildren(); i < N; ++i)
690
    {
691
419742
      ppStaticLearn(in[i], learned);
692
    }
693
  }
694
}
695
696
4
bool BVSolverLazy::applyAbstraction(const std::vector<Node>& assertions,
697
                                    std::vector<Node>& new_assertions)
698
{
699
  bool changed =
700
4
      d_abstractionModule->applyAbstraction(assertions, new_assertions);
701
4
  if (changed && options::bitblastMode() == options::BitblastMode::EAGER
702
4
      && options::bitvectorAig())
703
  {
704
    // disable AIG mode
705
    AlwaysAssert(!d_eagerSolver->isInitialized());
706
    d_eagerSolver->turnOffAig();
707
    d_eagerSolver->initialize();
708
  }
709
4
  return changed;
710
}
711
712
15193
void BVSolverLazy::setConflict(Node conflict)
713
{
714
15193
  if (options::bvAbstraction())
715
  {
716
    NodeManager* const nm = NodeManager::currentNM();
717
    Node new_conflict = d_abstractionModule->simplifyConflict(conflict);
718
719
    std::vector<Node> lemmas;
720
    lemmas.push_back(new_conflict);
721
    d_abstractionModule->generalizeConflict(new_conflict, lemmas);
722
    for (unsigned i = 0; i < lemmas.size(); ++i)
723
    {
724
      lemma(nm->mkNode(kind::NOT, lemmas[i]));
725
    }
726
  }
727
15193
  d_conflict = true;
728
15193
  d_conflictNode = conflict;
729
15193
}
730
731
}  // namespace bv
732
}  // namespace theory
733
348325
}  // namespace cvc5