summaryrefslogtreecommitdiff
path: root/src/theory/arith/simplex_update.h
blob: e223bba7f496c294cafcccf70dcd0d3579414c67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*********************                                                        */
/*! \file simplex_update.h
 ** \verbatim
 ** Original author: Tim King
 ** Major contributors: none
 ** Minor contributors (to current version): Morgan Deters
 ** This file is part of the CVC4 project.
 ** Copyright (c) 2009-2013  New York University and The University of Iowa
 ** See the file COPYING in the top-level source directory for licensing
 ** information.\endverbatim
 **
 ** \brief This provides a class for summarizing pivot proposals.
 **
 ** This shares with the theory a Tableau, and a PartialModel that:
 **  - satisfies the equalities in the Tableau, and
 **  - the assignment for the non-basic variables satisfies their bounds.
 ** This maintains the relationship needed by the SimplexDecisionProcedure.
 **
 ** In the language of Simplex for DPLL(T), this provides:
 ** - update()
 ** - pivotAndUpdate()
 **
 ** This class also provides utility functions that require
 ** using both the Tableau and PartialModel.
 **/


#include "cvc4_private.h"

#pragma once

#include "theory/arith/delta_rational.h"
#include "theory/arith/arithvar.h"
#include "theory/arith/constraint_forward.h"
#include "util/maybe.h"

namespace CVC4 {
namespace theory {
namespace arith {

enum WitnessImprovement {
  ConflictFound = 0,
  ErrorDropped = 1,
  FocusImproved = 2,
  FocusShrank = 3,
  Degenerate = 4,
  BlandsDegenerate = 5,
  HeuristicDegenerate = 6,
  AntiProductive = 7
};

inline bool strongImprovement(WitnessImprovement w){
  return w <= FocusImproved;
}

inline bool improvement(WitnessImprovement w){
  return w <= FocusShrank;
}

inline bool degenerate(WitnessImprovement w){
  switch(w){
  case Degenerate:
  case BlandsDegenerate:
  case HeuristicDegenerate:
    return true;
  default:
    return false;
  }
}

std::ostream& operator<<(std::ostream& out,  WitnessImprovement w);

/**
 * This class summarizes both potential:
 * - pivot-and-update operations or
 * - a pure update operation.
 * This stores enough information for the various algorithms  hat consider these operations.
 * These require slightly different pieces of information at different points
 * so they are a bit verbose and paranoid.
 */
class UpdateInfo {
private:

  /**
   * The nonbasic variables under consideration.
   * This is either the entering variable on a pivot and update
   * or the variable being updated.
   * This can only be set in the constructor or assignment.
   *
   * If this uninitialized, then this is ARITHVAR_SENTINEL.
   */
  ArithVar d_nonbasic;

  /**
   * The sgn of the "intended" derivative (delta) of the update to d_nonbasic.
   * This is either 1, -1, or 0.
   * It is "intended" as the delta is always allowed to be 0.
   * (See debugSgnAgreement().)
   *
   * If this uninitialized, then this is 0.
   * If this is initialized, then it is -1 or 1.
   *
   * This can only be set in the constructor or assignment.
   */
  int d_nonbasicDirection;

  /**
   * The change in the assignment of d_nonbasic.
   * This is changed via the updateProposal(...) methods.
   * The value needs to satisfy debugSgnAgreement() or it is in conflict.
   */
  Maybe<DeltaRational> d_nonbasicDelta;

  /**
   * This is true if the pivot-and-update is *known* to cause a conflict.
   * This can only be true if it was constructed through the static conflict(...) method.
   */
  bool d_foundConflict;

  /** This is the change in the size of the error set. */
  Maybe<int> d_errorsChange;

  /** This is the sgn of the change in the value of the focus set.*/
  Maybe<int> d_focusDirection;

  /** This is the sgn of the change in the value of the focus set.*/
  Maybe<DeltaRational> d_focusChange;

  /** This is the coefficient in the tableau for the entry.*/
  Maybe<const Rational*> d_tableauCoefficient;

  /**
   * This is the constraint that nonbasic is basic is updating s.t. its variable is against it.
   * This has 3 different possibilities:
   * - Unbounded : then this is NullConstraint and unbounded() is true.
   * - Pivot-And-Update: then this is not NullConstraint and the variable is not d_nonbasic.
   * - Update: then this is not NullConstraint and the variable is d_nonbasic.
   */
  ConstraintP d_limiting;

  WitnessImprovement d_witness;

  /**
   * This returns true if
   * d_nonbasicDelta is zero() or its sgn() must agree with d_nonbasicDirection.
   */
  bool debugSgnAgreement() const {
    int deltaSgn = d_nonbasicDelta.constValue().sgn();
    return deltaSgn == 0 || deltaSgn == d_nonbasicDirection;
  }

  /** This private constructor allows for setting conflict to true. */
  UpdateInfo(bool conflict, ArithVar nb, const DeltaRational& delta, const Rational& r, ConstraintP lim);

public:

  /** This constructs an uninitialized UpdateInfo. */
  UpdateInfo();

  /**
   * This constructs an initialized UpdateInfo.
   * dir must be 1 or -1.
   */
  UpdateInfo(ArithVar nb, int dir);

  /**
   * This updates the nonBasicDelta to d and limiting to NullConstraint.
   * This describes an unbounded() update.
   */
  void updateUnbounded(const DeltaRational& d, int ec, int f);


