Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
math_opt_proto_utils.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 <algorithm>
17#include <cmath>
18#include <cstdint>
19#include <functional>
20#include <limits>
21#include <optional>
22#include <string>
23
24#include "absl/container/flat_hash_set.h"
25#include "absl/log/check.h"
26#include "absl/log/log.h"
27#include "absl/status/status.h"
28#include "absl/strings/string_view.h"
40
41namespace operations_research {
42namespace math_opt {
43namespace {
44constexpr double kInf = std::numeric_limits<double>::infinity();
45} // namespace
46
48 if (solve_result.termination().has_objective_bounds()) {
49 return solve_result.termination().objective_bounds();
50 }
51 ObjectiveBoundsProto objective_bounds;
52 objective_bounds.set_primal_bound(
53 solve_result.solve_stats().best_primal_bound());
54 objective_bounds.set_dual_bound(solve_result.solve_stats().best_dual_bound());
55 return objective_bounds;
56}
57
59 if (solve_result.termination().has_problem_status()) {
60 return solve_result.termination().problem_status();
61 }
62 ProblemStatusProto problem_status;
63 problem_status.set_primal_status(
64 solve_result.solve_stats().problem_status().primal_status());
65 problem_status.set_dual_status(
66 solve_result.solve_stats().problem_status().dual_status());
67 problem_status.set_primal_or_dual_infeasible(
69 return problem_status;
70}
71
73 CHECK_EQ(sparse_vector.ids_size(), sparse_vector.values_size());
74 // Keep track of the next index that has not yet been used for a non zero
75 // value.
76 int next = 0;
77 for (const auto [id, value] : MakeView(sparse_vector)) {
78 // Se use `!(== 0.0)` here so that we keep NaN values for which both `v ==
79 // 0` and `v != 0` returns false.
80 if (!(value == 0.0)) {
81 sparse_vector.set_ids(next, id);
82 sparse_vector.set_values(next, value);
83 ++next;
84 }
85 }
86 // At the end of the iteration, `next` contains the index of the first unused
87 // index. This means it contains the number of used elements.
88 sparse_vector.mutable_ids()->Truncate(next);
89 sparse_vector.mutable_values()->Truncate(next);
90}
91
93 const SparseVectorFilterProto& filter)
94 : filter_(filter) {
95 // We only do this test in non-optimized builds.
96 if (DEBUG_MODE && filter_.filter_by_ids()) {
97 // Checks that input filtered_ids are strictly increasing.
98 // That is: for all i, ids(i) < ids(i+1).
99 // Hence here we fail if there exists i such that ids(i) >= ids(i+1).
100 const auto& ids = filter_.filtered_ids();
101 CHECK(std::adjacent_find(ids.begin(), ids.end(),
102 std::greater_equal<int64_t>()) == ids.end())
103 << "The input filter.filtered_ids must be strictly increasing.";
104 }
105}
106
109 const SparseVectorFilterProto& filter) {
111 SparseVectorFilterPredicate predicate(filter);
112 for (const auto [id, val] : MakeView(input)) {
113 if (predicate.AcceptsAndUpdate(id, val)) {
114 result.add_ids(id);
115 result.add_values(val);
116 }
117 }
118 return result;
119}
120
121void ApplyAllFilters(const ModelSolveParametersProto& model_solve_params,
123 if (model_solve_params.has_variable_values_filter() &&
124 solution.has_primal_solution()) {
125 *solution.mutable_primal_solution()->mutable_variable_values() =
126 FilterSparseVector(solution.primal_solution().variable_values(),
127 model_solve_params.variable_values_filter());
128 }
129 if (model_solve_params.has_dual_values_filter() &&
130 solution.has_dual_solution()) {
131 *solution.mutable_dual_solution()->mutable_dual_values() =
132 FilterSparseVector(solution.dual_solution().dual_values(),
133 model_solve_params.dual_values_filter());
134 }
135 if (model_solve_params.has_reduced_costs_filter() &&
136 solution.has_dual_solution()) {
137 *solution.mutable_dual_solution()->mutable_reduced_costs() =
138 FilterSparseVector(solution.dual_solution().reduced_costs(),
139 model_solve_params.reduced_costs_filter());
140 }
141}
142
143absl::flat_hash_set<CallbackEventProto> EventSet(
144 const CallbackRegistrationProto& callback_registration) {
145 // Here we don't use for-range loop since for repeated enum fields, the type
146 // used in C++ is RepeatedField<int>. Using the generated getter instead
147 // guarantees type safety.
148 absl::flat_hash_set<CallbackEventProto> events;
149 for (int i = 0; i < callback_registration.request_registration_size(); ++i) {
150 events.emplace(callback_registration.request_registration(i));
151 }
152 return events;
153}
154
155TerminationProto TerminateForLimit(const LimitProto limit, const bool feasible,
156 const absl::string_view detail) {
157 TerminationProto result;
158 if (feasible) {
160 } else {
162 }
163 result.set_limit(limit);
164 if (!detail.empty()) {
165 result.set_detail(std::string(detail));
166 }
167 return result;
168}
169
171 const absl::string_view detail) {
172 return TerminateForLimit(limit, /*feasible=*/true, detail);
173}
174
176 const absl::string_view detail) {
177 return TerminateForLimit(limit, /*feasible=*/false, detail);
178}
179
181 const absl::string_view detail) {
182 TerminationProto result;
183 result.set_reason(reason);
184 if (!detail.empty()) {
185 result.set_detail(std::string(detail));
186 }
187 return result;
188}
189
192 bounds.set_primal_bound(is_maximize ? -kInf : +kInf);
193 bounds.set_dual_bound(is_maximize ? +kInf : -kInf);
194 return bounds;
195}
196
197namespace {
198ObjectiveBoundsProto MakeUnboundedBounds(const bool is_maximize) {
199 ObjectiveBoundsProto bounds;
200 bounds.set_primal_bound(is_maximize ? +kInf : -kInf);
201 bounds.set_dual_bound(bounds.primal_bound());
202 return bounds;
203}
204} // namespace
205
207 const TerminationReasonProto reason,
208 const absl::string_view detail) {
209 TerminationProto result;
210 result.set_reason(reason);
215 *result.mutable_objective_bounds() = MakeTrivialBounds(is_maximize);
216 if (!detail.empty()) {
217 result.set_detail(std::string(detail));
218 }
219 return result;
220}
221
222TerminationProto OptimalTerminationProto(const double finite_primal_objective,
223 const double dual_objective,
224 const absl::string_view detail) {
225 TerminationProto result;
227 result.mutable_objective_bounds()->set_primal_bound(finite_primal_objective);
228 result.mutable_objective_bounds()->set_dual_bound(dual_objective);
232 if (!detail.empty()) {
233 result.set_detail(std::string(detail));
234 }
235 return result;
236}
237
239 const absl::string_view detail) {
240 TerminationProto result;
246 *result.mutable_objective_bounds() = MakeUnboundedBounds(is_maximize);
247 if (!detail.empty()) {
248 result.set_detail(std::string(detail));
249 }
250 return result;
251}
252
254 bool is_maximize, const FeasibilityStatusProto dual_feasibility_status,
255 const absl::string_view detail) {
256 TerminationProto result;
260 result.mutable_problem_status()->set_dual_status(dual_feasibility_status);
261 *result.mutable_objective_bounds() = MakeTrivialBounds(is_maximize);
262 if (dual_feasibility_status == FEASIBILITY_STATUS_FEASIBLE) {
264 result.objective_bounds().primal_bound());
265 }
266 if (!detail.empty()) {
267 result.set_detail(std::string(detail));
268 }
269 return result;
270}
271
273 const bool is_maximize, const LimitProto limit,
274 const std::optional<double> optional_finite_primal_objective,
275 const std::optional<double> optional_dual_objective,
276 const absl::string_view detail) {
277 if (optional_finite_primal_objective.has_value()) {
278 return FeasibleTerminationProto(is_maximize, limit,
279 *optional_finite_primal_objective,
280 optional_dual_objective, detail);
281 }
282 return NoSolutionFoundTerminationProto(is_maximize, limit,
283 optional_dual_objective, detail);
284}
285
287 LimitProto limit, const double primal_objective,
288 const double dual_objective, const bool claim_dual_feasible_solution_exists,
289 const absl::string_view detail) {
290 TerminationProto result;
291 if (std::isfinite(primal_objective)) {
295 } else {
299 }
300 if (claim_dual_feasible_solution_exists) {
303 } else {
306 }
307 result.mutable_objective_bounds()->set_primal_bound(primal_objective);
308 result.mutable_objective_bounds()->set_dual_bound(dual_objective);
309 result.set_limit(limit);
310 if (!detail.empty()) {
311 result.set_detail(std::string(detail));
312 }
313 return result;
314}
315
317 const absl::string_view detail) {
319 is_maximize, LIMIT_CUTOFF, /*optional_dual_objective=*/std::nullopt,
320 detail);
321}
322
324 const bool is_maximize, const LimitProto limit,
325 const std::optional<double> optional_dual_objective,
326 const absl::string_view detail) {
327 TerminationProto result;
333 *result.mutable_objective_bounds() = MakeTrivialBounds(is_maximize);
334 if (optional_dual_objective.has_value()) {
335 result.mutable_objective_bounds()->set_dual_bound(*optional_dual_objective);
338 }
339 result.set_limit(limit);
340 if (!detail.empty()) {
341 result.set_detail(std::string(detail));
342 }
343 return result;
344}
345
347 const bool is_maximize, const LimitProto limit,
348 const double primal_objective,
349 const std::optional<double> optional_dual_objective,
350 const absl::string_view detail) {
351 TerminationProto result;
357 *result.mutable_objective_bounds() = MakeTrivialBounds(is_maximize);
358 result.mutable_objective_bounds()->set_primal_bound(primal_objective);
359 if (optional_dual_objective.has_value()) {
360 result.mutable_objective_bounds()->set_dual_bound(*optional_dual_objective);
363 }
364 result.set_limit(limit);
365 if (!detail.empty()) {
366 result.set_detail(std::string(detail));
367 }
368 return result;
369}
370
372 bool is_maximize, const FeasibilityStatusProto dual_feasibility_status,
373 const absl::string_view detail) {
374 TerminationProto result;
378 result.mutable_problem_status()->set_dual_status(dual_feasibility_status);
379 if (dual_feasibility_status == FEASIBILITY_STATUS_UNDETERMINED) {
381 }
382 *result.mutable_objective_bounds() = MakeTrivialBounds(is_maximize);
383 if (!detail.empty()) {
384 result.set_detail(std::string(detail));
385 }
386 return result;
387}
388
389absl::Status ModelIsSupported(const ModelProto& model,
390 const SupportedProblemStructures& support_menu,
391 const absl::string_view solver_name) {
392 const auto error_status = [solver_name](
393 const absl::string_view structure,
394 const SupportType support) -> absl::Status {
395 switch (support) {
398 << solver_name << " does not support " << structure;
401 << "MathOpt does not currently support " << solver_name
402 << " models with " << structure;
404 LOG(FATAL) << "Unexpected call with `kSupported`";
405 }
406 };
407 if (const SupportType support = support_menu.integer_variables;
408 support != SupportType::kSupported) {
409 for (const bool is_integer : model.variables().integers()) {
410 if (is_integer) {
411 return error_status("integer variables", support);
412 }
413 }
414 }
415 if (const SupportType support = support_menu.multi_objectives;
416 support != SupportType::kSupported) {
417 if (!model.auxiliary_objectives().empty()) {
418 return error_status("multiple objectives", support);
419 }
420 }
421 if (const SupportType support = support_menu.quadratic_objectives;
422 support != SupportType::kSupported) {
423 if (!model.objective().quadratic_coefficients().row_ids().empty()) {
424 return error_status("quadratic objectives", support);
425 }
426 for (const auto& [_, objective] : model.auxiliary_objectives()) {
427 if (!objective.quadratic_coefficients().row_ids().empty()) {
428 return error_status("quadratic objectives", support);
429 }
430 }
431 }
432 if (const SupportType support = support_menu.quadratic_constraints;
433 support != SupportType::kSupported) {
434 if (!model.quadratic_constraints().empty()) {
435 return error_status("quadratic constraints", support);
436 }
437 }
438 if (const SupportType support = support_menu.second_order_cone_constraints;
439 support != SupportType::kSupported) {
440 if (!model.second_order_cone_constraints().empty()) {
441 return error_status("second-order cone constraints", support);
442 }
443 }
444 if (const SupportType support = support_menu.sos1_constraints;
445 support != SupportType::kSupported) {
446 if (!model.sos1_constraints().empty()) {
447 return error_status("sos1 constraints", support);
448 }
449 }
450 if (const SupportType support = support_menu.sos2_constraints;
451 support != SupportType::kSupported) {
452 if (!model.sos2_constraints().empty()) {
453 return error_status("sos2 constraints", support);
454 }
455 }
456 if (const SupportType support = support_menu.indicator_constraints;
457 support != SupportType::kSupported) {
458 if (!model.indicator_constraints().empty()) {
459 return error_status("indicator constraints", support);
460 }
461 }
462 return absl::OkStatus();
463}
464
466 const SupportedProblemStructures& support_menu) {
467 if (support_menu.integer_variables != SupportType::kSupported) {
468 for (const bool is_integer :
469 update.variable_updates().integers().values()) {
470 if (is_integer) {
471 return false;
472 }
473 }
474 for (const bool is_integer : update.new_variables().integers()) {
475 if (is_integer) {
476 return false;
477 }
478 }
479 }
480 if (support_menu.multi_objectives != SupportType::kSupported) {
481 if (!update.auxiliary_objectives_updates()
483 .empty() ||
484 !update.auxiliary_objectives_updates().new_objectives().empty() ||
486 return false;
487 }
488 }
489 if (support_menu.quadratic_objectives != SupportType::kSupported) {
490 if (!update.objective_updates()
492 .row_ids()
493 .empty()) {
494 return false;
495 }
496 for (const auto& [_, new_objective] :
498 if (!new_objective.quadratic_coefficients().row_ids().empty()) {
499 return false;
500 }
501 }
502 for (const auto& [_, objective_update] :
504 if (!objective_update.quadratic_coefficients().row_ids().empty()) {
505 return false;
506 }
507 }
508 }
509 // Duck-types that the proto parameter contains fields named `new_constraints`
510 // and `deleted_constraint_ids`. This is standard for "mapped" constraints.
511 const auto contains_new_or_deleted_constraints =
512 [](const auto& constraint_update) {
513 return !constraint_update.new_constraints().empty() ||
514 !constraint_update.deleted_constraint_ids().empty();
515 };
517 if (contains_new_or_deleted_constraints(
519 return false;
520 }
521 }
523 if (contains_new_or_deleted_constraints(
525 return false;
526 }
527 }
528 if (support_menu.sos1_constraints != SupportType::kSupported) {
529 if (contains_new_or_deleted_constraints(update.sos1_constraint_updates())) {
530 return false;
531 }
532 }
533 if (support_menu.sos2_constraints != SupportType::kSupported) {
534 if (contains_new_or_deleted_constraints(update.sos2_constraint_updates())) {
535 return false;
536 }
537 }
539 if (contains_new_or_deleted_constraints(
541 return false;
542 }
543 }
544 return true;
545}
546
548 const ModelSolveParametersProto& model_parameters,
549 const SupportedProblemStructures& support_menu,
550 const absl::string_view solver_name) {
551 const auto validate_support = [solver_name](
552 const absl::string_view structure,
553 const SupportType support) -> absl::Status {
554 switch (support) {
556 return absl::OkStatus();
559 << structure << " is not supported as " << solver_name
560 << " does not support multiple objectives";
563 << structure
564 << " is not supported as MathOpt does not currently support "
565 << solver_name << " models with multiple objectives";
566 }
567 return absl::OkStatus();
568 };
569 if (model_parameters.has_primary_objective_parameters()) {
570 RETURN_IF_ERROR(validate_support(
571 "ModelSolveParametersProto.primary_objective_parameters",
572 support_menu.multi_objectives));
573 }
574 if (!model_parameters.auxiliary_objective_parameters().empty()) {
575 RETURN_IF_ERROR(validate_support(
576 "ModelSolveParametersProto.auxiliary_objective_parameters",
577 support_menu.multi_objectives));
578 }
579 return absl::OkStatus();
580}
581
583 SolveResultProto& solve_result_proto) {
584 *solve_result_proto.mutable_termination()->mutable_problem_status() =
585 GetProblemStatus(solve_result_proto);
586 *solve_result_proto.mutable_solve_stats()->mutable_problem_status() =
587 GetProblemStatus(solve_result_proto);
588 *solve_result_proto.mutable_termination()->mutable_objective_bounds() =
589 GetObjectiveBounds(solve_result_proto);
590 solve_result_proto.mutable_solve_stats()->set_best_primal_bound(
591 solve_result_proto.termination().objective_bounds().primal_bound());
592 solve_result_proto.mutable_solve_stats()->set_best_dual_bound(
593 solve_result_proto.termination().objective_bounds().dual_bound());
594}
595
596} // namespace math_opt
597} // namespace operations_research
#define RETURN_IF_ERROR(expr)
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ObjectiveProto > & new_objectives() const
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ObjectiveUpdatesProto > & objective_updates() const
::operations_research::math_opt::CallbackEventProto request_registration(int index) const
int request_registration_size() const
repeated .operations_research.math_opt.CallbackEventProto request_registration = 1;
const ::operations_research::math_opt::VariablesProto & variables() const
Definition model.pb.h:4404
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::QuadraticConstraintProto > & quadratic_constraints() const
Definition model.pb.h:4819
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::SosConstraintProto > & sos1_constraints() const
Definition model.pb.h:4877
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::SosConstraintProto > & sos2_constraints() const
Definition model.pb.h:4906
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::SecondOrderConeConstraintProto > & second_order_cone_constraints() const
Definition model.pb.h:4848
const ::operations_research::math_opt::ObjectiveProto & objective() const
Definition model.pb.h:4502
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ObjectiveProto > & auxiliary_objectives() const
Definition model.pb.h:4599
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::IndicatorConstraintProto > & indicator_constraints() const
Definition model.pb.h:4935
const ::operations_research::math_opt::SparseVectorFilterProto & variable_values_filter() const
bool has_dual_values_filter() const
.operations_research.math_opt.SparseVectorFilterProto dual_values_filter = 2;
bool has_reduced_costs_filter() const
.operations_research.math_opt.SparseVectorFilterProto reduced_costs_filter = 3;
const ::operations_research::math_opt::SparseVectorFilterProto & reduced_costs_filter() const
const ::operations_research::math_opt::SparseVectorFilterProto & dual_values_filter() const
bool has_primary_objective_parameters() const
.operations_research.math_opt.ObjectiveParametersProto primary_objective_parameters = 7;
bool has_variable_values_filter() const
.operations_research.math_opt.SparseVectorFilterProto variable_values_filter = 1;
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ObjectiveParametersProto > & auxiliary_objective_parameters() const
const ::operations_research::math_opt::SosConstraintUpdatesProto & sos1_constraint_updates() const
const ::operations_research::math_opt::AuxiliaryObjectivesUpdatesProto & auxiliary_objectives_updates() const
const ::operations_research::math_opt::VariableUpdatesProto & variable_updates() const
const ::operations_research::math_opt::QuadraticConstraintUpdatesProto & quadratic_constraint_updates() const
const ::operations_research::math_opt::SosConstraintUpdatesProto & sos2_constraint_updates() const
const ::operations_research::math_opt::IndicatorConstraintUpdatesProto & indicator_constraint_updates() const
const ::operations_research::math_opt::ObjectiveUpdatesProto & objective_updates() const
const ::operations_research::math_opt::SecondOrderConeConstraintUpdatesProto & second_order_cone_constraint_updates() const
const ::operations_research::math_opt::VariablesProto & new_variables() const
const ::operations_research::math_opt::SparseDoubleMatrixProto & quadratic_coefficients() const
Definition model.pb.h:2984
const ::operations_research::math_opt::SparseDoubleMatrixProto & quadratic_coefficients() const
void set_primal_status(::operations_research::math_opt::FeasibilityStatusProto value)
Definition result.pb.h:1786
::operations_research::math_opt::FeasibilityStatusProto dual_status() const
Definition result.pb.h:1806
void set_dual_status(::operations_research::math_opt::FeasibilityStatusProto value)
Definition result.pb.h:1810
::operations_research::math_opt::FeasibilityStatusProto primal_status() const
Definition result.pb.h:1782
::operations_research::math_opt::TerminationProto *PROTOBUF_NONNULL mutable_termination()
Definition result.pb.h:2728
const ::operations_research::math_opt::SolveStatsProto & solve_stats() const
Definition result.pb.h:2910
::operations_research::math_opt::SolveStatsProto *PROTOBUF_NONNULL mutable_solve_stats()
Definition result.pb.h:2964
const ::operations_research::math_opt::TerminationProto & termination() const
Definition result.pb.h:2674
const ::operations_research::math_opt::ProblemStatusProto & problem_status() const
Definition result.pb.h:2010
::operations_research::math_opt::ProblemStatusProto *PROTOBUF_NONNULL mutable_problem_status()
Definition result.pb.h:2064
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_ids()
::google::protobuf::RepeatedField< double > *PROTOBUF_NONNULL mutable_values()
SparseVectorFilterPredicate(const SparseVectorFilterProto &filter)
bool has_problem_status() const
.operations_research.math_opt.ProblemStatusProto problem_status = 4;
Definition result.pb.h:2360
const ::operations_research::math_opt::ObjectiveBoundsProto & objective_bounds() const
Definition result.pb.h:2473
void set_limit(::operations_research::math_opt::LimitProto value)
Definition result.pb.h:2280
void set_detail(Arg_ &&arg, Args_... args)
::operations_research::math_opt::ObjectiveBoundsProto *PROTOBUF_NONNULL mutable_objective_bounds()
Definition result.pb.h:2527
::operations_research::math_opt::ProblemStatusProto *PROTOBUF_NONNULL mutable_problem_status()
Definition result.pb.h:2429
bool has_objective_bounds() const
.operations_research.math_opt.ObjectiveBoundsProto objective_bounds = 5;
Definition result.pb.h:2458
const ::operations_research::math_opt::ProblemStatusProto & problem_status() const
Definition result.pb.h:2375
void set_reason(::operations_research::math_opt::TerminationReasonProto value)
Definition result.pb.h:2256
const ::operations_research::math_opt::SparseBoolVectorProto & integers() const
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
TerminationProto TerminateForReason(const TerminationReasonProto reason, const absl::string_view detail)
absl::Status ModelIsSupported(const ModelProto &model, const SupportedProblemStructures &support_menu, const absl::string_view solver_name)
TerminationProto FeasibleTermination(const LimitProto limit, const absl::string_view detail)
void UpgradeSolveResultProtoForStatsMigration(SolveResultProto &solve_result_proto)
TerminationProto TerminateForLimit(const LimitProto limit, const bool feasible, const absl::string_view detail)
absl::Status ModelSolveParametersAreSupported(const ModelSolveParametersProto &model_parameters, const SupportedProblemStructures &support_menu, const absl::string_view solver_name)
absl::flat_hash_set< CallbackEventProto > EventSet(const CallbackRegistrationProto &callback_registration)
Returns the callback_registration.request_registration as a set of enums.
TerminationProto OptimalTerminationProto(const double finite_primal_objective, const double dual_objective, const absl::string_view detail)
TerminationProto LimitTerminationProto(const bool is_maximize, const LimitProto limit, const std::optional< double > optional_finite_primal_objective, const std::optional< double > optional_dual_objective, const absl::string_view detail)
TerminationProto InfeasibleOrUnboundedTerminationProto(bool is_maximize, const FeasibilityStatusProto dual_feasibility_status, const absl::string_view detail)
bool UpdateIsSupported(const ModelUpdateProto &update, const SupportedProblemStructures &support_menu)
ProblemStatusProto GetProblemStatus(const SolveResultProto &solve_result)
TerminationProto FeasibleTerminationProto(const bool is_maximize, const LimitProto limit, const double primal_objective, const std::optional< double > optional_dual_objective, const absl::string_view detail)
ObjectiveBoundsProto GetObjectiveBounds(const SolveResultProto &solve_result)
TerminationProto NoSolutionFoundTerminationProto(const bool is_maximize, const LimitProto limit, const std::optional< double > optional_dual_objective, const absl::string_view detail)
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
TerminationProto CutoffTerminationProto(bool is_maximize, const absl::string_view detail)
Calls NoSolutionFoundTerminationProto() with LIMIT_CUTOFF LIMIT.
TerminationProto NoSolutionFoundTermination(const LimitProto limit, const absl::string_view detail)
TerminationProto InfeasibleTerminationProto(bool is_maximize, const FeasibilityStatusProto dual_feasibility_status, const absl::string_view detail)
SparseDoubleVectorProto FilterSparseVector(const SparseDoubleVectorProto &input, const SparseVectorFilterProto &filter)
TerminationProto UnboundedTerminationProto(const bool is_maximize, const absl::string_view detail)
void RemoveSparseDoubleVectorZeros(SparseDoubleVectorProto &sparse_vector)
void ApplyAllFilters(const ModelSolveParametersProto &model_solve_params, SolutionProto &solution)
ObjectiveBoundsProto MakeTrivialBounds(const bool is_maximize)
In SWIG mode, we don't want anything besides these top-level includes.
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
const bool DEBUG_MODE
Definition radix_sort.h:266
StatusBuilder UnimplementedErrorBuilder()
StatusBuilder InvalidArgumentErrorBuilder()
static int input(yyscan_t yyscanner)