OR-Tools  9.3
glpk_solver.h
Go to the documentation of this file.
1// Copyright 2010-2021 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#ifndef OR_TOOLS_MATH_OPT_SOLVERS_GLPK_SOLVER_H_
15#define OR_TOOLS_MATH_OPT_SOLVERS_GLPK_SOLVER_H_
16
17#include <cstdint>
18#include <memory>
19#include <optional>
20#include <vector>
21
22#include "absl/container/flat_hash_map.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
26#include "ortools/math_opt/callback.pb.h"
29#include "ortools/math_opt/model.pb.h"
30#include "ortools/math_opt/model_parameters.pb.h"
31#include "ortools/math_opt/model_update.pb.h"
32#include "ortools/math_opt/parameters.pb.h"
33#include "ortools/math_opt/result.pb.h"
34
35extern "C" {
36#include <glpk.h>
37}
38
39namespace operations_research {
40namespace math_opt {
41
43 public:
44 static absl::StatusOr<std::unique_ptr<SolverInterface>> New(
45 const ModelProto& model, const InitArgs& init_args);
46
47 ~GlpkSolver() override;
48
49 absl::StatusOr<SolveResultProto> Solve(
50 const SolveParametersProto& parameters,
51 const ModelSolveParametersProto& model_parameters,
52 MessageCallback message_cb,
53 const CallbackRegistrationProto& callback_registration, Callback cb,
54 SolveInterrupter* interrupter) override;
55 absl::Status Update(const ModelUpdateProto& model_update) override;
56 bool CanUpdate(const ModelUpdateProto& model_update) override;
57
58 private:
59 // The columns of the GPLK problem.
60 //
61 // This structures is intentionally similar to LinearConstraints so that some
62 // template function can accept either of those to share code between rows and
63 // columns. For this purpose it also defines some aliases to some GLPK
64 // functions and the IsInteger() (which is trivially implemented for
65 // LinearConstraints).
66 struct Variables {
67 static constexpr auto kSetBounds = glp_set_col_bnds;
68 static constexpr auto kGetLb = glp_get_col_lb;
69 static constexpr auto kGetUb = glp_get_col_ub;
70 static constexpr auto kGetType = glp_get_col_type;
71 static constexpr auto kDelElts = glp_del_cols;
72
73 // Returns true if the given one-based column is an integer variable.
74 static inline bool IsInteger(glp_prob* const problem, const int j);
75
76 // The MathOpt variable id of each column in GLPK. This is zero-based, the
77 // first column corresponds to the 0 and the ids.size() matches the number
78 // of columns.
79 //
80 // The id_to_index map can be used to get the GLPK column index of a given
81 // MathOpt variable id but the return value will be one-based (the
82 // convention used in GLPK). Thus this invariant holds:
83 //
84 // for all i in [0, num_cols), id_to_index.at(ids[i]) == i + 1
85 std::vector<int64_t> ids;
86
87 // Map each MathOpt variable id to the column one-based index in GLPK (thus
88 // values are in [1, num_cols]). See the ids vector for the counter part.
89 absl::flat_hash_map<int64_t, int> id_to_index;
90
91 // The unrounded lower bound value of each column.
92 //
93 // We keep this value since GLPK's glp_intopt() expects integer bounds for
94 // integer variables. We need the unrounded value when the type of a
95 // variable is changed to continuous though by an update.
96 std::vector<double> unrounded_lower_bounds;
97
98 // The unrounded upper bound value of each column.
99 //
100 // See unrounded_lower_bounds documentation for details..
101 std::vector<double> unrounded_upper_bounds;
102 };
103
104 // The columns of the GPLK problem.
105 //
106 // See the comment on Variables for details.
107 struct LinearConstraints {
108 static constexpr auto kSetBounds = glp_set_row_bnds;
109 static constexpr auto kGetLb = glp_get_row_lb;
110 static constexpr auto kGetUb = glp_get_row_ub;
111 static constexpr auto kGetType = glp_get_row_type;
112 static constexpr auto kDelElts = glp_del_rows;
113
114 // Returns false. This function mirrors Variables::IsInteger() and enables
115 // sharing code between variables and constraints.
116 static bool IsInteger(glp_prob*, int) { return false; }
117
118 // The MathOpt linear constraint id of each row in GLPK. This is zero-based,
119 // the first row corresponds to the 0 and ids.size() matches the number of
120 // rows.
121 //
122 // The id_to_index map can be used to get the GLPK row index of a given
123 // MathOpt variable id but the return value will be one-based (the
124 // convention used in GLPK). Thus this invariant holds:
125 //
126 // for all i in [0, num_rows), id_to_index.at(ids[i]) == i + 1
127 std::vector<int64_t> ids;
128
129 // Map each MathOpt linear constraint id to the row one-based index in GLPK
130 // (thus values are in [1, num_rows]). See the ids vector for the counter
131 // part.
132 absl::flat_hash_map<int64_t, int> id_to_index;
133 };
134
135 explicit GlpkSolver(const ModelProto& model);
136
137 // Appends the variables to GLPK cols.
138 void AddVariables(const VariablesProto& new_variables);
139
140 // Appends the variables to GLPK rows.
141 void AddLinearConstraints(
142 const LinearConstraintsProto& new_linear_constraints);
143
144 // Updates the objective coefficients with the new values in
145 // coefficients_proto.
146 void UpdateObjectiveCoefficients(
147 const SparseDoubleVectorProto& coefficients_proto);
148
149 // Updates the constraints matrix with the new values in matrix_updates.
150 //
151 // The first_new_(var|cstr)_id are the smallest ids of the new
152 // variables/constraints (in MathOpt the same id is never reused thus all
153 // variables with ids greater or equal to these values are new). A nullopt
154 // value means that there are not new variables/constraints.
155 void UpdateLinearConstraintMatrix(
156 const SparseDoubleMatrixProto& matrix_updates,
157 std::optional<int64_t> first_new_var_id,
158 std::optional<int64_t> first_new_cstr_id);
159
160 // Adds the primal solution (if it exists) to the result using the provided
161 // functions to get the status of the solution (GLP_FEAS, ...), its
162 // objective value and the structural variables values.
163 //
164 // Here `col_val` is a functions that takes a column index (i.e. the index of
165 // a structural variable) and returns its primal value in the solution.
166 void AddPrimalSolution(int (*get_prim_stat)(glp_prob*),
167 double (*obj_val)(glp_prob*),
168 double (*col_val)(glp_prob*, int),
169 const ModelSolveParametersProto& model_parameters,
170 SolutionProto& solution_proto);
171
172 // Adds the dual solution (if it exists) to the result. This function must
173 // only be called after having solved an LP, with the provided methods
174 // depending on the type of LP solved.
175 //
176 // Here `col_dual` is a function that takes a column index (i.e. the index of
177 // a structural variable) and returns its dual value in the solution. The
178 // `row_dual` does the same for a row index (i.e. the index of an auxiliary
179 // variable associated to a constraint).
180 void AddDualSolution(int (*get_dual_stat)(glp_prob*),
181 double (*obj_val)(glp_prob*),
182 double (*row_dual)(glp_prob*, int),
183 double (*col_dual)(glp_prob*, int),
184 const ModelSolveParametersProto& model_parameters,
185 SolutionProto& solution_proto);
186
187 // Adds a primal or dual ray to the result depending on the value returned by
188 // glp_get_unbnd_ray().
189 absl::Status AddPrimalOrDualRay(
190 const ModelSolveParametersProto& model_parameters,
191 SolveResultProto& result);
192
193 glp_prob* const problem_;
194
195 Variables variables_;
196 LinearConstraints linear_constraints_;
197};
198
200// Inline functions implementation.
202
203bool GlpkSolver::Variables::IsInteger(glp_prob* const problem, const int j) {
204 const int kind = glp_get_col_kind(problem, j);
205 switch (kind) {
206 case GLP_IV:
207 case GLP_BV:
208 // GLP_BV is returned when the GLPK internal kind is GLP_IV and the
209 // bounds are [0,1].
210 return true;
211 case GLP_CV:
212 return false;
213 default:
214 LOG(FATAL) << "Unexpected column kind: " << kind;
215 }
216}
217
218} // namespace math_opt
219} // namespace operations_research
220
221#endif // OR_TOOLS_MATH_OPT_SOLVERS_GLPK_SOLVER_H_
#define LOG(severity)
Definition: base/logging.h:420
bool CanUpdate(const ModelUpdateProto &model_update) override
absl::Status Update(const ModelUpdateProto &model_update) override
static absl::StatusOr< std::unique_ptr< SolverInterface > > New(const ModelProto &model, const InitArgs &init_args)
Definition: glpk_solver.cc:844
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, SolveInterrupter *interrupter) override
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
SatParameters parameters
GRBmodel * model
const int FATAL
Definition: log_severity.h:32
Collection of objects used to extend the Constraint Solver library.