  void updatePureFocus(const DeltaRational& d, ConstraintP c);
  //void updatePureError(const DeltaRational& d, Constraint c, int e);
  //void updatePure(const DeltaRational& d, Constraint c, int e, int f);

  /**
   * This updates the nonBasicDelta to d and limiting to c.
   * This clears errorChange() and focusDir().
   */
  void updatePivot(const DeltaRational& d, const Rational& r,  ConstraintP c);

  /**
   * This updates the nonBasicDelta to d, limiting to c, and errorChange to e.
   * This clears focusDir().
   */
  void updatePivot(const DeltaRational& d, const Rational& r, ConstraintP c, int e);

  /**
   * This updates the nonBasicDelta to d, limiting to c, errorChange to e and
   * focusDir to f.
   */
  void witnessedUpdate(const DeltaRational& d, ConstraintP c, int e, int f);
  void update(const DeltaRational& d, const Rational& r, ConstraintP c, int e, int f);


  static UpdateInfo conflict(ArithVar nb, const DeltaRational& delta, const Rational& r, ConstraintP lim);

  inline ArithVar nonbasic() const { return d_nonbasic; }
  inline bool uninitialized() const {
    return d_nonbasic == ARITHVAR_SENTINEL;
  }

  /**
   * There is no limiting value to the improvement of the focus.
   * If this is true, this never describes an update.
   */
  inline bool unbounded() const {
    return d_limiting == NullConstraint;
  }

  /**
   * The update either describes a pivotAndUpdate operation
   * or it describes just an update.
   */
  bool describesPivot() const;

  /** Returns the . describesPivot() must be true. */
  ArithVar leaving() const;

  /**
   * Returns true if this is *known* to find a conflict.
   * If true, this must have been made through the static conflict(...) function.
   */
  bool foundConflict() const { return d_foundConflict; }

  /** Returns the direction nonbasic is supposed to move. */
  inline int nonbasicDirection() const{  return d_nonbasicDirection; }

  /** Requires errorsChange to be set through setErrorsChange or updateProposal. */
  inline int errorsChange() const { return d_errorsChange; }

  /**
   * If errorsChange has been set, return errorsChange().
   * Otherwise, return def.
   */
  inline int errorsChangeSafe(int def) const {
    if(d_errorsChange.just()){
      return d_errorsChange;
    }else{
      return def;
    }
  }

  /** Sets the errorChange. */
  void setErrorsChange(int ec){
    d_errorsChange = ec;
    updateWitness();
  }


  /** Requires errorsChange to be set through setErrorsChange or updateProposal. */
  inline int focusDirection() const{ return d_focusDirection; }

  /** Sets the focusDirection. */
  void setFocusDirection(int fd){
    Assert(-1 <= fd  && fd <= 1);
    d_focusDirection = fd;
    updateWitness();
  }

  /**
   * nonbasicDirection must be the same as the sign for the focus function's
   * coefficient for this to be safe.
   * The burden for this being safe is on the user!
   */
  void determineFocusDirection(){
    int deltaSgn = d_nonbasicDelta.constValue().sgn();
    setFocusDirection(deltaSgn * d_nonbasicDirection);
  }

  /** Requires nonbasicDelta to be set through updateProposal(...). */
  const DeltaRational& nonbasicDelta() const {
    return d_nonbasicDelta;
  }
  const Rational& getCoefficient() const {
    Assert(describesPivot());
    Assert(d_tableauCoefficient.constValue() != NULL);
    return *(d_tableauCoefficient.constValue());
  }
  int basicDirection() const {
    return nonbasicDirection() * (getCoefficient().sgn());
  }

  /** Returns the limiting constraint. */
  inline ConstraintP limiting() const {
    return d_limiting;
  }

  WitnessImprovement getWitness(bool useBlands = false) const{
    Assert(d_witness == computeWitness());

    if(d_witness == Degenerate){
      if(useBlands){
        return BlandsDegenerate;
      }else{
        return HeuristicDegenerate;
      }
    }else{
      return d_witness;
    }
  }

  const DeltaRational& focusChange() const {
    return d_focusChange;
  }
  void setFocusChange(const DeltaRational& fc) {
    d_focusChange = fc;
  }

  /** Outputs the UpdateInfo into out. */
  void output(std::ostream& out) const;

private:
  void updateWitness() {
    d_witness = computeWitness();
    Assert(describesPivot() || improvement(d_witness));
  }

  /**
   * Determines the appropriate WitnessImprovement for the update.
   * useBlands breaks ties for degenerate pivots.
   *
   * This is safe if:
   * - d_foundConflict is true, or
   * - d_foundConflict is false and d_errorsChange has been set and d_errorsChange < 0, or
   * - d_foundConflict is false and d_errorsChange has been set and d_errorsChange >= 0 and d_focusDirection has been set.
   */
  WitnessImprovement computeWitness() const {
    if(d_foundConflict){
      return ConflictFound;
    }else if(d_errorsChange.just() && d_errorsChange < 0){
      return ErrorDropped;
    }else if(d_errorsChange.nothing() || d_errorsChange == 0){
      if(d_focusDirection.just()){
        if(d_focusDirection > 0){
          return FocusImproved;
        }else if(d_focusDirection == 0){
          return Degenerate;
        }
      }
    }
    return AntiProductive;
  }

};

std::ostream& operator<<(std::ostream& out, const UpdateInfo& up);

}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback