OR-Tools  9.6
lp_data.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 //
15 // Storage classes for Linear Programs.
16 //
17 // LinearProgram stores the complete data for a Linear Program:
18 // - objective coefficients and offset,
19 // - cost coefficients,
20 // - coefficient matrix,
21 // - bounds for each variable,
22 // - bounds for each constraint.
23 
24 #ifndef OR_TOOLS_LP_DATA_LP_DATA_H_
25 #define OR_TOOLS_LP_DATA_LP_DATA_H_
26 
27 #include <algorithm> // for max
28 #include <cmath>
29 #include <cstdint>
30 #include <map>
31 #include <string> // for string
32 #include <vector> // for vector
33 
34 #include "absl/container/flat_hash_map.h"
35 #include "absl/container/flat_hash_set.h"
36 #include "ortools/base/hash.h"
37 #include "ortools/base/logging.h" // for CHECK*
38 #include "ortools/base/macros.h" // for DISALLOW_COPY_AND_ASSIGN, NULL
39 #include "ortools/glop/parameters.pb.h"
41 #include "ortools/lp_data/sparse.h"
42 #include "ortools/util/fp_utils.h"
44 
45 namespace operations_research {
46 namespace glop {
47 
48 class SparseMatrixScaler;
49 
50 // The LinearProgram class is used to store a linear problem in a form
51 // accepted by LPSolver.
52 //
53 // In addition to the simple setter functions used to create such problems, the
54 // class also contains a few more advanced modification functions used primarily
55 // by preprocessors. A client shouldn't need to use them directly.
57  public:
58  enum class VariableType {
59  // The variable can take any value between and including its lower and upper
60  // bound.
61  CONTINUOUS,
62  // The variable must only take integer values.
63  INTEGER,
64  // The variable is implied integer variable i.e. it was continuous variable
65  // in the LP and was detected to take only integer values.
67  };
68 
69  LinearProgram();
70 
71  // Clears, i.e. reset the object to its initial value.
72  void Clear();
73 
74  // Name setter and getter.
75  void SetName(const std::string& name) { name_ = name; }
76  const std::string& name() const { return name_; }
77 
78  // Creates a new variable and returns its index.
79  // By default, the column bounds will be [0, infinity).
80  ColIndex CreateNewVariable();
81 
82  // Creates a new slack variable and returns its index. Do not use this method
83  // to create non-slack variables.
84  ColIndex CreateNewSlackVariable(bool is_integer_slack_variable,
87  const std::string& name);
88 
89  // Creates a new constraint and returns its index.
90  // By default, the constraint bounds will be [0, 0].
91  RowIndex CreateNewConstraint();
92 
93  // Same as CreateNewVariable() or CreateNewConstraint() but also assign an
94  // immutable id to the variable or constraint so they can be retrieved later.
95  // By default, the name is also set to this id, but it can be changed later
96  // without changing the id.
97  //
98  // Note that these ids are NOT copied over by the Populate*() functions.
99  //
100  // TODO(user): Move these and the two corresponding hash_table into a new
101  // LinearProgramBuilder class to simplify the code of some functions like
102  // DeleteColumns() here and make the behavior on copy clear? or simply remove
103  // them as it is almost as easy to maintain a hash_table on the client side.
104  ColIndex FindOrCreateVariable(const std::string& variable_id);
105  RowIndex FindOrCreateConstraint(const std::string& constraint_id);
106 
107  // Functions to set the name of a variable or constraint. Note that you
108  // won't be able to find those named variables/constraints with
109  // FindOrCreate{Variable|Constraint}().
110  // TODO(user): Add PopulateIdsFromNames() so names added via
111  // Set{Variable|Constraint}Name() can be found.
112  void SetVariableName(ColIndex col, absl::string_view name);
113  void SetConstraintName(RowIndex row, absl::string_view name);
114 
115  // Set the type of the variable.
116  void SetVariableType(ColIndex col, VariableType type);
117 
118  // Returns whether the variable at column col is constrained to be integer.
119  bool IsVariableInteger(ColIndex col) const;
120 
121  // Returns whether the variable at column col must take binary values or not.
122  bool IsVariableBinary(ColIndex col) const;
123 
124  // Defines lower and upper bounds for the variable at col. Note that the
125  // bounds may be set to +/- infinity. The variable must have been created
126  // before or this will crash in non-debug mode.
129 
130  // Defines lower and upper bounds for the constraint at row. Note that the
131  // bounds may be set to +/- infinity. If the constraint wasn't created before,
132  // all the rows from the current GetNumberOfRows() to the given row will be
133  // created with a range [0,0].
136 
137  // Defines the coefficient for col / row.
138  void SetCoefficient(RowIndex row, ColIndex col, Fractional value);
139 
140  // Defines the objective coefficient of column col.
141  // It is set to 0.0 by default.
143 
144  // Define the objective offset (0.0 by default) and scaling factor (positive
145  // and equal to 1.0 by default). This is mainly used for displaying purpose
146  // and the real objective is factor * (objective + offset).
149 
150  // Defines the optimization direction. When maximize is true (resp. false),
151  // the objective is maximized (resp. minimized). The default is false.
152  void SetMaximizationProblem(bool maximize);
153 
154  // Calls CleanUp() on each columns.
155  // That is, removes duplicates, zeros, and orders the coefficients by row.
156  void CleanUp();
157 
158  // Returns true if all the columns are ordered by rows and contain no
159  // duplicates or zero entries (i.e. if IsCleanedUp() is true for all columns).
160  bool IsCleanedUp() const;
161 
162  // Functions that return the name of a variable or constraint. If the name is
163  // empty, they return a special name that depends on the index.
164  std::string GetVariableName(ColIndex col) const;
165  std::string GetConstraintName(RowIndex row) const;
166 
167  // Returns the type of variable.
168  VariableType GetVariableType(ColIndex col) const;
169 
170  // Returns true (resp. false) when the problem is a maximization
171  // (resp. minimization) problem.
172  bool IsMaximizationProblem() const { return maximize_; }
173 
174  // Returns the underlying SparseMatrix or its transpose (which may need to be
175  // computed).
176  const SparseMatrix& GetSparseMatrix() const { return matrix_; }
177  const SparseMatrix& GetTransposeSparseMatrix() const;
178 
179  // Some transformations are better done on the transpose representation. These
180  // two functions are here for that. Note that calling the first function and
181  // modifying the matrix does not change the result of any function in this
182  // class until UseTransposeMatrixAsReference() is called. This is because the
183  // transpose matrix is only used by GetTransposeSparseMatrix() and this
184  // function will recompute the whole transpose from the matrix. In particular,
185  // do not call GetTransposeSparseMatrix() while you modify the matrix returned
186  // by GetMutableTransposeSparseMatrix() otherwise all your changes will be
187  // lost.
188  //
189  // IMPORTANT: The matrix dimension cannot change. Otherwise this will cause
190  // problems. This is checked in debug mode when calling
191  // UseTransposeMatrixAsReference().
194 
195  // Release the memory used by the transpose matrix.
196  void ClearTransposeMatrix();
197 
198  // Gets the underlying SparseColumn with the given index.
199  // This is the same as GetSparseMatrix().column(col);
200  const SparseColumn& GetSparseColumn(ColIndex col) const;
201 
202  // Gets a pointer to the underlying SparseColumn with the given index.
204 
205  // Returns the number of variables.
206  ColIndex num_variables() const { return matrix_.num_cols(); }
207 
208  // Returns the number of constraints.
209  RowIndex num_constraints() const { return matrix_.num_rows(); }
210 
211  // Returns the number of entries in the linear program matrix.
212  EntryIndex num_entries() const { return matrix_.num_entries(); }
213 
214  // Return the lower bounds (resp. upper bounds) of constraints as a column
215  // vector. Note that the bound values may be +/- infinity.
217  return constraint_lower_bounds_;
218  }
220  return constraint_upper_bounds_;
221  }
222 
223  // Returns the objective coefficients (or cost) of variables as a row vector.
225  return objective_coefficients_;
226  }
227 
228  // Return the lower bounds (resp. upper bounds) of variables as a row vector.
229  // Note that the bound values may be +/- infinity.
231  return variable_lower_bounds_;
232  }
234  return variable_upper_bounds_;
235  }
236 
237  // Returns a row vector of VariableType representing types of variables.
239  return variable_types_;
240  }
241 
242  // Returns a list (technically a vector) of the ColIndices of the integer
243  // variables. This vector is lazily computed.
244  const std::vector<ColIndex>& IntegerVariablesList() const;
245 
246  // Returns a list (technically a vector) of the ColIndices of the binary
247  // integer variables. This vector is lazily computed.
248  const std::vector<ColIndex>& BinaryVariablesList() const;
249 
250  // Returns a list (technically a vector) of the ColIndices of the non-binary
251  // integer variables. This vector is lazily computed.
252  const std::vector<ColIndex>& NonBinaryVariablesList() const;
253 
254  // Returns the objective coefficient (or cost) of the given variable for the
255  // minimization version of the problem. That is, this is the same as
256  // GetObjectiveCoefficient() for a minimization problem and the opposite for a
257  // maximization problem.
259 
260  // Returns the objective offset and scaling factor.
261  Fractional objective_offset() const { return objective_offset_; }
263  return objective_scaling_factor_;
264  }
265 
266  // Checks if each variable respects its bounds, nothing else.
267  bool SolutionIsWithinVariableBounds(const DenseRow& solution,
268  Fractional absolute_tolerance) const;
269 
270  // Tests if the solution is LP-feasible within the given tolerance,
271  // i.e., satisfies all linear constraints within the absolute tolerance level.
272  // The solution does not need to satisfy the integer constraints.
273  bool SolutionIsLPFeasible(const DenseRow& solution,
274  Fractional absolute_tolerance) const;
275 
276  // Tests if the solution is integer within the given tolerance, i.e., all
277  // integer variables have integer values within the absolute tolerance level.
278  // The solution does not need to satisfy the linear constraints.
279  bool SolutionIsInteger(const DenseRow& solution,
280  Fractional absolute_tolerance) const;
281 
282  // Tests if the solution is both LP-feasible and integer within the tolerance.
283  bool SolutionIsMIPFeasible(const DenseRow& solution,
284  Fractional absolute_tolerance) const;
285 
286  // Fills the value of the slack from the other variable values.
287  // This requires that the slack have been added.
288  void ComputeSlackVariableValues(DenseRow* solution) const;
289 
290  // Functions to translate the sum(solution * objective_coefficients()) to
291  // the real objective of the problem and back. Note that these can also
292  // be used to translate bounds of the objective in the same way.
295 
296  // A short string with the problem dimension.
297  std::string GetDimensionString() const;
298 
299  // A short line with some stats on the problem coefficients.
300  std::string GetObjectiveStatsString() const;
301  std::string GetBoundsStatsString() const;
302 
303  // Returns a stringified LinearProgram. We use the LP file format used by
304  // lp_solve (see http://lpsolve.sourceforge.net/5.1/index.htm).
305  std::string Dump() const;
306 
307  // Returns a string that contains the provided solution of the LP in the
308  // format var1 = X, var2 = Y, var3 = Z, ...
309  std::string DumpSolution(const DenseRow& variable_values) const;
310 
311  // Returns a comma-separated string of integers containing (in that order)
312  // num_constraints_, num_variables_in_file_, num_entries_,
313  // num_objective_non_zeros_, num_rhs_non_zeros_, num_less_than_constraints_,
314  // num_greater_than_constraints_, num_equal_constraints_,
315  // num_range_constraints_, num_non_negative_variables_, num_boxed_variables_,
316  // num_free_variables_, num_fixed_variables_, num_other_variables_
317  // Very useful for reporting in the way used in journal articles.
318  std::string GetProblemStats() const;
319 
320  // Returns a string containing the same information as with GetProblemStats(),
321  // but in a much more human-readable form, for example:
322  // Number of rows : 27
323  // Number of variables in file : 32
324  // Number of entries (non-zeros) : 83
325  // Number of entries in the objective : 5
326  // Number of entries in the right-hand side : 7
327  // Number of <= constraints : 19
328  // Number of >= constraints : 0
329  // Number of = constraints : 8
330  // Number of range constraints : 0
331  // Number of non-negative variables : 32
332  // Number of boxed variables : 0
333  // Number of free variables : 0
334  // Number of fixed variables : 0
335  // Number of other variables : 0
336  std::string GetPrettyProblemStats() const;
337 
338  // Returns a comma-separated string of numbers containing (in that order)
339  // fill rate, max number of entries (length) in a row, average row length,
340  // standard deviation of row length, max column length, average column length,
341  // standard deviation of column length
342  // Useful for profiling algorithms.
343  //
344  // TODO(user): Theses are statistics about the underlying matrix and should be
345  // moved to SparseMatrix.
346  std::string GetNonZeroStats() const;
347 
348  // Returns a string containing the same information as with GetNonZeroStats(),
349  // but in a much more human-readable form, for example:
350  // Fill rate : 9.61%
351  // Entries in row (Max / average / std, dev.) : 9 / 3.07 / 1.94
352  // Entries in column (Max / average / std, dev.): 4 / 2.59 / 0.96
353  std::string GetPrettyNonZeroStats() const;
354 
355  // Adds slack variables to the problem for all rows which don't have slack
356  // variables. The new slack variables have bounds set to opposite of the
357  // bounds of the corresponding constraint, and changes all constraints to
358  // equality constraints with both bounds set to 0.0. If a constraint uses only
359  // integer variables and all their coefficients are integer, it will mark the
360  // slack variable as integer too.
361  //
362  // It is an error to call CreateNewVariable() or CreateNewConstraint() on a
363  // linear program on which this method was called.
364  //
365  // Note that many of the slack variables may not be useful at all, but in
366  // order not to recompute the matrix from one Solve() to the next, we always
367  // include all of them for a given lp matrix.
368  //
369  // TODO(user): investigate the impact on the running time. It seems low
370  // because we almost never iterate on fixed variables.
371  void AddSlackVariablesWhereNecessary(bool detect_integer_constraints);
372 
373  // Returns the index of the first slack variable in the linear program.
374  // Returns kInvalidCol if slack variables were not injected into the problem
375  // yet.
376  ColIndex GetFirstSlackVariable() const;
377 
378  // Returns the index of the slack variable corresponding to the given
379  // constraint. Returns kInvalidCol if slack variables were not injected into
380  // the problem yet.
381  ColIndex GetSlackVariable(RowIndex row) const;
382 
383  // Populates the calling object with the dual of the LinearProgram passed as
384  // parameter.
385  // For the general form that we solve,
386  // min c.x
387  // s.t. A_1 x = b_1
388  // A_2 x <= b_2
389  // A_3 x >= b_3
390  // l <= x <= u
391  // With x: n-column of unknowns
392  // l,u: n-columns of bound coefficients
393  // c: n-row of cost coefficients
394  // A_i: m_i×n-matrix of coefficients
395  // b_i: m_i-column of right-hand side coefficients
396  //
397  // The dual is
398  //
399  // max b_1.y_1 + b_2.y_2 + b_3.y_3 + l.v + u.w
400  // s.t. y_1 A_1 + y_2 A_2 + y_3 A_3 + v + w = c
401  // y_1 free, y_2 <= 0, y_3 >= 0, v >= 0, w <= 0
402  // With:
403  // y_i: m_i-row of unknowns
404  // v,w: n-rows of unknowns
405  //
406  // If range constraints are present, each of the corresponding row is
407  // duplicated (with one becoming lower bounded and the other upper bounded).
408  // For such ranged row in the primal, duplicated_rows[row] is set to the
409  // column index in the dual of the corresponding column duplicate. For
410  // non-ranged row, duplicated_rows[row] is set to kInvalidCol.
411  //
412  // IMPORTANT: The linear_program argument must not have any free constraints.
413  //
414  // IMPORTANT: This function always interprets the argument in its minimization
415  // form. So the dual solution of the dual needs to be negated if we want to
416  // compute the solution of a maximization problem given as an argument.
417  //
418  // TODO(user): Do not interpret as a minimization problem?
419  void PopulateFromDual(const LinearProgram& dual,
420  RowToColMapping* duplicated_rows);
421 
422  // Populates the calling object with the given LinearProgram.
423  void PopulateFromLinearProgram(const LinearProgram& linear_program);
424 
425  // Populates the calling object with the given LinearProgram while permuting
426  // variables and constraints. This is useful mainly for testing to generate
427  // a model with the same optimal objective value.
429  const LinearProgram& lp, const RowPermutation& row_permutation,
430  const ColumnPermutation& col_permutation);
431 
432  // Populates the calling object with the variables of the given LinearProgram.
433  // The function preserves the bounds, the integrality, the names of the
434  // variables and their objective coefficients. No constraints are copied (the
435  // matrix in the destination has 0 rows).
436  void PopulateFromLinearProgramVariables(const LinearProgram& linear_program);
437 
438  // Adds constraints to the linear program. The constraints are specified using
439  // a sparse matrix of the coefficients, and vectors that represent the
440  // left-hand side and the right-hand side of the constraints, i.e.
441  // left_hand_sides <= coefficients * variables <= right_hand_sides.
442  // The sizes of the columns and the names must be the same as the number of
443  // rows of the sparse matrix; the number of columns of the matrix must be
444  // equal to the number of variables of the linear program.
446  const DenseColumn& left_hand_sides,
447  const DenseColumn& right_hand_sides,
449 
450  // Calls the AddConstraints method. After adding the constraints it adds slack
451  // variables to the constraints.
453  const SparseMatrix& coefficients, const DenseColumn& left_hand_sides,
454  const DenseColumn& right_hand_sides,
456  bool detect_integer_constraints_for_slack);
457 
458  // Swaps the content of this LinearProgram with the one passed as argument.
459  // Works in O(1).
460  void Swap(LinearProgram* linear_program);
461 
462  // Removes the given column indices from the LinearProgram.
463  // This needs to allocate O(num_variables) memory to update variable_table_.
464  void DeleteColumns(const DenseBooleanRow& columns_to_delete);
465 
466  // Removes slack variables from the linear program. The method restores the
467  // bounds on constraints from the bounds of the slack variables, resets the
468  // index of the first slack variable, and removes the relevant columns from
469  // the matrix.
470  void DeleteSlackVariables();
471 
472  // Scales the problem using the given scaler.
473  void Scale(SparseMatrixScaler* scaler);
474 
475  // While Scale() makes sure the coefficients inside the linear program matrix
476  // are in [-1, 1], the objective coefficients, variable bounds and constraint
477  // bounds can still take large values (originally or due to the matrix
478  // scaling).
479  //
480  // It makes a lot of sense to also scale them given that internally we use
481  // absolute tolerances, and that it is nice to have the same behavior if users
482  // scale their problems. For instance one could change the unit of ALL the
483  // variables from Bytes to MBytes if they denote memory quantities. Or express
484  // a cost in dollars instead of thousands of dollars.
485  //
486  // Here, we are quite prudent and just make sure that the range of the
487  // non-zeros magnitudes contains one. So for instance if all non-zeros costs
488  // are in [1e4, 1e6], we will divide them by 1e4 so that the new range is
489  // [1, 1e2].
490  //
491  // TODO(user): Another more aggressive idea is to set the median/mean/geomean
492  // of the magnitudes to one. Investigate if this leads to better results. It
493  // does look more robust.
494  //
495  // Both functions update objective_scaling_factor()/objective_offset() and
496  // return the scaling coefficient so that:
497  // - For ScaleObjective(), the old coefficients can be retrieved by
498  // multiplying the new ones by the returned factor.
499  // - For ScaleBounds(), the old variable and constraint bounds can be
500  // retrieved by multiplying the new ones by the returned factor.
501  Fractional ScaleObjective(GlopParameters::CostScalingAlgorithm method);
503 
504  // Removes the given row indices from the LinearProgram.
505  // This needs to allocate O(num_variables) memory.
506  void DeleteRows(const DenseBooleanColumn& rows_to_delete);
507 
508  // Does basic checking on the linear program:
509  // - returns false if some coefficient are NaNs.
510  // - returns false if some coefficient other than the bounds are +/- infinity.
511  // Note that these conditions are also guarded by DCHECK on each of the
512  // SetXXX() function above.
513  //
514  // This also returns false if any finite value has a magnitude larger than
515  // the given threshold.
516  bool IsValid(Fractional max_valid_magnitude = kInfinity) const;
517 
518  // Updates the bounds of the variables to the intersection of their original
519  // bounds and the bounds specified by variable_lower_bounds and
520  // variable_upper_bounds. If the new bounds of all variables are non-empty,
521  // returns true; otherwise, returns false.
525 
526  // Returns true if the linear program is in equation form Ax = 0 and all slack
527  // variables have been added. This is also called "computational form" in some
528  // of the literature.
529  bool IsInEquationForm() const;
530 
531  // Returns true if all integer variables in the linear program have strictly
532  // integer bounds.
533  bool BoundsOfIntegerVariablesAreInteger(Fractional tolerance) const;
534 
535  // Returns true if all integer constraints in the linear program have strictly
536  // integer bounds.
537  bool BoundsOfIntegerConstraintsAreInteger(Fractional tolerance) const;
538 
539  // Advanced usage. Bypass the costly call to CleanUp() when we known that the
540  // change we made kept the matrix columns "clean" (see the comment of
541  // CleanUp()). This is unsafe but can save a big chunk of the running time
542  // when one does a small amount of incremental changes to the problem (like
543  // adding a new row with no duplicates or zero entries).
545  DCHECK(matrix_.IsCleanedUp());
546  columns_are_known_to_be_clean_ = true;
547  }
548 
549  // If true, checks bound validity in debug mode.
550  void SetDcheckBounds(bool dcheck_bounds) { dcheck_bounds_ = dcheck_bounds; }
551 
552  // In our presolve, the calls and the extra test inside SetConstraintBounds()
553  // can be visible when a lot of substitutions are performed.
555  return &constraint_lower_bounds_;
556  }
558  return &constraint_upper_bounds_;
559  }
560 
561  private:
562  // A helper function that updates the vectors integer_variables_list_,
563  // binary_variables_list_, and non_binary_variables_list_.
564  void UpdateAllIntegerVariableLists() const;
565 
566  // A helper function to format problem statistics. Used by GetProblemStats()
567  // and GetPrettyProblemStats().
568  std::string ProblemStatFormatter(const absl::string_view format) const;
569 
570  // A helper function to format non-zero statistics. Used by GetNonZeroStats()
571  // and GetPrettyNonZeroStats().
572  std::string NonZeroStatFormatter(const absl::string_view format) const;
573 
574  // Resizes all row vectors to include index 'row'.
575  void ResizeRowsIfNeeded(RowIndex row);
576 
577  // Populates the definitions of variables, name and objective in the calling
578  // linear program with the data from the given linear program. The method does
579  // not touch the data structures for storing constraints.
580  void PopulateNameObjectiveAndVariablesFromLinearProgram(
581  const LinearProgram& linear_program);
582 
583  // Stores the linear program coefficients.
584  SparseMatrix matrix_;
585 
586  // The transpose of matrix_. This will be lazily recomputed by
587  // GetTransposeSparseMatrix() if transpose_matrix_is_consistent_ is false.
588  mutable SparseMatrix transpose_matrix_;
589 
590  // Constraint related quantities.
591  DenseColumn constraint_lower_bounds_;
592  DenseColumn constraint_upper_bounds_;
593  StrictITIVector<RowIndex, std::string> constraint_names_;
594 
595  // Variable related quantities.
596  DenseRow objective_coefficients_;
597  DenseRow variable_lower_bounds_;
598  DenseRow variable_upper_bounds_;
601 
602  // The vector of the indices of variables constrained to be integer.
603  // Note(user): the set of indices in integer_variables_list_ is the union
604  // of the set of indices in binary_variables_list_ and of the set of indices
605  // in non_binary_variables_list_ below.
606  mutable std::vector<ColIndex> integer_variables_list_;
607 
608  // The vector of the indices of variables constrained to be binary.
609  mutable std::vector<ColIndex> binary_variables_list_;
610 
611  // The vector of the indices of variables constrained to be integer, but not
612  // binary.
613  mutable std::vector<ColIndex> non_binary_variables_list_;
614 
615  // Map used to find the index of a variable based on its id.
616  absl::flat_hash_map<std::string, ColIndex> variable_table_;
617 
618  // Map used to find the index of a constraint based on its id.
619  absl::flat_hash_map<std::string, RowIndex> constraint_table_;
620 
621  // Offset of the objective, i.e. value of the objective when all variables
622  // are set to zero.
623  Fractional objective_offset_;
624  Fractional objective_scaling_factor_;
625 
626  // Boolean true (resp. false) when the problem is a maximization
627  // (resp. minimization) problem.
628  bool maximize_;
629 
630  // Boolean to speed-up multiple calls to IsCleanedUp() or
631  // CleanUp(). Mutable so IsCleanedUp() can be const.
632  mutable bool columns_are_known_to_be_clean_;
633 
634  // Whether transpose_matrix_ is guaranteed to be the transpose of matrix_.
635  mutable bool transpose_matrix_is_consistent_;
636 
637  // Whether integer_variables_list_ is consistent with the current
638  // LinearProgram.
639  mutable bool integer_variables_list_is_consistent_;
640 
641  // The name of the LinearProgram.
642  std::string name_;
643 
644  // The index of the first slack variable added to the linear program by
645  // LinearProgram::AddSlackVariablesForAllRows().
646  ColIndex first_slack_variable_;
647 
648  // If true, checks bounds in debug mode.
649  bool dcheck_bounds_ = true;
650 
651  friend void Scale(LinearProgram* lp, SparseMatrixScaler* scaler,
652  GlopParameters::ScalingAlgorithm scaling_method);
653 
654  DISALLOW_COPY_AND_ASSIGN(LinearProgram);
655 };
656 
657 // --------------------------------------------------------
658 // ProblemSolution
659 // --------------------------------------------------------
660 // Contains the solution of a LinearProgram as returned by a preprocessor.
662  ProblemSolution(RowIndex num_rows, ColIndex num_cols)
664  primal_values(num_cols, 0.0),
665  dual_values(num_rows, 0.0),
668  // The solution status.
670 
671  // The actual primal/dual solution values. This is what most clients will
672  // need, and this is enough for LPSolver to easily check the optimality.
675 
676  // The status of the variables and constraints which is difficult to
677  // reconstruct from the solution values alone. Some remarks:
678  // - From this information alone, by factorizing the basis, it is easy to
679  // reconstruct the primal and dual values.
680  // - The main difficulty to construct this from the solution values is to
681  // reconstruct the optimal basis if some basic variables are exactly at
682  // one of their bounds (and their reduced costs are close to zero).
683  // - The non-basic information (VariableStatus::FIXED_VALUE,
684  // VariableStatus::AT_LOWER_BOUND, VariableStatus::AT_UPPER_BOUND,
685  // VariableStatus::FREE) is easy to construct for variables (because
686  // they are at their exact bounds). They can be guessed for constraints
687  // (here a small precision error is unavoidable). However, it is useful to
688  // carry this exact information during post-solve.
691 
692  std::string DebugString() const;
693 };
694 
695 // Helper function to check the bounds of the SetVariableBounds() and
696 // SetConstraintBounds() functions.
698  if (std::isnan(lower_bound)) return false;
699  if (std::isnan(upper_bound)) return false;
700  if (lower_bound == kInfinity && upper_bound == kInfinity) return false;
701  if (lower_bound == -kInfinity && upper_bound == -kInfinity) return false;
702  if (lower_bound > upper_bound) return false;
703  return true;
704 }
705 
706 } // namespace glop
707 } // namespace operations_research
708 
709 #endif // OR_TOOLS_LP_DATA_LP_DATA_H_
SparseMatrix * GetMutableTransposeSparseMatrix()
Definition: lp_data.cc:387
std::string GetObjectiveStatsString() const
Definition: lp_data.cc:453
void SetObjectiveScalingFactor(Fractional objective_scaling_factor)
Definition: lp_data.cc:337
DenseColumn * mutable_constraint_upper_bounds()
Definition: lp_data.h:557
void PopulateFromPermutedLinearProgram(const LinearProgram &lp, const RowPermutation &row_permutation, const ColumnPermutation &col_permutation)
Definition: lp_data.cc:884
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:250
std::string GetVariableName(ColIndex col) const
Definition: lp_data.cc:361
void SetConstraintName(RowIndex row, absl::string_view name)
Definition: lp_data.cc:246
const SparseMatrix & GetTransposeSparseMatrix() const
Definition: lp_data.cc:377
bool SolutionIsWithinVariableBounds(const DenseRow &solution, Fractional absolute_tolerance) const
Definition: lp_data.cc:482
bool BoundsOfIntegerConstraintsAreInteger(Fractional tolerance) const
Definition: lp_data.cc:1513
void SetObjectiveOffset(Fractional objective_offset)
Definition: lp_data.cc:332
void PopulateFromLinearProgram(const LinearProgram &linear_program)
Definition: lp_data.cc:863
void Scale(SparseMatrixScaler *scaler)
std::string GetPrettyProblemStats() const
Definition: lp_data.cc:665
bool SolutionIsMIPFeasible(const DenseRow &solution, Fractional absolute_tolerance) const
Definition: lp_data.cc:530
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
Definition: lp_data.cc:318
const SparseMatrix & GetSparseMatrix() const
Definition: lp_data.h:176
bool BoundsOfIntegerVariablesAreInteger(Fractional tolerance) const
Definition: lp_data.cc:1497
void SetVariableName(ColIndex col, absl::string_view name)
Definition: lp_data.cc:233
std::string DumpSolution(const DenseRow &variable_values) const
Definition: lp_data.cc:648
ColIndex GetSlackVariable(RowIndex row) const
Definition: lp_data.cc:756
const DenseRow & variable_lower_bounds() const
Definition: lp_data.h:230
ColIndex FindOrCreateVariable(const std::string &variable_id)
Definition: lp_data.cc:206
const DenseColumn & constraint_lower_bounds() const
Definition: lp_data.h:216
std::string GetBoundsStatsString() const
Definition: lp_data.cc:466
Fractional ScaleObjective(GlopParameters::CostScalingAlgorithm method)
Definition: lp_data.cc:1189
bool IsValid(Fractional max_valid_magnitude=kInfinity) const
Definition: lp_data.cc:1306
const std::vector< ColIndex > & BinaryVariablesList() const
Definition: lp_data.cc:286
const DenseRow & objective_coefficients() const
Definition: lp_data.h:224
Fractional RemoveObjectiveScalingAndOffset(Fractional value) const
Definition: lp_data.cc:556
const std::vector< ColIndex > & IntegerVariablesList() const
Definition: lp_data.cc:281
Fractional GetObjectiveCoefficientForMinimizationVersion(ColIndex col) const
Definition: lp_data.cc:420
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:310
ColIndex CreateNewSlackVariable(bool is_integer_slack_variable, Fractional lower_bound, Fractional upper_bound, const std::string &name)
Definition: lp_data.cc:177
VariableType GetVariableType(ColIndex col) const
Definition: lp_data.cc:373
RowIndex FindOrCreateConstraint(const std::string &constraint_id)
Definition: lp_data.cc:219
void SetDcheckBounds(bool dcheck_bounds)
Definition: lp_data.h:550
void Swap(LinearProgram *linear_program)
Definition: lp_data.cc:1032
void AddConstraints(const SparseMatrix &coefficients, const DenseColumn &left_hand_sides, const DenseColumn &right_hand_sides, const StrictITIVector< RowIndex, std::string > &names)
Definition: lp_data.cc:973
std::string GetPrettyNonZeroStats() const
Definition: lp_data.cc:691
void SetVariableType(ColIndex col, VariableType type)
Definition: lp_data.cc:237
const std::vector< ColIndex > & NonBinaryVariablesList() const
Definition: lp_data.cc:291
bool SolutionIsInteger(const DenseRow &solution, Fractional absolute_tolerance) const
Definition: lp_data.cc:518
SparseColumn * GetMutableSparseColumn(ColIndex col)
Definition: lp_data.cc:414
std::string GetConstraintName(RowIndex row) const
Definition: lp_data.cc:367
void SetName(const std::string &name)
Definition: lp_data.h:75
void AddSlackVariablesWhereNecessary(bool detect_integer_constraints)
Definition: lp_data.cc:698
const DenseColumn & constraint_upper_bounds() const
Definition: lp_data.h:219
void ComputeSlackVariableValues(DenseRow *solution) const
Definition: lp_data.cc:536
bool SolutionIsLPFeasible(const DenseRow &solution, Fractional absolute_tolerance) const
Definition: lp_data.cc:498
bool IsVariableInteger(ColIndex col) const
Definition: lp_data.cc:296
void SetObjectiveCoefficient(ColIndex col, Fractional value)
Definition: lp_data.cc:327
bool IsVariableBinary(ColIndex col) const
Definition: lp_data.cc:301
Fractional ApplyObjectiveScalingAndOffset(Fractional value) const
Definition: lp_data.cc:551
void DeleteRows(const DenseBooleanColumn &rows_to_delete)
Definition: lp_data.cc:1259
void DeleteColumns(const DenseBooleanRow &columns_to_delete)
Definition: lp_data.cc:1066
const DenseRow & variable_upper_bounds() const
Definition: lp_data.h:233
bool UpdateVariableBoundsToIntersection(const DenseRow &variable_lower_bounds, const DenseRow &variable_upper_bounds)
Definition: lp_data.cc:1007
void PopulateFromDual(const LinearProgram &dual, RowToColMapping *duplicated_rows)
Definition: lp_data.cc:765
const std::string & name() const
Definition: lp_data.h:76
void PopulateFromLinearProgramVariables(const LinearProgram &linear_program)
Definition: lp_data.cc:936
std::string GetDimensionString() const
Definition: lp_data.cc:426
Fractional objective_scaling_factor() const
Definition: lp_data.h:262
void SetMaximizationProblem(bool maximize)
Definition: lp_data.cc:344
void AddConstraintsWithSlackVariables(const SparseMatrix &coefficients, const DenseColumn &left_hand_sides, const DenseColumn &right_hand_sides, const StrictITIVector< RowIndex, std::string > &names, bool detect_integer_constraints_for_slack)
Definition: lp_data.cc:998
const StrictITIVector< ColIndex, VariableType > variable_types() const
Definition: lp_data.h:238
const SparseColumn & GetSparseColumn(ColIndex col) const
Definition: lp_data.cc:410
DenseColumn * mutable_constraint_lower_bounds()
Definition: lp_data.h:554
int64_t value
absl::Span< const double > coefficients
ColIndex col
Definition: markowitz.cc:186
RowIndex row
Definition: markowitz.cc:185
bool AreBoundsValid(Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.h:697
constexpr double kInfinity
Definition: lp_types.h:88
Collection of objects used to extend the Constraint Solver library.
IntVar * upper_bound
Definition: routing.cc:1087
IntVar * lower_bound
Definition: routing.cc:1086
ProblemSolution(RowIndex num_rows, ColIndex num_cols)
Definition: lp_data.h:662
ConstraintStatusColumn constraint_statuses
Definition: lp_data.h:690