Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
parameters.cc
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cstdint>
17#include <optional>
18#include <sstream>
19#include <string>
20#include <utility>
21
22#include "absl/log/check.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
25#include "absl/strings/str_cat.h"
26#include "absl/strings/string_view.h"
27#include "absl/time/time.h"
28#include "absl/types/span.h"
32#include "ortools/math_opt/parameters.pb.h"
33#include "ortools/math_opt/solvers/glpk.pb.h"
34#include "ortools/math_opt/solvers/gurobi.pb.h"
35#include "ortools/math_opt/solvers/highs.pb.h"
38
39namespace operations_research {
40namespace math_opt {
41namespace {
42
43template <typename EnumType>
44bool ParseEnumFlag(const absl::string_view text, EnumType* const value,
45 std::string* const error) {
46 const std::optional<EnumType> enum_value = EnumFromString<EnumType>(text);
47 if (!enum_value.has_value()) {
48 *error = "unknown value for enumeration";
49 return false;
50 }
51
52 *value = *enum_value;
53 return true;
54}
55
56template <typename EnumType>
57std::string UnparseEnumFlag(const EnumType value) {
58 std::ostringstream oss;
59 oss << value;
60 return oss.str();
61}
62
63} // namespace
64
65std::optional<absl::string_view> Enum<SolverType>::ToOptString(
67 switch (value) {
69 return "gscip";
71 return "gurobi";
73 return "glop";
75 return "cp_sat";
77 return "pdlp";
79 return "glpk";
81 return "ecos";
83 return "scs";
85 return "highs";
87 return "santorini";
88 }
89 return std::nullopt;
90}
91
92absl::Span<const SolverType> Enum<SolverType>::AllValues() {
93 static constexpr SolverType kSolverTypeValues[] = {
98 };
99 return absl::MakeConstSpan(kSolverTypeValues);
100}
101
102bool AbslParseFlag(const absl::string_view text, SolverType* const value,
103 std::string* const error) {
104 return ParseEnumFlag(text, value, error);
105}
106
107std::string AbslUnparseFlag(const SolverType value) {
108 return UnparseEnumFlag(value);
109}
110
111std::optional<absl::string_view> Enum<LPAlgorithm>::ToOptString(
113 switch (value) {
115 return "primal_simplex";
117 return "dual_simplex";
119 return "barrier";
121 return "first_order";
122 }
123 return std::nullopt;
124}
125
126absl::Span<const LPAlgorithm> Enum<LPAlgorithm>::AllValues() {
127 static constexpr LPAlgorithm kLPAlgorithmValues[] = {
132 };
133 return absl::MakeConstSpan(kLPAlgorithmValues);
134}
135
136bool AbslParseFlag(absl::string_view text, LPAlgorithm* const value,
137 std::string* const error) {
138 return ParseEnumFlag(text, value, error);
139}
140
142 return UnparseEnumFlag(value);
143}
144
145std::optional<absl::string_view> Enum<Emphasis>::ToOptString(Emphasis value) {
146 switch (value) {
147 case Emphasis::kOff:
148 return "off";
149 case Emphasis::kLow:
150 return "low";
152 return "medium";
153 case Emphasis::kHigh:
154 return "high";
156 return "very_high";
157 }
158 return std::nullopt;
159}
160
161absl::Span<const Emphasis> Enum<Emphasis>::AllValues() {
162 static constexpr Emphasis kEmphasisValues[] = {
165 };
166 return absl::MakeConstSpan(kEmphasisValues);
167}
168
169bool AbslParseFlag(absl::string_view text, Emphasis* const value,
170 std::string* const error) {
171 return ParseEnumFlag(text, value, error);
172}
173
174std::string AbslUnparseFlag(const Emphasis value) {
175 return UnparseEnumFlag(value);
176}
177
178GurobiParametersProto GurobiParameters::Proto() const {
179 GurobiParametersProto result;
180 for (const auto& [key, val] : param_values) {
181 GurobiParametersProto::Parameter& p = *result.add_parameters();
182 p.set_name(key);
183 p.set_value(val);
184 }
185 return result;
186}
187
189 const GurobiParametersProto& proto) {
190 GurobiParameters result;
191 for (const GurobiParametersProto::Parameter& p : proto.parameters()) {
192 result.param_values[p.name()] = p.value();
193 }
194 return result;
195}
196
197GlpkParametersProto GlpkParameters::Proto() const {
198 GlpkParametersProto result;
199 if (compute_unbound_rays_if_possible.has_value()) {
200 result.set_compute_unbound_rays_if_possible(
202 }
203 return result;
204}
205
206GlpkParameters GlpkParameters::FromProto(const GlpkParametersProto& proto) {
207 GlpkParameters result;
208 if (proto.has_compute_unbound_rays_if_possible()) {
210 proto.compute_unbound_rays_if_possible();
211 }
212 return result;
213}
214
215SolveParametersProto SolveParameters::Proto() const {
216 SolveParametersProto result;
217 result.set_enable_output(enable_output);
218 if (time_limit < absl::InfiniteDuration()) {
220 result.mutable_time_limit()));
221 }
222 if (iteration_limit.has_value()) {
223 result.set_iteration_limit(*iteration_limit);
224 }
225 if (node_limit.has_value()) {
226 result.set_node_limit(*node_limit);
227 }
228 if (cutoff_limit.has_value()) {
229 result.set_cutoff_limit(*cutoff_limit);
230 }
231 if (objective_limit.has_value()) {
232 result.set_objective_limit(*objective_limit);
233 }
234 if (best_bound_limit.has_value()) {
235 result.set_best_bound_limit(*best_bound_limit);
236 }
237 if (solution_limit.has_value()) {
238 result.set_solution_limit(*solution_limit);
239 }
240 if (threads.has_value()) {
241 result.set_threads(*threads);
242 }
243 if (random_seed.has_value()) {
244 result.set_random_seed(*random_seed);
245 }
246 if (relative_gap_tolerance.has_value()) {
247 result.set_relative_gap_tolerance(*relative_gap_tolerance);
248 }
249 if (absolute_gap_tolerance.has_value()) {
250 result.set_absolute_gap_tolerance(*absolute_gap_tolerance);
251 }
252 if (solution_pool_size.has_value()) {
253 result.set_solution_pool_size(*solution_pool_size);
254 }
255 result.set_lp_algorithm(EnumToProto(lp_algorithm));
256 result.set_presolve(EnumToProto(presolve));
257 result.set_cuts(EnumToProto(cuts));
258 result.set_heuristics(EnumToProto(heuristics));
259 result.set_scaling(EnumToProto(scaling));
260 *result.mutable_gscip() = gscip;
261 *result.mutable_gurobi() = gurobi.Proto();
262 *result.mutable_glop() = glop;
263 *result.mutable_cp_sat() = cp_sat;
264 *result.mutable_pdlp() = pdlp;
265 *result.mutable_glpk() = glpk.Proto();
266 *result.mutable_highs() = highs;
267 return result;
268}
269
270absl::StatusOr<SolveParameters> SolveParameters::FromProto(
271 const SolveParametersProto& proto) {
272 SolveParameters result;
273 result.enable_output = proto.enable_output();
274 if (proto.has_time_limit()) {
277 _ << "invalid time_limit");
278 } else {
279 result.time_limit = absl::InfiniteDuration();
280 }
281 if (proto.has_iteration_limit()) {
282 result.iteration_limit = proto.iteration_limit();
283 }
284 if (proto.has_node_limit()) {
285 result.node_limit = proto.node_limit();
286 }
287 if (proto.has_cutoff_limit()) {
288 result.cutoff_limit = proto.cutoff_limit();
289 }
290 if (proto.has_objective_limit()) {
291 result.objective_limit = proto.objective_limit();
292 }
293 if (proto.has_best_bound_limit()) {
294 result.best_bound_limit = proto.best_bound_limit();
295 }
296 if (proto.has_solution_limit()) {
297 result.solution_limit = proto.solution_limit();
298 }
299 if (proto.has_threads()) {
300 result.threads = proto.threads();
301 }
302 if (proto.has_random_seed()) {
303 result.random_seed = proto.random_seed();
304 }
305 if (proto.has_absolute_gap_tolerance()) {
306 result.absolute_gap_tolerance = proto.absolute_gap_tolerance();
307 }
308 if (proto.has_relative_gap_tolerance()) {
309 result.relative_gap_tolerance = proto.relative_gap_tolerance();
310 }
311 if (proto.has_solution_pool_size()) {
312 result.solution_pool_size = proto.solution_pool_size();
313 }
314 result.lp_algorithm = EnumFromProto(proto.lp_algorithm());
315 result.presolve = EnumFromProto(proto.presolve());
316 result.cuts = EnumFromProto(proto.cuts());
317 result.heuristics = EnumFromProto(proto.heuristics());
318 result.scaling = EnumFromProto(proto.scaling());
319 result.gscip = proto.gscip();
320 result.gurobi = GurobiParameters::FromProto(proto.gurobi());
321 result.glop = proto.glop();
322 result.cp_sat = proto.cp_sat();
323 result.pdlp = proto.pdlp();
324 result.glpk = GlpkParameters::FromProto(proto.glpk());
325 result.highs = proto.highs();
326 return result;
327}
328
329bool AbslParseFlag(absl::string_view text, SolveParameters* solve_parameters,
330 std::string* error) {
331 SolveParametersProto proto;
332 if (!ProtobufParseTextProtoForFlag(text, &proto, error)) {
333 return false;
334 }
335 absl::StatusOr<SolveParameters> params = SolveParameters::FromProto(proto);
336 if (!params.ok()) {
337 *error = absl::StrCat(
338 "SolveParametersProto was invalid and could not convert to "
339 "SolveParameters: ",
340 params.status().ToString());
341 return false;
342 }
343 *solve_parameters = *std::move(params);
344 return true;
345}
346
347std::string AbslUnparseFlag(SolveParameters solve_parameters) {
348 return ProtobufTextFormatPrintToStringForFlag(solve_parameters.Proto());
349}
350
351} // namespace math_opt
352} // namespace operations_research
CpModelProto proto
The output proto.
int64_t value
bool AbslParseFlag(const absl::string_view text, SolverType *const value, std::string *const error)
SolverType
The solvers supported by MathOpt.
Definition parameters.h:42
Emphasis
never give an error, and will map onto their best match.
Definition parameters.h:179
LPAlgorithm
Selects an algorithm for solving linear programs.
Definition parameters.h:128
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(P proto_value)
Definition enums.h:281
std::optional< E > EnumFromString(absl::string_view str)
Definition enums.h:302
Enum< E >::Proto EnumToProto(std::optional< E > value)
Definition enums.h:270
std::string AbslUnparseFlag(const SolverType value)
In SWIG mode, we don't want anything besides these top-level includes.
std::string ProtobufTextFormatPrintToStringForFlag(const google::protobuf::Message &proto)
bool ProtobufParseTextProtoForFlag(absl::string_view text, ProtoType *message_out, std::string *error_out)
Definition proto_utils.h:86
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
Definition protoutil.h:42
inline ::absl::StatusOr< google::protobuf::Duration > EncodeGoogleApiProto(absl::Duration d)
Definition protoutil.h:27
static absl::Span< const E > AllValues()
Returns all possible values of the enum.
static std::optional< absl::string_view > ToOptString(E value)
std::optional< bool > compute_unbound_rays_if_possible
Definition parameters.h:246
static GlpkParameters FromProto(const GlpkParametersProto &proto)
gtl::linked_hash_map< std::string, std::string > param_values
Parameter name-value pairs to set in insertion order.
Definition parameters.h:216
static GurobiParameters FromProto(const GurobiParametersProto &proto)
std::optional< LPAlgorithm > lp_algorithm
Definition parameters.h:393
pdlp::PrimalDualHybridGradientParams pdlp
Definition parameters.h:419
static absl::StatusOr< SolveParameters > FromProto(const SolveParametersProto &proto)
std::optional< int32_t > threads
If unset, use the solver default. If set, it must be >= 1.
Definition parameters.h:332
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)