GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_solver_lazy.cpp Lines: 295 333 88.6 %
Date: 2021-05-22 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
9444
BVSolverLazy::BVSolverLazy(TheoryBV& bv,
41
                           context::Context* c,
42
                           context::UserContext* u,
43
                           ProofNodeManager* pnm,
44
9444
                           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
28332
      d_abstractionModule(new AbstractionModule(getStatsPrefix(THEORY_BV))),
62
37776
      d_calledPreregister(false)
63
{
64
9444
  if (options::bitblastMode() == options::BitblastMode::EAGER)
65
  {
66
39
    d_eagerSolver.reset(new EagerBitblastSolver(c, this));
67
39
    return;
68
  }
69
70
9405
  if (options::bitvectorEqualitySolver())
71
  {
72
9403
    d_subtheories.emplace_back(new CoreSolver(c, this));
73
9403
    d_subtheoryMap[SUB_CORE] = d_subtheories.back().get();
74
  }
75
76
18810
  if (options::bitvectorInequalitySolver())
77
  {
78
9405
    d_subtheories.emplace_back(new InequalitySolver(c, u, this));
79
9405
    d_subtheoryMap[SUB_INEQUALITY] = d_subtheories.back().get();
80
  }
81
82
9405
  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
9405
  BitblastSolver* bb_solver = new BitblastSolver(c, this);
89
9405
  if (options::bvAbstraction())
90
  {
91
2
    bb_solver->setAbstraction(d_abstractionModule.get());
92
  }
93
9405
  d_subtheories.emplace_back(bb_solver);
94
9405
  d_subtheoryMap[SUB_BITBLAST] = bb_solver;
95
}
96
97
18888
BVSolverLazy::~BVSolverLazy() {}
98
99
9444
bool BVSolverLazy::needsEqualityEngine(EeSetupInfo& esi)
100
{
101
9444
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
102
9444
  if (core)
103
  {
104
9403
    return core->needsEqualityEngine(esi);
105
  }
106
  // otherwise we don't use an equality engine
107
41
  return false;
108
}
109
110
9444
void BVSolverLazy::finishInit()
111
{
112
9444
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
113
9444
  if (core)
114
  {
115
    // must finish initialization in the core solver
116
9403
    core->finishInit();
117
  }
118
9444
}
119
120
489872
void BVSolverLazy::spendResource(Resource r)
121
{
122
489872
  d_im.spendResource(r);
123
489872
}
124
125
9444
BVSolverLazy::Statistics::Statistics()
126
9444
    : d_avgConflictSize(smtStatisticsRegistry().registerAverage(
127
18888
        "theory::bv::lazy::AvgBVConflictSize")),
128
9444
      d_solveTimer(smtStatisticsRegistry().registerTimer(
129
18888
          "theory::bv::lazy::solveTimer")),
130
9444
      d_numCallsToCheckFullEffort(smtStatisticsRegistry().registerInt(
131
18888
          "theory::bv::lazy::NumFullCheckCalls")),
132
9444
      d_numCallsToCheckStandardEffort(smtStatisticsRegistry().registerInt(
133
18888
          "theory::bv::lazy::NumStandardCheckCalls")),
134
9444
      d_weightComputationTimer(smtStatisticsRegistry().registerTimer(
135
18888
          "theory::bv::lazy::weightComputationTimer")),
136
9444
      d_numMultSlice(smtStatisticsRegistry().registerInt(
137
56664
          "theory::bv::lazy::NumMultSliceApplied"))
138
{
139
9444
}
140
141
223289
void BVSolverLazy::preRegisterTerm(TNode node)
142
{
143
223289
  d_calledPreregister = true;
144
446578
  Debug("bitvector-preregister")
145
223289
      << "BVSolverLazy::preRegister(" << node << ")" << std::endl;
146
147
223289
  if (options::bitblastMode() == options::BitblastMode::EAGER)
148
  {
149
    // the aig bit-blaster option is set heuristically
150
    // if bv abstraction is used
151
1996
    if (!d_eagerSolver->isInitialized())
152
    {
153
27
      d_eagerSolver->initialize();
154
    }
155
156
1996
    if (node.getKind() == kind::BITVECTOR_EAGER_ATOM)
157
    {
158
612
      Node formula = node[0];
159
306
      d_eagerSolver->assertFormula(formula);
160
    }
161
1996
    return;
162
  }
163
164
885158
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
165
  {
166
663865
    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
15249
void BVSolverLazy::sendConflict()
175
{
176
15249
  Assert(d_conflict);
177
15249
  if (d_conflictNode.isNull())
178
  {
179
    return;
180
  }
181
  else
182
  {
183
30498
    Debug("bitvector") << indent() << "BVSolverLazy::check(): conflict "
184
15249
                       << d_conflictNode << std::endl;
185
15249
    d_im.conflict(d_conflictNode, InferenceId::BV_LAZY_CONFLICT);
186
15249
    d_statistics.d_avgConflictSize << d_conflictNode.getNumChildren();
187
15249
    d_conflictNode = Node::null();
188
  }
189
}
190
191
1397643
void BVSolverLazy::checkForLemma(TNode fact)
192
{
193
1397643
  if (fact.getKind() == kind::EQUAL)
194
  {
195
458007
    NodeManager* nm = NodeManager::currentNM();
196
458007
    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
458007
    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
1397643
}
222
223
238457
bool BVSolverLazy::preCheck(Theory::Effort e)
224
{
225
238457
  check(e);
226
238457
  return true;
227
}
228
229
238457
void BVSolverLazy::check(Theory::Effort e)
230
{
231
238457
  if (done() && e < Theory::EFFORT_FULL)
232
  {
233
15503
    return;
234
  }
235
236
  // last call : do reductions on extended bitvector functions
237
238457
  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
238457
  Debug("bitvector") << "BVSolverLazy::check(" << e << ")" << std::endl;
249
461411
  TimerStat::CodeTimer codeTimer(d_statistics.d_solveTimer);
250
  // we may be getting new assertions so the model cache may not be sound
251
238457
  d_invalidateModelCache.set(true);
252
  // if we are using the eager solver
253
238457
  if (options::bitblastMode() == options::BitblastMode::EAGER)
254
  {
255
    // this can only happen on an empty benchmark
256
254
    if (!d_eagerSolver->isInitialized())
257
    {
258
2
      d_eagerSolver->initialize();
259
    }
260
254
    if (!Theory::fullEffort(e)) return;
261
262
106
    std::vector<TNode> assertions;
263
681
    while (!done())
264
    {
265
628
      TNode fact = get().d_assertion;
266
314
      Assert(fact.getKind() == kind::BITVECTOR_EAGER_ATOM);
267
314
      assertions.push_back(fact);
268
314
      d_eagerSolver->assertFormula(fact[0]);
269
    }
270
271
53
    bool ok = d_eagerSolver->checkSat();
272
53
    if (!ok)
273
    {
274
20
      if (assertions.size() == 1)
275
      {
276
6
        d_im.conflict(assertions[0], InferenceId::BV_LAZY_CONFLICT);
277
6
        return;
278
      }
279
28
      Node conflict = utils::mkAnd(assertions);
280
14
      d_im.conflict(conflict, InferenceId::BV_LAZY_CONFLICT);
281
14
      return;
282
    }
283
33
    return;
284
  }
285
286
238203
  if (Theory::fullEffort(e))
287
  {
288
30936
    ++(d_statistics.d_numCallsToCheckFullEffort);
289
  }
290
  else
291
  {
292
207267
    ++(d_statistics.d_numCallsToCheckStandardEffort);
293
  }
294
  // if we are already in conflict just return the conflict
295
238203
  if (inConflict())
296
  {
297
    sendConflict();
298
    return;
299
  }
300
301
3033489
  while (!done())
302
  {
303
2795286
    TNode fact = get().d_assertion;
304
305
1397643
    checkForLemma(fact);
306
307
5590564
    for (unsigned i = 0; i < d_subtheories.size(); ++i)
308
    {
309
4192921
      d_subtheories[i]->assertFact(fact);
310
    }
311
  }
312
313
238203
  bool ok = true;
314
238203
  bool complete = false;
315
639221
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
316
  {
317
639221
    Assert(!inConflict());
318
639221
    ok = d_subtheories[i]->check(e);
319
639221
    complete = d_subtheories[i]->isComplete();
320
321
639221
    if (!ok)
322
    {
323
      // if we are in a conflict no need to check with other theories
324
15249
      Assert(inConflict());
325
15249
      sendConflict();
326
15249
      return;
327
    }
328
623972
    if (complete)
329
    {
330
      // if the last subtheory was complete we stop
331
222954
      break;
332
    }
333
  }
334
335
  // check extended functions
336
222954
  if (Theory::fullEffort(e))
337
  {
338
25784
    CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
339
25784
    if (core)
340
    {
341
      // check extended functions at full effort
342
25782
      core->checkExtf(e);
343
    }
344
  }
345
}
346
347
8473
bool BVSolverLazy::needsCheckLastEffort()
348
{
349
8473
  CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
350
8473
  if (core)
351
  {
352
8438
    return core->needsCheckLastEffort();
353
  }
354
35
  return false;
355
}
356
357
7158
bool BVSolverLazy::collectModelValues(TheoryModel* m,
358
                                      const std::set<Node>& termSet)
359
{
360
7158
  Assert(!inConflict());
361
7158
  if (options::bitblastMode() == options::BitblastMode::EAGER)
362
  {
363
9
    if (!d_eagerSolver->collectModelInfo(m, true))
364
    {
365
      return false;
366
    }
367
  }
368
13560
  for (unsigned i = 0; i < d_subtheories.size(); ++i)
369
  {
370
13551
    if (d_subtheories[i]->isComplete())
371
    {
372
7149
      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
829493
void BVSolverLazy::propagate(Theory::Effort e)
392
{
393
829493
  Debug("bitvector") << indent() << "BVSolverLazy::propagate()" << std::endl;
394
829493
  if (options::bitblastMode() == options::BitblastMode::EAGER)
395
  {
396
234
    return;
397
  }
398
399
829259
  if (inConflict())
400
  {
401
    return;
402
  }
403
404
  // go through stored propagations
405
829259
  bool ok = true;
406
2535653
  for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok;
407
1137596
       d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1)
408
  {
409
1137596
    TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
410
    // temporary fix for incremental bit-blasting
411
568798
    if (d_state.isSatLiteral(literal))
412
    {
413
1062380
      Debug("bitvector::propagate")
414
531190
          << "BVSolverLazy:: propagating " << literal << "\n";
415
531190
      ok = d_im.propagateLit(literal);
416
    }
417
  }
418
419
829259
  if (!ok)
420
  {
421
    Debug("bitvector::propagate")
422
        << indent() << "BVSolverLazy::propagate(): conflict from theory engine"
423
        << std::endl;
424
    setConflict();
425
  }
426
}
427
428
315684
TrustNode BVSolverLazy::ppRewrite(TNode t)
429
{
430
315684
  Debug("bv-pp-rewrite") << "BVSolverLazy::ppRewrite " << t << "\n";
431
631368
  Node res = t;
432
631368
  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
315264
  else if (RewriteRule<UltAddOne>::applies(t))
438
  {
439
108
    Node result = RewriteRule<UltAddOne>::run<false>(t);
440
54
    res = Rewriter::rewrite(result);
441
  }
442
630420
  else if (res.getKind() == kind::EQUAL
443
945634
           && ((res[0].getKind() == kind::BITVECTOR_ADD
444
316010
                && RewriteRule<ConcatToMult>::applies(res[1]))
445
332688
               || (res[1].getKind() == kind::BITVECTOR_ADD
446
315636
                   && 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
315206
  else if (RewriteRule<SignExtendEqConst>::applies(t))
465
  {
466
346
    res = RewriteRule<SignExtendEqConst>::run<false>(t);
467
  }
468
314860
  else if (RewriteRule<ZeroExtendEqConst>::applies(t))
469
  {
470
    res = RewriteRule<ZeroExtendEqConst>::run<false>(t);
471
  }
472
314860
  else if (RewriteRule<NormalizeEqAddNeg>::applies(t))
473
  {
474
1216
    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
315684
  if (options::bvAbstraction() && t.getType().isBoolean())
514
  {
515
12
    d_abstractionModule->addInputAtom(res);
516
  }
517
315684
  Debug("bv-pp-rewrite") << "to   " << res << "\n";
518
315684
  if (res != t)
519
  {
520
1138
    return TrustNode::mkTrustRewrite(t, res, nullptr);
521
  }
522
314546
  return TrustNode::null();
523
}
524
525
14287
void BVSolverLazy::presolve()
526
{
527
14287
  Debug("bitvector") << "BVSolverLazy::presolve" << std::endl;
528
14287
}
529
530
static int prop_count = 0;
531
532
2435890
bool BVSolverLazy::storePropagation(TNode literal, SubTheory subtheory)
533
{
534
4871780
  Debug("bitvector::propagate") << indent() << d_context->getLevel() << " "
535
2435890
                                << "BVSolverLazy::storePropagation(" << literal
536
2435890
                                << ", " << subtheory << ")" << std::endl;
537
2435890
  prop_count++;
538
539
  // If already in conflict, no more propagation
540
2435890
  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
2435890
  PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
550
2435890
  if (find != d_propagatedBy.end())
551
  {
552
887100
    return true;
553
  }
554
  else
555
  {
556
1548790
    bool polarity = literal.getKind() != kind::NOT;
557
3095551
    Node negatedLiteral = polarity ? literal.notNode() : (Node)literal[0];
558
1548790
    find = d_propagatedBy.find(negatedLiteral);
559
1548790
    if (find != d_propagatedBy.end() && (*find).second != subtheory)
560
    {
561
      // Safe to ignore this one, subtheory should produce a conflict
562
2029
      return true;
563
    }
564
565
1546761
    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
1546761
  constexpr bool ok = true;
574
1546761
  if (subtheory == SUB_CORE)
575
  {
576
782000
    d_im.propagateLit(literal);
577
    if (!ok)
578
    {
579
      setConflict();
580
    }
581
  }
582
  else
583
  {
584
764761
    d_literalsToPropagate.push_back(literal);
585
  }
586
1546761
  return ok;
587
588
} /* BVSolverLazy::propagate(TNode) */
589
590
23652
void BVSolverLazy::explain(TNode literal, std::vector<TNode>& assumptions)
591
{
592
23652
  Assert(wasPropagatedBySubtheory(literal));
593
23652
  SubTheory sub = getPropagatingSubtheory(literal);
594
23652
  d_subtheoryMap[sub]->explain(literal, assumptions);
595
23652
}
596
597
23652
TrustNode BVSolverLazy::explain(TNode node)
598
{
599
47304
  Debug("bitvector::explain")
600
23652
      << "BVSolverLazy::explain(" << node << ")" << std::endl;
601
47304
  std::vector<TNode> assumptions;
602
603
  // Ask for the explanation
604
23652
  explain(node, assumptions);
605
  // this means that it is something true at level 0
606
47304
  Node explanation;
607
23652
  if (assumptions.size() == 0)
608
  {
609
132
    explanation = utils::mkTrue();
610
  }
611
  else
612
  {
613
    // return the explanation
614
23520
    explanation = utils::mkAnd(assumptions);
615
  }
616
47304
  Debug("bitvector::explain") << "BVSolverLazy::explain(" << node << ") => "
617
23652
                              << explanation << std::endl;
618
23652
  Debug("bitvector::explain") << "BVSolverLazy::explain done. \n";
619
47304
  return TrustNode::mkTrustPropExp(node, explanation, nullptr);
620
}
621
622
52392
void BVSolverLazy::notifySharedTerm(TNode t)
623
{
624
104784
  Debug("bitvector::sharing")
625
52392
      << indent() << "BVSolverLazy::notifySharedTerm(" << t << ")" << std::endl;
626
52392
  d_sharedTermsSet.insert(t);
627
52392
}
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
525438
void BVSolverLazy::ppStaticLearn(TNode in, NodeBuilder& learned)
647
{
648
525438
  if (d_staticLearnCache.find(in) != d_staticLearnCache.end())
649
  {
650
61154
    return;
651
  }
652
464284
  d_staticLearnCache.insert(in);
653
654
464284
  if (in.getKind() == kind::EQUAL)
655
  {
656
68688
    if ((in[0].getKind() == kind::BITVECTOR_ADD
657
22910
         && in[1].getKind() == kind::BITVECTOR_SHL)
658
114480
        || (in[1].getKind() == kind::BITVECTOR_ADD
659
22898
            && 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
441388
  else if (in.getKind() == kind::AND)
688
  {
689
426069
    for (size_t i = 0, N = in.getNumChildren(); i < N; ++i)
690
    {
691
421404
      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
15249
void BVSolverLazy::setConflict(Node conflict)
713
{
714
15249
  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
15249
  d_conflict = true;
728
15249
  d_conflictNode = conflict;
729
15249
}
730
731
}  // namespace bv
732
}  // namespace theory
733
353280
}  // namespace cvc5