Google OR-Tools v9.12
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-2025 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(
66 SolverType value) {
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";
89 return "xpress";
90 }
91 return std::nullopt;
92}
93
94absl::Span<const SolverType> Enum<SolverType>::AllValues() {
95 static constexpr SolverType kSolverTypeValues[] = {
100 };
101 return absl::MakeConstSpan(kSolverTypeValues);
102}
103
104bool AbslParseFlag(const absl::string_view text, SolverType* const value,
105 std::string* const error) {
106 return ParseEnumFlag(text, value, error);
107}
108
109std::string AbslUnparseFlag(const SolverType value) {
110 return UnparseEnumFlag(value);
111}
112
113std::optional<absl::string_view> Enum<LPAlgorithm>::ToOptString(
114 LPAlgorithm value) {
115 switch (value) {
117 return "primal_simplex";
119 return "dual_simplex";
121 return "barrier";
123 return "first_order";
124 }
125 return std::nullopt;
126}
127
128absl::Span<const LPAlgorithm> Enum<LPAlgorithm>::AllValues() {
129 static constexpr LPAlgorithm kLPAlgorithmValues[] = {
134 };
135 return absl::MakeConstSpan(kLPAlgorithmValues);
136}
137
138bool AbslParseFlag(absl::string_view text, LPAlgorithm* const value,
139 std::string* const error) {
140 return ParseEnumFlag(text, value, error);
141}
142
143std::string AbslUnparseFlag(const LPAlgorithm value) {
144 return UnparseEnumFlag(value);
145}
146
147std::optional<absl::string_view> Enum<Emphasis>::ToOptString(Emphasis value) {
148 switch (value) {
149 case Emphasis::kOff:
150 return "off";
151 case Emphasis::kLow:
152 return "low";
154 return "medium";
155 case Emphasis::kHigh:
156 return "high";
158 return "very_high";
159 }
160 return std::nullopt;
161}
162
163absl::Span<const Emphasis> Enum<Emphasis>::AllValues() {
164 static constexpr Emphasis kEmphasisValues[] = {
167 };
168 return absl::MakeConstSpan(kEmphasisValues);
169}
170
171bool AbslParseFlag(absl::string_view text, Emphasis* const value,
172 std::string* const error) {
173 return ParseEnumFlag(text, value, error);
174}
175
176std::string AbslUnparseFlag(const Emphasis value) {
177 return UnparseEnumFlag(value);
178}
179
180GurobiParametersProto GurobiParameters::Proto() const {
181 GurobiParametersProto result;
182 for (const auto& [key, val] : param_values) {
183 GurobiParametersProto::Parameter& p = *result.add_parameters();
184 p.set_name(key);
185 p.set_value(val);
186 }
187 return result;
188}
189
191 const GurobiParametersProto& proto) {
192 GurobiParameters result;
193 for (const GurobiParametersProto::Parameter& p : proto.parameters()) {
194 result.param_values[p.name()] = p.value();
195 }
196 return result;
197}
198
199GlpkParametersProto GlpkParameters::Proto() const {
200 GlpkParametersProto result;
201 if (compute_unbound_rays_if_possible.has_value()) {
202 result.set_compute_unbound_rays_if_possible(
204 }
205 return result;
206}
207
208GlpkParameters GlpkParameters::FromProto(const GlpkParametersProto& proto) {
209 GlpkParameters result;
210 if (proto.has_compute_unbound_rays_if_possible()) {
212 proto.compute_unbound_rays_if_possible();
213 }
214 return result;
215}
216
217SolveParametersProto SolveParameters::Proto() const {
218 SolveParametersProto result;
219 result.set_enable_output(enable_output);
220 if (time_limit < absl::InfiniteDuration()) {
222 result.mutable_time_limit()));
223 }
224 if (iteration_limit.has_value()) {
225 result.set_iteration_limit(*iteration_limit);
226 }
227 if (node_limit.has_value()) {
228 result.set_node_limit(*node_limit);
229 }
230 if (cutoff_limit.has_value()) {
231 result.set_cutoff_limit(*cutoff_limit);
232 }
233 if (objective_limit.has_value()) {
234 result.set_objective_limit(*objective_limit);
235 }
236 if (best_bound_limit.has_value()) {
237 result.set_best_bound_limit(*best_bound_limit);
238 }
239 if (solution_limit.has_value()) {
240 result.set_solution_limit(*solution_limit);
241 }
242 if (threads.has_value()) {
243 result.set_threads(*threads);
244 }
245 if (random_seed.has_value()) {
246 result.set_random_seed(*random_seed);
247 }
248 if (relative_gap_tolerance.has_value()) {
249 result.set_relative_gap_tolerance(*relative_gap_tolerance);
250 }
251 if (absolute_gap_tolerance.has_value()) {
252 result.set_absolute_gap_tolerance(*absolute_gap_tolerance);
253 }
254 if (solution_pool_size.has_value()) {
255 result.set_solution_pool_size(*solution_pool_size);
256 }
257 result.set_lp_algorithm(EnumToProto(lp_algorithm));
258 result.set_presolve(EnumToProto(presolve));
259 result.set_cuts(EnumToProto(cuts));
260 result.set_heuristics(EnumToProto(heuristics));
261 result.set_scaling(EnumToProto(scaling));
262 *result.mutable_gscip() = gscip;
263 *result.mutable_gurobi() = gurobi.Proto();
264 *result.mutable_glop() = glop;
265 *result.mutable_cp_sat() = cp_sat;
266 *result.mutable_pdlp() = pdlp;
267 *result.mutable_glpk() = glpk.Proto();
268 *result.mutable_highs() = highs;
269 return result;
270}
271
272absl::StatusOr<SolveParameters> SolveParameters::FromProto(
273 const SolveParametersProto& proto) {
274 SolveParameters result;
275 result.enable_output = proto.enable_output();
276 if (proto.has_time_limit()) {
278 util_time::DecodeGoogleApiProto(proto.time_limit()),
279 _ << "invalid time_limit");
280 } else {
281 result.time_limit = absl::InfiniteDuration();
282 }
283 if (proto.has_iteration_limit()) {
284 result.iteration_limit = proto.iteration_limit();
285 }
286 if (proto.has_node_limit()) {
287 result.node_limit = proto.node_limit();
288 }
289 if (proto.has_cutoff_limit()) {
290 result.cutoff_limit = proto.cutoff_limit();
291 }
292 if (proto.has_objective_limit()) {
293 result.objective_limit = proto.objective_limit();
294 }
295 if (proto.has_best_bound_limit()) {
296 result.best_bound_limit = proto.best_bound_limit();
297 }
298 if (proto.has_solution_limit()) {
299 result.solution_limit = proto.solution_limit();
300 }
301 if (proto.has_threads()) {
302 result.threads = proto.threads();
303 }
304 if (proto.has_random_seed()) {
305 result.random_seed = proto.random_seed();
306 }
307 if (proto.has_absolute_gap_tolerance()) {
308 result.absolute_gap_tolerance = proto.absolute_gap_tolerance();
309 }
310 if (proto.has_relative_gap_tolerance()) {
311 result.relative_gap_tolerance = proto.relative_gap_tolerance();
312 }
313 if (proto.has_solution_pool_size()) {
314 result.solution_pool_size = proto.solution_pool_size();
315 }
316 result.lp_algorithm = EnumFromProto(proto.lp_algorithm());
317 result.presolve = EnumFromProto(proto.presolve());
318 result.cuts = EnumFromProto(proto.cuts());
319 result.heuristics = EnumFromProto(proto.heuristics());
320 result.scaling = EnumFromProto(proto.scaling());
321 result.gscip = proto.gscip();
322 result.gurobi = GurobiParameters::FromProto(proto.gurobi());
323 result.glop = proto.glop();
324 result.cp_sat = proto.cp_sat();
325 result.pdlp = proto.pdlp();
326 result.glpk = GlpkParameters::FromProto(proto.glpk());
327 result.highs = proto.highs();
328 return result;
329}
330
331bool AbslParseFlag(absl::string_view text, SolveParameters* solve_parameters,
332 std::string* error) {
333 SolveParametersProto proto;
334 if (!ProtobufParseTextProtoForFlag(text, &proto, error)) {
335 return false;
336 }
337 absl::StatusOr<SolveParameters> params = SolveParameters::FromProto(proto);
338 if (!params.ok()) {
339 *error = absl::StrCat(
340 "SolveParametersProto was invalid and could not convert to "
341 "SolveParameters: ",
342 params.status().ToString());
343 return false;
344 }
345 *solve_parameters = *std::move(params);
346 return true;
347}
348
349std::string AbslUnparseFlag(SolveParameters solve_parameters) {
350 return ProtobufTextFormatPrintToStringForFlag(solve_parameters.Proto());
351}
352
353} // namespace math_opt
354} // namespace operations_research
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
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:185
LPAlgorithm
Selects an algorithm for solving linear programs.
Definition parameters.h:134
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:252
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:222
static GurobiParameters FromProto(const GurobiParametersProto &proto)
std::optional< LPAlgorithm > lp_algorithm
Definition parameters.h:399
pdlp::PrimalDualHybridGradientParams pdlp
Definition parameters.h:425
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:338
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)