MLIR 24.0.0git
Simplex.h
Go to the documentation of this file.
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
23#include "llvm/ADT/SmallBitVector.h"
24#include <optional>
25
26namespace mlir {
27namespace presburger {
28
29class GBRSimplex;
30
31/// The Simplex class implements a version of the Simplex and Generalized Basis
32/// Reduction algorithms, which can perform analysis of integer sets with affine
33/// inequalities and equalities. A Simplex can be constructed
34/// by specifying the dimensionality of the set. It supports adding affine
35/// inequalities and equalities, and can perform emptiness checks, i.e., it can
36/// find a solution to the set of constraints if one exists, or say that the
37/// set is empty if no solution exists. Furthermore, it can find a subset of
38/// these constraints that are redundant, i.e. a subset of constraints that
39/// doesn't constrain the affine set further after adding the non-redundant
40/// constraints. The LexSimplex class provides support for computing the
41/// lexicographic minimum of an IntegerRelation. The SymbolicLexOpt class
42/// provides support for computing symbolic lexicographic minimums. All of these
43/// classes can be constructed from an IntegerRelation, and all inherit common
44/// functionality from SimplexBase.
45///
46/// The implementations of the Simplex and SimplexBase classes, other than the
47/// functionality for obtaining an integer sample, are based on the paper
48/// "Simplify: A Theorem Prover for Program Checking"
49/// by D. Detlefs, G. Nelson, J. B. Saxe.
50///
51/// We define variables, constraints, and unknowns. Consider the example of a
52/// two-dimensional set defined by 1 + 2x + 3y >= 0 and 2x - 3y >= 0. Here,
53/// x, y, are variables while 1 + 2x + 3y >= 0, 2x - 3y >= 0 are constraints.
54/// Unknowns are either variables or constraints, i.e., x, y, 1 + 2x + 3y >= 0,
55/// 2x - 3y >= 0 are all unknowns.
56///
57/// The implementation involves a matrix called a tableau, which can be thought
58/// of as a 2D matrix of rational numbers having number of rows equal to the
59/// number of constraints and number of columns equal to one plus the number of
60/// variables. In our implementation, instead of storing rational numbers, we
61/// store a common denominator for each row, so it is in fact a matrix of
62/// integers with number of rows equal to number of constraints and number of
63/// columns equal to _two_ plus the number of variables. For example, instead of
64/// storing a row of three rationals [1/2, 2/3, 3], we would store [6, 3, 4, 18]
65/// since 3/6 = 1/2, 4/6 = 2/3, and 18/6 = 3.
66///
67/// Every row and column except the first and second columns is associated with
68/// an unknown and every unknown is associated with a row or column. An unknown
69/// associated with a row or column is said to be in row or column orientation
70/// respectively. As described above, the first column is the common
71/// denominator. The second column represents the constant term, explained in
72/// more detail below. These two are _fixed columns_; they always retain their
73/// position as the first and second columns. Additionally, LexSimplexBase
74/// stores a so-call big M parameter (explained below) in the third column, so
75/// LexSimplexBase has three fixed columns. Finally, SymbolicLexSimplex has
76/// `nSymbol` variables designated as symbols. These occupy the next `nSymbol`
77/// columns, viz. the columns [3, 3 + nSymbol). For more information on symbols,
78/// see LexSimplexBase and SymbolicLexSimplex.
79///
80/// LexSimplexBase does not directly support variables which can be negative, so
81/// we introduce the so-called big M parameter, an artificial variable that is
82/// considered to have an arbitrarily large value. We then transform the
83/// variables, say x, y, z, ... to M, M + x, M + y, M + z. Since M has been
84/// added to these variables, they are now known to have non-negative values.
85/// For more details, see the documentation for LexSimplexBase. The big M
86/// parameter is not considered a real unknown and is not stored in the `var`
87/// data structure; rather the tableau just has an extra fixed column for it
88/// just like the constant term.
89///
90/// The vectors var and con store information about the variables and
91/// constraints respectively, namely, whether they are in row or column
92/// position, which row or column they are associated with, and whether they
93/// correspond to a variable or a constraint.
94///
95/// An unknown is addressed by its index. If the index i is non-negative, then
96/// the variable var[i] is being addressed. If the index i is negative, then
97/// the constraint con[~i] is being addressed. Effectively this maps
98/// 0 -> var[0], 1 -> var[1], -1 -> con[0], -2 -> con[1], etc. rowUnknown[r] and
99/// colUnknown[c] are the indexes of the unknowns associated with row r and
100/// column c, respectively.
101///
102/// The unknowns in column position are together called the basis. Initially the
103/// basis is the set of variables -- in our example above, the initial basis is
104/// x, y.
105///
106/// The unknowns in row position are represented in terms of the basis unknowns.
107/// If the basis unknowns are u_1, u_2, ... u_m, and a row in the tableau is
108/// d, c, a_1, a_2, ... a_m, this represents the unknown for that row as
109/// (c + a_1*u_1 + a_2*u_2 + ... + a_m*u_m)/d. In our running example, if the
110/// basis is the initial basis of x, y, then the constraint 1 + 2x + 3y >= 0
111/// would be represented by the row [1, 1, 2, 3].
112///
113/// The association of unknowns to rows and columns can be changed by a process
114/// called pivoting, where a row unknown and a column unknown exchange places
115/// and the remaining row variables' representation is changed accordingly
116/// by eliminating the old column unknown in favour of the new column unknown.
117/// If we had pivoted the column for x with the row for 2x - 3y >= 0,
118/// the new row for x would be [2, 1, 3] since x = (1*(2x - 3y) + 3*y)/2.
119/// See the documentation for the pivot member function for details.
120///
121/// The association of unknowns to rows and columns is called the _tableau
122/// configuration_. The _sample value_ of an unknown in a particular tableau
123/// configuration is its value if all the column unknowns were set to zero.
124/// Concretely, for unknowns in column position the sample value is zero; when
125/// the big M parameter is not used, for unknowns in row position the sample
126/// value is the constant term divided by the common denominator. When the big M
127/// parameter is used, if d is the denominator, p is the big M coefficient, and
128/// c is the constant term, then the sample value is (p*M + c)/d. Since M is
129/// considered to be positive infinity, this is positive (negative) infinity
130/// when p is positive or negative, and c/d when p is zero.
131///
132/// The tableau configuration is called _consistent_ if the sample value of all
133/// restricted unknowns is non-negative. Initially there are no constraints, and
134/// the tableau is consistent. When a new constraint is added, its sample value
135/// in the current tableau configuration may be negative. In that case, we try
136/// to find a series of pivots to bring us to a consistent tableau
137/// configuration, i.e. we try to make the new constraint's sample value
138/// non-negative without making that of any other constraints negative. (See
139/// findPivot and findPivotRow for details.) If this is not possible, then the
140/// set of constraints is mutually contradictory and the tableau is marked
141/// _empty_, which means the set of constraints has no solution.
142///
143/// This SimplexBase class also supports taking snapshots of the current state
144/// and rolling back to prior snapshots. This works by maintaining an undo log
145/// of operations. Snapshots are just pointers to a particular location in the
146/// log, and rolling back to a snapshot is done by reverting each log entry's
147/// operation from the end until we reach the snapshot's location. SimplexBase
148/// also supports taking a snapshot including the exact set of basis unknowns;
149/// if this functionality is used, then on rolling back the exact basis will
150/// also be restored. This is used by LexSimplexBase because the lex algorithm,
151/// unlike `Simplex`, is sensitive to the exact basis used at a point.
153public:
154 SimplexBase() = delete;
155 virtual ~SimplexBase() = default;
156
157 /// Returns true if the tableau is empty (has conflicting constraints),
158 /// false otherwise.
159 bool isEmpty() const;
160
161 /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
162 /// is the current number of variables, then the corresponding inequality is
163 /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0.
164 virtual void addInequality(ArrayRef<DynamicAPInt> coeffs) = 0;
165
166 /// Returns the number of variables in the tableau.
167 unsigned getNumVariables() const;
168
169 /// Returns the number of constraints in the tableau.
170 unsigned getNumConstraints() const;
171
172 /// Add an equality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
173 /// is the current number of variables, then the corresponding equality is
174 /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} == 0.
176
177 /// Add new variables to the end of the list of variables.
178 void appendVariable(unsigned count = 1);
179
180 /// Append a new variable to the simplex and constrain it such that its only
181 /// integer value is the floor div of `coeffs` and `denom`.
182 ///
183 /// `denom` must be positive.
185 const DynamicAPInt &denom);
186
187 /// Mark the tableau as being empty.
188 void markEmpty();
189
190 /// Get a snapshot of the current state. This is used for rolling back.
191 /// The same basis will not necessarily be restored on rolling back.
192 /// The snapshot only captures the set of variables and constraints present
193 /// in the Simplex.
194 unsigned getSnapshot() const;
195
196 /// Get a snapshot of the current state including the basis. When rolling
197 /// back, the exact basis will be restored.
198 unsigned getSnapshotBasis();
199
200 /// Rollback to a snapshot. This invalidates all later snapshots.
201 void rollback(unsigned snapshot);
202
203 /// Add all the constraints from the given IntegerRelation.
205
206 /// Print the tableau's internal state.
207 void print(raw_ostream &os) const;
208#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
209 LLVM_DUMP_METHOD void dump() const;
210#endif
211
212protected:
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)
239 : pos(oPos), orientation(oOrientation), restricted(oRestricted),
240 isSymbol(oIsSymbol) {}
241 unsigned pos;
243 bool restricted : 1;
244 bool isSymbol : 1;
245
246 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 std::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.
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<DynamicAPInt> 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.
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.
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.
323 unsigned getNumFixedCols() const { return usingBigM ? 3u : 2u; }
324 unsigned getNumRows() const { return tableau.getNumRows(); }
325 unsigned getNumColumns() const { return tableau.getNumColumns(); }
326
327 /// Stores whether or not a big M column is present in the tableau.
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.
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.
347
348 /// Holds a vector of bases. The ith saved basis is the basis that should be
349 /// restored when processing the ith occurrence of UndoLogEntry::RestoreBasis
350 /// in undoLog. This is used by getSnapshotBasis.
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.
361
362 /// These hold information about each unknown.
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 artificial 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!)
415public:
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<DynamicAPInt> coeffs) final;
425
426 /// Get a snapshot of the current state. This is used for rolling back.
428
429protected:
430 LexSimplexBase(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/true) {}
431 LexSimplexBase(unsigned nVar, const llvm::SmallBitVector &isSymbol)
432 : SimplexBase(nVar, /*mustUseBigM=*/true, isSymbol) {}
433 explicit LexSimplexBase(const IntegerRelation &constraints)
434 : LexSimplexBase(constraints.getNumVars()) {
435 intersectIntegerRelation(constraints);
436 }
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.
481public:
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.
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.
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<DynamicAPInt> coeffs);
504 bool isRedundantInequality(ArrayRef<DynamicAPInt> coeffs);
505
506private:
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 std::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 std::optional<unsigned> maybeGetNonIntegralVarRow() const;
528};
529
530/// Represents the result of a symbolic lexicographic optimization computation.
533 : lexopt(space),
534 unboundedDomain(PresburgerSet::getEmpty(space.getDomainSpace())) {}
535
536 /// This maps assignments of symbols to the corresponding lexopt.
537 /// Takes no value when no integer sample exists for the assignment or if the
538 /// lexopt is unbounded.
540 /// Contains all assignments to the symbols that made the lexopt unbounded.
541 /// Note that the symbols of the input set to the symbolic lexopt are dims
542 /// of this PrebsurgerSet.
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` corresponding 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.
575public:
576 /// `constraints` is the set for which the symbolic lexopt will be computed.
577 /// `symbolDomain` is the set of values of the symbols for which the lexopt
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 SymbolicLexOpt's space will be compatible with that of
583 /// symbolDomain.
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 lexopt.
596 /// The symbol ids are the range of ids with absolute index
597 /// [symbolOffset, symbolOffset + symbolDomain.getNumVars())
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 lexopt.
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 `lexopt` 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 SymbolicLexOpt computeSymbolicIntegerLexMin();
624
625private:
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 std::optional<unsigned> maybeGetAlwaysViolatedRow();
635
636 /// Get a row corresponding to a variable with non-integral sample value, if
637 /// one exists.
638 std::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<DynamicAPInt, 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<DynamicAPInt, 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(SymbolicLexOpt &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.
693class Simplex : public SimplexBase {
694public:
695 enum class Direction { Up, Down };
696
697 Simplex() = delete;
698 explicit Simplex(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/false) {}
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<DynamicAPInt> 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.
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);
760 void detectRedundant(unsigned offset) {
761 assert(offset <= con.size() && "invalid offset!");
762 detectRedundant(offset, con.size() - offset);
763 }
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<DynamicAPInt>, MaybeOptimum<DynamicAPInt>>
770 computeIntegerBounds(ArrayRef<DynamicAPInt> coeffs);
771
772 /// Check if the simplex takes only one rational value along the
773 /// direction of `coeffs`.
774 ///
775 /// `this` must be nonempty.
776 bool isFlatAlong(ArrayRef<DynamicAPInt> coeffs);
777
778 /// Returns true if the polytope is unbounded, i.e., extends to infinity in
779 /// some direction. Otherwise, returns false.
780 bool isUnbounded();
781
782 /// Make a tableau to represent a pair of points in the given tableaus, one in
783 /// tableau A and one in B.
784 static Simplex makeProduct(const Simplex &a, const Simplex &b);
785
786 /// Returns an integer sample point if one exists, or std::nullopt
787 /// otherwise. This should only be called for bounded sets.
788 std::optional<SmallVector<DynamicAPInt, 8>> findIntegerSample();
789
790 enum class IneqType { Redundant, Cut, Separate };
791
792 /// Returns the type of the inequality with coefficients `coeffs`.
793 ///
794 /// Possible types are:
795 /// Redundant The inequality is satisfied in the polytope
796 /// Cut The inequality is satisfied by some points, but not by others
797 /// Separate The inequality is not satisfied by any point
798 IneqType findIneqType(ArrayRef<DynamicAPInt> coeffs);
799
800 /// Check if the specified inequality already holds in the polytope.
801 bool isRedundantInequality(ArrayRef<DynamicAPInt> coeffs);
802
803 /// Check if the specified equality already holds in the polytope.
804 bool isRedundantEquality(ArrayRef<DynamicAPInt> coeffs);
805
806 /// Returns true if this Simplex's polytope is a rational subset of `rel`.
807 /// Otherwise, returns false.
808 bool isRationalSubsetOf(const IntegerRelation &rel);
809
810 /// Returns the current sample point if it is integral. Otherwise, returns
811 /// std::nullopt.
812 std::optional<SmallVector<DynamicAPInt, 8>> getSamplePointIfIntegral() const;
813
814 /// Returns the current sample point, which may contain non-integer (rational)
815 /// coordinates. Returns an empty optional when the tableau is empty.
816 std::optional<SmallVector<Fraction, 8>> getRationalSample() const;
817
818private:
819 friend class GBRSimplex;
820
821 /// Restore the unknown to a non-negative sample value.
822 ///
823 /// Returns success if the unknown was successfully restored to a non-negative
824 /// sample value, failure otherwise.
825 LogicalResult restoreRow(Unknown &u);
826
827 /// Find a pivot to change the sample value of row in the specified
828 /// direction while preserving tableau consistency, except that if the
829 /// direction is down then the pivot may make the specified row take a
830 /// negative value. The returned pivot row will be row if and only if the
831 /// unknown is unbounded in the specified direction.
832 ///
833 /// Returns a (row, col) pair denoting a pivot, or an empty Optional if
834 /// no valid pivot exists.
835 std::optional<Pivot> findPivot(int row, Direction direction) const;
836
837 /// Find a row that can be used to pivot the column in the specified
838 /// direction. If skipRow is not null, then this row is excluded
839 /// from consideration. The returned pivot will maintain all constraints
840 /// except the column itself and skipRow, if it is set. (if these unknowns
841 /// are restricted).
842 ///
843 /// Returns the row to pivot to, or an empty Optional if the column
844 /// is unbounded in the specified direction.
845 std::optional<unsigned> findPivotRow(std::optional<unsigned> skipRow,
846 Direction direction, unsigned col) const;
847
848 /// Undo the addition of the last constraint while preserving tableau
849 /// consistency.
850 void undoLastConstraint() final;
851
852 /// Compute the maximum or minimum of the specified Unknown, depending on
853 /// direction. The specified unknown may be pivoted. If the unknown is
854 /// restricted, it will have a non-negative sample value on return.
855 /// Should not be called if the Simplex is empty.
856 ///
857 /// Returns a Fraction denoting the optimum, or a null value if no optimum
858 /// exists, i.e., if the expression is unbounded in this direction.
860
861 /// Mark the specified unknown redundant. This operation is added to the undo
862 /// log and will be undone by rollbacks. The specified unknown must be in row
863 /// orientation.
864 void markRowRedundant(Unknown &u);
865
866 /// Reduce the given basis, starting at the specified level, using general
867 /// basis reduction.
868 void reduceBasis(IntMatrix &basis, unsigned level);
869};
870
871/// Takes a snapshot of the simplex state on construction and rolls back to the
872/// snapshot on destruction.
873///
874/// Useful for performing operations in a "transient context", all changes from
875/// which get rolled back on scope exit.
877public:
878 SimplexRollbackScopeExit(SimplexBase &simplex) : simplex(simplex) {
879 snapshot = simplex.getSnapshot();
880 };
881 ~SimplexRollbackScopeExit() { simplex.rollback(snapshot); }
882
883private:
884 SimplexBase &simplex;
885 unsigned snapshot;
886};
887
888} // namespace presburger
889} // namespace mlir
890
891#endif // MLIR_ANALYSIS_PRESBURGER_SIMPLEX_H
true
Given two iterators into the same block, return "true" if a is before `b.
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
false
Parses a map_entries map type from a string format back into its numeric value.
An IntegerPolyhedron represents the set of points from a PresburgerSpace that satisfy a list of affin...
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
void undoLastConstraint() final
Undo the addition of the last constraint.
Definition Simplex.cpp:1212
LexSimplexBase(const IntegerRelation &constraints)
Definition Simplex.h:433
LogicalResult moveRowUnknownToColumn(unsigned row)
Try to move the specified row to column orientation while preserving the lexicopositivity of the basi...
Definition Simplex.cpp:776
~LexSimplexBase() override=default
LexSimplexBase(const IntegerRelation &constraints, const llvm::SmallBitVector &isSymbol)
Definition Simplex.h:437
LexSimplexBase(unsigned nVar, const llvm::SmallBitVector &isSymbol)
Definition Simplex.h:431
LogicalResult addCut(unsigned row)
Given a row that has a non-integer sample value, add an inequality to cut away this fractional sample...
Definition Simplex.cpp:281
unsigned getLexMinPivotColumn(unsigned row, unsigned colA, unsigned colB) const
Given two potential pivot columns for a row, return the one that results in the lexicographically sma...
Definition Simplex.cpp:792
void addInequality(ArrayRef< DynamicAPInt > coeffs) final
Add an inequality to the tableau.
Definition Simplex.cpp:1591
unsigned getSnapshot()
Get a snapshot of the current state. This is used for rolling back.
Definition Simplex.h:427
void appendSymbol()
Add new symbolic variables to the end of the list of variables.
Definition Simplex.cpp:364
A class for lexicographic optimization without any symbols.
Definition Simplex.h:480
LexSimplex(const IntegerRelation &constraints)
Definition Simplex.h:486
LexSimplex(unsigned nVar)
Definition Simplex.h:482
This class represents a piece-wise MultiAffineFunction.
PresburgerSpace is the space of all possible values of a tuple of integer valued variables/variables.
The Simplex class implements a version of the Simplex and Generalized Basis Reduction algorithms,...
Definition Simplex.h:152
unsigned addZeroRow(bool makeRestricted=false)
Add a new row to the tableau and the associated data structures.
Definition Simplex.cpp:107
bool isEmpty() const
Returns true if the tableau is empty (has conflicting constraints), false otherwise.
Definition Simplex.cpp:1069
void appendVariable(unsigned count=1)
Add new variables to the end of the list of variables.
Definition Simplex.cpp:1320
virtual void undoLastConstraint()=0
Undo the addition of the last constraint.
SmallVector< int, 8 > rowUnknown
These hold the indexes of the unknown at a given row or column position.
Definition Simplex.h:360
SmallVector< SmallVector< int, 8 >, 8 > savedBases
Holds a vector of bases.
Definition Simplex.h:351
void intersectIntegerRelation(const IntegerRelation &rel)
Add all the constraints from the given IntegerRelation.
Definition Simplex.cpp:1335
SmallVector< UndoLogEntry, 8 > undoLog
Holds a log of operations, used for rolling back to a previous state.
Definition Simplex.h:346
bool usingBigM
Stores whether or not a big M column is present in the tableau.
Definition Simplex.h:328
unsigned getSnapshot() const
Get a snapshot of the current state.
Definition Simplex.cpp:1136
void print(raw_ostream &os) const
Print the tableau's internal state.
Definition Simplex.cpp:2128
UndoLogEntry
Enum to denote operations that need to be undone during rollback.
Definition Simplex.h:303
unsigned getNumRows() const
Definition Simplex.h:324
const Unknown & unknownFromRow(unsigned row) const
Returns the unknown associated with row.
Definition Simplex.cpp:87
SmallVector< int, 8 > colUnknown
Definition Simplex.h:360
SmallVector< Unknown, 8 > var
Definition Simplex.h:363
void addEquality(ArrayRef< DynamicAPInt > coeffs)
Add an equality to the tableau.
Definition Simplex.cpp:1122
unsigned getSnapshotBasis()
Get a snapshot of the current state including the basis.
Definition Simplex.cpp:1138
unsigned getNumFixedCols() const
Return the number of fixed columns, as described in the constructor above, this is the number of colu...
Definition Simplex.h:323
SmallVector< Unknown, 8 > con
These hold information about each unknown.
Definition Simplex.h:363
void markEmpty()
Mark the tableau as being empty.
Definition Simplex.cpp:1092
bool empty
This is true if the tableau has been detected to be empty, false otherwise.
Definition Simplex.h:343
void addDivisionVariable(ArrayRef< DynamicAPInt > coeffs, const DynamicAPInt &denom)
Append a new variable to the simplex and constrain it such that its only integer value is the floor d...
Definition Simplex.cpp:1303
void swapColumns(unsigned i, unsigned j)
Definition Simplex.cpp:1080
void removeLastConstraintRowOrientation()
Remove the last constraint, which must be in row orientation.
Definition Simplex.cpp:1151
virtual ~SimplexBase()=default
LLVM_DUMP_METHOD void dump() const
Definition Simplex.cpp:2171
std::optional< unsigned > findAnyPivotRow(unsigned col)
Return any row that this column can be pivoted with, ignoring tableau consistency.
Definition Simplex.cpp:1174
virtual void addInequality(ArrayRef< DynamicAPInt > coeffs)=0
Add an inequality to the tableau.
const Unknown & unknownFromColumn(unsigned col) const
Returns the unknown associated with col.
Definition Simplex.cpp:82
void rollback(unsigned snapshot)
Rollback to a snapshot. This invalidates all later snapshots.
Definition Simplex.cpp:1290
IntMatrix tableau
The matrix representing the tableau.
Definition Simplex.h:339
void pivot(unsigned row, unsigned col)
Pivot the row with the column.
Definition Simplex.cpp:950
void swapRows(unsigned i, unsigned j)
Swap the two rows/columns in the tableau and associated data structures.
Definition Simplex.cpp:1071
void undo(UndoLogEntry entry)
Undo the operation represented by the log entry.
Definition Simplex.cpp:1228
const Unknown & unknownFromIndex(int index) const
Returns the unknown associated with index.
Definition Simplex.cpp:77
unsigned nSymbol
The number of parameters.
Definition Simplex.h:336
unsigned nRedundant
The number of redundant rows in the tableau.
Definition Simplex.h:332
unsigned addRow(ArrayRef< DynamicAPInt > coeffs, bool makeRestricted=false)
Add a new row to the tableau and the associated data structures.
Definition Simplex.cpp:121
unsigned getNumVariables() const
Returns the number of variables in the tableau.
Definition Simplex.cpp:1131
void swapRowWithCol(unsigned row, unsigned col)
Swap the row with the column in the tableau's data structures but not the tableau itself.
Definition Simplex.cpp:913
unsigned getNumColumns() const
Definition Simplex.h:325
unsigned getNumConstraints() const
Returns the number of constraints in the tableau.
Definition Simplex.cpp:1132
SimplexRollbackScopeExit(SimplexBase &simplex)
Definition Simplex.h:878
The Simplex class uses the Normal pivot rule and supports integer emptiness checks as well as detecti...
Definition Simplex.h:693
bool isMarkedRedundant(unsigned constraintIndex) const
Returns whether the specified constraint has been marked as redundant.
Definition Simplex.cpp:1408
void detectRedundant(unsigned offset)
Definition Simplex.h:760
friend class GBRSimplex
Definition Simplex.h:819
MaybeOptimum< Fraction > computeRowOptimum(Direction direction, unsigned row)
Compute the maximum or minimum value of the given row, depending on direction.
Definition Simplex.cpp:1344
bool isBoundedAlongConstraint(unsigned constraintIndex)
Returns whether the perpendicular of the specified constraint is a is a direction along which the pol...
Definition Simplex.cpp:1398
Simplex(unsigned nVar)
Definition Simplex.h:698
void addInequality(ArrayRef< DynamicAPInt > coeffs) final
Add an inequality to the tableau.
Definition Simplex.cpp:1109
Simplex(const IntegerRelation &constraints)
Definition Simplex.h:699
void detectRedundant(unsigned offset, unsigned count)
Finds a subset of constraints that is redundant, i.e., such that the set of solutions does not change...
Definition Simplex.cpp:1428
MaybeOptimum< Fraction > computeOptimum(Direction direction, ArrayRef< DynamicAPInt > coeffs)
Compute the maximum or minimum value of the given expression, depending on direction.
Definition Simplex.cpp:1363
~Simplex() override=default
SymbolicLexSimplex(const IntegerRelation &constraints, const IntegerPolyhedron &symbolDomain, const llvm::SmallBitVector &isSymbol)
constraints is the set for which the symbolic lexopt will be computed.
Definition Simplex.h:584
SymbolicLexSimplex(const IntegerRelation &constraints, unsigned symbolOffset, const IntegerPolyhedron &symbolDomain)
An overload to select some subrange of ids as symbols for lexopt.
Definition Simplex.h:598
SymbolicLexSimplex(const IntegerRelation &constraints, const IntegerPolyhedron &symbolDomain)
An overload to select the symbols of constraints as symbols for lexopt.
Definition Simplex.h:606
Given a simplex for a polytope, construct a new simplex whose variables are identified with a pair of...
Definition Simplex.cpp:1654
VarKind
Kind of variable.
llvm::SmallBitVector getSubrangeBitVector(unsigned len, unsigned setOffset, unsigned numSet)
Definition Utils.cpp:280
Include the generated interface declarations.
A class to represent fractions.
Definition Fraction.h:29
An Unknown is either a variable or a constraint.
Definition Simplex.h:236
void print(raw_ostream &os) const
Definition Simplex.h:246
Unknown(Orientation oOrientation, bool oRestricted, unsigned oPos, bool oIsSymbol=false)
Definition Simplex.h:237
Represents the result of a symbolic lexicographic optimization computation.
Definition Simplex.h:531
PWMAFunction lexopt
This maps assignments of symbols to the corresponding lexopt.
Definition Simplex.h:539
SymbolicLexOpt(const PresburgerSpace &space)
Definition Simplex.h:532
PresburgerSet unboundedDomain
Contains all assignments to the symbols that made the lexopt unbounded.
Definition Simplex.h:543
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.