GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/simplex_update.h Lines: 0 57 0.0 %
Date: 2021-09-18 Branches: 0 98 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, 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
 * This provides a class for summarizing pivot proposals.
14
 *
15
 * This shares with the theory a Tableau, and a PartialModel that:
16
 *  - satisfies the equalities in the Tableau, and
17
 *  - the assignment for the non-basic variables satisfies their bounds.
18
 * This maintains the relationship needed by the SimplexDecisionProcedure.
19
 *
20
 * In the language of Simplex for DPLL(T), this provides:
21
 * - update()
22
 * - pivotAndUpdate()
23
 *
24
 * This class also provides utility functions that require
25
 * using both the Tableau and PartialModel.
26
 */
27
28
#include "cvc5_private.h"
29
30
#pragma once
31
32
#include <optional>
33
34
#include "theory/arith/arithvar.h"
35
#include "theory/arith/constraint_forward.h"
36
#include "theory/arith/delta_rational.h"
37
38
namespace cvc5 {
39
namespace theory {
40
namespace arith {
41
42
enum WitnessImprovement {
43
  ConflictFound = 0,
44
  ErrorDropped = 1,
45
  FocusImproved = 2,
46
  FocusShrank = 3,
47
  Degenerate = 4,
48
  BlandsDegenerate = 5,
49
  HeuristicDegenerate = 6,
50
  AntiProductive = 7
51
};
52
53
inline bool strongImprovement(WitnessImprovement w){
54
  return w <= FocusImproved;
55
}
56
57
inline bool improvement(WitnessImprovement w){
58
  return w <= FocusShrank;
59
}
60
61
inline bool degenerate(WitnessImprovement w){
62
  switch(w){
63
  case Degenerate:
64
  case BlandsDegenerate:
65
  case HeuristicDegenerate:
66
    return true;
67
  default:
68
    return false;
69
  }
70
}
71
72
std::ostream& operator<<(std::ostream& out,  WitnessImprovement w);
73
74
/**
75
 * This class summarizes both potential:
76
 * - pivot-and-update operations or
77
 * - a pure update operation.
78
 * This stores enough information for the various algorithms  hat consider these operations.
79
 * These require slightly different pieces of information at different points
80
 * so they are a bit verbose and paranoid.
81
 */
82
class UpdateInfo {
83
private:
84
85
  /**
86
   * The nonbasic variables under consideration.
87
   * This is either the entering variable on a pivot and update
88
   * or the variable being updated.
89
   * This can only be set in the constructor or assignment.
90
   *
91
   * If this uninitialized, then this is ARITHVAR_SENTINEL.
92
   */
93
  ArithVar d_nonbasic;
94
95
  /**
96
   * The sgn of the "intended" derivative (delta) of the update to d_nonbasic.
97
   * This is either 1, -1, or 0.
98
   * It is "intended" as the delta is always allowed to be 0.
99
   * (See debugSgnAgreement().)
100
   *
101
   * If this uninitialized, then this is 0.
102
   * If this is initialized, then it is -1 or 1.
103
   *
104
   * This can only be set in the constructor or assignment.
105
   */
106
  int d_nonbasicDirection;
107
108
  /**
109
   * The change in the assignment of d_nonbasic.
110
   * This is changed via the updateProposal(...) methods.
111
   * The value needs to satisfy debugSgnAgreement() or it is in conflict.
112
   */
113
  std::optional<DeltaRational> d_nonbasicDelta;
114
115
  /**
116
   * This is true if the pivot-and-update is *known* to cause a conflict.
117
   * This can only be true if it was constructed through the static conflict(...) method.
118
   */
119
  bool d_foundConflict;
120
121
  /** This is the change in the size of the error set. */
122
  std::optional<int> d_errorsChange;
123
124
  /** This is the sgn of the change in the value of the focus set.*/
125
  std::optional<int> d_focusDirection;
126
127
  /** This is the sgn of the change in the value of the focus set.*/
128
  std::optional<DeltaRational> d_focusChange;
129
130
  /** This is the coefficient in the tableau for the entry.*/
131
  std::optional<const Rational*> d_tableauCoefficient;
132
133
  /**
134
   * This is the constraint that nonbasic is basic is updating s.t. its variable is against it.
135
   * This has 3 different possibilities:
136
   * - Unbounded : then this is NullConstraint and unbounded() is true.
137
   * - Pivot-And-Update: then this is not NullConstraint and the variable is not d_nonbasic.
138
   * - Update: then this is not NullConstraint and the variable is d_nonbasic.
139
   */
140
  ConstraintP d_limiting;
141
142
  WitnessImprovement d_witness;
143
144
  /**
145
   * This returns true if
146
   * d_nonbasicDelta is zero() or its sgn() must agree with d_nonbasicDirection.
147
   */
148
  bool debugSgnAgreement() const {
149
    int deltaSgn = d_nonbasicDelta.value().sgn();
150
    return deltaSgn == 0 || deltaSgn == d_nonbasicDirection;
151
  }
152
153
  /** This private constructor allows for setting conflict to true. */
154
  UpdateInfo(bool conflict, ArithVar nb, const DeltaRational& delta, const Rational& r, ConstraintP lim);
155
156
public:
157
158
  /** This constructs an uninitialized UpdateInfo. */
159
  UpdateInfo();
160
161
  /**
162
   * This constructs an initialized UpdateInfo.
163
   * dir must be 1 or -1.
164
   */
165
  UpdateInfo(ArithVar nb, int dir);
166
167
  /**
168
   * This updates the nonBasicDelta to d and limiting to NullConstraint.
169
   * This describes an unbounded() update.
170
   */
171
  void updateUnbounded(const DeltaRational& d, int ec, int f);
172
173
174
  void updatePureFocus(const DeltaRational& d, ConstraintP c);
175
  //void updatePureError(const DeltaRational& d, Constraint c, int e);
176
  //void updatePure(const DeltaRational& d, Constraint c, int e, int f);
177
178
  /**
179
   * This updates the nonBasicDelta to d and limiting to c.
180
   * This clears errorChange() and focusDir().
181
   */
182
  void updatePivot(const DeltaRational& d, const Rational& r,  ConstraintP c);
183
184
  /**
185
   * This updates the nonBasicDelta to d, limiting to c, and errorChange to e.
186
   * This clears focusDir().
187
   */
188
  void updatePivot(const DeltaRational& d, const Rational& r, ConstraintP c, int e);
189
190
  /**
191
   * This updates the nonBasicDelta to d, limiting to c, errorChange to e and
192
   * focusDir to f.
193
   */
194
  void witnessedUpdate(const DeltaRational& d, ConstraintP c, int e, int f);
195
  void update(const DeltaRational& d, const Rational& r, ConstraintP c, int e, int f);
196
197
198
  static UpdateInfo conflict(ArithVar nb, const DeltaRational& delta, const Rational& r, ConstraintP lim);
199
200
  inline ArithVar nonbasic() const { return d_nonbasic; }
201
  inline bool uninitialized() const {
202
    return d_nonbasic == ARITHVAR_SENTINEL;
203
  }
204
205
  /**
206
   * There is no limiting value to the improvement of the focus.
207
   * If this is true, this never describes an update.
208
   */
209
  inline bool unbounded() const {
210
    return d_limiting == NullConstraint;
211
  }
212
213
  /**
214
   * The update either describes a pivotAndUpdate operation
215
   * or it describes just an update.
216
   */
217
  bool describesPivot() const;
218
219
  /** Returns the . describesPivot() must be true. */
220
  ArithVar leaving() const;
221
222
  /**
223
   * Returns true if this is *known* to find a conflict.
224
   * If true, this must have been made through the static conflict(...) function.
225
   */
226
  bool foundConflict() const { return d_foundConflict; }
227
228
  /** Returns the direction nonbasic is supposed to move. */
229
  inline int nonbasicDirection() const{  return d_nonbasicDirection; }
230
231
  /** Requires errorsChange to be set through setErrorsChange or updateProposal. */
232
  inline int errorsChange() const { return d_errorsChange.value(); }
233
234
  /**
235
   * If errorsChange has been set, return errorsChange().
236
   * Otherwise, return def.
237
   */
238
  inline int errorsChangeSafe(int def) const {
239
    if (d_errorsChange)
240
    {
241
      return d_errorsChange.value();
242
    }
243
    else
244
    {
245
      return def;
246
    }
247
  }
248
249
  /** Sets the errorChange. */
250
  void setErrorsChange(int ec){
251
    d_errorsChange = ec;
252
    updateWitness();
253
  }
254
255
256
  /** Requires errorsChange to be set through setErrorsChange or updateProposal. */
257
  inline int focusDirection() const { return d_focusDirection.value(); }
258
259
  /** Sets the focusDirection. */
260
  void setFocusDirection(int fd){
261
    Assert(-1 <= fd && fd <= 1);
262
    d_focusDirection = fd;
263
    updateWitness();
264
  }
265
266
  /**
267
   * nonbasicDirection must be the same as the sign for the focus function's
268
   * coefficient for this to be safe.
269
   * The burden for this being safe is on the user!
270
   */
271
  void determineFocusDirection(){
272
    const int deltaSgn = d_nonbasicDelta.value().sgn();
273
    setFocusDirection(deltaSgn * d_nonbasicDirection);
274
  }
275
276
  /** Requires nonbasicDelta to be set through updateProposal(...). */
277
  const DeltaRational& nonbasicDelta() const { return d_nonbasicDelta.value(); }
278
  const Rational& getCoefficient() const {
279
    Assert(describesPivot());
280
    Assert(d_tableauCoefficient.value() != NULL);
281
    return *(d_tableauCoefficient.value());
282
  }
283
  int basicDirection() const {
284
    return nonbasicDirection() * (getCoefficient().sgn());
285
  }
286
287
  /** Returns the limiting constraint. */
288
  inline ConstraintP limiting() const {
289
    return d_limiting;
290
  }
291
292
  WitnessImprovement getWitness(bool useBlands = false) const{
293
    Assert(d_witness == computeWitness());
294
295
    if(d_witness == Degenerate){
296
      if(useBlands){
297
        return BlandsDegenerate;
298
      }else{
299
        return HeuristicDegenerate;
300
      }
301
    }else{
302
      return d_witness;
303
    }
304
  }
305
306
  const DeltaRational& focusChange() const { return d_focusChange.value(); }
307
  void setFocusChange(const DeltaRational& fc) {
308
    d_focusChange = fc;
309
  }
310
311
  /** Outputs the UpdateInfo into out. */
312
  void output(std::ostream& out) const;
313
314
private:
315
  void updateWitness() {
316
    d_witness = computeWitness();
317
    Assert(describesPivot() || improvement(d_witness));
318
  }
319
320
  /**
321
   * Determines the appropriate WitnessImprovement for the update.
322
   * useBlands breaks ties for degenerate pivots.
323
   *
324
   * This is safe if:
325
   * - d_foundConflict is true, or
326
   * - d_foundConflict is false and d_errorsChange has been set and d_errorsChange < 0, or
327
   * - d_foundConflict is false and d_errorsChange has been set and d_errorsChange >= 0 and d_focusDirection has been set.
328
   */
329
  WitnessImprovement computeWitness() const {
330
    if(d_foundConflict){
331
      return ConflictFound;
332
    }
333
    else if (d_errorsChange && d_errorsChange.value() < 0)
334
    {
335
      return ErrorDropped;
336
    }
337
    else if (d_errorsChange.value_or(0) == 0)
338
    {
339
      if (d_focusDirection)
340
      {
341
        if (*d_focusDirection > 0)
342
        {
343
          return FocusImproved;
344
        }
345
        else if (*d_focusDirection == 0)
346
        {
347
          return Degenerate;
348
        }
349
      }
350
    }
351
    return AntiProductive;
352
  }
353
354
};
355
356
std::ostream& operator<<(std::ostream& out, const UpdateInfo& up);
357
358
}  // namespace arith
359
}  // namespace theory
360
}  // namespace cvc5