1 //===- Simplex.h - MLIR Simplex Class ---------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Functionality to perform analysis on an IntegerRelation. In particular,
10 // support for performing emptiness checks, redundancy checks and obtaining the
11 // lexicographically minimum rational element in a set.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef MLIR_ANALYSIS_PRESBURGER_SIMPLEX_H
16 #define MLIR_ANALYSIS_PRESBURGER_SIMPLEX_H
17 
18 #include "mlir/Analysis/Presburger/Fraction.h"
19 #include "mlir/Analysis/Presburger/IntegerRelation.h"
20 #include "mlir/Analysis/Presburger/Matrix.h"
21 #include "mlir/Analysis/Presburger/PWMAFunction.h"
22 #include "mlir/Analysis/Presburger/Utils.h"
23 #include "mlir/Support/LogicalResult.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/Optional.h"
26 #include "llvm/ADT/SmallBitVector.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include "llvm/Support/StringSaver.h"
29 #include "llvm/Support/raw_ostream.h"
30 
31 namespace mlir {
32 namespace presburger {
33 
34 class GBRSimplex;
35 
36 /// The Simplex class implements a version of the Simplex and Generalized Basis
37 /// Reduction algorithms, which can perform analysis of integer sets with affine
38 /// inequalities and equalities. A Simplex can be constructed
39 /// by specifying the dimensionality of the set. It supports adding affine
40 /// inequalities and equalities, and can perform emptiness checks, i.e., it can
41 /// find a solution to the set of constraints if one exists, or say that the
42 /// set is empty if no solution exists. Furthermore, it can find a subset of
43 /// these constraints that are redundant, i.e. a subset of constraints that
44 /// doesn't constrain the affine set further after adding the non-redundant
45 /// constraints. The LexSimplex class provides support for computing the
46 /// lexicographic minimum of an IntegerRelation. The SymbolicLexMin class
47 /// provides support for computing symbolic lexicographic minimums. All of these
48 /// classes can be constructed from an IntegerRelation, and all inherit common
49 /// functionality from SimplexBase.
50 ///
51 /// The implementations of the Simplex and SimplexBase classes, other than the
52 /// functionality for obtaining an integer sample, are based on the paper
53 /// "Simplify: A Theorem Prover for Program Checking"
54 /// by D. Detlefs, G. Nelson, J. B. Saxe.
55 ///
56 /// We define variables, constraints, and unknowns. Consider the example of a
57 /// two-dimensional set defined by 1 + 2x + 3y >= 0 and 2x - 3y >= 0. Here,
58 /// x, y, are variables while 1 + 2x + 3y >= 0, 2x - 3y >= 0 are constraints.
59 /// Unknowns are either variables or constraints, i.e., x, y, 1 + 2x + 3y >= 0,
60 /// 2x - 3y >= 0 are all unknowns.
61 ///
62 /// The implementation involves a matrix called a tableau, which can be thought
63 /// of as a 2D matrix of rational numbers having number of rows equal to the
64 /// number of constraints and number of columns equal to one plus the number of
65 /// variables. In our implementation, instead of storing rational numbers, we
66 /// store a common denominator for each row, so it is in fact a matrix of
67 /// integers with number of rows equal to number of constraints and number of
68 /// columns equal to _two_ plus the number of variables. For example, instead of
69 /// storing a row of three rationals [1/2, 2/3, 3], we would store [6, 3, 4, 18]
70 /// since 3/6 = 1/2, 4/6 = 2/3, and 18/6 = 3.
71 ///
72 /// Every row and column except the first and second columns is associated with
73 /// an unknown and every unknown is associated with a row or column. An unknown
74 /// associated with a row or column is said to be in row or column orientation
75 /// respectively. As described above, the first column is the common
76 /// denominator. The second column represents the constant term, explained in
77 /// more detail below. These two are _fixed columns_; they always retain their
78 /// position as the first and second columns. Additionally, LexSimplexBase
79 /// stores a so-call big M parameter (explained below) in the third column, so
80 /// LexSimplexBase has three fixed columns. Finally, SymbolicLexSimplex has
81 /// `nSymbol` variables designated as symbols. These occupy the next `nSymbol`
82 /// columns, viz. the columns [3, 3 + nSymbol). For more information on symbols,
83 /// see LexSimplexBase and SymbolicLexSimplex.
84 ///
85 /// LexSimplexBase does not directly support variables which can be negative, so
86 /// we introduce the so-called big M parameter, an artificial variable that is
87 /// considered to have an arbitrarily large value. We then transform the
88 /// variables, say x, y, z, ... to M, M + x, M + y, M + z. Since M has been
89 /// added to these variables, they are now known to have non-negative values.
90 /// For more details, see the documentation for LexSimplexBase. The big M
91 /// parameter is not considered a real unknown and is not stored in the `var`
92 /// data structure; rather the tableau just has an extra fixed column for it
93 /// just like the constant term.
94 ///
95 /// The vectors var and con store information about the variables and
96 /// constraints respectively, namely, whether they are in row or column
97 /// position, which row or column they are associated with, and whether they
98 /// correspond to a variable or a constraint.
99 ///
100 /// An unknown is addressed by its index. If the index i is non-negative, then
101 /// the variable var[i] is being addressed. If the index i is negative, then
102 /// the constraint con[~i] is being addressed. Effectively this maps
103 /// 0 -> var[0], 1 -> var[1], -1 -> con[0], -2 -> con[1], etc. rowUnknown[r] and
104 /// colUnknown[c] are the indexes of the unknowns associated with row r and
105 /// column c, respectively.
106 ///
107 /// The unknowns in column position are together called the basis. Initially the
108 /// basis is the set of variables -- in our example above, the initial basis is
109 /// x, y.
110 ///
111 /// The unknowns in row position are represented in terms of the basis unknowns.
112 /// If the basis unknowns are u_1, u_2, ... u_m, and a row in the tableau is
113 /// d, c, a_1, a_2, ... a_m, this represents the unknown for that row as
114 /// (c + a_1*u_1 + a_2*u_2 + ... + a_m*u_m)/d. In our running example, if the
115 /// basis is the initial basis of x, y, then the constraint 1 + 2x + 3y >= 0
116 /// would be represented by the row [1, 1, 2, 3].
117 ///
118 /// The association of unknowns to rows and columns can be changed by a process
119 /// called pivoting, where a row unknown and a column unknown exchange places
120 /// and the remaining row variables' representation is changed accordingly
121 /// by eliminating the old column unknown in favour of the new column unknown.
122 /// If we had pivoted the column for x with the row for 2x - 3y >= 0,
123 /// the new row for x would be [2, 1, 3] since x = (1*(2x - 3y) + 3*y)/2.
124 /// See the documentation for the pivot member function for details.
125 ///
126 /// The association of unknowns to rows and columns is called the _tableau
127 /// configuration_. The _sample value_ of an unknown in a particular tableau
128 /// configuration is its value if all the column unknowns were set to zero.
129 /// Concretely, for unknowns in column position the sample value is zero; when
130 /// the big M parameter is not used, for unknowns in row position the sample
131 /// value is the constant term divided by the common denominator. When the big M
132 /// parameter is used, if d is the denominator, p is the big M coefficient, and
133 /// c is the constant term, then the sample value is (p*M + c)/d. Since M is
134 /// considered to be positive infinity, this is positive (negative) infinity
135 /// when p is positive or negative, and c/d when p is zero.
136 ///
137 /// The tableau configuration is called _consistent_ if the sample value of all
138 /// restricted unknowns is non-negative. Initially there are no constraints, and
139 /// the tableau is consistent. When a new constraint is added, its sample value
140 /// in the current tableau configuration may be negative. In that case, we try
141 /// to find a series of pivots to bring us to a consistent tableau
142 /// configuration, i.e. we try to make the new constraint's sample value
143 /// non-negative without making that of any other constraints negative. (See
144 /// findPivot and findPivotRow for details.) If this is not possible, then the
145 /// set of constraints is mutually contradictory and the tableau is marked
146 /// _empty_, which means the set of constraints has no solution.
147 ///
148 /// This SimplexBase class also supports taking snapshots of the current state
149 /// and rolling back to prior snapshots. This works by maintaining an undo log
150 /// of operations. Snapshots are just pointers to a particular location in the
151 /// log, and rolling back to a snapshot is done by reverting each log entry's
152 /// operation from the end until we reach the snapshot's location. SimplexBase
153 /// also supports taking a snapshot including the exact set of basis unknowns;
154 /// if this functionality is used, then on rolling back the exact basis will
155 /// also be restored. This is used by LexSimplexBase because the lex algorithm,
156 /// unlike `Simplex`, is sensitive to the exact basis used at a point.
157 class SimplexBase {
158 public:
159   SimplexBase() = delete;
160   virtual ~SimplexBase() = default;
161 
162   /// Returns true if the tableau is empty (has conflicting constraints),
163   /// false otherwise.
164   bool isEmpty() const;
165 
166   /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
167   /// is the current number of variables, then the corresponding inequality is
168   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0.
169   virtual void addInequality(ArrayRef<int64_t> coeffs) = 0;
170 
171   /// Returns the number of variables in the tableau.
172   unsigned getNumVariables() const;
173 
174   /// Returns the number of constraints in the tableau.
175   unsigned getNumConstraints() const;
176 
177   /// Add an equality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
178   /// is the current number of variables, then the corresponding equality is
179   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} == 0.
180   void addEquality(ArrayRef<int64_t> coeffs);
181 
182   /// Add new variables to the end of the list of variables.
183   void appendVariable(unsigned count = 1);
184 
185   /// Append a new variable to the simplex and constrain it such that its only
186   /// integer value is the floor div of `coeffs` and `denom`.
187   void addDivisionVariable(ArrayRef<int64_t> coeffs, int64_t denom);
188 
189   /// Mark the tableau as being empty.
190   void markEmpty();
191 
192   /// Get a snapshot of the current state. This is used for rolling back.
193   /// The same basis will not necessarily be restored on rolling back.
194   /// The snapshot only captures the set of variables and constraints present
195   /// in the Simplex.
196   unsigned getSnapshot() const;
197 
198   /// Get a snapshot of the current state including the basis. When rolling
199   /// back, the exact basis will be restored.
200   unsigned getSnapshotBasis();
201 
202   /// Rollback to a snapshot. This invalidates all later snapshots.
203   void rollback(unsigned snapshot);
204 
205   /// Add all the constraints from the given IntegerRelation.
206   void intersectIntegerRelation(const IntegerRelation &rel);
207 
208   /// Print the tableau's internal state.
209   void print(raw_ostream &os) const;
210   void dump() const;
211 
212 protected:
213   /// Construct a SimplexBase with the specified number of variables and fixed
214   /// columns. The first overload should be used when there are nosymbols.
215   /// With the second overload, the specified range of vars will be marked
216   /// as symbols. With the third overload, `isSymbol` is a bitmask denoting
217   /// which vars are symbols. The size of `isSymbol` must be `nVar`.
218   ///
219   /// For example, Simplex uses two fixed columns: the denominator and the
220   /// constant term, whereas LexSimplex has an extra fixed column for the
221   /// so-called big M parameter. For more information see the documentation for
222   /// LexSimplex.
223   SimplexBase(unsigned nVar, bool mustUseBigM);
224   SimplexBase(unsigned nVar, bool mustUseBigM,
225               const llvm::SmallBitVector &isSymbol);
226 
227   enum class Orientation { Row, Column };
228 
229   /// An Unknown is either a variable or a constraint. It is always associated
230   /// with either a row or column. Whether it's a row or a column is specified
231   /// by the orientation and pos identifies the specific row or column it is
232   /// associated with. If the unknown is restricted, then it has a
233   /// non-negativity constraint associated with it, i.e., its sample value must
234   /// always be non-negative and if it cannot be made non-negative without
235   /// violating other constraints, the tableau is empty.
236   struct Unknown {
237     Unknown(Orientation oOrientation, bool oRestricted, unsigned oPos,
238             bool oIsSymbol = false)
posUnknown239         : pos(oPos), orientation(oOrientation), restricted(oRestricted),
240           isSymbol(oIsSymbol) {}
241     unsigned pos;
242     Orientation orientation;
243     bool restricted : 1;
244     bool isSymbol : 1;
245 
printUnknown246     void print(raw_ostream &os) const {
247       os << (orientation == Orientation::Row ? "r" : "c");
248       os << pos;
249       if (restricted)
250         os << " [>=0]";
251     }
252   };
253 
254   struct Pivot {
255     unsigned row, column;
256   };
257 
258   /// Return any row that this column can be pivoted with, ignoring tableau
259   /// consistency.
260   ///
261   /// Returns an empty optional if no pivot is possible, which happens only when
262   /// the column unknown is a variable and no constraint has a non-zero
263   /// coefficient for it.
264   Optional<unsigned> findAnyPivotRow(unsigned col);
265 
266   /// Swap the row with the column in the tableau's data structures but not the
267   /// tableau itself. This is used by pivot.
268   void swapRowWithCol(unsigned row, unsigned col);
269 
270   /// Pivot the row with the column.
271   void pivot(unsigned row, unsigned col);
272   void pivot(Pivot pair);
273 
274   /// Returns the unknown associated with index.
275   const Unknown &unknownFromIndex(int index) const;
276   /// Returns the unknown associated with col.
277   const Unknown &unknownFromColumn(unsigned col) const;
278   /// Returns the unknown associated with row.
279   const Unknown &unknownFromRow(unsigned row) const;
280   /// Returns the unknown associated with index.
281   Unknown &unknownFromIndex(int index);
282   /// Returns the unknown associated with col.
283   Unknown &unknownFromColumn(unsigned col);
284   /// Returns the unknown associated with row.
285   Unknown &unknownFromRow(unsigned row);
286 
287   /// Add a new row to the tableau and the associated data structures. The row
288   /// is initialized to zero. Returns the index of the added row.
289   unsigned addZeroRow(bool makeRestricted = false);
290 
291   /// Add a new row to the tableau and the associated data structures.
292   /// The new row is considered to be a constraint; the new Unknown lives in
293   /// con.
294   ///
295   /// Returns the index of the new Unknown in con.
296   unsigned addRow(ArrayRef<int64_t> coeffs, bool makeRestricted = false);
297 
298   /// Swap the two rows/columns in the tableau and associated data structures.
299   void swapRows(unsigned i, unsigned j);
300   void swapColumns(unsigned i, unsigned j);
301 
302   /// Enum to denote operations that need to be undone during rollback.
303   enum class UndoLogEntry {
304     RemoveLastConstraint,
305     RemoveLastVariable,
306     UnmarkEmpty,
307     UnmarkLastRedundant,
308     RestoreBasis
309   };
310 
311   /// Undo the addition of the last constraint. This will only be called from
312   /// undo, when rolling back.
313   virtual void undoLastConstraint() = 0;
314 
315   /// Remove the last constraint, which must be in row orientation.
316   void removeLastConstraintRowOrientation();
317 
318   /// Undo the operation represented by the log entry.
319   void undo(UndoLogEntry entry);
320 
321   /// Return the number of fixed columns, as described in the constructor above,
322   /// this is the number of columns beyond those for the variables in var.
getNumFixedCols()323   unsigned getNumFixedCols() const { return usingBigM ? 3u : 2u; }
getNumRows()324   unsigned getNumRows() const { return tableau.getNumRows(); }
getNumColumns()325   unsigned getNumColumns() const { return tableau.getNumColumns(); }
326 
327   /// Stores whether or not a big M column is present in the tableau.
328   bool usingBigM;
329 
330   /// The number of redundant rows in the tableau. These are the first
331   /// nRedundant rows.
332   unsigned nRedundant;
333 
334   /// The number of parameters. This must be consistent with the number of
335   /// Unknowns in `var` below that have `isSymbol` set to true.
336   unsigned nSymbol;
337 
338   /// The matrix representing the tableau.
339   Matrix tableau;
340 
341   /// This is true if the tableau has been detected to be empty, false
342   /// otherwise.
343   bool empty;
344 
345   /// Holds a log of operations, used for rolling back to a previous state.
346   SmallVector<UndoLogEntry, 8> undoLog;
347 
348   /// Holds a vector of bases. The ith saved basis is the basis that should be
349   /// restored when processing the ith occurrance of UndoLogEntry::RestoreBasis
350   /// in undoLog. This is used by getSnapshotBasis.
351   SmallVector<SmallVector<int, 8>, 8> savedBases;
352 
353   /// These hold the indexes of the unknown at a given row or column position.
354   /// We keep these as signed integers since that makes it convenient to check
355   /// if an index corresponds to a variable or a constraint by checking the
356   /// sign.
357   ///
358   /// colUnknown is padded with two null indexes at the front since the first
359   /// two columns don't correspond to any unknowns.
360   SmallVector<int, 8> rowUnknown, colUnknown;
361 
362   /// These hold information about each unknown.
363   SmallVector<Unknown, 8> con, var;
364 };
365 
366 /// Simplex class using the lexicographic pivot rule. Used for lexicographic
367 /// optimization. The implementation of this class is based on the paper
368 /// "Parametric Integer Programming" by Paul Feautrier.
369 ///
370 /// This does not directly support negative-valued variables, so it uses the big
371 /// M parameter trick to make all the variables non-negative. Basically we
372 /// introduce an artifical variable M that is considered to have a value of
373 /// +infinity and instead of the variables x, y, z, we internally use variables
374 /// M + x, M + y, M + z, which are now guaranteed to be non-negative. See the
375 /// documentation for SimplexBase for more details. M is also considered to be
376 /// an integer that is divisible by everything.
377 ///
378 /// The whole algorithm is performed with M treated as a symbol;
379 /// it is just considered to be infinite throughout and it never appears in the
380 /// final outputs. We will deal with sample values throughout that may in
381 /// general be some affine expression involving M, like pM + q or aM + b. We can
382 /// compare these with each other. They have a total order:
383 ///
384 /// aM + b < pM + q iff  a < p or (a == p and b < q).
385 /// In particular, aM + b < 0 iff a < 0 or (a == 0 and b < 0).
386 ///
387 /// When performing symbolic optimization, sample values will be affine
388 /// expressions in M and the symbols. For example, we could have sample values
389 /// aM + bS + c and pM + qS + r, where S is a symbol. Now we have
390 /// aM + bS + c < pM + qS + r iff (a < p) or (a == p and bS + c < qS + r).
391 /// bS + c < qS + r can be always true, always false, or neither,
392 /// depending on the set of values S can take. The symbols are always stored
393 /// in columns [3, 3 + nSymbols). For more details, see the
394 /// documentation for SymbolicLexSimplex.
395 ///
396 /// Initially all the constraints to be added are added as rows, with no attempt
397 /// to keep the tableau consistent. Pivots are only performed when some query
398 /// is made, such as a call to getRationalLexMin. Care is taken to always
399 /// maintain a lexicopositive basis transform, explained below.
400 ///
401 /// Let the variables be x = (x_1, ... x_n).
402 /// Let the symbols be   s = (s_1, ... s_m). Let the basis unknowns at a
403 /// particular point be  y = (y_1, ... y_n). We know that x = A*y + T*s + b for
404 /// some n x n matrix A, n x m matrix s, and n x 1 column vector b. We want
405 /// every column in A to be lexicopositive, i.e., have at least one non-zero
406 /// element, with the first such element being positive. This property is
407 /// preserved throughout the operation of LexSimplexBase. Note that on
408 /// construction, the basis transform A is the identity matrix and so every
409 /// column is lexicopositive. Note that for LexSimplexBase, for the tableau to
410 /// be consistent we must have non-negative sample values not only for the
411 /// constraints but also for the variables. So if the tableau is consistent then
412 /// x >= 0 and y >= 0, by which we mean every element in these vectors is
413 /// non-negative. (note that this is a different concept from lexicopositivity!)
414 class LexSimplexBase : public SimplexBase {
415 public:
416   ~LexSimplexBase() override = default;
417 
418   /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
419   /// is the current number of variables, then the corresponding inequality is
420   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0.
421   ///
422   /// This just adds the inequality to the tableau and does not try to create a
423   /// consistent tableau configuration.
424   void addInequality(ArrayRef<int64_t> coeffs) final;
425 
426   /// Get a snapshot of the current state. This is used for rolling back.
getSnapshot()427   unsigned getSnapshot() { return SimplexBase::getSnapshotBasis(); }
428 
429 protected:
LexSimplexBase(unsigned nVar)430   LexSimplexBase(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/true) {}
LexSimplexBase(unsigned nVar,const llvm::SmallBitVector & isSymbol)431   LexSimplexBase(unsigned nVar, const llvm::SmallBitVector &isSymbol)
432       : SimplexBase(nVar, /*mustUseBigM=*/true, isSymbol) {}
LexSimplexBase(const IntegerRelation & constraints)433   explicit LexSimplexBase(const IntegerRelation &constraints)
434       : LexSimplexBase(constraints.getNumVars()) {
435     intersectIntegerRelation(constraints);
436   }
LexSimplexBase(const IntegerRelation & constraints,const llvm::SmallBitVector & isSymbol)437   explicit LexSimplexBase(const IntegerRelation &constraints,
438                           const llvm::SmallBitVector &isSymbol)
439       : LexSimplexBase(constraints.getNumVars(), isSymbol) {
440     intersectIntegerRelation(constraints);
441   }
442 
443   /// Add new symbolic variables to the end of the list of variables.
444   void appendSymbol();
445 
446   /// Try to move the specified row to column orientation while preserving the
447   /// lexicopositivity of the basis transform. The row must have a non-positive
448   /// sample value. If this is not possible, return failure. This occurs when
449   /// the constraints have no solution or the sample value is zero.
450   LogicalResult moveRowUnknownToColumn(unsigned row);
451 
452   /// Given a row that has a non-integer sample value, add an inequality to cut
453   /// away this fractional sample value from the polytope without removing any
454   /// integer points. The integer lexmin, if one existed, remains the same on
455   /// return.
456   ///
457   /// This assumes that the symbolic part of the sample is integral,
458   /// i.e., if the symbolic sample is (c + aM + b_1*s_1 + ... b_n*s_n)/d,
459   /// where s_1, ... s_n are symbols, this assumes that
460   /// (b_1*s_1 + ... + b_n*s_n)/s is integral.
461   ///
462   /// Return failure if the tableau became empty, and success if it didn't.
463   /// Failure status indicates that the polytope was integer empty.
464   LogicalResult addCut(unsigned row);
465 
466   /// Undo the addition of the last constraint. This is only called while
467   /// rolling back.
468   void undoLastConstraint() final;
469 
470   /// Given two potential pivot columns for a row, return the one that results
471   /// in the lexicographically smallest sample vector. The row's sample value
472   /// must be negative. If symbols are involved, the sample value must be
473   /// negative for all possible assignments to the symbols.
474   unsigned getLexMinPivotColumn(unsigned row, unsigned colA,
475                                 unsigned colB) const;
476 };
477 
478 /// A class for lexicographic optimization without any symbols. This also
479 /// provides support for integer-exact redundancy and separateness checks.
480 class LexSimplex : public LexSimplexBase {
481 public:
LexSimplex(unsigned nVar)482   explicit LexSimplex(unsigned nVar) : LexSimplexBase(nVar) {}
483   // Note that LexSimplex does NOT support symbolic lexmin;
484   // use SymbolicLexSimplex if that is required. LexSimplex ignores the VarKinds
485   // of the passed IntegerRelation. Symbols will be treated as ordinary vars.
LexSimplex(const IntegerRelation & constraints)486   explicit LexSimplex(const IntegerRelation &constraints)
487       : LexSimplexBase(constraints) {}
488 
489   /// Return the lexicographically minimum rational solution to the constraints.
490   MaybeOptimum<SmallVector<Fraction, 8>> findRationalLexMin();
491 
492   /// Return the lexicographically minimum integer solution to the constraints.
493   ///
494   /// Note: this should be used only when the lexmin is really needed. To obtain
495   /// any integer sample, use Simplex::findIntegerSample as that is more robust.
496   MaybeOptimum<SmallVector<int64_t, 8>> findIntegerLexMin();
497 
498   /// Return whether the specified inequality is redundant/separate for the
499   /// polytope. Redundant means every point satisfies the given inequality, and
500   /// separate means no point satisfies it.
501   ///
502   /// These checks are integer-exact.
503   bool isSeparateInequality(ArrayRef<int64_t> coeffs);
504   bool isRedundantInequality(ArrayRef<int64_t> coeffs);
505 
506 private:
507   /// Returns the current sample point, which may contain non-integer (rational)
508   /// coordinates. Returns an empty optimum when the tableau is empty.
509   ///
510   /// Returns an unbounded optimum when the big M parameter is used and a
511   /// variable has a non-zero big M coefficient, meaning its value is infinite
512   /// or unbounded.
513   MaybeOptimum<SmallVector<Fraction, 8>> getRationalSample() const;
514 
515   /// Make the tableau configuration consistent.
516   LogicalResult restoreRationalConsistency();
517 
518   /// Return whether the specified row is violated;
519   bool rowIsViolated(unsigned row) const;
520 
521   /// Get a constraint row that is violated, if one exists.
522   /// Otherwise, return an empty optional.
523   Optional<unsigned> maybeGetViolatedRow() const;
524 
525   /// Get a row corresponding to a var that has a non-integral sample value, if
526   /// one exists. Otherwise, return an empty optional.
527   Optional<unsigned> maybeGetNonIntegralVarRow() const;
528 };
529 
530 /// Represents the result of a symbolic lexicographic minimization computation.
531 struct SymbolicLexMin {
SymbolicLexMinSymbolicLexMin532   SymbolicLexMin(const PresburgerSpace &domainSpace, unsigned numOutputs)
533       : lexmin(domainSpace, numOutputs),
534         unboundedDomain(PresburgerSet::getEmpty(domainSpace)) {}
535 
536   /// This maps assignments of symbols to the corresponding lexmin.
537   /// Takes no value when no integer sample exists for the assignment or if the
538   /// lexmin is unbounded.
539   PWMAFunction lexmin;
540   /// Contains all assignments to the symbols that made the lexmin unbounded.
541   /// Note that the symbols of the input set to the symbolic lexmin are dims
542   /// of this PrebsurgerSet.
543   PresburgerSet unboundedDomain;
544 };
545 
546 /// A class to perform symbolic lexicographic optimization,
547 /// i.e., to find, for every assignment to the symbols the specified
548 /// `symbolDomain`, the lexicographically minimum value integer value attained
549 /// by the non-symbol variables.
550 ///
551 /// The input is a set parametrized by some symbols, i.e., the constant terms
552 /// of the constraints in the set are affine expressions in the symbols, and
553 /// every assignment to the symbols defines a non-symbolic set.
554 ///
555 /// Accordingly, the sample values of the rows in our tableau will be affine
556 /// expressions in the symbols, and every assignment to the symbols will define
557 /// a non-symbolic LexSimplex. We then run the algorithm of
558 /// LexSimplex::findIntegerLexMin simultaneously for every value of the symbols
559 /// in the domain.
560 ///
561 /// Often, the pivot to be performed is the same for all values of the symbols,
562 /// in which case we just do it. For example, if the symbolic sample of a row is
563 /// negative for all values in the symbol domain, the row needs to be pivoted
564 /// irrespective of the precise value of the symbols. To answer queries like
565 /// "Is this symbolic sample always negative in the symbol domain?", we maintain
566 /// a `LexSimplex domainSimplex` correponding to the symbol domain.
567 ///
568 /// In other cases, it may be that the symbolic sample is violated at some
569 /// values in the symbol domain and not violated at others. In this case,
570 /// the pivot to be performed does depend on the value of the symbols. We
571 /// handle this by splitting the symbol domain. We run the algorithm for the
572 /// case where the row isn't violated, and then come back and run the case
573 /// where it is.
574 class SymbolicLexSimplex : public LexSimplexBase {
575 public:
576   /// `constraints` is the set for which the symbolic lexmin will be computed.
577   /// `symbolDomain` is the set of values of the symbols for which the lexmin
578   /// will be computed. `symbolDomain` should have a dim var for every symbol in
579   /// `constraints`, and no other vars. `isSymbol` specifies which vars of
580   /// `constraints` should be considered as symbols.
581   ///
582   /// The resulting SymbolicLexMin's space will be compatible with that of
583   /// symbolDomain.
SymbolicLexSimplex(const IntegerRelation & constraints,const IntegerPolyhedron & symbolDomain,const llvm::SmallBitVector & isSymbol)584   SymbolicLexSimplex(const IntegerRelation &constraints,
585                      const IntegerPolyhedron &symbolDomain,
586                      const llvm::SmallBitVector &isSymbol)
587       : LexSimplexBase(constraints, isSymbol), domainPoly(symbolDomain),
588         domainSimplex(symbolDomain) {
589     // TODO consider supporting this case. It amounts
590     // to just returning the input constraints.
591     assert(domainPoly.getNumVars() > 0 &&
592            "there must be some non-symbols to optimize!");
593   }
594 
595   /// An overload to select some subrange of ids as symbols for lexmin.
596   /// The symbol ids are the range of ids with absolute index
597   /// [symbolOffset, symbolOffset + symbolDomain.getNumVars())
SymbolicLexSimplex(const IntegerRelation & constraints,unsigned symbolOffset,const IntegerPolyhedron & symbolDomain)598   SymbolicLexSimplex(const IntegerRelation &constraints, unsigned symbolOffset,
599                      const IntegerPolyhedron &symbolDomain)
600       : SymbolicLexSimplex(constraints, symbolDomain,
601                            getSubrangeBitVector(constraints.getNumVars(),
602                                                 symbolOffset,
603                                                 symbolDomain.getNumVars())) {}
604 
605   /// An overload to select the symbols of `constraints` as symbols for lexmin.
SymbolicLexSimplex(const IntegerRelation & constraints,const IntegerPolyhedron & symbolDomain)606   SymbolicLexSimplex(const IntegerRelation &constraints,
607                      const IntegerPolyhedron &symbolDomain)
608       : SymbolicLexSimplex(constraints,
609                            constraints.getVarKindOffset(VarKind::Symbol),
610                            symbolDomain) {
611     assert(constraints.getNumSymbolVars() == symbolDomain.getNumVars() &&
612            "symbolDomain must have as many vars as constraints has symbols!");
613   }
614 
615   /// The lexmin will be stored as a function `lexmin` from symbols to
616   /// non-symbols in the result.
617   ///
618   /// For some values of the symbols, the lexmin may be unbounded.
619   /// These parts of the symbol domain will be stored in `unboundedDomain`.
620   ///
621   /// The spaces of the sets in the result are compatible with the symbolDomain
622   /// passed in the SymbolicLexSimplex constructor.
623   SymbolicLexMin computeSymbolicIntegerLexMin();
624 
625 private:
626   /// Perform all pivots that do not require branching.
627   ///
628   /// Return failure if the tableau became empty, indicating that the polytope
629   /// is always integer empty in the current symbol domain.
630   /// Return success otherwise.
631   LogicalResult doNonBranchingPivots();
632 
633   /// Get a row that is always violated in the current domain, if one exists.
634   Optional<unsigned> maybeGetAlwaysViolatedRow();
635 
636   /// Get a row corresponding to a variable with non-integral sample value, if
637   /// one exists.
638   Optional<unsigned> maybeGetNonIntegralVarRow();
639 
640   /// Given a row that has a non-integer sample value, cut away this fractional
641   /// sample value witahout removing any integer points, i.e., the integer
642   /// lexmin, if it exists, remains the same after a call to this function. This
643   /// may add constraints or local variables to the tableau, as well as to the
644   /// domain.
645   ///
646   /// Returns whether the cut constraint could be enforced, i.e. failure if the
647   /// cut made the polytope empty, and success if it didn't. Failure status
648   /// indicates that the polytope is always integer empty in the symbol domain
649   /// at the time of the call. (This function may modify the symbol domain, but
650   /// failure statu indicates that the polytope was empty for all symbol values
651   /// in the initial domain.)
652   LogicalResult addSymbolicCut(unsigned row);
653 
654   /// Get the numerator of the symbolic sample of the specific row.
655   /// This is an affine expression in the symbols with integer coefficients.
656   /// The last element is the constant term. This ignores the big M coefficient.
657   SmallVector<int64_t, 8> getSymbolicSampleNumerator(unsigned row) const;
658 
659   /// Get an affine inequality in the symbols with integer coefficients that
660   /// holds iff the symbolic sample of the specified row is non-negative.
661   SmallVector<int64_t, 8> getSymbolicSampleIneq(unsigned row) const;
662 
663   /// Return whether all the coefficients of the symbolic sample are integers.
664   ///
665   /// This does not consult the domain to check if the specified expression
666   /// is always integral despite coefficients being fractional.
667   bool isSymbolicSampleIntegral(unsigned row) const;
668 
669   /// Record a lexmin. The tableau must be consistent with all variables
670   /// having symbolic samples with integer coefficients.
671   void recordOutput(SymbolicLexMin &result) const;
672 
673   /// The symbol domain.
674   IntegerPolyhedron domainPoly;
675   /// Simplex corresponding to the symbol domain.
676   LexSimplex domainSimplex;
677 };
678 
679 /// The Simplex class uses the Normal pivot rule and supports integer emptiness
680 /// checks as well as detecting redundancies.
681 ///
682 /// The Simplex class supports redundancy checking via detectRedundant and
683 /// isMarkedRedundant. A redundant constraint is one which is never violated as
684 /// long as the other constraints are not violated, i.e., removing a redundant
685 /// constraint does not change the set of solutions to the constraints. As a
686 /// heuristic, constraints that have been marked redundant can be ignored for
687 /// most operations. Therefore, these constraints are kept in rows 0 to
688 /// nRedundant - 1, where nRedundant is a member variable that tracks the number
689 /// of constraints that have been marked redundant.
690 ///
691 /// Finding an integer sample is done with the Generalized Basis Reduction
692 /// algorithm. See the documentation for findIntegerSample and reduceBasis.
693 class Simplex : public SimplexBase {
694 public:
695   enum class Direction { Up, Down };
696 
697   Simplex() = delete;
Simplex(unsigned nVar)698   explicit Simplex(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/false) {}
Simplex(const IntegerRelation & constraints)699   explicit Simplex(const IntegerRelation &constraints)
700       : Simplex(constraints.getNumVars()) {
701     intersectIntegerRelation(constraints);
702   }
703   ~Simplex() override = default;
704 
705   /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
706   /// is the current number of variables, then the corresponding inequality is
707   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0.
708   ///
709   /// This also tries to restore the tableau configuration to a consistent
710   /// state and marks the Simplex empty if this is not possible.
711   void addInequality(ArrayRef<int64_t> coeffs) final;
712 
713   /// Compute the maximum or minimum value of the given row, depending on
714   /// direction. The specified row is never pivoted. On return, the row may
715   /// have a negative sample value if the direction is down.
716   ///
717   /// Returns a Fraction denoting the optimum, or a null value if no optimum
718   /// exists, i.e., if the expression is unbounded in this direction.
719   MaybeOptimum<Fraction> computeRowOptimum(Direction direction, unsigned row);
720 
721   /// Compute the maximum or minimum value of the given expression, depending on
722   /// direction. Should not be called when the Simplex is empty.
723   ///
724   /// Returns a Fraction denoting the optimum, or a null value if no optimum
725   /// exists, i.e., if the expression is unbounded in this direction.
726   MaybeOptimum<Fraction> computeOptimum(Direction direction,
727                                         ArrayRef<int64_t> coeffs);
728 
729   /// Returns whether the perpendicular of the specified constraint is a
730   /// is a direction along which the polytope is bounded.
731   bool isBoundedAlongConstraint(unsigned constraintIndex);
732 
733   /// Returns whether the specified constraint has been marked as redundant.
734   /// Constraints are numbered from 0 starting at the first added inequality.
735   /// Equalities are added as a pair of inequalities and so correspond to two
736   /// inequalities with successive indices.
737   bool isMarkedRedundant(unsigned constraintIndex) const;
738 
739   /// Finds a subset of constraints that is redundant, i.e., such that
740   /// the set of solutions does not change if these constraints are removed.
741   /// Marks these constraints as redundant. Whether a specific constraint has
742   /// been marked redundant can be queried using isMarkedRedundant.
743   ///
744   /// The first overload only tries to find redundant constraints with indices
745   /// in the range [offset, offset + count), by scanning constraints from left
746   /// to right in this range. If `count` is not provided, all constraints
747   /// starting at `offset` are scanned, and if neither are provided, all
748   /// constraints are scanned, starting from 0 and going to the last constraint.
749   ///
750   /// As an example, in the set (x) : (x >= 0, x >= 0, x >= 0), calling
751   /// `detectRedundant` with no parameters will result in the first two
752   /// constraints being marked redundant. All copies cannot be marked redundant
753   /// because removing all the constraints changes the set. The first two are
754   /// the ones marked redundant because we scan from left to right. Thus, when
755   /// there is some preference among the constraints as to which should be
756   /// marked redundant with priority when there are multiple possibilities, this
757   /// could be accomplished by succesive calls to detectRedundant(offset,
758   /// count).
759   void detectRedundant(unsigned offset, unsigned count);
detectRedundant(unsigned offset)760   void detectRedundant(unsigned offset) {
761     assert(offset <= con.size() && "invalid offset!");
762     detectRedundant(offset, con.size() - offset);
763   }
detectRedundant()764   void detectRedundant() { detectRedundant(0, con.size()); }
765 
766   /// Returns a (min, max) pair denoting the minimum and maximum integer values
767   /// of the given expression. If no integer value exists, both results will be
768   /// of kind Empty.
769   std::pair<MaybeOptimum<int64_t>, MaybeOptimum<int64_t>>
770   computeIntegerBounds(ArrayRef<int64_t> coeffs);
771 
772   /// Returns true if the polytope is unbounded, i.e., extends to infinity in
773   /// some direction. Otherwise, returns false.
774   bool isUnbounded();
775 
776   /// Make a tableau to represent a pair of points in the given tableaus, one in
777   /// tableau A and one in B.
778   static Simplex makeProduct(const Simplex &a, const Simplex &b);
779 
780   /// Returns an integer sample point if one exists, or None
781   /// otherwise. This should only be called for bounded sets.
782   Optional<SmallVector<int64_t, 8>> findIntegerSample();
783 
784   enum class IneqType { Redundant, Cut, Separate };
785 
786   /// Returns the type of the inequality with coefficients `coeffs`.
787   ///
788   /// Possible types are:
789   /// Redundant   The inequality is satisfied in the polytope
790   /// Cut         The inequality is satisfied by some points, but not by others
791   /// Separate    The inequality is not satisfied by any point
792   IneqType findIneqType(ArrayRef<int64_t> coeffs);
793 
794   /// Check if the specified inequality already holds in the polytope.
795   bool isRedundantInequality(ArrayRef<int64_t> coeffs);
796 
797   /// Check if the specified equality already holds in the polytope.
798   bool isRedundantEquality(ArrayRef<int64_t> coeffs);
799 
800   /// Returns true if this Simplex's polytope is a rational subset of `rel`.
801   /// Otherwise, returns false.
802   bool isRationalSubsetOf(const IntegerRelation &rel);
803 
804   /// Returns the current sample point if it is integral. Otherwise, returns
805   /// None.
806   Optional<SmallVector<int64_t, 8>> getSamplePointIfIntegral() const;
807 
808   /// Returns the current sample point, which may contain non-integer (rational)
809   /// coordinates. Returns an empty optional when the tableau is empty.
810   Optional<SmallVector<Fraction, 8>> getRationalSample() const;
811 
812 private:
813   friend class GBRSimplex;
814 
815   /// Restore the unknown to a non-negative sample value.
816   ///
817   /// Returns success if the unknown was successfully restored to a non-negative
818   /// sample value, failure otherwise.
819   LogicalResult restoreRow(Unknown &u);
820 
821   /// Find a pivot to change the sample value of row in the specified
822   /// direction while preserving tableau consistency, except that if the
823   /// direction is down then the pivot may make the specified row take a
824   /// negative value. The returned pivot row will be row if and only if the
825   /// unknown is unbounded in the specified direction.
826   ///
827   /// Returns a (row, col) pair denoting a pivot, or an empty Optional if
828   /// no valid pivot exists.
829   Optional<Pivot> findPivot(int row, Direction direction) const;
830 
831   /// Find a row that can be used to pivot the column in the specified
832   /// direction. If skipRow is not null, then this row is excluded
833   /// from consideration. The returned pivot will maintain all constraints
834   /// except the column itself and skipRow, if it is set. (if these unknowns
835   /// are restricted).
836   ///
837   /// Returns the row to pivot to, or an empty Optional if the column
838   /// is unbounded in the specified direction.
839   Optional<unsigned> findPivotRow(Optional<unsigned> skipRow,
840                                   Direction direction, unsigned col) const;
841 
842   /// Undo the addition of the last constraint while preserving tableau
843   /// consistency.
844   void undoLastConstraint() final;
845 
846   /// Compute the maximum or minimum of the specified Unknown, depending on
847   /// direction. The specified unknown may be pivoted. If the unknown is
848   /// restricted, it will have a non-negative sample value on return.
849   /// Should not be called if the Simplex is empty.
850   ///
851   /// Returns a Fraction denoting the optimum, or a null value if no optimum
852   /// exists, i.e., if the expression is unbounded in this direction.
853   MaybeOptimum<Fraction> computeOptimum(Direction direction, Unknown &u);
854 
855   /// Mark the specified unknown redundant. This operation is added to the undo
856   /// log and will be undone by rollbacks. The specified unknown must be in row
857   /// orientation.
858   void markRowRedundant(Unknown &u);
859 
860   /// Reduce the given basis, starting at the specified level, using general
861   /// basis reduction.
862   void reduceBasis(Matrix &basis, unsigned level);
863 };
864 
865 /// Takes a snapshot of the simplex state on construction and rolls back to the
866 /// snapshot on destruction.
867 ///
868 /// Useful for performing operations in a "transient context", all changes from
869 /// which get rolled back on scope exit.
870 class SimplexRollbackScopeExit {
871 public:
SimplexRollbackScopeExit(SimplexBase & simplex)872   SimplexRollbackScopeExit(SimplexBase &simplex) : simplex(simplex) {
873     snapshot = simplex.getSnapshot();
874   };
~SimplexRollbackScopeExit()875   ~SimplexRollbackScopeExit() { simplex.rollback(snapshot); }
876 
877 private:
878   SimplexBase &simplex;
879   unsigned snapshot;
880 };
881 
882 } // namespace presburger
883 } // namespace mlir
884 
885 #endif // MLIR_ANALYSIS_PRESBURGER_SIMPLEX_H
886