Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
lp_types.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Common types and constants used by the Linear Programming solver.
15
16#ifndef OR_TOOLS_LP_DATA_LP_TYPES_H_
17#define OR_TOOLS_LP_DATA_LP_TYPES_H_
18
19#include <cstddef>
20#include <cstdint>
21#include <initializer_list>
22#include <limits>
23#include <memory>
24#include <ostream>
25#include <string>
26#include <vector>
27
28#include "absl/log/check.h"
31#include "ortools/util/bitset.h"
33
34// We use typedefs as much as possible to later permit the usage of
35// types such as quad-doubles or rationals.
36
37namespace operations_research {
38namespace glop {
39
40// This type is defined to avoid cast issues during index conversions,
41// e.g. converting ColIndex into RowIndex.
42// All types should use 'Index' instead of int32_t.
43typedef int32_t Index;
44
45// ColIndex is the type for integers representing column/variable indices.
46// int32s are enough for handling even the largest problems.
48
49// RowIndex is the type for integers representing row/constraint indices.
50// int32s are enough for handling even the largest problems.
52
53// Get the ColIndex corresponding to the column # row.
54inline ColIndex RowToColIndex(RowIndex row) { return ColIndex(row.value()); }
55
56// Get the RowIndex corresponding to the row # col.
57inline RowIndex ColToRowIndex(ColIndex col) { return RowIndex(col.value()); }
58
59// Get the integer index corresponding to the col.
60inline Index ColToIntIndex(ColIndex col) { return col.value(); }
61
62// Get the integer index corresponding to the row.
63inline Index RowToIntIndex(RowIndex row) { return row.value(); }
64
65// EntryIndex is the type for integers representing entry indices.
66// An entry in a sparse matrix is a pair (row, value) for a given known column.
67// See classes SparseColumn and SparseMatrix.
68#if defined(__ANDROID__)
69DEFINE_STRONG_INDEX_TYPE(EntryIndex);
70#else
72#endif
73
74static inline double ToDouble(double f) { return f; }
75
76static inline double ToDouble(long double f) { return static_cast<double>(f); }
77
78// The type Fractional denotes the type of numbers on which the computations are
79// performed. This is defined as double here, but it could as well be float,
80// DoubleDouble, QuadDouble, or infinite-precision rationals.
81// Floating-point representations are binary fractional numbers, thus the name.
82// (See http://en.wikipedia.org/wiki/Fraction_(mathematics) .)
83typedef double Fractional;
84
85// Range max for type Fractional. DBL_MAX for double for example.
86constexpr double kRangeMax = std::numeric_limits<double>::max();
87
88// Infinity for type Fractional.
89constexpr double kInfinity = std::numeric_limits<double>::infinity();
90
91// Epsilon for type Fractional, i.e. the smallest e such that 1.0 + e != 1.0 .
92constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
93
94// Returns true if the given value is finite, that means for a double:
95// not a NaN and not +/- infinity.
97 return value > -kInfinity && value < kInfinity;
98}
99
100// Constants to represent invalid row or column index.
101// It is important that their values be the same because during transposition,
102// one needs to be converted into the other.
103constexpr RowIndex kInvalidRow(-1);
104constexpr ColIndex kInvalidCol(-1);
105
106// Different statuses for a given problem.
107enum class ProblemStatus : int8_t {
108 // The problem has been solved to optimality. Both the primal and dual have
109 // a feasible solution.
110 OPTIMAL,
111
112 // The problem has been proven primal-infeasible. Note that the problem is not
113 // necessarily DUAL_UNBOUNDED (See Chvatal p.60). The solver does not have a
114 // dual unbounded ray in this case.
116
117 // The problem has been proven dual-infeasible. Note that the problem is not
118 // necessarily PRIMAL_UNBOUNDED (See Chvatal p.60). The solver does
119 // note have a primal unbounded ray in this case,
121
122 // The problem is either INFEASIBLE or UNBOUNDED (this applies to both the
123 // primal and dual algorithms). This status is only returned by the presolve
124 // step and means that a primal or dual unbounded ray was found during
125 // presolve. Note that because some presolve techniques assume that a feasible
126 // solution exists to simplify the problem further, it is difficult to
127 // distinguish between infeasibility and unboundedness.
128 //
129 // If a client needs to distinguish, it is possible to run the primal
130 // algorithm on the same problem with a 0 objective function to know if the
131 // problem was PRIMAL_INFEASIBLE.
133
134 // The problem has been proven feasible and unbounded. That means that the
135 // problem is DUAL_INFEASIBLE and that the solver has a primal unbounded ray.
137
138 // The problem has been proven dual-feasible and dual-unbounded. That means
139 // the problem is PRIMAL_INFEASIBLE and that the solver has a dual unbounded
140 // ray to prove it.
142
143 // All the statuses below correspond to a case where the solver was
144 // interrupted. This can happen because of a timeout, an iteration limit or an
145 // error.
146
147 // The solver didn't had a chance to prove anything.
148 INIT,
149
150 // The problem has been proven primal-feasible but may still be
151 // PRIMAL_UNBOUNDED.
153
154 // The problem has been proven dual-feasible, but may still be DUAL_UNBOUNDED.
155 // That means that if the primal is feasible, then it has a finite optimal
156 // solution.
158
159 // An error occurred during the solving process.
160 ABNORMAL,
161
162 // The input problem was invalid (see LinearProgram.IsValid()).
164
165 // The problem was solved to a feasible status, but the solution checker found
166 // the primal and/or dual infeasibilities too important for the specified
167 // parameters.
168 IMPRECISE,
169};
170
171// Returns the string representation of the ProblemStatus enum.
172std::string GetProblemStatusString(ProblemStatus problem_status);
173
174inline std::ostream& operator<<(std::ostream& os, ProblemStatus status) {
176 return os;
177}
178
179// Different types of variables.
187
188// Returns the string representation of the VariableType enum.
189std::string GetVariableTypeString(VariableType variable_type);
190
191inline std::ostream& operator<<(std::ostream& os, VariableType type) {
192 os << GetVariableTypeString(type);
193 return os;
194}
195
196// Different variables statuses.
197// If a solution is OPTIMAL or FEASIBLE, then all the properties described here
198// should be satisfied. These properties should also be true during the
199// execution of the revised simplex algorithm, except that because of
200// bound-shifting, the variable may not be at their exact bounds until the
201// shifts are removed.
202enum class VariableStatus : int8_t {
203 // The basic status is special and takes precedence over all the other
204 // statuses. It means that the variable is part of the basis.
205 BASIC,
206 // Only possible status of a FIXED_VARIABLE not in the basis. The variable
207 // value should be exactly equal to its bounds (which are the same).
209 // Only possible statuses of a non-basic variable which is not UNCONSTRAINED
210 // or FIXED. The variable value should be at its exact specified bound (which
211 // must be finite).
214 // Only possible status of an UNCONSTRAINED non-basic variable.
215 // Its value should be zero.
216 //
217 // Note that during crossover, this status is relaxed, and any variable that
218 // can currently move in both directions can be marked as free.
219 FREE,
220};
221
222// Returns the string representation of the VariableStatus enum.
224
225inline std::ostream& operator<<(std::ostream& os, VariableStatus status) {
227 return os;
228}
229
230// Different constraints statuses.
231// The meaning is the same for the constraint activity relative to its bounds as
232// it is for a variable value relative to its bounds. Actually, this is the
233// VariableStatus of the slack variable associated to a constraint modulo a
234// change of sign. The difference is that because of precision error, a
235// constraint activity cannot exactly be equal to one of its bounds or to zero.
236enum class ConstraintStatus : int8_t {
237 BASIC,
241 FREE,
242};
243
244// Returns the string representation of the ConstraintStatus enum.
246
247inline std::ostream& operator<<(std::ostream& os, ConstraintStatus status) {
249 return os;
250}
251
252// Returns the ConstraintStatus corresponding to a given VariableStatus.
254
255// A span of `T`, indexed by a strict int type `IntType`. Intended to be passed
256// by value. See b/259677543.
257template <typename IntType, typename T>
259 public:
260 using IndexType = IntType;
261 using reference = T&;
262 using value_type = T;
263
264 StrictITISpan(T* data, IntType size) : data_(data), size_(size) {}
265
266 reference operator[](IntType i) const {
267 return data_[static_cast<size_t>(i.value())];
268 }
269
270 IntType size() const { return size_; }
271
272 // TODO(user): This should probably be a strictly typed iterator too, but
273 // `StrongVector::begin()` already suffers from this problem.
274 auto begin() const { return data_; }
275 auto end() const { return data_ + static_cast<size_t>(size_.value()); }
276
277 private:
278 T* const data_;
279 const IntType size_;
280};
281
282// Wrapper around a StrongVector to allow (and enforce) creation/resize/assign
283// to use the index type for the size.
284//
285// TODO(user): This should probably move to StrongVector, but note that this
286// version is stricter and does not allow any other size types.
287template <typename IntType, typename T, typename Alloc = std::allocator<T>>
288class StrictITIVector : public util_intops::StrongVector<IntType, T, Alloc> {
289 public:
290 using IndexType = IntType;
294
295 StrictITIVector() = default;
296 explicit StrictITIVector(IntType size) : ParentType(size) {}
297 explicit StrictITIVector(const Alloc& a) : ParentType(a) {}
298 StrictITIVector(IntType n, const T& v, const Alloc& a = Alloc())
299 : ParentType(n, v, a) {}
300
301 // This allows for brace initialization, which is really useful in tests.
302 // It is not 'explicit' by design, so one can do vector = {...};
303#if !defined(__ANDROID__) && (!defined(_MSC_VER) || (_MSC_VER >= 1800))
304 StrictITIVector(std::initializer_list<T> init_list,
305 const Alloc& a = Alloc()) // NOLINT
306 : ParentType(init_list.begin(), init_list.end(), a) {}
307#endif
308
309 template <typename InputIteratorType>
310 StrictITIVector(InputIteratorType first, InputIteratorType last,
311 const Alloc& a = Alloc())
312 : ParentType(first, last, a) {}
313
314 void resize(IntType size) { ParentType::resize(size.value()); }
315 void resize(IntType size, const T& v) { ParentType::resize(size.value(), v); }
316
317 void reserve(IntType size) { ParentType::reserve(size.value()); }
318
319 void assign(IntType size, const T& v) { ParentType::assign(size.value(), v); }
320
321 IntType size() const { return IntType(ParentType::size()); }
322
323 IntType capacity() const { return IntType(ParentType::capacity()); }
324
325 View view() { return View(ParentType::data(), size()); }
327 ConstView view() const { return const_view(); }
328
330 ParentType::assign(data.begin(), data.end());
331 return *this;
332 }
333
334 // Since calls to resize() must use a default value, we introduce a new
335 // function for convenience to reduce the size of a vector.
336 void resize_down(IntType size) {
337 DCHECK_GE(size, IntType(0));
338 DCHECK_LE(size, IntType(ParentType::size()));
339 ParentType::resize(size.value());
340 }
341
342 // This function can be up to 4 times faster than calling assign(size, 0).
343 // Note that it only works with StrictITIVector of basic types.
344 void AssignToZero(IntType size) {
345 resize(size, 0);
346 memset(ParentType::data(), 0, size.value() * sizeof(T));
347 }
348};
349
350// Row-vector types. Row-vector types are indexed by a column index.
351
352// Row of fractional values.
354
355// Row of booleans.
357
358// Row of column indices. Used to represent mappings between columns.
360
361// Vector of row or column indices. Useful to list the non-zero positions.
362typedef std::vector<ColIndex> ColIndexVector;
363typedef std::vector<RowIndex> RowIndexVector;
364
365// Row of row indices.
366// Useful for knowing which row corresponds to a particular column in the basis,
367// or for storing the number of rows for a given column.
369
370// Row of variable types.
372
373// Row of variable statuses.
375
376// Row of bits.
378
379// Column-vector types. Column-vector types are indexed by a row index.
380
381// Column of fractional values.
383
384// Column of booleans.
386
387// Column of bits.
389
390// Column of row indices. Used to represent mappings between rows.
392
393// Column of column indices.
394// Used to represent which column corresponds to a particular row in the basis,
395// or for storing the number of columns for a given row.
397
398// Column of constraints (slack variables) statuses.
400
401// --------------------------------------------------------
402// VectorIterator
403// --------------------------------------------------------
404
405// An iterator over the elements of a sparse data structure that stores the
406// elements in arrays for indices and coefficients. The iterator is
407// built as a wrapper over a sparse vector entry class; the concrete entry class
408// is provided through the template argument EntryType.
409template <typename EntryType>
410class VectorIterator : EntryType {
411 public:
412 using Index = typename EntryType::Index;
413 using Entry = EntryType;
416 EntryIndex i)
417 : EntryType(indices, coefficients, i) {}
418
419 void operator++() { ++this->i_; }
420 bool operator!=(const VectorIterator& other) const {
421 // This operator is intended for use in natural range iteration ONLY.
422 // Therefore, we prefer to use '<' so that a buggy range iteration which
423 // start point is *after* its end point stops immediately, instead of
424 // iterating 2^(number of bits of EntryIndex) times.
425 return this->i_ < other.i_;
426 }
427 const Entry& operator*() const { return *this; }
428};
430// This is used during the deterministic time computation to convert a given
431// number of floating-point operations to something in the same order of
432// magnitude as a second (on a 2014 desktop).
433static inline double DeterministicTimeForFpOperations(int64_t n) {
434 const double kConversionFactor = 2e-9;
435 return kConversionFactor * static_cast<double>(n);
436}
437
438} // namespace glop
439} // namespace operations_research
440
441#endif // OR_TOOLS_LP_DATA_LP_TYPES_H_
StrictITISpan(T *data, IntType size)
Definition lp_types.h:264
reference operator[](IntType i) const
Definition lp_types.h:266
StrictITIVector(std::initializer_list< T > init_list, const Alloc &a=Alloc())
Definition lp_types.h:304
StrictITISpan< IntType, T > View
Definition lp_types.h:292
void assign(IntType size, const T &v)
Definition lp_types.h:319
StrictITIVector & operator=(ConstView data)
Definition lp_types.h:329
void resize(IntType size, const T &v)
Definition lp_types.h:315
StrictITISpan< IntType, const T > ConstView
Definition lp_types.h:293
StrictITIVector(InputIteratorType first, InputIteratorType last, const Alloc &a=Alloc())
Definition lp_types.h:310
StrictITIVector(IntType n, const T &v, const Alloc &a=Alloc())
Definition lp_types.h:298
bool operator!=(const VectorIterator &other) const
Definition lp_types.h:422
VectorIterator(const Index *indices, const Fractional *coefficients, EntryIndex i)
Definition lp_types.h:417
typename EntryType::Index Index
Definition lp_types.h:414
void assign(size_type n, const value_type &val)
value_type * data()
– Pass-through methods to STL vector ----------------------------------—
void reserve(size_type n)
void resize(size_type new_size)
int64_t a
Definition table.cc:44
int64_t value
absl::Status status
Definition g_gurobi.cc:44
absl::Span< const double > coefficients
ColIndex col
Definition markowitz.cc:187
RowIndex row
Definition markowitz.cc:186
constexpr ColIndex kInvalidCol(-1)
constexpr double kInfinity
Infinity for type Fractional.
Definition lp_types.h:89
std::string GetVariableTypeString(VariableType variable_type)
Returns the string representation of the VariableType enum.
Definition lp_types.cc:56
StrictITIVector< RowIndex, ColIndex > RowToColMapping
Definition lp_types.h:396
std::vector< RowIndex > RowIndexVector
Definition lp_types.h:363
StrictITIVector< ColIndex, RowIndex > ColToRowMapping
Definition lp_types.h:368
StrictITIVector< RowIndex, bool > DenseBooleanColumn
Column of booleans.
Definition lp_types.h:385
std::vector< ColIndex > ColIndexVector
Vector of row or column indices. Useful to list the non-zero positions.
Definition lp_types.h:362
StrictITIVector< ColIndex, ColIndex > ColMapping
Row of column indices. Used to represent mappings between columns.
Definition lp_types.h:359
StrictITIVector< RowIndex, ConstraintStatus > ConstraintStatusColumn
Column of constraints (slack variables) statuses.
Definition lp_types.h:399
Bitset64< ColIndex > DenseBitRow
Row of bits.
Definition lp_types.h:377
std::string GetVariableStatusString(VariableStatus status)
Returns the string representation of the VariableStatus enum.
Definition lp_types.cc:75
Index ColToIntIndex(ColIndex col)
Get the integer index corresponding to the col.
Definition lp_types.h:60
Bitset64< RowIndex > DenseBitColumn
Column of bits.
Definition lp_types.h:388
constexpr double kRangeMax
Range max for type Fractional. DBL_MAX for double for example.
Definition lp_types.h:86
ColIndex RowToColIndex(RowIndex row)
Get the ColIndex corresponding to the column # row.
Definition lp_types.h:54
bool IsFinite(Fractional value)
Definition lp_types.h:96
constexpr RowIndex kInvalidRow(-1)
StrictITIVector< RowIndex, RowIndex > RowMapping
Column of row indices. Used to represent mappings between rows.
Definition lp_types.h:391
VariableType
Different types of variables.
Definition lp_types.h:180
StrictITIVector< ColIndex, VariableType > VariableTypeRow
Row of variable types.
Definition lp_types.h:371
RowIndex ColToRowIndex(ColIndex col)
Get the RowIndex corresponding to the row # col.
Definition lp_types.h:57
std::string GetConstraintStatusString(ConstraintStatus status)
Returns the string representation of the ConstraintStatus enum.
Definition lp_types.cc:94
StrictITIVector< ColIndex, VariableStatus > VariableStatusRow
Row of variable statuses.
Definition lp_types.h:374
constexpr double kEpsilon
Epsilon for type Fractional, i.e. the smallest e such that 1.0 + e != 1.0 .
Definition lp_types.h:92
StrictITIVector< RowIndex, Fractional > DenseColumn
Column-vector types. Column-vector types are indexed by a row index.
Definition lp_types.h:382
StrictITIVector< ColIndex, Fractional > DenseRow
Row-vector types. Row-vector types are indexed by a column index.
Definition lp_types.h:353
StrictITIVector< ColIndex, bool > DenseBooleanRow
Row of booleans.
Definition lp_types.h:356
std::ostream & operator<<(std::ostream &os, ProblemStatus status)
Definition lp_types.h:174
ProblemStatus
Different statuses for a given problem.
Definition lp_types.h:107
@ ABNORMAL
An error occurred during the solving process.
@ INVALID_PROBLEM
The input problem was invalid (see LinearProgram.IsValid()).
@ INIT
The solver didn't had a chance to prove anything.
ConstraintStatus VariableToConstraintStatus(VariableStatus status)
Returns the ConstraintStatus corresponding to a given VariableStatus.
Definition lp_types.cc:113
static double DeterministicTimeForFpOperations(int64_t n)
Definition lp_types.h:435
std::string GetProblemStatusString(ProblemStatus problem_status)
Returns the string representation of the ProblemStatus enum.
Definition lp_types.cc:23
Index RowToIntIndex(RowIndex row)
Get the integer index corresponding to the row.
Definition lp_types.h:63
static double ToDouble(double f)
Definition lp_types.h:74
In SWIG mode, we don't want anything besides these top-level includes.
std::optional< int64_t > end
#define DEFINE_STRONG_INT64_TYPE(integer_type_name)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)