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