GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/error_set.h Lines: 47 92 51.1 %
Date: 2021-05-22 Branches: 12 138 8.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Mathias Preiner, Morgan Deters
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
 * [[ Add one-line brief description here ]]
14
 *
15
 * [[ Add lengthier description here ]]
16
 * \todo document this file
17
 */
18
19
#include "cvc5_private.h"
20
21
#pragma once
22
23
#include <vector>
24
25
#include "options/arith_options.h"
26
#include "theory/arith/arithvar.h"
27
#include "theory/arith/bound_counts.h"
28
#include "theory/arith/callbacks.h"
29
#include "theory/arith/delta_rational.h"
30
#include "theory/arith/partial_model.h"
31
#include "theory/arith/tableau_sizes.h"
32
#include "util/bin_heap.h"
33
#include "util/statistics_stats.h"
34
35
namespace cvc5 {
36
namespace theory {
37
namespace arith {
38
39
40
/**
41
 * The priority queue has 3 different modes of operation:
42
 * - Collection
43
 *   This passively collects arithmetic variables that may be inconsistent.
44
 *   This does not maintain any heap structure.
45
 *   dequeueInconsistentBasicVariable() does not work in this mode!
46
 *   Entering this mode requires the queue to be empty.
47
 *
48
 * - Difference Queue
49
 *   This mode uses the difference between a variables and its bound
50
 *   to determine which to dequeue first.
51
 *
52
 * - Variable Order Queue
53
 *   This mode uses the variable order to determine which ArithVar is dequeued first.
54
 *
55
 * The transitions between the modes of operation are:
56
 *  Collection => Difference Queue
57
 *  Difference Queue => Variable Order Queue
58
 *  Difference Queue => Collection (queue must be empty!)
59
 *  Variable Order Queue => Collection (queue must be empty!)
60
 *
61
 * The queue begins in Collection mode.
62
 */
63
64
65
class ErrorSet;
66
67
class ComparatorPivotRule {
68
private:
69
  const ErrorSet* d_errorSet;
70
71
  options::ErrorSelectionRule d_rule;
72
73
 public:
74
  ComparatorPivotRule();
75
  ComparatorPivotRule(const ErrorSet* es, options::ErrorSelectionRule r);
76
77
  bool operator()(ArithVar v, ArithVar u) const;
78
  options::ErrorSelectionRule getRule() const { return d_rule; }
79
};
80
81
// typedef boost::heap::d_ary_heap<
82
//   ArithVar,
83
//   boost::heap::arity<2>,
84
//   boost::heap::compare<ComparatorPivotRule>,
85
//   boost::heap::mutable_<true> > FocusSet;
86
//
87
// typedef FocusSet::handle_type FocusSetHandle;
88
89
// typedef CVC5_PB_DS_NAMESPACE::priority_queue<
90
//   ArithVar,
91
//   ComparatorPivotRule,
92
//   CVC5_PB_DS_NAMESPACE::pairing_heap_tag> FocusSet;
93
94
// typedef FocusSet::point_iterator FocusSetHandle;
95
96
typedef BinaryHeap<ArithVar, ComparatorPivotRule> FocusSet;
97
typedef FocusSet::handle FocusSetHandle;
98
99
100
class ErrorInformation {
101
private:
102
  /** The variable that is in error. */
103
  ArithVar d_variable;
104
105
  /**
106
   * The constraint that was violated.
107
   * This needs to be saved in case that the
108
   * violated constraint
109
   */
110
  ConstraintP d_violated;
111
112
  /**
113
   * This is the sgn of the first derivate the variable must move to satisfy
114
   * the bound violated.
115
   * If d_sgn > 0, then d_violated was a lowerbound.
116
   * If d_sgn < 0, then d_violated was an upperbound.
117
   */
118
  int d_sgn;
119
120
  /**
121
   * If this is true, then the bound is no longer set on d_variables.
122
   * This MUST be undone before this is deleted.
123
   */
124
  bool d_relaxed;
125
126
  /**
127
   * If this is true, then the variable is in the focus set and the focus heap.
128
   * d_handle is then a reasonable thing to interpret.
129
   * If this is false, the variable is somewhere in
130
   */
131
  bool d_inFocus;
132
  FocusSetHandle d_handle;
133
134
  /**
135
   * Auxillary information for storing the difference between a variable and its bound.
136
   * Only set on signals.
137
   */
138
  DeltaRational* d_amount;
139
140
  /** */
141
  uint32_t d_metric;
142
143
public:
144
  ErrorInformation();
145
  ErrorInformation(ArithVar var, ConstraintP vio, int sgn);
146
  ~ErrorInformation();
147
  ErrorInformation(const ErrorInformation& ei);
148
  ErrorInformation& operator=(const ErrorInformation& ei);
149
150
  void reset(ConstraintP c, int sgn);
151
152
270222
  inline ArithVar getVariable() const { return d_variable; }
153
154
298871
  bool isRelaxed() const { return d_relaxed; }
155
  void setRelaxed()
156
  {
157
    Assert(!d_relaxed);
158
    d_relaxed = true;
159
  }
160
  void setUnrelaxed()
161
  {
162
    Assert(d_relaxed);
163
    d_relaxed = false;
164
  }
165
166
1061980
  inline int sgn() const { return d_sgn; }
167
168
692178
  inline bool inFocus() const { return d_inFocus; }
169
530990
  inline int focusSgn() const {
170
530990
    return (d_inFocus) ? sgn() : 0;
171
  }
172
173
685555
  inline void setInFocus(bool inFocus) { d_inFocus = inFocus; }
174
175
978412
  const DeltaRational& getAmount() const {
176
978412
    Assert(d_amount != NULL);
177
978412
    return *d_amount;
178
  }
179
180
  void setAmount(const DeltaRational& am);
181
  void setMetric(uint32_t m) { d_metric = m; }
182
  uint32_t getMetric() const { return d_metric; }
183
184
549049
  inline void setHandle(FocusSetHandle h) {
185
549049
    Assert(d_inFocus);
186
549049
    d_handle = h;
187
549049
  }
188
357867
  inline const FocusSetHandle& getHandle() const{ return d_handle; }
189
190
  inline ConstraintP getViolated() const { return d_violated; }
191
192
685555
  bool debugInitialized() const {
193
    return
194
1371110
      d_variable != ARITHVAR_SENTINEL &&
195
1371110
      d_violated != NullConstraint &&
196
1371110
      d_sgn != 0;
197
  }
198
  void print(std::ostream& os) const {
199
    os << "{ErrorInfo: " << d_variable
200
       << ", " << d_violated
201
       << ", " << d_sgn
202
       << ", " << d_relaxed
203
       << ", " << d_inFocus;
204
    if(d_amount == NULL){
205
      os << "NULL";
206
    }else{
207
      os << (*d_amount);
208
    }
209
    os << "}";
210
  }
211
};
212
213
18918
class ErrorInfoMap : public DenseMap<ErrorInformation> {};
214
215
9459
class ErrorSet {
216
private:
217
  /**
218
   * Reference to the arithmetic partial model for checking if a variable
219
   * is consistent with its upper and lower bounds.
220
   */
221
  ArithVariables& d_variables;
222
223
  /**
224
   * The set of all variables that violate exactly one of their bounds.
225
   */
226
  ErrorInfoMap d_errInfo;
227
228
  options::ErrorSelectionRule d_selectionRule;
229
  /**
230
   * The ordered heap for the variables that are in ErrorSet.
231
   */
232
  FocusSet d_focus;
233
234
235
  /**
236
   * A strict subset of the error set.
237
   *   d_outOfFocus \neq d_errInfo.
238
   *
239
   * Its symbolic complement is Focus.
240
   *   d_outOfFocus \intersect Focus == \emptyset
241
   *   d_outOfFocus \union Focus == d_errInfo
242
   */
243
  ArithVarVec d_outOfFocus;
244
245
  /**
246
   * Before a variable is added to the error set, it is added to the signals list.
247
   * A variable may appear on the list multiple times.
248
   * This introduces a delay.
249
   */
250
  ArithVarVec d_signals;
251
252
  TableauSizes d_tableauSizes;
253
254
  BoundCountingLookup d_boundLookup;
255
256
  /**
257
   * Computes the difference between the assignment and its bound for x.
258
   */
259
public:
260
  DeltaRational computeDiff(ArithVar x) const;
261
private:
262
 void recomputeAmount(ErrorInformation& ei, options::ErrorSelectionRule r);
263
264
 void update(ErrorInformation& ei);
265
 void transitionVariableOutOfError(ArithVar v);
266
 void transitionVariableIntoError(ArithVar v);
267
 void addBackIntoFocus(ArithVar v);
268
269
public:
270
271
  /** The new focus set is the entire error set. */
272
  void blur();
273
  void dropFromFocus(ArithVar v);
274
275
  void dropFromFocusAll(const ArithVarVec& vec) {
276
    for(ArithVarVec::const_iterator i = vec.begin(), i_end = vec.end(); i != i_end; ++i){
277
      ArithVar v = *i;
278
      dropFromFocus(v);
279
    }
280
  }
281
282
  ErrorSet(ArithVariables& var, TableauSizes tabSizes, BoundCountingLookup boundLookup);
283
284
  typedef ErrorInfoMap::const_iterator error_iterator;
285
598393
  error_iterator errorBegin() const { return d_errInfo.begin(); }
286
598393
  error_iterator errorEnd() const { return d_errInfo.end(); }
287
288
7184155
  bool inError(ArithVar v) const { return d_errInfo.isKey(v); }
289
  bool inFocus(ArithVar v) const { return d_errInfo[v].inFocus(); }
290
291
  void pushErrorInto(ArithVarVec& vec) const;
292
  void pushFocusInto(ArithVarVec& vec) const;
293
294
  options::ErrorSelectionRule getSelectionRule() const;
295
  void setSelectionRule(options::ErrorSelectionRule rule);
296
297
193540
  inline ArithVar topFocusVariable() const{
298
193540
    Assert(!focusEmpty());
299
193540
    return d_focus.top();
300
  }
301
302
7184569
  inline void signalVariable(ArithVar var){
303
7184569
    d_signals.push_back(var);
304
7184569
  }
305
306
  inline void signalUnderCnd(ArithVar var, bool b){
307
    if(b){ signalVariable(var); }
308
  }
309
310
7623046
  inline bool inconsistent(ArithVar var) const{
311
7623046
    return !d_variables.assignmentIsConsistent(var) ;
312
  }
313
  inline void signalIfInconsistent(ArithVar var){
314
    signalUnderCnd(var, inconsistent(var));
315
  }
316
317
2071178
  inline bool errorEmpty() const{
318
2071178
    return d_errInfo.empty();
319
  }
320
1179013
  inline uint32_t errorSize() const{
321
1179013
    return d_errInfo.size();
322
  }
323
324
599056
  inline bool focusEmpty() const {
325
599056
    return d_focus.empty();
326
  }
327
  inline uint32_t focusSize() const{
328
    return d_focus.size();
329
  }
330
331
  inline int getSgn(ArithVar x) const {
332
    Assert(inError(x));
333
    return d_errInfo[x].sgn();
334
  }
335
  inline int focusSgn(ArithVar v) const {
336
    if(inError(v)){
337
      return d_errInfo[v].focusSgn();
338
    }else{
339
      return 0;
340
    }
341
  }
342
343
  void focusDownToJust(ArithVar v);
344
345
  void clearFocus();
346
347
  /** Clears the set. */
348
  void clear();
349
  void reduceToSignals();
350
351
17915879
  bool noSignals() const {
352
17915879
    return d_signals.empty();
353
  }
354
17051988
  bool moreSignals() const {
355
17051988
    return !noSignals();
356
  }
357
7184155
  ArithVar topSignal() const {
358
7184155
    Assert(moreSignals());
359
7184155
    return d_signals.back();
360
  }
361
362
  /**
363
   * Moves a variable out of the signals.
364
   * This moves it into the error set.
365
   * Return the previous focus sign.
366
   */
367
  int popSignal();
368
369
978412
  const DeltaRational& getAmount(ArithVar v) const {
370
978412
    return d_errInfo[v].getAmount();
371
  }
372
373
  uint32_t sumMetric(ArithVar a) const{
374
    Assert(inError(a));
375
    BoundCounts bcs = d_boundLookup.atBounds(a);
376
    uint32_t count = getSgn(a) > 0 ? bcs.upperBoundCount() : bcs.lowerBoundCount();
377
378
    uint32_t length = d_tableauSizes.getRowLength(a);
379
380
    return (length - count);
381
  }
382
383
  uint32_t getMetric(ArithVar a) const {
384
    return d_errInfo[a].getMetric();
385
  }
386
387
  ConstraintP getViolated(ArithVar a) const {
388
    return d_errInfo[a].getViolated();
389
  }
390
391
392
  typedef FocusSet::const_iterator focus_iterator;
393
  focus_iterator focusBegin() const { return d_focus.begin(); }
394
  focus_iterator focusEnd() const { return d_focus.end(); }
395
396
  void debugPrint(std::ostream& out) const;
397
398
private:
399
  class Statistics {
400
  public:
401
    IntStat d_enqueues;
402
    IntStat d_enqueuesCollection;
403
    IntStat d_enqueuesDiffMode;
404
    IntStat d_enqueuesVarOrderMode;
405
406
    IntStat d_enqueuesCollectionDuplicates;
407
    IntStat d_enqueuesVarOrderModeDuplicates;
408
409
    Statistics();
410
  };
411
412
  Statistics d_statistics;
413
};
414
415
}  // namespace arith
416
}  // namespace theory
417
}  // namespace cvc5