GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/error_set.cpp Lines: 197 308 64.0 %
Date: 2021-09-17 Branches: 167 625 26.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Mathias Preiner
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 "theory/arith/error_set.h"
20
21
#include "smt/smt_statistics_registry.h"
22
#include "theory/arith/constraint.h"
23
24
using namespace std;
25
26
namespace cvc5 {
27
namespace theory {
28
namespace arith {
29
30
31
580322
ErrorInformation::ErrorInformation()
32
  : d_variable(ARITHVAR_SENTINEL)
33
  , d_violated(NullConstraint)
34
  , d_sgn(0)
35
  , d_relaxed(false)
36
  , d_inFocus(false)
37
  , d_handle()
38
  , d_amount(NULL)
39
580322
  , d_metric(0)
40
{
41
580322
  Debug("arith::error::mem") << "def constructor " << d_variable << " "  << d_amount << endl;
42
580322
}
43
44
434493
ErrorInformation::ErrorInformation(ArithVar var, ConstraintP vio, int sgn)
45
  : d_variable(var)
46
  , d_violated(vio)
47
  , d_sgn(sgn)
48
  , d_relaxed(false)
49
  , d_inFocus(false)
50
  , d_handle()
51
  , d_amount(NULL)
52
434493
  , d_metric(0)
53
{
54
434493
  Assert(debugInitialized());
55
434493
  Debug("arith::error::mem") << "constructor " << d_variable << " "  << d_amount << endl;
56
434493
}
57
58
59
2329374
ErrorInformation::~ErrorInformation() {
60
1164687
  Assert(d_relaxed != true);
61
1164687
  if(d_amount != NULL){
62
602
    Debug("arith::error::mem") << d_amount << endl;
63
602
    Debug("arith::error::mem") << "destroy " << d_variable << " "  << d_amount << endl;
64
602
    delete d_amount;
65
602
    d_amount = NULL;
66
  }
67
1164687
}
68
69
149872
ErrorInformation::ErrorInformation(const ErrorInformation& ei)
70
149872
  : d_variable(ei.d_variable)
71
149872
  , d_violated(ei.d_violated)
72
149872
  , d_sgn(ei.d_sgn)
73
149872
  , d_relaxed(ei.d_relaxed)
74
149872
  , d_inFocus(ei.d_inFocus)
75
  , d_handle(ei.d_handle)
76
749360
  , d_metric(0)
77
{
78
149872
  if(ei.d_amount == NULL){
79
149704
    d_amount = NULL;
80
  }else{
81
168
    d_amount = new DeltaRational(*ei.d_amount);
82
  }
83
149872
  Debug("arith::error::mem") << "copy const " << d_variable << " "  << d_amount << endl;
84
149872
}
85
86
868254
ErrorInformation& ErrorInformation::operator=(const ErrorInformation& ei){
87
868254
  d_variable = ei.d_variable;
88
868254
  d_violated = ei.d_violated;
89
868254
  d_sgn = ei.d_sgn;
90
868254
  d_relaxed = (ei.d_relaxed);
91
868254
  d_inFocus = (ei.d_inFocus);
92
868254
  d_handle = (ei.d_handle);
93
868254
  d_metric = ei.d_metric;
94
868254
  if(d_amount != NULL && ei.d_amount != NULL){
95
    Debug("arith::error::mem") << "assignment assign " << d_variable << " "  << d_amount << endl;
96
    *d_amount = *ei.d_amount;
97
868254
  }else if(ei.d_amount != NULL){
98
    d_amount = new DeltaRational(*ei.d_amount);
99
    Debug("arith::error::mem") << "assignment alloc " << d_variable << " "  << d_amount << endl;
100
868254
  }else if(d_amount != NULL){
101
261460
    Debug("arith::error::mem") << "assignment release " << d_variable << " "  << d_amount << endl;
102
261460
    delete d_amount;
103
261460
    d_amount = NULL;
104
  }else{
105
606794
    d_amount = NULL;
106
  }
107
868254
  return *this;
108
}
109
110
1131
void ErrorInformation::reset(ConstraintP c, int sgn){
111
1131
  Assert(!isRelaxed());
112
1131
  Assert(c != NullConstraint);
113
1131
  d_violated = c;
114
1131
  d_sgn = sgn;
115
116
1131
  if(d_amount != NULL){
117
194
    delete d_amount;
118
194
    Debug("arith::error::mem") << "reset " << d_variable << " "  << d_amount << endl;
119
194
    d_amount = NULL;
120
  }
121
1131
}
122
123
337434
void ErrorInformation::setAmount(const DeltaRational& am){
124
337434
  if(d_amount == NULL){
125
262088
    d_amount = new DeltaRational;
126
262088
    Debug("arith::error::mem") << "setAmount " << d_variable << " "  << d_amount << endl;
127
  }
128
337434
  (*d_amount) = am;
129
337434
}
130
131
9942
ErrorSet::Statistics::Statistics()
132
    : d_enqueues(
133
19884
        smtStatisticsRegistry().registerInt("theory::arith::pqueue::enqueues")),
134
9942
      d_enqueuesCollection(smtStatisticsRegistry().registerInt(
135
19884
          "theory::arith::pqueue::enqueuesCollection")),
136
9942
      d_enqueuesDiffMode(smtStatisticsRegistry().registerInt(
137
19884
          "theory::arith::pqueue::enqueuesDiffMode")),
138
9942
      d_enqueuesVarOrderMode(smtStatisticsRegistry().registerInt(
139
19884
          "theory::arith::pqueue::enqueuesVarOrderMode")),
140
9942
      d_enqueuesCollectionDuplicates(smtStatisticsRegistry().registerInt(
141
19884
          "theory::arith::pqueue::enqueuesCollectionDuplicates")),
142
9942
      d_enqueuesVarOrderModeDuplicates(smtStatisticsRegistry().registerInt(
143
59652
          "theory::arith::pqueue::enqueuesVarOrderModeDuplicates"))
144
{
145
9942
}
146
147
9942
ErrorSet::ErrorSet(ArithVariables& vars,
148
                   TableauSizes tabSizes,
149
9942
                   BoundCountingLookup lookups)
150
    : d_variables(vars),
151
      d_errInfo(),
152
      d_selectionRule(options::ErrorSelectionRule::VAR_ORDER),
153
19884
      d_focus(ComparatorPivotRule(this, d_selectionRule)),
154
      d_outOfFocus(),
155
      d_signals(),
156
      d_tableauSizes(tabSizes),
157
29826
      d_boundLookup(lookups)
158
9942
{}
159
160
2670106
options::ErrorSelectionRule ErrorSet::getSelectionRule() const
161
{
162
2670106
  return d_selectionRule;
163
}
164
165
187926
void ErrorSet::recomputeAmount(ErrorInformation& ei,
166
                               options::ErrorSelectionRule rule)
167
{
168
187926
  switch(rule){
169
171914
    case options::ErrorSelectionRule::MINIMUM_AMOUNT:
170
    case options::ErrorSelectionRule::MAXIMUM_AMOUNT:
171
171914
      ei.setAmount(computeDiff(ei.getVariable()));
172
171914
      break;
173
    case options::ErrorSelectionRule::SUM_METRIC:
174
      ei.setMetric(sumMetric(ei.getVariable()));
175
      break;
176
16012
    case options::ErrorSelectionRule::VAR_ORDER:
177
      // do nothing
178
16012
      break;
179
  }
180
187926
}
181
182
988401
void ErrorSet::setSelectionRule(options::ErrorSelectionRule rule)
183
{
184
988401
  if(rule != getSelectionRule()){
185
359004
    FocusSet into(ComparatorPivotRule(this, rule));
186
179502
    FocusSet::const_iterator iter = d_focus.begin();
187
179502
    FocusSet::const_iterator i_end = d_focus.end();
188
555354
    for(; iter != i_end; ++iter){
189
187926
      ArithVar v = *iter;
190
187926
      ErrorInformation& ei = d_errInfo.get(v);
191
187926
      if(ei.inFocus()){
192
187926
        recomputeAmount(ei, rule);
193
187926
        FocusSetHandle handle = into.push(v);
194
187926
        ei.setHandle(handle);
195
      }
196
    }
197
179502
    d_focus.swap(into);
198
179502
    d_selectionRule = rule;
199
  }
200
988401
  Assert(getSelectionRule() == rule);
201
988401
}
202
203
189444
ComparatorPivotRule::ComparatorPivotRule(const ErrorSet* es,
204
189444
                                         options::ErrorSelectionRule r)
205
189444
    : d_errorSet(es), d_rule(r)
206
189444
{}
207
208
1175048
bool ComparatorPivotRule::operator()(ArithVar v, ArithVar u) const {
209
1175048
  switch(d_rule){
210
594812
    case options::ErrorSelectionRule::VAR_ORDER:
211
      // This needs to be the reverse of the minVariableOrder
212
594812
      return v > u;
213
    case options::ErrorSelectionRule::SUM_METRIC:
214
    {
215
      uint32_t v_metric = d_errorSet->getMetric(v);
216
      uint32_t u_metric = d_errorSet->getMetric(u);
217
      if(v_metric == u_metric){
218
        return v > u;
219
      }else{
220
        return v_metric > u_metric;
221
      }
222
    }
223
580236
    case options::ErrorSelectionRule::MINIMUM_AMOUNT:
224
    {
225
580236
      const DeltaRational& vamt = d_errorSet->getAmount(v);
226
580236
      const DeltaRational& uamt = d_errorSet->getAmount(u);
227
580236
      int cmp = vamt.cmp(uamt);
228
580236
      if(cmp == 0){
229
213865
        return v > u;
230
      }else{
231
366371
        return cmp > 0;
232
      }
233
    }
234
    case options::ErrorSelectionRule::MAXIMUM_AMOUNT:
235
    {
236
      const DeltaRational& vamt = d_errorSet->getAmount(v);
237
      const DeltaRational& uamt = d_errorSet->getAmount(u);
238
      int cmp = vamt.cmp(uamt);
239
      if(cmp == 0){
240
        return v > u;
241
      }else{
242
        return cmp < 0;
243
      }
244
    }
245
  }
246
  Unreachable();
247
}
248
249
258811
void ErrorSet::update(ErrorInformation& ei){
250
258811
  if(ei.inFocus()){
251
252
258811
    switch(getSelectionRule()){
253
75495
      case options::ErrorSelectionRule::MINIMUM_AMOUNT:
254
      case options::ErrorSelectionRule::MAXIMUM_AMOUNT:
255
75495
        ei.setAmount(computeDiff(ei.getVariable()));
256
75495
        d_focus.update(ei.getHandle(), ei.getVariable());
257
75495
        break;
258
      case options::ErrorSelectionRule::SUM_METRIC:
259
        ei.setMetric(sumMetric(ei.getVariable()));
260
        d_focus.update(ei.getHandle(), ei.getVariable());
261
        break;
262
183316
      case options::ErrorSelectionRule::VAR_ORDER:
263
        // do nothing
264
183316
        break;
265
    }
266
  }
267
258811
}
268
269
/** A variable becomes satisfied. */
270
324099
void ErrorSet::transitionVariableOutOfError(ArithVar v) {
271
324099
  Assert(!inconsistent(v));
272
324099
  ErrorInformation& ei = d_errInfo.get(v);
273
324099
  Assert(ei.debugInitialized());
274
324099
  if(ei.isRelaxed()){
275
    ConstraintP viol = ei.getViolated();
276
    if(ei.sgn() > 0){
277
      d_variables.setLowerBoundConstraint(viol);
278
    }else{
279
      d_variables.setUpperBoundConstraint(viol);
280
    }
281
    Assert(!inconsistent(v));
282
    ei.setUnrelaxed();
283
  }
284
324099
  if(ei.inFocus()){
285
324099
    d_focus.erase(ei.getHandle());
286
324099
    ei.setInFocus(false);
287
  }
288
324099
  d_errInfo.remove(v);
289
324099
}
290
291
292
434493
void ErrorSet::transitionVariableIntoError(ArithVar v) {
293
434493
  Assert(inconsistent(v));
294
434493
  bool vilb = d_variables.cmpAssignmentLowerBound(v) < 0;
295
434493
  int sgn = vilb ? 1 : -1;
296
868986
  ConstraintP c = vilb ?
297
868986
    d_variables.getLowerBoundConstraint(v) : d_variables.getUpperBoundConstraint(v);
298
434493
  d_errInfo.set(v, ErrorInformation(v, c, sgn));
299
434493
  ErrorInformation& ei = d_errInfo.get(v);
300
301
434493
  switch(getSelectionRule()){
302
90025
    case options::ErrorSelectionRule::MINIMUM_AMOUNT:
303
    case options::ErrorSelectionRule::MAXIMUM_AMOUNT:
304
90025
      ei.setAmount(computeDiff(v));
305
90025
      break;
306
    case options::ErrorSelectionRule::SUM_METRIC:
307
      ei.setMetric(sumMetric(ei.getVariable()));
308
      break;
309
344468
    case options::ErrorSelectionRule::VAR_ORDER:
310
      // do nothing
311
344468
      break;
312
  }
313
434493
  ei.setInFocus(true);
314
434493
  FocusSetHandle handle = d_focus.push(v);
315
434493
  ei.setHandle(handle);
316
434493
}
317
318
void ErrorSet::dropFromFocus(ArithVar v) {
319
  Assert(inError(v));
320
  ErrorInformation& ei = d_errInfo.get(v);
321
  Assert(ei.inFocus());
322
  d_focus.erase(ei.getHandle());
323
  ei.setInFocus(false);
324
  d_outOfFocus.push_back(v);
325
}
326
327
void ErrorSet::addBackIntoFocus(ArithVar v) {
328
  Assert(inError(v));
329
  ErrorInformation& ei = d_errInfo.get(v);
330
  Assert(!ei.inFocus());
331
  switch(getSelectionRule()){
332
    case options::ErrorSelectionRule::MINIMUM_AMOUNT:
333
    case options::ErrorSelectionRule::MAXIMUM_AMOUNT:
334
      ei.setAmount(computeDiff(v));
335
      break;
336
    case options::ErrorSelectionRule::SUM_METRIC:
337
      ei.setMetric(sumMetric(v));
338
      break;
339
    case options::ErrorSelectionRule::VAR_ORDER:
340
      // do nothing
341
      break;
342
  }
343
344
  ei.setInFocus(true);
345
  FocusSetHandle handle = d_focus.push(v);
346
  ei.setHandle(handle);
347
}
348
349
void ErrorSet::blur(){
350
  while(!d_outOfFocus.empty()){
351
    ArithVar v = d_outOfFocus.back();
352
    d_outOfFocus.pop_back();
353
354
    if(inError(v) && !inFocus(v)){
355
      addBackIntoFocus(v);
356
    }
357
  }
358
}
359
360
361
362
8449561
int ErrorSet::popSignal() {
363
8449561
  ArithVar back = d_signals.back();
364
8449561
  d_signals.pop_back();
365
366
8449561
  if(inError(back)){
367
582910
    ErrorInformation& ei = d_errInfo.get(back);
368
582910
    int prevSgn = ei.sgn();
369
582910
    int focusSgn = ei.focusSgn();
370
582910
    bool vilb = d_variables.cmpAssignmentLowerBound(back) < 0;
371
582910
    bool viub = d_variables.cmpAssignmentUpperBound(back) > 0;
372
582910
    if(vilb || viub){
373
258811
      Assert(!vilb || !viub);
374
258811
      int currSgn = vilb ? 1 : -1;
375
258811
      if(currSgn != prevSgn){
376
1671
        ConstraintP curr = vilb ?  d_variables.getLowerBoundConstraint(back)
377
1671
          : d_variables.getUpperBoundConstraint(back);
378
1131
        ei.reset(curr, currSgn);
379
      }
380
258811
      update(ei);
381
    }else{
382
324099
      transitionVariableOutOfError(back);
383
    }
384
582910
    return focusSgn;
385
7866651
  }else if(inconsistent(back)){
386
434493
    transitionVariableIntoError(back);
387
  }
388
7866651
  return 0;
389
}
390
391
void ErrorSet::clear(){
392
  // Nothing should be relaxed!
393
  d_signals.clear();
394
  d_errInfo.purge();
395
  d_focus.clear();
396
}
397
398
void ErrorSet::clearFocus(){
399
  for(ErrorSet::focus_iterator i =focusBegin(), i_end = focusEnd(); i != i_end; ++i){
400
    ArithVar f = *i;
401
    ErrorInformation& fei = d_errInfo.get(f);
402
    fei.setInFocus(false);
403
    d_outOfFocus.push_back(f);
404
  }
405
  d_focus.clear();
406
}
407
408
850230
void ErrorSet::reduceToSignals(){
409
959892
  for(error_iterator ei=errorBegin(), ei_end=errorEnd(); ei != ei_end; ++ei){
410
109662
    ArithVar curr = *ei;
411
109662
    signalVariable(curr);
412
  }
413
414
850230
  d_errInfo.purge();
415
850230
  d_focus.clear();
416
850230
  d_outOfFocus.clear();
417
850230
}
418
419
337434
DeltaRational ErrorSet::computeDiff(ArithVar v) const{
420
337434
  Assert(inconsistent(v));
421
337434
  const DeltaRational& beta = d_variables.getAssignment(v);
422
337434
  DeltaRational diff = d_variables.cmpAssignmentLowerBound(v) < 0 ?
423
170026
    d_variables.getLowerBound(v) - beta:
424
507460
    beta - d_variables.getUpperBound(v);
425
426
337434
  Assert(diff.sgn() > 0);
427
337434
  return diff;
428
}
429
430
void ErrorSet::debugPrint(std::ostream& out) const {
431
  static int instance = 0;
432
  ++instance;
433
  out << "error set debugprint " << instance << endl;
434
  for(error_iterator i = errorBegin(), i_end = errorEnd();
435
      i != i_end; ++i){
436
    ArithVar e = *i;
437
    const ErrorInformation& ei = d_errInfo[e];
438
    ei.print(out);
439
    out << "  ";
440
    d_variables.printModel(e, out);
441
    out << endl;
442
  }
443
  out << "focus ";
444
  for(focus_iterator i = focusBegin(), i_end = focusEnd();
445
      i != i_end; ++i){
446
    out << *i << " ";
447
  }
448
  out << ";" << endl;
449
}
450
451
void ErrorSet::focusDownToJust(ArithVar v) {
452
  clearFocus();
453
454
  ErrorInformation& vei = d_errInfo.get(v);
455
  vei.setInFocus(true);
456
  FocusSetHandle handle = d_focus.push(v);
457
  vei.setHandle(handle);
458
}
459
460
void ErrorSet::pushErrorInto(ArithVarVec& vec) const{
461
  for(error_iterator i = errorBegin(), e = errorEnd(); i != e; ++i ){
462
    vec.push_back(*i);
463
  }
464
}
465
466
void ErrorSet::pushFocusInto(ArithVarVec& vec) const{
467
  for(focus_iterator i = focusBegin(), e = focusEnd(); i != e; ++i ){
468
    vec.push_back(*i);
469
  }
470
}
471
472
}  // namespace arith
473
}  // namespace theory
474
29577
}  // namespace cvc5