|
23 | 23 | #include "mlir/Support/LogicalResult.h" |
24 | 24 | #include "llvm/ADT/ArrayRef.h" |
25 | 25 | #include "llvm/ADT/Optional.h" |
| 26 | +#include "llvm/ADT/SmallBitVector.h" |
26 | 27 | #include "llvm/ADT/SmallVector.h" |
27 | 28 | #include "llvm/Support/StringSaver.h" |
28 | 29 | #include "llvm/Support/raw_ostream.h" |
@@ -210,14 +211,18 @@ class SimplexBase { |
210 | 211 |
|
211 | 212 | protected: |
212 | 213 | /// Construct a SimplexBase with the specified number of variables and fixed |
213 | | - /// columns. |
| 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`. |
214 | 218 | /// |
215 | 219 | /// For example, Simplex uses two fixed columns: the denominator and the |
216 | 220 | /// constant term, whereas LexSimplex has an extra fixed column for the |
217 | 221 | /// so-called big M parameter. For more information see the documentation for |
218 | 222 | /// LexSimplex. |
219 | | - SimplexBase(unsigned nVar, bool mustUseBigM, unsigned symbolOffset, |
220 | | - unsigned nSymbol); |
| 223 | + SimplexBase(unsigned nVar, bool mustUseBigM); |
| 224 | + SimplexBase(unsigned nVar, bool mustUseBigM, |
| 225 | + const llvm::SmallBitVector &isSymbol); |
221 | 226 |
|
222 | 227 | enum class Orientation { Row, Column }; |
223 | 228 |
|
@@ -422,12 +427,16 @@ class LexSimplexBase : public SimplexBase { |
422 | 427 | unsigned getSnapshot() { return SimplexBase::getSnapshotBasis(); } |
423 | 428 |
|
424 | 429 | protected: |
425 | | - LexSimplexBase(unsigned nVar, unsigned symbolOffset, unsigned nSymbol) |
426 | | - : SimplexBase(nVar, /*mustUseBigM=*/true, symbolOffset, nSymbol) {} |
| 430 | + LexSimplexBase(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/true) {} |
| 431 | + LexSimplexBase(unsigned nVar, const llvm::SmallBitVector &isSymbol) |
| 432 | + : SimplexBase(nVar, /*mustUseBigM=*/true, isSymbol) {} |
427 | 433 | explicit LexSimplexBase(const IntegerRelation &constraints) |
428 | | - : LexSimplexBase(constraints.getNumVars(), |
429 | | - constraints.getVarKindOffset(VarKind::Symbol), |
430 | | - constraints.getNumSymbolVars()) { |
| 434 | + : LexSimplexBase(constraints.getNumVars()) { |
| 435 | + intersectIntegerRelation(constraints); |
| 436 | + } |
| 437 | + explicit LexSimplexBase(const IntegerRelation &constraints, |
| 438 | + const llvm::SmallBitVector &isSymbol) |
| 439 | + : LexSimplexBase(constraints.getNumVars(), isSymbol) { |
431 | 440 | intersectIntegerRelation(constraints); |
432 | 441 | } |
433 | 442 |
|
@@ -470,13 +479,12 @@ class LexSimplexBase : public SimplexBase { |
470 | 479 | /// provides support for integer-exact redundancy and separateness checks. |
471 | 480 | class LexSimplex : public LexSimplexBase { |
472 | 481 | public: |
473 | | - explicit LexSimplex(unsigned nVar) |
474 | | - : LexSimplexBase(nVar, /*symbolOffset=*/0, /*nSymbol=*/0) {} |
| 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. |
475 | 486 | explicit LexSimplex(const IntegerRelation &constraints) |
476 | | - : LexSimplexBase(constraints) { |
477 | | - assert(constraints.getNumSymbolVars() == 0 && |
478 | | - "LexSimplex does not support symbols!"); |
479 | | - } |
| 487 | + : LexSimplexBase(constraints) {} |
480 | 488 |
|
481 | 489 | /// Return the lexicographically minimum rational solution to the constraints. |
482 | 490 | MaybeOptimum<SmallVector<Fraction, 8>> findRationalLexMin(); |
@@ -521,10 +529,9 @@ class LexSimplex : public LexSimplexBase { |
521 | 529 |
|
522 | 530 | /// Represents the result of a symbolic lexicographic minimization computation. |
523 | 531 | struct SymbolicLexMin { |
524 | | - SymbolicLexMin(unsigned nSymbols, unsigned nNonSymbols) |
525 | | - : lexmin(PresburgerSpace::getSetSpace(nSymbols), nNonSymbols), |
526 | | - unboundedDomain( |
527 | | - PresburgerSet::getEmpty(PresburgerSpace::getSetSpace(nSymbols))) {} |
| 532 | + SymbolicLexMin(const PresburgerSpace &domainSpace, unsigned numOutputs) |
| 533 | + : lexmin(domainSpace, numOutputs), |
| 534 | + unboundedDomain(PresburgerSet::getEmpty(domainSpace)) {} |
528 | 535 |
|
529 | 536 | /// This maps assignments of symbols to the corresponding lexmin. |
530 | 537 | /// Takes no value when no integer sample exists for the assignment or if the |
@@ -569,30 +576,40 @@ class SymbolicLexSimplex : public LexSimplexBase { |
569 | 576 | /// `constraints` is the set for which the symbolic lexmin will be computed. |
570 | 577 | /// `symbolDomain` is the set of values of the symbols for which the lexmin |
571 | 578 | /// will be computed. `symbolDomain` should have a dim var for every symbol in |
572 | | - /// `constraints`, and no other vars. |
| 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. |
573 | 584 | SymbolicLexSimplex(const IntegerRelation &constraints, |
574 | | - const IntegerPolyhedron &symbolDomain) |
575 | | - : SymbolicLexSimplex(constraints, |
576 | | - constraints.getVarKindOffset(VarKind::Symbol), |
577 | | - symbolDomain) { |
578 | | - assert(constraints.getNumSymbolVars() == symbolDomain.getNumVars()); |
| 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!"); |
579 | 593 | } |
580 | 594 |
|
581 | | - /// An overload to select some other subrange of ids as symbols for lexmin. |
| 595 | + /// An overload to select some subrange of ids as symbols for lexmin. |
582 | 596 | /// The symbol ids are the range of ids with absolute index |
583 | 597 | /// [symbolOffset, symbolOffset + symbolDomain.getNumVars()) |
584 | | - /// symbolDomain should only have dim ids. |
585 | 598 | SymbolicLexSimplex(const IntegerRelation &constraints, unsigned symbolOffset, |
586 | 599 | const IntegerPolyhedron &symbolDomain) |
587 | | - : LexSimplexBase(/*nVar=*/constraints.getNumVars(), symbolOffset, |
588 | | - symbolDomain.getNumVars()), |
589 | | - domainPoly(symbolDomain), domainSimplex(symbolDomain) { |
590 | | - // TODO consider supporting this case. It amounts |
591 | | - // to just returning the input constraints. |
592 | | - assert(domainPoly.getNumVars() > 0 && |
593 | | - "there must be some non-symbols to optimize!"); |
594 | | - assert(domainPoly.getNumVars() == domainPoly.getNumDimVars()); |
595 | | - intersectIntegerRelation(constraints); |
| 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. |
| 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!"); |
596 | 613 | } |
597 | 614 |
|
598 | 615 | /// The lexmin will be stored as a function `lexmin` from symbols to |
@@ -678,9 +695,7 @@ class Simplex : public SimplexBase { |
678 | 695 | enum class Direction { Up, Down }; |
679 | 696 |
|
680 | 697 | Simplex() = delete; |
681 | | - explicit Simplex(unsigned nVar) |
682 | | - : SimplexBase(nVar, /*mustUseBigM=*/false, /*symbolOffset=*/0, |
683 | | - /*nSymbol=*/0) {} |
| 698 | + explicit Simplex(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/false) {} |
684 | 699 | explicit Simplex(const IntegerRelation &constraints) |
685 | 700 | : Simplex(constraints.getNumVars()) { |
686 | 701 | intersectIntegerRelation(constraints); |
|
0 commit comments