GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_subtheory_bitblast.cpp Lines: 26 142 18.3 %
Date: 2021-09-17 Branches: 41 452 9.1 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Aina Niemetz, Dejan Jovanovic
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_bitblast.h"
17
18
#include "decision/decision_attributes.h"
19
#include "options/bv_options.h"
20
#include "options/decision_options.h"
21
#include "smt/smt_statistics_registry.h"
22
#include "theory/bv/abstraction.h"
23
#include "theory/bv/bitblast/lazy_bitblaster.h"
24
#include "theory/bv/bv_quick_check.h"
25
#include "theory/bv/bv_solver_layered.h"
26
#include "theory/bv/theory_bv_utils.h"
27
28
using namespace std;
29
using namespace cvc5::context;
30
31
namespace cvc5 {
32
namespace theory {
33
namespace bv {
34
35
2
BitblastSolver::BitblastSolver(context::Context* c, BVSolverLayered* bv)
36
    : SubtheorySolver(c, bv),
37
2
      d_bitblaster(new TLazyBitblaster(c, bv, "theory::bv::lazy")),
38
      d_bitblastQueue(c),
39
      d_statistics(),
40
      d_validModelCache(c, true),
41
      d_lemmaAtomsQueue(c),
42
2
      d_useSatPropagation(options::bitvectorPropagate()),
43
      d_abstractionModule(NULL),
44
      d_quickCheck(),
45
6
      d_quickXplain()
46
{
47
2
  if (options::bitvectorQuickXplain())
48
  {
49
    d_quickCheck.reset(new BVQuickCheck("bb", bv));
50
    d_quickXplain.reset(new QuickXPlain("bb", d_quickCheck.get()));
51
  }
52
2
}
53
54
4
BitblastSolver::~BitblastSolver() {}
55
56
2
BitblastSolver::Statistics::Statistics()
57
2
    : d_numCallstoCheck(smtStatisticsRegistry().registerInt(
58
4
        "theory::bv::BitblastSolver::NumCallsToCheck")),
59
2
      d_numBBLemmas(smtStatisticsRegistry().registerInt(
60
4
          "theory::bv::BitblastSolver::NumTimesLemmasBB"))
61
{
62
2
}
63
64
void BitblastSolver::setAbstraction(AbstractionModule* abs) {
65
  d_abstractionModule = abs;
66
  d_bitblaster->setAbstraction(abs);
67
}
68
69
28
void BitblastSolver::preRegister(TNode node) {
70
74
  if ((node.getKind() == kind::EQUAL ||
71
36
       node.getKind() == kind::BITVECTOR_ULT ||
72
36
       node.getKind() == kind::BITVECTOR_ULE ||
73
36
       node.getKind() == kind::BITVECTOR_SLT ||
74
94
       node.getKind() == kind::BITVECTOR_SLE) &&
75
48
      !d_bitblaster->hasBBAtom(node)) {
76
20
    CodeTimer weightComputationTime(d_bv->d_statistics.d_weightComputationTimer);
77
10
    d_bitblastQueue.push_back(node);
78
20
    if ((options::decisionUseWeight() || options::decisionThreshold() != 0) &&
79
10
        !node.hasAttribute(decision::DecisionWeightAttr())) {
80
      node.setAttribute(decision::DecisionWeightAttr(),computeAtomWeight(node));
81
    }
82
  }
83
28
}
84
85
uint64_t BitblastSolver::computeAtomWeight(TNode node) {
86
  NodeSet seen;
87
  return d_bitblaster->computeAtomWeight(node, seen);
88
}
89
90
void BitblastSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
91
  d_bitblaster->explain(literal, assumptions);
92
}
93
94
void BitblastSolver::bitblastQueue() {
95
  while (!d_bitblastQueue.empty()) {
96
    TNode atom = d_bitblastQueue.front();
97
    d_bitblastQueue.pop();
98
    Debug("bv-bitblast-queue") << "BitblastSolver::bitblastQueue (" << atom << ")\n";
99
    if (options::bvAbstraction() &&
100
        d_abstractionModule->isLemmaAtom(atom)) {
101
      // don't bit-blast lemma atoms
102
      continue;
103
    }
104
    if( !utils::isBitblastAtom(atom) ){
105
      continue;
106
    }
107
    Debug("bitblast-queue") << "Bitblasting atom " << atom <<"\n";
108
    {
109
      TimerStat::CodeTimer codeTimer(d_bitblaster->d_statistics.d_bitblastTimer);
110
      d_bitblaster->bbAtom(atom);
111
    }
112
  }
113
}
114
115
bool BitblastSolver::check(Theory::Effort e)
116
{
117
  Debug("bv-bitblast") << "BitblastSolver::check (" << e << ")\n";
118
  Assert(options::bitblastMode() == options::BitblastMode::LAZY);
119
120
  ++(d_statistics.d_numCallstoCheck);
121
122
  Debug("bv-bitblast-debug") << "...process queue" << std::endl;
123
  //// Lazy bit-blasting
124
  // bit-blast enqueued nodes
125
  bitblastQueue();
126
127
  // Processing assertions
128
  while (!done())
129
  {
130
    TNode fact = get();
131
    d_validModelCache = false;
132
    Debug("bv-bitblast") << "  fact " << fact << ")\n";
133
134
    if (options::bvAbstraction())
135
    {
136
      // skip atoms that are the result of abstraction lemmas
137
      if (d_abstractionModule->isLemmaAtom(fact))
138
      {
139
        d_lemmaAtomsQueue.push_back(fact);
140
        continue;
141
      }
142
    }
143
    // skip facts involving integer equalities (from bv2nat)
144
    if (!utils::isBitblastAtom(fact))
145
    {
146
      continue;
147
    }
148
149
    if (!d_bv->inConflict()
150
        && (!d_bv->wasPropagatedBySubtheory(fact)
151
            || d_bv->getPropagatingSubtheory(fact) != SUB_BITBLAST))
152
    {
153
      // Some atoms have not been bit-blasted yet
154
      d_bitblaster->bbAtom(fact);
155
      // Assert to sat
156
      bool ok = d_bitblaster->assertToSat(fact, d_useSatPropagation);
157
      if (!ok)
158
      {
159
        std::vector<TNode> conflictAtoms;
160
        d_bitblaster->getConflict(conflictAtoms);
161
        setConflict(utils::mkAnd(conflictAtoms));
162
        return false;
163
      }
164
    }
165
  }
166
167
  Debug("bv-bitblast-debug") << "...do propagation" << std::endl;
168
  // We need to ensure we are fully propagated, so propagate now
169
  if (d_useSatPropagation)
170
  {
171
    d_bv->spendResource(Resource::BvPropagationStep);
172
    bool ok = d_bitblaster->propagate();
173
    if (!ok)
174
    {
175
      std::vector<TNode> conflictAtoms;
176
      d_bitblaster->getConflict(conflictAtoms);
177
      setConflict(utils::mkAnd(conflictAtoms));
178
      return false;
179
    }
180
  }
181
182
  // Solving
183
  Debug("bv-bitblast-debug") << "...do solving" << std::endl;
184
  if (e == Theory::EFFORT_FULL)
185
  {
186
    Assert(!d_bv->inConflict());
187
    Debug("bitvector::bitblaster")
188
        << "BitblastSolver::addAssertions solving. \n";
189
    bool ok = d_bitblaster->solve();
190
    if (!ok)
191
    {
192
      std::vector<TNode> conflictAtoms;
193
      d_bitblaster->getConflict(conflictAtoms);
194
      Node conflict = utils::mkAnd(conflictAtoms);
195
      setConflict(conflict);
196
      return false;
197
    }
198
  }
199
200
  Debug("bv-bitblast-debug") << "...do abs bb" << std::endl;
201
  if (options::bvAbstraction() && e == Theory::EFFORT_FULL
202
      && d_lemmaAtomsQueue.size())
203
  {
204
    // bit-blast lemma atoms
205
    while (!d_lemmaAtomsQueue.empty())
206
    {
207
      TNode lemma_atom = d_lemmaAtomsQueue.front();
208
      d_lemmaAtomsQueue.pop();
209
      if (!utils::isBitblastAtom(lemma_atom))
210
      {
211
        continue;
212
      }
213
      d_bitblaster->bbAtom(lemma_atom);
214
      // Assert to sat and check for conflicts
215
      bool ok = d_bitblaster->assertToSat(lemma_atom, d_useSatPropagation);
216
      if (!ok)
217
      {
218
        std::vector<TNode> conflictAtoms;
219
        d_bitblaster->getConflict(conflictAtoms);
220
        setConflict(utils::mkAnd(conflictAtoms));
221
        return false;
222
      }
223
    }
224
225
    Assert(!d_bv->inConflict());
226
    bool ok = d_bitblaster->solve();
227
    if (!ok)
228
    {
229
      std::vector<TNode> conflictAtoms;
230
      d_bitblaster->getConflict(conflictAtoms);
231
      Node conflict = utils::mkAnd(conflictAtoms);
232
      setConflict(conflict);
233
      ++(d_statistics.d_numBBLemmas);
234
      return false;
235
    }
236
  }
237
238
239
  return true;
240
}
241
242
EqualityStatus BitblastSolver::getEqualityStatus(TNode a, TNode b) {
243
  return d_bitblaster->getEqualityStatus(a, b);
244
}
245
246
bool BitblastSolver::collectModelValues(TheoryModel* m,
247
                                        const std::set<Node>& termSet)
248
{
249
  return d_bitblaster->collectModelValues(m, termSet);
250
}
251
252
Node BitblastSolver::getModelValue(TNode node)
253
{
254
  if (d_bv->d_invalidateModelCache.get()) {
255
    d_bitblaster->invalidateModelCache();
256
  }
257
  d_bv->d_invalidateModelCache.set(false);
258
  Node val = d_bitblaster->getTermModel(node, true);
259
  return val;
260
}
261
262
void BitblastSolver::setConflict(TNode conflict)
263
{
264
  Node final_conflict = conflict;
265
  if (options::bitvectorQuickXplain() &&
266
      conflict.getKind() == kind::AND) {
267
    // std::cout << "Original conflict " << conflict.getNumChildren() << "\n";
268
    final_conflict = d_quickXplain->minimizeConflict(conflict);
269
    //std::cout << "Minimized conflict " << final_conflict.getNumChildren() << "\n";
270
  }
271
  d_bv->setConflict(final_conflict);
272
}
273
274
}  // namespace bv
275
}  // namespace theory
276
29577
}  // namespace cvc5