1 //===- Simplex.cpp - MLIR Simplex Class -----------------------------------===// 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 #include "mlir/Analysis/Presburger/Simplex.h" 10 #include "mlir/Analysis/Presburger/Matrix.h" 11 #include "mlir/Support/MathExtras.h" 12 #include "llvm/ADT/Optional.h" 13 14 namespace mlir { 15 16 using namespace presburger_utils; 17 using Direction = Simplex::Direction; 18 19 const int nullIndex = std::numeric_limits<int>::max(); 20 21 SimplexBase::SimplexBase(unsigned nVar, bool mustUseBigM) 22 : usingBigM(mustUseBigM), nRow(0), nCol(getNumFixedCols() + nVar), 23 nRedundant(0), tableau(0, nCol), empty(false) { 24 colUnknown.insert(colUnknown.begin(), getNumFixedCols(), nullIndex); 25 for (unsigned i = 0; i < nVar; ++i) { 26 var.emplace_back(Orientation::Column, /*restricted=*/false, 27 /*pos=*/getNumFixedCols() + i); 28 colUnknown.push_back(i); 29 } 30 } 31 32 const Simplex::Unknown &SimplexBase::unknownFromIndex(int index) const { 33 assert(index != nullIndex && "nullIndex passed to unknownFromIndex"); 34 return index >= 0 ? var[index] : con[~index]; 35 } 36 37 const Simplex::Unknown &SimplexBase::unknownFromColumn(unsigned col) const { 38 assert(col < nCol && "Invalid column"); 39 return unknownFromIndex(colUnknown[col]); 40 } 41 42 const Simplex::Unknown &SimplexBase::unknownFromRow(unsigned row) const { 43 assert(row < nRow && "Invalid row"); 44 return unknownFromIndex(rowUnknown[row]); 45 } 46 47 Simplex::Unknown &SimplexBase::unknownFromIndex(int index) { 48 assert(index != nullIndex && "nullIndex passed to unknownFromIndex"); 49 return index >= 0 ? var[index] : con[~index]; 50 } 51 52 Simplex::Unknown &SimplexBase::unknownFromColumn(unsigned col) { 53 assert(col < nCol && "Invalid column"); 54 return unknownFromIndex(colUnknown[col]); 55 } 56 57 Simplex::Unknown &SimplexBase::unknownFromRow(unsigned row) { 58 assert(row < nRow && "Invalid row"); 59 return unknownFromIndex(rowUnknown[row]); 60 } 61 62 /// Add a new row to the tableau corresponding to the given constant term and 63 /// list of coefficients. The coefficients are specified as a vector of 64 /// (variable index, coefficient) pairs. 65 unsigned SimplexBase::addRow(ArrayRef<int64_t> coeffs, bool makeRestricted) { 66 assert(coeffs.size() == var.size() + 1 && 67 "Incorrect number of coefficients!"); 68 69 ++nRow; 70 // If the tableau is not big enough to accomodate the extra row, we extend it. 71 if (nRow >= tableau.getNumRows()) 72 tableau.resizeVertically(nRow); 73 rowUnknown.push_back(~con.size()); 74 con.emplace_back(Orientation::Row, makeRestricted, nRow - 1); 75 76 // Zero out the new row. 77 tableau.fillRow(nRow - 1, 0); 78 79 tableau(nRow - 1, 0) = 1; 80 tableau(nRow - 1, 1) = coeffs.back(); 81 if (usingBigM) { 82 // When the lexicographic pivot rule is used, instead of the variables 83 // 84 // x, y, z ... 85 // 86 // we internally use the variables 87 // 88 // M, M + x, M + y, M + z, ... 89 // 90 // where M is the big M parameter. As such, when the user tries to add 91 // a row ax + by + cz + d, we express it in terms of our internal variables 92 // as -(a + b + c)M + a(M + x) + b(M + y) + c(M + z) + d. 93 int64_t bigMCoeff = 0; 94 for (unsigned i = 0; i < coeffs.size() - 1; ++i) 95 bigMCoeff -= coeffs[i]; 96 // The coefficient to the big M parameter is stored in column 2. 97 tableau(nRow - 1, 2) = bigMCoeff; 98 } 99 100 // Process each given variable coefficient. 101 for (unsigned i = 0; i < var.size(); ++i) { 102 unsigned pos = var[i].pos; 103 if (coeffs[i] == 0) 104 continue; 105 106 if (var[i].orientation == Orientation::Column) { 107 // If a variable is in column position at column col, then we just add the 108 // coefficient for that variable (scaled by the common row denominator) to 109 // the corresponding entry in the new row. 110 tableau(nRow - 1, pos) += coeffs[i] * tableau(nRow - 1, 0); 111 continue; 112 } 113 114 // If the variable is in row position, we need to add that row to the new 115 // row, scaled by the coefficient for the variable, accounting for the two 116 // rows potentially having different denominators. The new denominator is 117 // the lcm of the two. 118 int64_t lcm = mlir::lcm(tableau(nRow - 1, 0), tableau(pos, 0)); 119 int64_t nRowCoeff = lcm / tableau(nRow - 1, 0); 120 int64_t idxRowCoeff = coeffs[i] * (lcm / tableau(pos, 0)); 121 tableau(nRow - 1, 0) = lcm; 122 for (unsigned col = 1; col < nCol; ++col) 123 tableau(nRow - 1, col) = 124 nRowCoeff * tableau(nRow - 1, col) + idxRowCoeff * tableau(pos, col); 125 } 126 127 normalizeRow(nRow - 1); 128 // Push to undo log along with the index of the new constraint. 129 undoLog.push_back(UndoLogEntry::RemoveLastConstraint); 130 return con.size() - 1; 131 } 132 133 /// Normalize the row by removing factors that are common between the 134 /// denominator and all the numerator coefficients. 135 void SimplexBase::normalizeRow(unsigned row) { 136 int64_t gcd = 0; 137 for (unsigned col = 0; col < nCol; ++col) { 138 gcd = llvm::greatestCommonDivisor(gcd, std::abs(tableau(row, col))); 139 // If the gcd becomes 1 then the row is already normalized. 140 if (gcd == 1) 141 return; 142 } 143 144 // Note that the gcd can never become zero since the first element of the row, 145 // the denominator, is non-zero. 146 assert(gcd != 0); 147 for (unsigned col = 0; col < nCol; ++col) 148 tableau(row, col) /= gcd; 149 } 150 151 namespace { 152 bool signMatchesDirection(int64_t elem, Direction direction) { 153 assert(elem != 0 && "elem should not be 0"); 154 return direction == Direction::Up ? elem > 0 : elem < 0; 155 } 156 157 Direction flippedDirection(Direction direction) { 158 return direction == Direction::Up ? Direction::Down : Simplex::Direction::Up; 159 } 160 } // namespace 161 162 MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalLexMin() { 163 restoreRationalConsistency(); 164 return getRationalSample(); 165 } 166 167 bool LexSimplex::rowIsViolated(unsigned row) const { 168 if (tableau(row, 2) < 0) 169 return true; 170 if (tableau(row, 2) == 0 && tableau(row, 1) < 0) 171 return true; 172 return false; 173 } 174 175 Optional<unsigned> LexSimplex::maybeGetViolatedRow() const { 176 for (unsigned row = 0; row < nRow; ++row) 177 if (rowIsViolated(row)) 178 return row; 179 return {}; 180 } 181 182 // We simply look for violated rows and keep trying to move them to column 183 // orientation, which always succeeds unless the constraints have no solution 184 // in which case we just give up and return. 185 void LexSimplex::restoreRationalConsistency() { 186 while (Optional<unsigned> maybeViolatedRow = maybeGetViolatedRow()) { 187 LogicalResult status = moveRowUnknownToColumn(*maybeViolatedRow); 188 if (failed(status)) 189 return; 190 } 191 } 192 193 // Move the row unknown to column orientation while preserving lexicopositivity 194 // of the basis transform. 195 // 196 // We only consider pivots where the pivot element is positive. Suppose no such 197 // pivot exists, i.e., some violated row has no positive coefficient for any 198 // basis unknown. The row can be represented as (s + c_1*u_1 + ... + c_n*u_n)/d, 199 // where d is the denominator, s is the sample value and the c_i are the basis 200 // coefficients. Since any feasible assignment of the basis satisfies u_i >= 0 201 // for all i, and we have s < 0 as well as c_i < 0 for all i, any feasible 202 // assignment would violate this row and therefore the constraints have no 203 // solution. 204 // 205 // We can preserve lexicopositivity by picking the pivot column with positive 206 // pivot element that makes the lexicographically smallest change to the sample 207 // point. 208 // 209 // Proof. Let 210 // x = (x_1, ... x_n) be the variables, 211 // z = (z_1, ... z_m) be the constraints, 212 // y = (y_1, ... y_n) be the current basis, and 213 // define w = (x_1, ... x_n, z_1, ... z_m) = B*y + s. 214 // B is basically the simplex tableau of our implementation except that instead 215 // of only describing the transform to get back the non-basis unknowns, it 216 // defines the values of all the unknowns in terms of the basis unknowns. 217 // Similarly, s is the column for the sample value. 218 // 219 // Our goal is to show that each column in B, restricted to the first n 220 // rows, is lexicopositive after the pivot if it is so before. This is 221 // equivalent to saying the columns in the whole matrix are lexicopositive; 222 // there must be some non-zero element in every column in the first n rows since 223 // the n variables cannot be spanned without using all the n basis unknowns. 224 // 225 // Consider a pivot where z_i replaces y_j in the basis. Recall the pivot 226 // transform for the tableau derived for SimplexBase::pivot: 227 // 228 // pivot col other col pivot col other col 229 // pivot row a b -> pivot row 1/a -b/a 230 // other row c d other row c/a d - bc/a 231 // 232 // Similarly, a pivot results in B changing to B' and c to c'; the difference 233 // between the tableau and these matrices B and B' is that there is no special 234 // case for the pivot row, since it continues to represent the same unknown. The 235 // same formula applies for all rows: 236 // 237 // B'.col(j) = B.col(j) / B(i,j) 238 // B'.col(k) = B.col(k) - B(i,k) * B.col(j) / B(i,j) for k != j 239 // and similarly, s' = s - s_i * B.col(j) / B(i,j). 240 // 241 // Since the row is violated, we have s_i < 0, so the change in sample value 242 // when pivoting with column a is lexicographically smaller than that when 243 // pivoting with column b iff B.col(a) / B(i, a) is lexicographically smaller 244 // than B.col(b) / B(i, b). 245 // 246 // Since B(i, j) > 0, column j remains lexicopositive. 247 // 248 // For the other columns, suppose C.col(k) is not lexicopositive. 249 // This means that for some p, for all t < p, 250 // C(t,k) = 0 => B(t,k) = B(t,j) * B(i,k) / B(i,j) and 251 // C(t,k) < 0 => B(p,k) < B(t,j) * B(i,k) / B(i,j), 252 // which is in contradiction to the fact that B.col(j) / B(i,j) must be 253 // lexicographically smaller than B.col(k) / B(i,k), since it lexicographically 254 // minimizes the change in sample value. 255 LogicalResult LexSimplex::moveRowUnknownToColumn(unsigned row) { 256 Optional<unsigned> maybeColumn; 257 for (unsigned col = 3; col < nCol; ++col) { 258 if (tableau(row, col) <= 0) 259 continue; 260 maybeColumn = 261 !maybeColumn ? col : getLexMinPivotColumn(row, *maybeColumn, col); 262 } 263 264 if (!maybeColumn) { 265 markEmpty(); 266 return failure(); 267 } 268 269 pivot(row, *maybeColumn); 270 return success(); 271 } 272 273 unsigned LexSimplex::getLexMinPivotColumn(unsigned row, unsigned colA, 274 unsigned colB) const { 275 // A pivot causes the following change. (in the diagram the matrix elements 276 // are shown as rationals and there is no common denominator used) 277 // 278 // pivot col big M col const col 279 // pivot row a p b 280 // other row c q d 281 // | 282 // v 283 // 284 // pivot col big M col const col 285 // pivot row 1/a -p/a -b/a 286 // other row c/a q - pc/a d - bc/a 287 // 288 // Let the sample value of the pivot row be s = pM + b before the pivot. Since 289 // the pivot row represents a violated constraint we know that s < 0. 290 // 291 // If the variable is a non-pivot column, its sample value is zero before and 292 // after the pivot. 293 // 294 // If the variable is the pivot column, then its sample value goes from 0 to 295 // (-p/a)M + (-b/a), i.e. 0 to -(pM + b)/a. Thus the change in the sample 296 // value is -s/a. 297 // 298 // If the variable is the pivot row, it sampel value goes from s to 0, for a 299 // change of -s. 300 // 301 // If the variable is a non-pivot row, its sample value changes from 302 // qM + d to qM + d + (-pc/a)M + (-bc/a). Thus the change in sample value 303 // is -(pM + b)(c/a) = -sc/a. 304 // 305 // Thus the change in sample value is either 0, -s/a, -s, or -sc/a. Here -s is 306 // fixed for all calls to this function since the row and tableau are fixed. 307 // The callee just wants to compare the return values with the return value of 308 // other invocations of the same function. So the -s is common for all 309 // comparisons involved and can be ignored, since -s is strictly positive. 310 // 311 // Thus we take away this common factor and just return 0, 1/a, 1, or c/a as 312 // appropriate. This allows us to run the entire algorithm without ever having 313 // to fix a value of M. 314 auto getSampleChangeCoeffForVar = [this, row](unsigned col, 315 const Unknown &u) -> Fraction { 316 int64_t a = tableau(row, col); 317 if (u.orientation == Orientation::Column) { 318 // Pivot column case. 319 if (u.pos == col) 320 return {1, a}; 321 322 // Non-pivot column case. 323 return {0, 1}; 324 } 325 326 // Pivot row case. 327 if (u.pos == row) 328 return {1, 1}; 329 330 // Non-pivot row case. 331 int64_t c = tableau(u.pos, col); 332 return {c, a}; 333 }; 334 335 for (const Unknown &u : var) { 336 Fraction changeA = getSampleChangeCoeffForVar(colA, u); 337 Fraction changeB = getSampleChangeCoeffForVar(colB, u); 338 if (changeA < changeB) 339 return colA; 340 if (changeA > changeB) 341 return colB; 342 } 343 344 // If we reached here, both result in exactly the same changes, so it 345 // doesn't matter which we return. 346 return colA; 347 } 348 349 /// Find a pivot to change the sample value of the row in the specified 350 /// direction. The returned pivot row will involve `row` if and only if the 351 /// unknown is unbounded in the specified direction. 352 /// 353 /// To increase (resp. decrease) the value of a row, we need to find a live 354 /// column with a non-zero coefficient. If the coefficient is positive, we need 355 /// to increase (decrease) the value of the column, and if the coefficient is 356 /// negative, we need to decrease (increase) the value of the column. Also, 357 /// we cannot decrease the sample value of restricted columns. 358 /// 359 /// If multiple columns are valid, we break ties by considering a lexicographic 360 /// ordering where we prefer unknowns with lower index. 361 Optional<SimplexBase::Pivot> Simplex::findPivot(int row, 362 Direction direction) const { 363 Optional<unsigned> col; 364 for (unsigned j = 2; j < nCol; ++j) { 365 int64_t elem = tableau(row, j); 366 if (elem == 0) 367 continue; 368 369 if (unknownFromColumn(j).restricted && 370 !signMatchesDirection(elem, direction)) 371 continue; 372 if (!col || colUnknown[j] < colUnknown[*col]) 373 col = j; 374 } 375 376 if (!col) 377 return {}; 378 379 Direction newDirection = 380 tableau(row, *col) < 0 ? flippedDirection(direction) : direction; 381 Optional<unsigned> maybePivotRow = findPivotRow(row, newDirection, *col); 382 return Pivot{maybePivotRow.getValueOr(row), *col}; 383 } 384 385 /// Swap the associated unknowns for the row and the column. 386 /// 387 /// First we swap the index associated with the row and column. Then we update 388 /// the unknowns to reflect their new position and orientation. 389 void SimplexBase::swapRowWithCol(unsigned row, unsigned col) { 390 std::swap(rowUnknown[row], colUnknown[col]); 391 Unknown &uCol = unknownFromColumn(col); 392 Unknown &uRow = unknownFromRow(row); 393 uCol.orientation = Orientation::Column; 394 uRow.orientation = Orientation::Row; 395 uCol.pos = col; 396 uRow.pos = row; 397 } 398 399 void SimplexBase::pivot(Pivot pair) { pivot(pair.row, pair.column); } 400 401 /// Pivot pivotRow and pivotCol. 402 /// 403 /// Let R be the pivot row unknown and let C be the pivot col unknown. 404 /// Since initially R = a*C + sum b_i * X_i 405 /// (where the sum is over the other column's unknowns, x_i) 406 /// C = (R - (sum b_i * X_i))/a 407 /// 408 /// Let u be some other row unknown. 409 /// u = c*C + sum d_i * X_i 410 /// So u = c*(R - sum b_i * X_i)/a + sum d_i * X_i 411 /// 412 /// This results in the following transform: 413 /// pivot col other col pivot col other col 414 /// pivot row a b -> pivot row 1/a -b/a 415 /// other row c d other row c/a d - bc/a 416 /// 417 /// Taking into account the common denominators p and q: 418 /// 419 /// pivot col other col pivot col other col 420 /// pivot row a/p b/p -> pivot row p/a -b/a 421 /// other row c/q d/q other row cp/aq (da - bc)/aq 422 /// 423 /// The pivot row transform is accomplished be swapping a with the pivot row's 424 /// common denominator and negating the pivot row except for the pivot column 425 /// element. 426 void SimplexBase::pivot(unsigned pivotRow, unsigned pivotCol) { 427 assert(pivotCol >= getNumFixedCols() && "Refusing to pivot invalid column"); 428 429 swapRowWithCol(pivotRow, pivotCol); 430 std::swap(tableau(pivotRow, 0), tableau(pivotRow, pivotCol)); 431 // We need to negate the whole pivot row except for the pivot column. 432 if (tableau(pivotRow, 0) < 0) { 433 // If the denominator is negative, we negate the row by simply negating the 434 // denominator. 435 tableau(pivotRow, 0) = -tableau(pivotRow, 0); 436 tableau(pivotRow, pivotCol) = -tableau(pivotRow, pivotCol); 437 } else { 438 for (unsigned col = 1; col < nCol; ++col) { 439 if (col == pivotCol) 440 continue; 441 tableau(pivotRow, col) = -tableau(pivotRow, col); 442 } 443 } 444 normalizeRow(pivotRow); 445 446 for (unsigned row = 0; row < nRow; ++row) { 447 if (row == pivotRow) 448 continue; 449 if (tableau(row, pivotCol) == 0) // Nothing to do. 450 continue; 451 tableau(row, 0) *= tableau(pivotRow, 0); 452 for (unsigned j = 1; j < nCol; ++j) { 453 if (j == pivotCol) 454 continue; 455 // Add rather than subtract because the pivot row has been negated. 456 tableau(row, j) = tableau(row, j) * tableau(pivotRow, 0) + 457 tableau(row, pivotCol) * tableau(pivotRow, j); 458 } 459 tableau(row, pivotCol) *= tableau(pivotRow, pivotCol); 460 normalizeRow(row); 461 } 462 } 463 464 /// Perform pivots until the unknown has a non-negative sample value or until 465 /// no more upward pivots can be performed. Return success if we were able to 466 /// bring the row to a non-negative sample value, and failure otherwise. 467 LogicalResult Simplex::restoreRow(Unknown &u) { 468 assert(u.orientation == Orientation::Row && 469 "unknown should be in row position"); 470 471 while (tableau(u.pos, 1) < 0) { 472 Optional<Pivot> maybePivot = findPivot(u.pos, Direction::Up); 473 if (!maybePivot) 474 break; 475 476 pivot(*maybePivot); 477 if (u.orientation == Orientation::Column) 478 return success(); // the unknown is unbounded above. 479 } 480 return success(tableau(u.pos, 1) >= 0); 481 } 482 483 /// Find a row that can be used to pivot the column in the specified direction. 484 /// This returns an empty optional if and only if the column is unbounded in the 485 /// specified direction (ignoring skipRow, if skipRow is set). 486 /// 487 /// If skipRow is set, this row is not considered, and (if it is restricted) its 488 /// restriction may be violated by the returned pivot. Usually, skipRow is set 489 /// because we don't want to move it to column position unless it is unbounded, 490 /// and we are either trying to increase the value of skipRow or explicitly 491 /// trying to make skipRow negative, so we are not concerned about this. 492 /// 493 /// If the direction is up (resp. down) and a restricted row has a negative 494 /// (positive) coefficient for the column, then this row imposes a bound on how 495 /// much the sample value of the column can change. Such a row with constant 496 /// term c and coefficient f for the column imposes a bound of c/|f| on the 497 /// change in sample value (in the specified direction). (note that c is 498 /// non-negative here since the row is restricted and the tableau is consistent) 499 /// 500 /// We iterate through the rows and pick the row which imposes the most 501 /// stringent bound, since pivoting with a row changes the row's sample value to 502 /// 0 and hence saturates the bound it imposes. We break ties between rows that 503 /// impose the same bound by considering a lexicographic ordering where we 504 /// prefer unknowns with lower index value. 505 Optional<unsigned> Simplex::findPivotRow(Optional<unsigned> skipRow, 506 Direction direction, 507 unsigned col) const { 508 Optional<unsigned> retRow; 509 // Initialize these to zero in order to silence a warning about retElem and 510 // retConst being used uninitialized in the initialization of `diff` below. In 511 // reality, these are always initialized when that line is reached since these 512 // are set whenever retRow is set. 513 int64_t retElem = 0, retConst = 0; 514 for (unsigned row = nRedundant; row < nRow; ++row) { 515 if (skipRow && row == *skipRow) 516 continue; 517 int64_t elem = tableau(row, col); 518 if (elem == 0) 519 continue; 520 if (!unknownFromRow(row).restricted) 521 continue; 522 if (signMatchesDirection(elem, direction)) 523 continue; 524 int64_t constTerm = tableau(row, 1); 525 526 if (!retRow) { 527 retRow = row; 528 retElem = elem; 529 retConst = constTerm; 530 continue; 531 } 532 533 int64_t diff = retConst * elem - constTerm * retElem; 534 if ((diff == 0 && rowUnknown[row] < rowUnknown[*retRow]) || 535 (diff != 0 && !signMatchesDirection(diff, direction))) { 536 retRow = row; 537 retElem = elem; 538 retConst = constTerm; 539 } 540 } 541 return retRow; 542 } 543 544 bool SimplexBase::isEmpty() const { return empty; } 545 546 void SimplexBase::swapRows(unsigned i, unsigned j) { 547 if (i == j) 548 return; 549 tableau.swapRows(i, j); 550 std::swap(rowUnknown[i], rowUnknown[j]); 551 unknownFromRow(i).pos = i; 552 unknownFromRow(j).pos = j; 553 } 554 555 void SimplexBase::swapColumns(unsigned i, unsigned j) { 556 assert(i < nCol && j < nCol && "Invalid columns provided!"); 557 if (i == j) 558 return; 559 tableau.swapColumns(i, j); 560 std::swap(colUnknown[i], colUnknown[j]); 561 unknownFromColumn(i).pos = i; 562 unknownFromColumn(j).pos = j; 563 } 564 565 /// Mark this tableau empty and push an entry to the undo stack. 566 void SimplexBase::markEmpty() { 567 // If the set is already empty, then we shouldn't add another UnmarkEmpty log 568 // entry, since in that case the Simplex will be erroneously marked as 569 // non-empty when rolling back past this point. 570 if (empty) 571 return; 572 undoLog.push_back(UndoLogEntry::UnmarkEmpty); 573 empty = true; 574 } 575 576 /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n 577 /// is the current number of variables, then the corresponding inequality is 578 /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0. 579 /// 580 /// We add the inequality and mark it as restricted. We then try to make its 581 /// sample value non-negative. If this is not possible, the tableau has become 582 /// empty and we mark it as such. 583 void Simplex::addInequality(ArrayRef<int64_t> coeffs) { 584 unsigned conIndex = addRow(coeffs, /*makeRestricted=*/true); 585 LogicalResult result = restoreRow(con[conIndex]); 586 if (failed(result)) 587 markEmpty(); 588 } 589 590 /// Add an equality to the tableau. If coeffs is c_0, c_1, ... c_n, where n 591 /// is the current number of variables, then the corresponding equality is 592 /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} == 0. 593 /// 594 /// We simply add two opposing inequalities, which force the expression to 595 /// be zero. 596 void SimplexBase::addEquality(ArrayRef<int64_t> coeffs) { 597 addInequality(coeffs); 598 SmallVector<int64_t, 8> negatedCoeffs; 599 for (int64_t coeff : coeffs) 600 negatedCoeffs.emplace_back(-coeff); 601 addInequality(negatedCoeffs); 602 } 603 604 unsigned SimplexBase::getNumVariables() const { return var.size(); } 605 unsigned SimplexBase::getNumConstraints() const { return con.size(); } 606 607 /// Return a snapshot of the current state. This is just the current size of the 608 /// undo log. 609 unsigned SimplexBase::getSnapshot() const { return undoLog.size(); } 610 611 unsigned SimplexBase::getSnapshotBasis() { 612 SmallVector<int, 8> basis; 613 for (int index : colUnknown) { 614 if (index != nullIndex) 615 basis.push_back(index); 616 } 617 savedBases.push_back(std::move(basis)); 618 619 undoLog.emplace_back(UndoLogEntry::RestoreBasis); 620 return undoLog.size() - 1; 621 } 622 623 void SimplexBase::removeLastConstraintRowOrientation() { 624 assert(con.back().orientation == Orientation::Row); 625 626 // Move this unknown to the last row and remove the last row from the 627 // tableau. 628 swapRows(con.back().pos, nRow - 1); 629 // It is not strictly necessary to shrink the tableau, but for now we 630 // maintain the invariant that the tableau has exactly nRow rows. 631 tableau.resizeVertically(nRow - 1); 632 nRow--; 633 rowUnknown.pop_back(); 634 con.pop_back(); 635 } 636 637 // This doesn't find a pivot row only if the column has zero 638 // coefficients for every row. 639 // 640 // If the unknown is a constraint, this can't happen, since it was added 641 // initially as a row. Such a row could never have been pivoted to a column. So 642 // a pivot row will always be found if we have a constraint. 643 // 644 // If we have a variable, then the column has zero coefficients for every row 645 // iff no constraints have been added with a non-zero coefficient for this row. 646 Optional<unsigned> SimplexBase::findAnyPivotRow(unsigned col) { 647 for (unsigned row = nRedundant; row < nRow; ++row) 648 if (tableau(row, col) != 0) 649 return row; 650 return {}; 651 } 652 653 // It's not valid to remove the constraint by deleting the column since this 654 // would result in an invalid basis. 655 void Simplex::undoLastConstraint() { 656 if (con.back().orientation == Orientation::Column) { 657 // We try to find any pivot row for this column that preserves tableau 658 // consistency (except possibly the column itself, which is going to be 659 // deallocated anyway). 660 // 661 // If no pivot row is found in either direction, then the unknown is 662 // unbounded in both directions and we are free to perform any pivot at 663 // all. To do this, we just need to find any row with a non-zero 664 // coefficient for the column. findAnyPivotRow will always be able to 665 // find such a row for a constraint. 666 unsigned column = con.back().pos; 667 if (Optional<unsigned> maybeRow = findPivotRow({}, Direction::Up, column)) { 668 pivot(*maybeRow, column); 669 } else if (Optional<unsigned> maybeRow = 670 findPivotRow({}, Direction::Down, column)) { 671 pivot(*maybeRow, column); 672 } else { 673 Optional<unsigned> row = findAnyPivotRow(column); 674 assert(row.hasValue() && "Pivot should always exist for a constraint!"); 675 pivot(*row, column); 676 } 677 } 678 removeLastConstraintRowOrientation(); 679 } 680 681 // It's not valid to remove the constraint by deleting the column since this 682 // would result in an invalid basis. 683 void LexSimplex::undoLastConstraint() { 684 if (con.back().orientation == Orientation::Column) { 685 // When removing the last constraint during a rollback, we just need to find 686 // any pivot at all, i.e., any row with non-zero coefficient for the 687 // column, because when rolling back a lexicographic simplex, we always 688 // end by restoring the exact basis that was present at the time of the 689 // snapshot, so what pivots we perform while undoing doesn't matter as 690 // long as we get the unknown to row orientation and remove it. 691 unsigned column = con.back().pos; 692 Optional<unsigned> row = findAnyPivotRow(column); 693 assert(row.hasValue() && "Pivot should always exist for a constraint!"); 694 pivot(*row, column); 695 } 696 removeLastConstraintRowOrientation(); 697 } 698 699 void SimplexBase::undo(UndoLogEntry entry) { 700 if (entry == UndoLogEntry::RemoveLastConstraint) { 701 // Simplex and LexSimplex handle this differently, so we call out to a 702 // virtual function to handle this. 703 undoLastConstraint(); 704 } else if (entry == UndoLogEntry::RemoveLastVariable) { 705 // Whenever we are rolling back the addition of a variable, it is guaranteed 706 // that the variable will be in column position. 707 // 708 // We can see this as follows: any constraint that depends on this variable 709 // was added after this variable was added, so the addition of such 710 // constraints should already have been rolled back by the time we get to 711 // rolling back the addition of the variable. Therefore, no constraint 712 // currently has a component along the variable, so the variable itself must 713 // be part of the basis. 714 assert(var.back().orientation == Orientation::Column && 715 "Variable to be removed must be in column orientation!"); 716 717 // Move this variable to the last column and remove the column from the 718 // tableau. 719 swapColumns(var.back().pos, nCol - 1); 720 tableau.resizeHorizontally(nCol - 1); 721 var.pop_back(); 722 colUnknown.pop_back(); 723 nCol--; 724 } else if (entry == UndoLogEntry::UnmarkEmpty) { 725 empty = false; 726 } else if (entry == UndoLogEntry::UnmarkLastRedundant) { 727 nRedundant--; 728 } else if (entry == UndoLogEntry::RestoreBasis) { 729 assert(!savedBases.empty() && "No bases saved!"); 730 731 SmallVector<int, 8> basis = std::move(savedBases.back()); 732 savedBases.pop_back(); 733 734 for (int index : basis) { 735 Unknown &u = unknownFromIndex(index); 736 if (u.orientation == Orientation::Column) 737 continue; 738 for (unsigned col = getNumFixedCols(); col < nCol; col++) { 739 assert(colUnknown[col] != nullIndex && 740 "Column should not be a fixed column!"); 741 if (std::find(basis.begin(), basis.end(), colUnknown[col]) != 742 basis.end()) 743 continue; 744 if (tableau(u.pos, col) == 0) 745 continue; 746 pivot(u.pos, col); 747 break; 748 } 749 750 assert(u.orientation == Orientation::Column && "No pivot found!"); 751 } 752 } 753 } 754 755 /// Rollback to the specified snapshot. 756 /// 757 /// We undo all the log entries until the log size when the snapshot was taken 758 /// is reached. 759 void SimplexBase::rollback(unsigned snapshot) { 760 while (undoLog.size() > snapshot) { 761 undo(undoLog.back()); 762 undoLog.pop_back(); 763 } 764 } 765 766 void SimplexBase::appendVariable(unsigned count) { 767 if (count == 0) 768 return; 769 var.reserve(var.size() + count); 770 colUnknown.reserve(colUnknown.size() + count); 771 for (unsigned i = 0; i < count; ++i) { 772 nCol++; 773 var.emplace_back(Orientation::Column, /*restricted=*/false, 774 /*pos=*/nCol - 1); 775 colUnknown.push_back(var.size() - 1); 776 } 777 tableau.resizeHorizontally(nCol); 778 undoLog.insert(undoLog.end(), count, UndoLogEntry::RemoveLastVariable); 779 } 780 781 /// Add all the constraints from the given IntegerPolyhedron. 782 void SimplexBase::intersectIntegerPolyhedron(const IntegerPolyhedron &poly) { 783 assert(poly.getNumIds() == getNumVariables() && 784 "IntegerPolyhedron must have same dimensionality as simplex"); 785 for (unsigned i = 0, e = poly.getNumInequalities(); i < e; ++i) 786 addInequality(poly.getInequality(i)); 787 for (unsigned i = 0, e = poly.getNumEqualities(); i < e; ++i) 788 addEquality(poly.getEquality(i)); 789 } 790 791 MaybeOptimum<Fraction> Simplex::computeRowOptimum(Direction direction, 792 unsigned row) { 793 // Keep trying to find a pivot for the row in the specified direction. 794 while (Optional<Pivot> maybePivot = findPivot(row, direction)) { 795 // If findPivot returns a pivot involving the row itself, then the optimum 796 // is unbounded, so we return None. 797 if (maybePivot->row == row) 798 return OptimumKind::Unbounded; 799 pivot(*maybePivot); 800 } 801 802 // The row has reached its optimal sample value, which we return. 803 // The sample value is the entry in the constant column divided by the common 804 // denominator for this row. 805 return Fraction(tableau(row, 1), tableau(row, 0)); 806 } 807 808 /// Compute the optimum of the specified expression in the specified direction, 809 /// or None if it is unbounded. 810 MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction, 811 ArrayRef<int64_t> coeffs) { 812 if (empty) 813 return OptimumKind::Empty; 814 unsigned snapshot = getSnapshot(); 815 unsigned conIndex = addRow(coeffs); 816 unsigned row = con[conIndex].pos; 817 MaybeOptimum<Fraction> optimum = computeRowOptimum(direction, row); 818 rollback(snapshot); 819 return optimum; 820 } 821 822 MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction, 823 Unknown &u) { 824 if (empty) 825 return OptimumKind::Empty; 826 if (u.orientation == Orientation::Column) { 827 unsigned column = u.pos; 828 Optional<unsigned> pivotRow = findPivotRow({}, direction, column); 829 // If no pivot is returned, the constraint is unbounded in the specified 830 // direction. 831 if (!pivotRow) 832 return OptimumKind::Unbounded; 833 pivot(*pivotRow, column); 834 } 835 836 unsigned row = u.pos; 837 MaybeOptimum<Fraction> optimum = computeRowOptimum(direction, row); 838 if (u.restricted && direction == Direction::Down && 839 (optimum.isUnbounded() || *optimum < Fraction(0, 1))) { 840 if (failed(restoreRow(u))) 841 llvm_unreachable("Could not restore row!"); 842 } 843 return optimum; 844 } 845 846 bool Simplex::isBoundedAlongConstraint(unsigned constraintIndex) { 847 assert(!empty && "It is not meaningful to ask whether a direction is bounded " 848 "in an empty set."); 849 // The constraint's perpendicular is already bounded below, since it is a 850 // constraint. If it is also bounded above, we can return true. 851 return computeOptimum(Direction::Up, con[constraintIndex]).isBounded(); 852 } 853 854 /// Redundant constraints are those that are in row orientation and lie in 855 /// rows 0 to nRedundant - 1. 856 bool Simplex::isMarkedRedundant(unsigned constraintIndex) const { 857 const Unknown &u = con[constraintIndex]; 858 return u.orientation == Orientation::Row && u.pos < nRedundant; 859 } 860 861 /// Mark the specified row redundant. 862 /// 863 /// This is done by moving the unknown to the end of the block of redundant 864 /// rows (namely, to row nRedundant) and incrementing nRedundant to 865 /// accomodate the new redundant row. 866 void Simplex::markRowRedundant(Unknown &u) { 867 assert(u.orientation == Orientation::Row && 868 "Unknown should be in row position!"); 869 assert(u.pos >= nRedundant && "Unknown is already marked redundant!"); 870 swapRows(u.pos, nRedundant); 871 ++nRedundant; 872 undoLog.emplace_back(UndoLogEntry::UnmarkLastRedundant); 873 } 874 875 /// Find a subset of constraints that is redundant and mark them redundant. 876 void Simplex::detectRedundant() { 877 // It is not meaningful to talk about redundancy for empty sets. 878 if (empty) 879 return; 880 881 // Iterate through the constraints and check for each one if it can attain 882 // negative sample values. If it can, it's not redundant. Otherwise, it is. 883 // We mark redundant constraints redundant. 884 // 885 // Constraints that get marked redundant in one iteration are not respected 886 // when checking constraints in later iterations. This prevents, for example, 887 // two identical constraints both being marked redundant since each is 888 // redundant given the other one. In this example, only the first of the 889 // constraints that is processed will get marked redundant, as it should be. 890 for (Unknown &u : con) { 891 if (u.orientation == Orientation::Column) { 892 unsigned column = u.pos; 893 Optional<unsigned> pivotRow = findPivotRow({}, Direction::Down, column); 894 // If no downward pivot is returned, the constraint is unbounded below 895 // and hence not redundant. 896 if (!pivotRow) 897 continue; 898 pivot(*pivotRow, column); 899 } 900 901 unsigned row = u.pos; 902 MaybeOptimum<Fraction> minimum = computeRowOptimum(Direction::Down, row); 903 if (minimum.isUnbounded() || *minimum < Fraction(0, 1)) { 904 // Constraint is unbounded below or can attain negative sample values and 905 // hence is not redundant. 906 if (failed(restoreRow(u))) 907 llvm_unreachable("Could not restore non-redundant row!"); 908 continue; 909 } 910 911 markRowRedundant(u); 912 } 913 } 914 915 bool Simplex::isUnbounded() { 916 if (empty) 917 return false; 918 919 SmallVector<int64_t, 8> dir(var.size() + 1); 920 for (unsigned i = 0; i < var.size(); ++i) { 921 dir[i] = 1; 922 923 if (computeOptimum(Direction::Up, dir).isUnbounded()) 924 return true; 925 926 if (computeOptimum(Direction::Down, dir).isUnbounded()) 927 return true; 928 929 dir[i] = 0; 930 } 931 return false; 932 } 933 934 /// Make a tableau to represent a pair of points in the original tableau. 935 /// 936 /// The product constraints and variables are stored as: first A's, then B's. 937 /// 938 /// The product tableau has row layout: 939 /// A's redundant rows, B's redundant rows, A's other rows, B's other rows. 940 /// 941 /// It has column layout: 942 /// denominator, constant, A's columns, B's columns. 943 Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) { 944 unsigned numVar = a.getNumVariables() + b.getNumVariables(); 945 unsigned numCon = a.getNumConstraints() + b.getNumConstraints(); 946 Simplex result(numVar); 947 948 result.tableau.resizeVertically(numCon); 949 result.empty = a.empty || b.empty; 950 951 auto concat = [](ArrayRef<Unknown> v, ArrayRef<Unknown> w) { 952 SmallVector<Unknown, 8> result; 953 result.reserve(v.size() + w.size()); 954 result.insert(result.end(), v.begin(), v.end()); 955 result.insert(result.end(), w.begin(), w.end()); 956 return result; 957 }; 958 result.con = concat(a.con, b.con); 959 result.var = concat(a.var, b.var); 960 961 auto indexFromBIndex = [&](int index) { 962 return index >= 0 ? a.getNumVariables() + index 963 : ~(a.getNumConstraints() + ~index); 964 }; 965 966 result.colUnknown.assign(2, nullIndex); 967 for (unsigned i = 2; i < a.nCol; ++i) { 968 result.colUnknown.push_back(a.colUnknown[i]); 969 result.unknownFromIndex(result.colUnknown.back()).pos = 970 result.colUnknown.size() - 1; 971 } 972 for (unsigned i = 2; i < b.nCol; ++i) { 973 result.colUnknown.push_back(indexFromBIndex(b.colUnknown[i])); 974 result.unknownFromIndex(result.colUnknown.back()).pos = 975 result.colUnknown.size() - 1; 976 } 977 978 auto appendRowFromA = [&](unsigned row) { 979 for (unsigned col = 0; col < a.nCol; ++col) 980 result.tableau(result.nRow, col) = a.tableau(row, col); 981 result.rowUnknown.push_back(a.rowUnknown[row]); 982 result.unknownFromIndex(result.rowUnknown.back()).pos = 983 result.rowUnknown.size() - 1; 984 result.nRow++; 985 }; 986 987 // Also fixes the corresponding entry in rowUnknown and var/con (as the case 988 // may be). 989 auto appendRowFromB = [&](unsigned row) { 990 result.tableau(result.nRow, 0) = b.tableau(row, 0); 991 result.tableau(result.nRow, 1) = b.tableau(row, 1); 992 993 unsigned offset = a.nCol - 2; 994 for (unsigned col = 2; col < b.nCol; ++col) 995 result.tableau(result.nRow, offset + col) = b.tableau(row, col); 996 result.rowUnknown.push_back(indexFromBIndex(b.rowUnknown[row])); 997 result.unknownFromIndex(result.rowUnknown.back()).pos = 998 result.rowUnknown.size() - 1; 999 result.nRow++; 1000 }; 1001 1002 result.nRedundant = a.nRedundant + b.nRedundant; 1003 for (unsigned row = 0; row < a.nRedundant; ++row) 1004 appendRowFromA(row); 1005 for (unsigned row = 0; row < b.nRedundant; ++row) 1006 appendRowFromB(row); 1007 for (unsigned row = a.nRedundant; row < a.nRow; ++row) 1008 appendRowFromA(row); 1009 for (unsigned row = b.nRedundant; row < b.nRow; ++row) 1010 appendRowFromB(row); 1011 1012 return result; 1013 } 1014 1015 Optional<SmallVector<Fraction, 8>> Simplex::getRationalSample() const { 1016 if (empty) 1017 return {}; 1018 1019 SmallVector<Fraction, 8> sample; 1020 sample.reserve(var.size()); 1021 // Push the sample value for each variable into the vector. 1022 for (const Unknown &u : var) { 1023 if (u.orientation == Orientation::Column) { 1024 // If the variable is in column position, its sample value is zero. 1025 sample.emplace_back(0, 1); 1026 } else { 1027 // If the variable is in row position, its sample value is the 1028 // entry in the constant column divided by the denominator. 1029 int64_t denom = tableau(u.pos, 0); 1030 sample.emplace_back(tableau(u.pos, 1), denom); 1031 } 1032 } 1033 return sample; 1034 } 1035 1036 MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const { 1037 if (empty) 1038 return OptimumKind::Empty; 1039 1040 SmallVector<Fraction, 8> sample; 1041 sample.reserve(var.size()); 1042 // Push the sample value for each variable into the vector. 1043 for (const Unknown &u : var) { 1044 // When the big M parameter is being used, each variable x is represented 1045 // as M + x, so its sample value is finite if and only if it is of the 1046 // form 1*M + c. If the coefficient of M is not one then the sample value 1047 // is infinite, and we return an empty optional. 1048 1049 if (u.orientation == Orientation::Column) { 1050 // If the variable is in column position, the sample value of M + x is 1051 // zero, so x = -M which is unbounded. 1052 return OptimumKind::Unbounded; 1053 } 1054 1055 // If the variable is in row position, its sample value is the 1056 // entry in the constant column divided by the denominator. 1057 int64_t denom = tableau(u.pos, 0); 1058 if (usingBigM) 1059 if (tableau(u.pos, 2) != denom) 1060 return OptimumKind::Unbounded; 1061 sample.emplace_back(tableau(u.pos, 1), denom); 1062 } 1063 return sample; 1064 } 1065 1066 Optional<SmallVector<int64_t, 8>> Simplex::getSamplePointIfIntegral() const { 1067 // If the tableau is empty, no sample point exists. 1068 if (empty) 1069 return {}; 1070 1071 // The value will always exist since the Simplex is non-empty. 1072 SmallVector<Fraction, 8> rationalSample = *getRationalSample(); 1073 SmallVector<int64_t, 8> integerSample; 1074 integerSample.reserve(var.size()); 1075 for (const Fraction &coord : rationalSample) { 1076 // If the sample is non-integral, return None. 1077 if (coord.num % coord.den != 0) 1078 return {}; 1079 integerSample.push_back(coord.num / coord.den); 1080 } 1081 return integerSample; 1082 } 1083 1084 /// Given a simplex for a polytope, construct a new simplex whose variables are 1085 /// identified with a pair of points (x, y) in the original polytope. Supports 1086 /// some operations needed for generalized basis reduction. In what follows, 1087 /// dotProduct(x, y) = x_1 * y_1 + x_2 * y_2 + ... x_n * y_n where n is the 1088 /// dimension of the original polytope. 1089 /// 1090 /// This supports adding equality constraints dotProduct(dir, x - y) == 0. It 1091 /// also supports rolling back this addition, by maintaining a snapshot stack 1092 /// that contains a snapshot of the Simplex's state for each equality, just 1093 /// before that equality was added. 1094 class GBRSimplex { 1095 using Orientation = Simplex::Orientation; 1096 1097 public: 1098 GBRSimplex(const Simplex &originalSimplex) 1099 : simplex(Simplex::makeProduct(originalSimplex, originalSimplex)), 1100 simplexConstraintOffset(simplex.getNumConstraints()) {} 1101 1102 /// Add an equality dotProduct(dir, x - y) == 0. 1103 /// First pushes a snapshot for the current simplex state to the stack so 1104 /// that this can be rolled back later. 1105 void addEqualityForDirection(ArrayRef<int64_t> dir) { 1106 assert( 1107 std::any_of(dir.begin(), dir.end(), [](int64_t x) { return x != 0; }) && 1108 "Direction passed is the zero vector!"); 1109 snapshotStack.push_back(simplex.getSnapshot()); 1110 simplex.addEquality(getCoeffsForDirection(dir)); 1111 } 1112 /// Compute max(dotProduct(dir, x - y)). 1113 Fraction computeWidth(ArrayRef<int64_t> dir) { 1114 MaybeOptimum<Fraction> maybeWidth = 1115 simplex.computeOptimum(Direction::Up, getCoeffsForDirection(dir)); 1116 assert(maybeWidth.isBounded() && "Width should be bounded!"); 1117 return *maybeWidth; 1118 } 1119 1120 /// Compute max(dotProduct(dir, x - y)) and save the dual variables for only 1121 /// the direction equalities to `dual`. 1122 Fraction computeWidthAndDuals(ArrayRef<int64_t> dir, 1123 SmallVectorImpl<int64_t> &dual, 1124 int64_t &dualDenom) { 1125 // We can't just call into computeWidth or computeOptimum since we need to 1126 // access the state of the tableau after computing the optimum, and these 1127 // functions rollback the insertion of the objective function into the 1128 // tableau before returning. We instead add a row for the objective function 1129 // ourselves, call into computeOptimum, compute the duals from the tableau 1130 // state, and finally rollback the addition of the row before returning. 1131 unsigned snap = simplex.getSnapshot(); 1132 unsigned conIndex = simplex.addRow(getCoeffsForDirection(dir)); 1133 unsigned row = simplex.con[conIndex].pos; 1134 MaybeOptimum<Fraction> maybeWidth = 1135 simplex.computeRowOptimum(Simplex::Direction::Up, row); 1136 assert(maybeWidth.isBounded() && "Width should be bounded!"); 1137 dualDenom = simplex.tableau(row, 0); 1138 dual.clear(); 1139 1140 // The increment is i += 2 because equalities are added as two inequalities, 1141 // one positive and one negative. Each iteration processes one equality. 1142 for (unsigned i = simplexConstraintOffset; i < conIndex; i += 2) { 1143 // The dual variable for an inequality in column orientation is the 1144 // negative of its coefficient at the objective row. If the inequality is 1145 // in row orientation, the corresponding dual variable is zero. 1146 // 1147 // We want the dual for the original equality, which corresponds to two 1148 // inequalities: a positive inequality, which has the same coefficients as 1149 // the equality, and a negative equality, which has negated coefficients. 1150 // 1151 // Note that at most one of these inequalities can be in column 1152 // orientation because the column unknowns should form a basis and hence 1153 // must be linearly independent. If the positive inequality is in column 1154 // position, its dual is the dual corresponding to the equality. If the 1155 // negative inequality is in column position, the negation of its dual is 1156 // the dual corresponding to the equality. If neither is in column 1157 // position, then that means that this equality is redundant, and its dual 1158 // is zero. 1159 // 1160 // Note that it is NOT valid to perform pivots during the computation of 1161 // the duals. This entire dual computation must be performed on the same 1162 // tableau configuration. 1163 assert(!(simplex.con[i].orientation == Orientation::Column && 1164 simplex.con[i + 1].orientation == Orientation::Column) && 1165 "Both inequalities for the equality cannot be in column " 1166 "orientation!"); 1167 if (simplex.con[i].orientation == Orientation::Column) 1168 dual.push_back(-simplex.tableau(row, simplex.con[i].pos)); 1169 else if (simplex.con[i + 1].orientation == Orientation::Column) 1170 dual.push_back(simplex.tableau(row, simplex.con[i + 1].pos)); 1171 else 1172 dual.push_back(0); 1173 } 1174 simplex.rollback(snap); 1175 return *maybeWidth; 1176 } 1177 1178 /// Remove the last equality that was added through addEqualityForDirection. 1179 /// 1180 /// We do this by rolling back to the snapshot at the top of the stack, which 1181 /// should be a snapshot taken just before the last equality was added. 1182 void removeLastEquality() { 1183 assert(!snapshotStack.empty() && "Snapshot stack is empty!"); 1184 simplex.rollback(snapshotStack.back()); 1185 snapshotStack.pop_back(); 1186 } 1187 1188 private: 1189 /// Returns coefficients of the expression 'dot_product(dir, x - y)', 1190 /// i.e., dir_1 * x_1 + dir_2 * x_2 + ... + dir_n * x_n 1191 /// - dir_1 * y_1 - dir_2 * y_2 - ... - dir_n * y_n, 1192 /// where n is the dimension of the original polytope. 1193 SmallVector<int64_t, 8> getCoeffsForDirection(ArrayRef<int64_t> dir) { 1194 assert(2 * dir.size() == simplex.getNumVariables() && 1195 "Direction vector has wrong dimensionality"); 1196 SmallVector<int64_t, 8> coeffs(dir.begin(), dir.end()); 1197 coeffs.reserve(2 * dir.size()); 1198 for (int64_t coeff : dir) 1199 coeffs.push_back(-coeff); 1200 coeffs.push_back(0); // constant term 1201 return coeffs; 1202 } 1203 1204 Simplex simplex; 1205 /// The first index of the equality constraints, the index immediately after 1206 /// the last constraint in the initial product simplex. 1207 unsigned simplexConstraintOffset; 1208 /// A stack of snapshots, used for rolling back. 1209 SmallVector<unsigned, 8> snapshotStack; 1210 }; 1211 1212 // Return a + scale*b; 1213 static SmallVector<int64_t, 8> scaleAndAdd(ArrayRef<int64_t> a, int64_t scale, 1214 ArrayRef<int64_t> b) { 1215 assert(a.size() == b.size()); 1216 SmallVector<int64_t, 8> res; 1217 res.reserve(a.size()); 1218 for (unsigned i = 0, e = a.size(); i < e; ++i) 1219 res.push_back(a[i] + scale * b[i]); 1220 return res; 1221 } 1222 1223 /// Reduce the basis to try and find a direction in which the polytope is 1224 /// "thin". This only works for bounded polytopes. 1225 /// 1226 /// This is an implementation of the algorithm described in the paper 1227 /// "An Implementation of Generalized Basis Reduction for Integer Programming" 1228 /// by W. Cook, T. Rutherford, H. E. Scarf, D. Shallcross. 1229 /// 1230 /// Let b_{level}, b_{level + 1}, ... b_n be the current basis. 1231 /// Let width_i(v) = max <v, x - y> where x and y are points in the original 1232 /// polytope such that <b_j, x - y> = 0 is satisfied for all level <= j < i. 1233 /// 1234 /// In every iteration, we first replace b_{i+1} with b_{i+1} + u*b_i, where u 1235 /// is the integer such that width_i(b_{i+1} + u*b_i) is minimized. Let dual_i 1236 /// be the dual variable associated with the constraint <b_i, x - y> = 0 when 1237 /// computing width_{i+1}(b_{i+1}). It can be shown that dual_i is the 1238 /// minimizing value of u, if it were allowed to be fractional. Due to 1239 /// convexity, the minimizing integer value is either floor(dual_i) or 1240 /// ceil(dual_i), so we just need to check which of these gives a lower 1241 /// width_{i+1} value. If dual_i turned out to be an integer, then u = dual_i. 1242 /// 1243 /// Now if width_i(b_{i+1}) < 0.75 * width_i(b_i), we swap b_i and (the new) 1244 /// b_{i + 1} and decrement i (unless i = level, in which case we stay at the 1245 /// same i). Otherwise, we increment i. 1246 /// 1247 /// We keep f values and duals cached and invalidate them when necessary. 1248 /// Whenever possible, we use them instead of recomputing them. We implement the 1249 /// algorithm as follows. 1250 /// 1251 /// In an iteration at i we need to compute: 1252 /// a) width_i(b_{i + 1}) 1253 /// b) width_i(b_i) 1254 /// c) the integer u that minimizes width_i(b_{i + 1} + u*b_i) 1255 /// 1256 /// If width_i(b_i) is not already cached, we compute it. 1257 /// 1258 /// If the duals are not already cached, we compute width_{i+1}(b_{i+1}) and 1259 /// store the duals from this computation. 1260 /// 1261 /// We call updateBasisWithUAndGetFCandidate, which finds the minimizing value 1262 /// of u as explained before, caches the duals from this computation, sets 1263 /// b_{i+1} to b_{i+1} + u*b_i, and returns the new value of width_i(b_{i+1}). 1264 /// 1265 /// Now if width_i(b_{i+1}) < 0.75 * width_i(b_i), we swap b_i and b_{i+1} and 1266 /// decrement i, resulting in the basis 1267 /// ... b_{i - 1}, b_{i + 1} + u*b_i, b_i, b_{i+2}, ... 1268 /// with corresponding f values 1269 /// ... width_{i-1}(b_{i-1}), width_i(b_{i+1} + u*b_i), width_{i+1}(b_i), ... 1270 /// The values up to i - 1 remain unchanged. We have just gotten the middle 1271 /// value from updateBasisWithUAndGetFCandidate, so we can update that in the 1272 /// cache. The value at width_{i+1}(b_i) is unknown, so we evict this value from 1273 /// the cache. The iteration after decrementing needs exactly the duals from the 1274 /// computation of width_i(b_{i + 1} + u*b_i), so we keep these in the cache. 1275 /// 1276 /// When incrementing i, no cached f values get invalidated. However, the cached 1277 /// duals do get invalidated as the duals for the higher levels are different. 1278 void Simplex::reduceBasis(Matrix &basis, unsigned level) { 1279 const Fraction epsilon(3, 4); 1280 1281 if (level == basis.getNumRows() - 1) 1282 return; 1283 1284 GBRSimplex gbrSimplex(*this); 1285 SmallVector<Fraction, 8> width; 1286 SmallVector<int64_t, 8> dual; 1287 int64_t dualDenom; 1288 1289 // Finds the value of u that minimizes width_i(b_{i+1} + u*b_i), caches the 1290 // duals from this computation, sets b_{i+1} to b_{i+1} + u*b_i, and returns 1291 // the new value of width_i(b_{i+1}). 1292 // 1293 // If dual_i is not an integer, the minimizing value must be either 1294 // floor(dual_i) or ceil(dual_i). We compute the expression for both and 1295 // choose the minimizing value. 1296 // 1297 // If dual_i is an integer, we don't need to perform these computations. We 1298 // know that in this case, 1299 // a) u = dual_i. 1300 // b) one can show that dual_j for j < i are the same duals we would have 1301 // gotten from computing width_i(b_{i + 1} + u*b_i), so the correct duals 1302 // are the ones already in the cache. 1303 // c) width_i(b_{i+1} + u*b_i) = min_{alpha} width_i(b_{i+1} + alpha * b_i), 1304 // which 1305 // one can show is equal to width_{i+1}(b_{i+1}). The latter value must 1306 // be in the cache, so we get it from there and return it. 1307 auto updateBasisWithUAndGetFCandidate = [&](unsigned i) -> Fraction { 1308 assert(i < level + dual.size() && "dual_i is not known!"); 1309 1310 int64_t u = floorDiv(dual[i - level], dualDenom); 1311 basis.addToRow(i, i + 1, u); 1312 if (dual[i - level] % dualDenom != 0) { 1313 SmallVector<int64_t, 8> candidateDual[2]; 1314 int64_t candidateDualDenom[2]; 1315 Fraction widthI[2]; 1316 1317 // Initially u is floor(dual) and basis reflects this. 1318 widthI[0] = gbrSimplex.computeWidthAndDuals( 1319 basis.getRow(i + 1), candidateDual[0], candidateDualDenom[0]); 1320 1321 // Now try ceil(dual), i.e. floor(dual) + 1. 1322 ++u; 1323 basis.addToRow(i, i + 1, 1); 1324 widthI[1] = gbrSimplex.computeWidthAndDuals( 1325 basis.getRow(i + 1), candidateDual[1], candidateDualDenom[1]); 1326 1327 unsigned j = widthI[0] < widthI[1] ? 0 : 1; 1328 if (j == 0) 1329 // Subtract 1 to go from u = ceil(dual) back to floor(dual). 1330 basis.addToRow(i, i + 1, -1); 1331 1332 // width_i(b{i+1} + u*b_i) should be minimized at our value of u. 1333 // We assert that this holds by checking that the values of width_i at 1334 // u - 1 and u + 1 are greater than or equal to the value at u. If the 1335 // width is lesser at either of the adjacent values, then our computed 1336 // value of u is clearly not the minimizer. Otherwise by convexity the 1337 // computed value of u is really the minimizer. 1338 1339 // Check the value at u - 1. 1340 assert(gbrSimplex.computeWidth(scaleAndAdd( 1341 basis.getRow(i + 1), -1, basis.getRow(i))) >= widthI[j] && 1342 "Computed u value does not minimize the width!"); 1343 // Check the value at u + 1. 1344 assert(gbrSimplex.computeWidth(scaleAndAdd( 1345 basis.getRow(i + 1), +1, basis.getRow(i))) >= widthI[j] && 1346 "Computed u value does not minimize the width!"); 1347 1348 dual = std::move(candidateDual[j]); 1349 dualDenom = candidateDualDenom[j]; 1350 return widthI[j]; 1351 } 1352 1353 assert(i + 1 - level < width.size() && "width_{i+1} wasn't saved"); 1354 // f_i(b_{i+1} + dual*b_i) == width_{i+1}(b_{i+1}) when `dual` minimizes the 1355 // LHS. (note: the basis has already been updated, so b_{i+1} + dual*b_i in 1356 // the above expression is equal to basis.getRow(i+1) below.) 1357 assert(gbrSimplex.computeWidth(basis.getRow(i + 1)) == 1358 width[i + 1 - level]); 1359 return width[i + 1 - level]; 1360 }; 1361 1362 // In the ith iteration of the loop, gbrSimplex has constraints for directions 1363 // from `level` to i - 1. 1364 unsigned i = level; 1365 while (i < basis.getNumRows() - 1) { 1366 if (i >= level + width.size()) { 1367 // We don't even know the value of f_i(b_i), so let's find that first. 1368 // We have to do this first since later we assume that width already 1369 // contains values up to and including i. 1370 1371 assert((i == 0 || i - 1 < level + width.size()) && 1372 "We are at level i but we don't know the value of width_{i-1}"); 1373 1374 // We don't actually use these duals at all, but it doesn't matter 1375 // because this case should only occur when i is level, and there are no 1376 // duals in that case anyway. 1377 assert(i == level && "This case should only occur when i == level"); 1378 width.push_back( 1379 gbrSimplex.computeWidthAndDuals(basis.getRow(i), dual, dualDenom)); 1380 } 1381 1382 if (i >= level + dual.size()) { 1383 assert(i + 1 >= level + width.size() && 1384 "We don't know dual_i but we know width_{i+1}"); 1385 // We don't know dual for our level, so let's find it. 1386 gbrSimplex.addEqualityForDirection(basis.getRow(i)); 1387 width.push_back(gbrSimplex.computeWidthAndDuals(basis.getRow(i + 1), dual, 1388 dualDenom)); 1389 gbrSimplex.removeLastEquality(); 1390 } 1391 1392 // This variable stores width_i(b_{i+1} + u*b_i). 1393 Fraction widthICandidate = updateBasisWithUAndGetFCandidate(i); 1394 if (widthICandidate < epsilon * width[i - level]) { 1395 basis.swapRows(i, i + 1); 1396 width[i - level] = widthICandidate; 1397 // The values of width_{i+1}(b_{i+1}) and higher may change after the 1398 // swap, so we remove the cached values here. 1399 width.resize(i - level + 1); 1400 if (i == level) { 1401 dual.clear(); 1402 continue; 1403 } 1404 1405 gbrSimplex.removeLastEquality(); 1406 i--; 1407 continue; 1408 } 1409 1410 // Invalidate duals since the higher level needs to recompute its own duals. 1411 dual.clear(); 1412 gbrSimplex.addEqualityForDirection(basis.getRow(i)); 1413 i++; 1414 } 1415 } 1416 1417 /// Search for an integer sample point using a branch and bound algorithm. 1418 /// 1419 /// Each row in the basis matrix is a vector, and the set of basis vectors 1420 /// should span the space. Initially this is the identity matrix, 1421 /// i.e., the basis vectors are just the variables. 1422 /// 1423 /// In every level, a value is assigned to the level-th basis vector, as 1424 /// follows. Compute the minimum and maximum rational values of this direction. 1425 /// If only one integer point lies in this range, constrain the variable to 1426 /// have this value and recurse to the next variable. 1427 /// 1428 /// If the range has multiple values, perform generalized basis reduction via 1429 /// reduceBasis and then compute the bounds again. Now we try constraining 1430 /// this direction in the first value in this range and "recurse" to the next 1431 /// level. If we fail to find a sample, we try assigning the direction the next 1432 /// value in this range, and so on. 1433 /// 1434 /// If no integer sample is found from any of the assignments, or if the range 1435 /// contains no integer value, then of course the polytope is empty for the 1436 /// current assignment of the values in previous levels, so we return to 1437 /// the previous level. 1438 /// 1439 /// If we reach the last level where all the variables have been assigned values 1440 /// already, then we simply return the current sample point if it is integral, 1441 /// and go back to the previous level otherwise. 1442 /// 1443 /// To avoid potentially arbitrarily large recursion depths leading to stack 1444 /// overflows, this algorithm is implemented iteratively. 1445 Optional<SmallVector<int64_t, 8>> Simplex::findIntegerSample() { 1446 if (empty) 1447 return {}; 1448 1449 unsigned nDims = var.size(); 1450 Matrix basis = Matrix::identity(nDims); 1451 1452 unsigned level = 0; 1453 // The snapshot just before constraining a direction to a value at each level. 1454 SmallVector<unsigned, 8> snapshotStack; 1455 // The maximum value in the range of the direction for each level. 1456 SmallVector<int64_t, 8> upperBoundStack; 1457 // The next value to try constraining the basis vector to at each level. 1458 SmallVector<int64_t, 8> nextValueStack; 1459 1460 snapshotStack.reserve(basis.getNumRows()); 1461 upperBoundStack.reserve(basis.getNumRows()); 1462 nextValueStack.reserve(basis.getNumRows()); 1463 while (level != -1u) { 1464 if (level == basis.getNumRows()) { 1465 // We've assigned values to all variables. Return if we have a sample, 1466 // or go back up to the previous level otherwise. 1467 if (auto maybeSample = getSamplePointIfIntegral()) 1468 return maybeSample; 1469 level--; 1470 continue; 1471 } 1472 1473 if (level >= upperBoundStack.size()) { 1474 // We haven't populated the stack values for this level yet, so we have 1475 // just come down a level ("recursed"). Find the lower and upper bounds. 1476 // If there is more than one integer point in the range, perform 1477 // generalized basis reduction. 1478 SmallVector<int64_t, 8> basisCoeffs = 1479 llvm::to_vector<8>(basis.getRow(level)); 1480 basisCoeffs.push_back(0); 1481 1482 MaybeOptimum<int64_t> minRoundedUp, maxRoundedDown; 1483 std::tie(minRoundedUp, maxRoundedDown) = 1484 computeIntegerBounds(basisCoeffs); 1485 1486 // We don't have any integer values in the range. 1487 // Pop the stack and return up a level. 1488 if (minRoundedUp.isEmpty() || maxRoundedDown.isEmpty()) { 1489 assert((minRoundedUp.isEmpty() && maxRoundedDown.isEmpty()) && 1490 "If one bound is empty, both should be."); 1491 snapshotStack.pop_back(); 1492 nextValueStack.pop_back(); 1493 upperBoundStack.pop_back(); 1494 level--; 1495 continue; 1496 } 1497 1498 // We already checked the empty case above. 1499 assert((minRoundedUp.isBounded() && maxRoundedDown.isBounded()) && 1500 "Polyhedron should be bounded!"); 1501 1502 // Heuristic: if the sample point is integral at this point, just return 1503 // it. 1504 if (auto maybeSample = getSamplePointIfIntegral()) 1505 return *maybeSample; 1506 1507 if (*minRoundedUp < *maxRoundedDown) { 1508 reduceBasis(basis, level); 1509 basisCoeffs = llvm::to_vector<8>(basis.getRow(level)); 1510 basisCoeffs.push_back(0); 1511 std::tie(minRoundedUp, maxRoundedDown) = 1512 computeIntegerBounds(basisCoeffs); 1513 } 1514 1515 snapshotStack.push_back(getSnapshot()); 1516 // The smallest value in the range is the next value to try. 1517 // The values in the optionals are guaranteed to exist since we know the 1518 // polytope is bounded. 1519 nextValueStack.push_back(*minRoundedUp); 1520 upperBoundStack.push_back(*maxRoundedDown); 1521 } 1522 1523 assert((snapshotStack.size() - 1 == level && 1524 nextValueStack.size() - 1 == level && 1525 upperBoundStack.size() - 1 == level) && 1526 "Mismatched variable stack sizes!"); 1527 1528 // Whether we "recursed" or "returned" from a lower level, we rollback 1529 // to the snapshot of the starting state at this level. (in the "recursed" 1530 // case this has no effect) 1531 rollback(snapshotStack.back()); 1532 int64_t nextValue = nextValueStack.back(); 1533 nextValueStack.back()++; 1534 if (nextValue > upperBoundStack.back()) { 1535 // We have exhausted the range and found no solution. Pop the stack and 1536 // return up a level. 1537 snapshotStack.pop_back(); 1538 nextValueStack.pop_back(); 1539 upperBoundStack.pop_back(); 1540 level--; 1541 continue; 1542 } 1543 1544 // Try the next value in the range and "recurse" into the next level. 1545 SmallVector<int64_t, 8> basisCoeffs(basis.getRow(level).begin(), 1546 basis.getRow(level).end()); 1547 basisCoeffs.push_back(-nextValue); 1548 addEquality(basisCoeffs); 1549 level++; 1550 } 1551 1552 return {}; 1553 } 1554 1555 /// Compute the minimum and maximum integer values the expression can take. We 1556 /// compute each separately. 1557 std::pair<MaybeOptimum<int64_t>, MaybeOptimum<int64_t>> 1558 Simplex::computeIntegerBounds(ArrayRef<int64_t> coeffs) { 1559 MaybeOptimum<int64_t> minRoundedUp( 1560 computeOptimum(Simplex::Direction::Down, coeffs).map(ceil)); 1561 MaybeOptimum<int64_t> maxRoundedDown( 1562 computeOptimum(Simplex::Direction::Up, coeffs).map(floor)); 1563 return {minRoundedUp, maxRoundedDown}; 1564 } 1565 1566 void SimplexBase::print(raw_ostream &os) const { 1567 os << "rows = " << nRow << ", columns = " << nCol << "\n"; 1568 if (empty) 1569 os << "Simplex marked empty!\n"; 1570 os << "var: "; 1571 for (unsigned i = 0; i < var.size(); ++i) { 1572 if (i > 0) 1573 os << ", "; 1574 var[i].print(os); 1575 } 1576 os << "\ncon: "; 1577 for (unsigned i = 0; i < con.size(); ++i) { 1578 if (i > 0) 1579 os << ", "; 1580 con[i].print(os); 1581 } 1582 os << '\n'; 1583 for (unsigned row = 0; row < nRow; ++row) { 1584 if (row > 0) 1585 os << ", "; 1586 os << "r" << row << ": " << rowUnknown[row]; 1587 } 1588 os << '\n'; 1589 os << "c0: denom, c1: const"; 1590 for (unsigned col = 2; col < nCol; ++col) 1591 os << ", c" << col << ": " << colUnknown[col]; 1592 os << '\n'; 1593 for (unsigned row = 0; row < nRow; ++row) { 1594 for (unsigned col = 0; col < nCol; ++col) 1595 os << tableau(row, col) << '\t'; 1596 os << '\n'; 1597 } 1598 os << '\n'; 1599 } 1600 1601 void SimplexBase::dump() const { print(llvm::errs()); } 1602 1603 bool Simplex::isRationalSubsetOf(const IntegerPolyhedron &poly) { 1604 if (isEmpty()) 1605 return true; 1606 1607 for (unsigned i = 0, e = poly.getNumInequalities(); i < e; ++i) 1608 if (findIneqType(poly.getInequality(i)) != IneqType::Redundant) 1609 return false; 1610 1611 for (unsigned i = 0, e = poly.getNumEqualities(); i < e; ++i) 1612 if (!isRedundantEquality(poly.getEquality(i))) 1613 return false; 1614 1615 return true; 1616 } 1617 1618 /// Returns the type of the inequality with coefficients `coeffs`. 1619 /// Possible types are: 1620 /// Redundant The inequality is satisfied by all points in the polytope 1621 /// Cut The inequality is satisfied by some points, but not by others 1622 /// Separate The inequality is not satisfied by any point 1623 /// 1624 /// Internally, this computes the minimum and the maximum the inequality with 1625 /// coefficients `coeffs` can take. If the minimum is >= 0, the inequality holds 1626 /// for all points in the polytope, so it is redundant. If the minimum is <= 0 1627 /// and the maximum is >= 0, the points in between the minimum and the 1628 /// inequality do not satisfy it, the points in between the inequality and the 1629 /// maximum satisfy it. Hence, it is a cut inequality. If both are < 0, no 1630 /// points of the polytope satisfy the inequality, which means it is a separate 1631 /// inequality. 1632 Simplex::IneqType Simplex::findIneqType(ArrayRef<int64_t> coeffs) { 1633 MaybeOptimum<Fraction> minimum = computeOptimum(Direction::Down, coeffs); 1634 if (minimum.isBounded() && *minimum >= Fraction(0, 1)) { 1635 return IneqType::Redundant; 1636 } 1637 MaybeOptimum<Fraction> maximum = computeOptimum(Direction::Up, coeffs); 1638 if ((!minimum.isBounded() || *minimum <= Fraction(0, 1)) && 1639 (!maximum.isBounded() || *maximum >= Fraction(0, 1))) { 1640 return IneqType::Cut; 1641 } 1642 return IneqType::Separate; 1643 } 1644 1645 /// Checks whether the type of the inequality with coefficients `coeffs` 1646 /// is Redundant. 1647 bool Simplex::isRedundantInequality(ArrayRef<int64_t> coeffs) { 1648 assert(!empty && 1649 "It is not meaningful to ask about redundancy in an empty set!"); 1650 return findIneqType(coeffs) == IneqType::Redundant; 1651 } 1652 1653 /// Check whether the equality given by `coeffs == 0` is redundant given 1654 /// the existing constraints. This is redundant when `coeffs` is already 1655 /// always zero under the existing constraints. `coeffs` is always zero 1656 /// when the minimum and maximum value that `coeffs` can take are both zero. 1657 bool Simplex::isRedundantEquality(ArrayRef<int64_t> coeffs) { 1658 assert(!empty && 1659 "It is not meaningful to ask about redundancy in an empty set!"); 1660 MaybeOptimum<Fraction> minimum = computeOptimum(Direction::Down, coeffs); 1661 MaybeOptimum<Fraction> maximum = computeOptimum(Direction::Up, coeffs); 1662 assert((!minimum.isEmpty() && !maximum.isEmpty()) && 1663 "Optima should be non-empty for a non-empty set"); 1664 return minimum.isBounded() && maximum.isBounded() && 1665 *maximum == Fraction(0, 1) && *minimum == Fraction(0, 1); 1666 } 1667 1668 } // namespace mlir 1669