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