GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_inequality_graph.h Lines: 41 41 100.0 %
Date: 2021-05-22 Branches: 23 82 28.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Mathias Preiner, Tim King
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 "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__BV__BV_INEQUALITY__GRAPH_H
19
#define CVC5__THEORY__BV__BV_INEQUALITY__GRAPH_H
20
21
#include <queue>
22
#include <unordered_map>
23
#include <unordered_set>
24
25
#include "context/cdhashmap.h"
26
#include "context/cdhashset.h"
27
#include "context/cdo.h"
28
#include "context/cdqueue.h"
29
#include "context/context.h"
30
31
namespace cvc5 {
32
namespace theory {
33
namespace bv {
34
35
typedef unsigned TermId;
36
typedef unsigned ReasonId;
37
extern const TermId UndefinedTermId;
38
extern const ReasonId UndefinedReasonId;
39
extern const ReasonId AxiomReasonId;
40
41
class InequalityGraph : public context::ContextNotifyObj{
42
43
  struct InequalityEdge {
44
    TermId next;
45
    ReasonId reason;
46
    bool strict;
47
1158509
    InequalityEdge(TermId n, bool s, ReasonId r)
48
1158509
      : next(n),
49
        reason(r),
50
1158509
        strict(s)
51
1158509
    {}
52
1158509
    bool operator==(const InequalityEdge& other) const {
53
1158509
      return next == other.next && reason == other.reason && strict == other.strict;
54
    }
55
  };
56
57
  class InequalityNode {
58
    TermId d_id;
59
    unsigned d_bitwidth;
60
    bool d_isConstant;
61
  public:
62
29632
    InequalityNode(TermId id, unsigned bitwidth, bool isConst)
63
29632
      : d_id(id),
64
        d_bitwidth(bitwidth),
65
29632
        d_isConstant(isConst)
66
29632
    {}
67
    TermId getId() const { return d_id; }
68
445227
    unsigned getBitwidth() const { return d_bitwidth; }
69
5940016
    bool isConstant() const { return d_isConstant; }
70
  };
71
72
20736386
  struct ModelValue {
73
    TermId parent;
74
    ReasonId reason;
75
    BitVector value;
76
927954
    ModelValue()
77
927954
      : parent(UndefinedTermId),
78
        reason(UndefinedReasonId),
79
927954
        value(0, 0u)
80
927954
    {}
81
82
5238447
    ModelValue(const BitVector& val, TermId p, ReasonId r)
83
5238447
      : parent(p),
84
        reason(r),
85
5238447
        value(val)
86
5238447
    {}
87
  };
88
89
  typedef context::CDHashMap<TermId, ModelValue> ModelValues;
90
91
  struct QueueComparator {
92
    const ModelValues* d_model;
93
215480
    QueueComparator(const ModelValues* model)
94
215480
      : d_model(model)
95
215480
    {}
96
3687
    bool operator() (TermId left, TermId right) const {
97
3687
      Assert(d_model->find(left) != d_model->end()
98
             && d_model->find(right) != d_model->end());
99
100
3687
      return (*(d_model->find(left))).second.value < (*(d_model->find(right))).second.value;
101
    }
102
  };
103
104
  typedef std::unordered_map<TNode, ReasonId> ReasonToIdMap;
105
  typedef std::unordered_map<TNode, TermId> TermNodeToIdMap;
106
107
  typedef std::vector<InequalityEdge> Edges;
108
  typedef std::unordered_set<TermId> TermIdSet;
109
110
  typedef std::priority_queue<TermId, std::vector<TermId>, QueueComparator>
111
      BFSQueue;
112
  typedef std::unordered_set<TNode> TNodeSet;
113
  typedef std::unordered_set<Node> NodeSet;
114
115
  std::vector<InequalityNode> d_ineqNodes;
116
  std::vector< Edges > d_ineqEdges;
117
118
  // to keep the explanation nodes alive
119
  NodeSet d_reasonSet;
120
  std::vector<TNode> d_reasonNodes;
121
  ReasonToIdMap d_reasonToIdMap;
122
123
  std::vector<Node> d_termNodes;
124
  TermNodeToIdMap d_termNodeToIdMap;
125
126
  context::CDO<bool> d_inConflict;
127
  std::vector<TNode> d_conflict;
128
129
  ModelValues  d_modelValues;
130
  void initializeModelValue(TNode node);
131
  void setModelValue(TermId term, const ModelValue& mv);
132
  ModelValue getModelValue(TermId term) const;
133
  bool hasModelValue(TermId id) const;
134
  bool hasReason(TermId id) const;
135
136
  /**
137
   * Registers the term by creating its corresponding InequalityNode
138
   * and adding the min <= term <= max default edges.
139
   *
140
   * @param term
141
   *
142
   * @return
143
   */
144
  TermId registerTerm(TNode term);
145
  TNode getTermNode(TermId id) const;
146
  TermId getTermId(TNode node) const;
147
  bool isRegistered(TNode term) const;
148
149
  ReasonId registerReason(TNode reason);
150
  TNode getReasonNode(ReasonId id) const;
151
152
2762245
  Edges& getEdges(TermId id)
153
  {
154
2762245
    Assert(id < d_ineqEdges.size());
155
2762245
    return d_ineqEdges[id];
156
  }
157
  InequalityNode& getInequalityNode(TermId id)
158
  {
159
    Assert(id < d_ineqNodes.size());
160
    return d_ineqNodes[id];
161
  }
162
6385243
  const InequalityNode& getInequalityNode(TermId id) const
163
  {
164
6385243
    Assert(id < d_ineqNodes.size());
165
6385243
    return d_ineqNodes[id];
166
  }
167
445227
  unsigned getBitwidth(TermId id) const { return getInequalityNode(id).getBitwidth(); }
168
5940016
  bool isConst(TermId id) const { return getInequalityNode(id).isConstant(); }
169
170
  BitVector getValue(TermId id) const;
171
172
  void addEdge(TermId a, TermId b, bool strict, TermId reason);
173
174
  void setConflict(const std::vector<ReasonId>& conflict);
175
  /**
176
   * If necessary update the value in the model of the current queue element.
177
   *
178
   * @param id current queue element we are updating
179
   * @param start node we started with, to detect cycles
180
   *
181
   * @return
182
   */
183
  bool updateValue(TermId id, ModelValue new_mv, TermId start, bool& changed);
184
  /**
185
   * Update the current model starting with the start term.
186
   *
187
   * @param queue
188
   * @param start
189
   *
190
   * @return
191
   */
192
  bool processQueue(BFSQueue& queue, TermId start);
193
  /**
194
   * Return the reasons why from <= to. If from is undefined we just
195
   * explain the current value of to.
196
   *
197
   * @param from
198
   * @param to
199
   * @param explanation
200
   */
201
  void computeExplanation(TermId from, TermId to, std::vector<ReasonId>& explanation);
202
  //  void splitDisequality(TNode diseq);
203
204
  /**
205
     Disequality reasoning
206
   */
207
208
  /*** The currently asserted disequalities */
209
  context::CDQueue<TNode> d_disequalities;
210
  typedef context::CDHashSet<Node> CDNodeSet;
211
  CDNodeSet d_disequalitiesAlreadySplit;
212
  Node makeDiseqSplitLemma(TNode diseq);
213
  /** Backtracking mechanisms **/
214
  std::vector<std::pair<TermId, InequalityEdge> > d_undoStack;
215
  context::CDO<unsigned> d_undoStackIndex;
216
217
2239992
  void contextNotifyPop() override { backtrack(); }
218
219
  void backtrack();
220
221
public:
222
223
9405
  InequalityGraph(context::Context* c, context::Context* u, bool s = false)
224
9405
    : ContextNotifyObj(c),
225
      d_ineqNodes(),
226
      d_ineqEdges(),
227
      d_inConflict(c, false),
228
      d_conflict(),
229
      d_modelValues(c),
230
      d_disequalities(c),
231
      d_disequalitiesAlreadySplit(u),
232
      d_undoStack(),
233
9405
      d_undoStackIndex(c)
234
9405
  {}
235
  /**
236
   * Add a new inequality to the graph
237
   *
238
   * @param a
239
   * @param b
240
   * @param strict
241
   * @param reason
242
   *
243
   * @return
244
   */
245
  bool addInequality(TNode a, TNode b, bool strict, TNode reason);
246
  /**
247
   * Add a new disequality to the graph. This may lead in a lemma.
248
   *
249
   * @param a
250
   * @param b
251
   * @param reason
252
   *
253
   * @return
254
   */
255
  bool addDisequality(TNode a, TNode b, TNode reason);
256
  void getConflict(std::vector<TNode>& conflict);
257
9405
  virtual ~InequalityGraph() {}
258
  /**
259
   * Check that the currently asserted disequalities that have not been split on
260
   * are still true in the current model.
261
   */
262
  void checkDisequalities(std::vector<Node>& lemmas);
263
  /**
264
   * Return true if a < b is entailed by the current set of assertions.
265
   *
266
   * @param a
267
   * @param b
268
   *
269
   * @return
270
   */
271
  bool isLessThan(TNode a, TNode b);
272
  /**
273
   * Returns true if the term has a value in the model (i.e. if we have seen it)
274
   *
275
   * @param a
276
   *
277
   * @return
278
   */
279
  bool hasValueInModel(TNode a) const;
280
  /**
281
   * Return the value of a in the current model.
282
   *
283
   * @param a
284
   *
285
   * @return
286
   */
287
  BitVector getValueInModel(TNode a) const;
288
289
  void getAllValuesInModel(std::vector<Node>& assignments);
290
};
291
292
}
293
}
294
}  // namespace cvc5
295
296
#endif /* CVC5__THEORY__BV__BV_INEQUALITY__GRAPH_H */