24#include "absl/cleanup/cleanup.h"
25#include "absl/container/flat_hash_map.h"
26#include "absl/log/check.h"
27#include "absl/log/log.h"
28#include "absl/memory/memory.h"
29#include "absl/status/status.h"
30#include "absl/status/statusor.h"
31#include "absl/strings/str_cat.h"
32#include "absl/strings/str_join.h"
33#include "absl/strings/str_split.h"
34#include "absl/strings/string_view.h"
35#include "absl/time/clock.h"
36#include "absl/time/time.h"
37#include "absl/types/span.h"
74absl::string_view SafeName(
const VariablesProto& variables,
int index) {
75 if (variables.names().empty()) {
78 return variables.names(index);
83 if (linear_constraints.names().empty()) {
86 return linear_constraints.names(index);
89absl::StatusOr<TerminationProto> BuildTermination(
91 const bool is_maximize,
const double objective_value) {
120 is_maximize, interrupter !=
nullptr && interrupter->IsInterrupted()
131 interrupter !=
nullptr && interrupter->IsInterrupted()
143 interrupter !=
nullptr && interrupter->IsInterrupted()
151 return absl::InternalError(
152 absl::StrCat(
"Unexpected GLOP termination reason: ",
155 LOG(FATAL) <<
"Unimplemented GLOP termination reason: "
160absl::Status ValidateGlopParameters(
const glop::GlopParameters& parameters) {
162 if (!error.empty()) {
164 <<
"invalid GlopParameters: " << error;
166 return absl::OkStatus();
171GlopSolver::GlopSolver() : linear_program_(), lp_solver_() {}
173void GlopSolver::AddVariables(
const VariablesProto& variables) {
175 const glop::ColIndex col_index = linear_program_.CreateNewVariable();
176 linear_program_.SetVariableBounds(col_index, variables.lower_bounds(i),
177 variables.upper_bounds(i));
178 linear_program_.SetVariableName(col_index, SafeName(variables, i));
186template <
typename IndexType>
189 IndexType num_indices,
190 absl::flat_hash_map<int64_t, IndexType>& id_index_map) {
192 num_indices.value(), IndexType(0));
193 IndexType new_index(0);
194 for (IndexType index(0); index < num_indices; ++index) {
195 if (indices_to_delete[index]) {
197 new_indices[index] = IndexType(-1);
199 new_indices[index] = new_index;
203 for (
auto it = id_index_map.begin(); it != id_index_map.end();) {
204 IndexType index = it->second;
205 if (indices_to_delete[index]) {
207 id_index_map.erase(it++);
209 it->second = new_indices[index];
215void GlopSolver::DeleteVariables(absl::Span<const int64_t> ids_to_delete) {
216 const glop::ColIndex num_cols = linear_program_.num_variables();
219 for (
const int64_t deleted_variable_id : ids_to_delete) {
220 columns_to_delete[variables_.at(deleted_variable_id)] =
true;
222 linear_program_.DeleteColumns(columns_to_delete);
223 UpdateIdIndexMap<glop::ColIndex>(columns_to_delete, num_cols, variables_);
226void GlopSolver::DeleteLinearConstraints(
227 absl::Span<const int64_t> ids_to_delete) {
228 const glop::RowIndex num_rows = linear_program_.num_constraints();
229 glop::DenseBooleanColumn rows_to_delete(num_rows,
false);
230 for (
const int64_t deleted_constraint_id : ids_to_delete) {
231 rows_to_delete[linear_constraints_.at(deleted_constraint_id)] =
true;
233 linear_program_.DeleteRows(rows_to_delete);
234 UpdateIdIndexMap<glop::RowIndex>(rows_to_delete, num_rows,
235 linear_constraints_);
238void GlopSolver::AddLinearConstraints(
239 const LinearConstraintsProto& linear_constraints) {
241 const glop::RowIndex row_index = linear_program_.CreateNewConstraint();
242 linear_program_.SetConstraintBounds(row_index,
243 linear_constraints.lower_bounds(i),
244 linear_constraints.upper_bounds(i));
245 linear_program_.SetConstraintName(row_index,
246 SafeName(linear_constraints, i));
252void GlopSolver::SetOrUpdateObjectiveCoefficients(
253 const SparseDoubleVectorProto& linear_objective_coefficients) {
254 for (
int i = 0;
i < linear_objective_coefficients.ids_size(); ++
i) {
255 const glop::ColIndex col_index =
256 variables_.at(linear_objective_coefficients.ids(i));
257 linear_program_.SetObjectiveCoefficient(
258 col_index, linear_objective_coefficients.values(i));
262void GlopSolver::SetOrUpdateConstraintMatrix(
263 const SparseDoubleMatrixProto& linear_constraint_matrix) {
265 const glop::ColIndex col_index =
266 variables_.at(linear_constraint_matrix.column_ids(j));
267 const glop::RowIndex row_index =
268 linear_constraints_.at(linear_constraint_matrix.row_ids(j));
269 const double coefficient = linear_constraint_matrix.coefficients(j);
270 linear_program_.SetCoefficient(row_index, col_index, coefficient);
274void GlopSolver::UpdateVariableBounds(
275 const VariableUpdatesProto& variable_updates) {
276 for (
const auto [
id, lb] :
MakeView(variable_updates.lower_bounds())) {
277 const auto col_index = variables_.at(
id);
278 linear_program_.SetVariableBounds(
279 col_index, lb, linear_program_.variable_upper_bounds()[col_index]);
281 for (
const auto [
id, ub] :
MakeView(variable_updates.upper_bounds())) {
282 const auto col_index = variables_.at(
id);
283 linear_program_.SetVariableBounds(
284 col_index, linear_program_.variable_lower_bounds()[col_index], ub);
288void GlopSolver::UpdateLinearConstraintBounds(
289 const LinearConstraintUpdatesProto& linear_constraint_updates) {
290 for (
const auto [
id, lb] :
291 MakeView(linear_constraint_updates.lower_bounds())) {
292 const auto row_index = linear_constraints_.at(
id);
293 linear_program_.SetConstraintBounds(
294 row_index, lb, linear_program_.constraint_upper_bounds()[row_index]);
296 for (
const auto [
id, ub] :
297 MakeView(linear_constraint_updates.upper_bounds())) {
298 const auto row_index = linear_constraints_.at(
id);
299 linear_program_.SetConstraintBounds(
300 row_index, linear_program_.constraint_lower_bounds()[row_index], ub);
306 const bool setting_initial_basis,
const bool has_message_callback,
307 const bool is_maximization) {
310 <<
"invalid SolveParametersProto.glop value";
313 std::vector<std::string> warnings;
319 if (has_message_callback) {
337 const int random_seed = std::max(0, solve_parameters.
random_seed());
345 warnings.emplace_back(
"GLOP does snot support 'node_limit' parameter");
357 warnings.emplace_back(absl::StrCat(
358 "GLOP does not support the 'lp_algorithm' parameter value: ",
364 switch (solve_parameters.
scaling()) {
376 LOG(FATAL) <<
"Scaling emphasis: "
378 <<
" unknown, error setting GLOP parameters";
381 if (setting_initial_basis) {
385 switch (solve_parameters.
presolve()) {
396 LOG(FATAL) <<
"Presolve emphasis: "
398 <<
" unknown, error setting GLOP parameters";
402 warnings.push_back(absl::StrCat(
403 "GLOP does not support 'cuts' parameters, but cuts was set to: ",
408 absl::StrCat(
"GLOP does not support 'heuristics' parameter, but "
409 "heuristics was set to: ",
413 warnings.push_back(
"GLOP does not support 'cutoff_limit' parameter");
417 const auto set_upper_limit_if_missing = [&result](
const double limit) {
423 const auto set_lower_limit_if_missing = [&result](
const double limit) {
429 if (is_maximization) {
436 if (is_maximization) {
443 warnings.push_back(
"GLOP does not support 'solution_limit' parameter");
445 if (!warnings.empty()) {
446 return absl::InvalidArgumentError(absl::StrJoin(warnings,
"; "));
455 <<
"invalid GlopParameters generated from SolveParametersProto";
460template <
typename IndexType>
462 absl::Span<const int64_t> ids_in_order,
463 const absl::flat_hash_map<int64_t, IndexType>& id_map,
468 for (
const int64_t variable_id : ids_in_order) {
469 const double value = values[id_map.at(variable_id)];
479template <
typename ValueType>
481 switch (glop_basis_status) {
482 case ValueType::BASIC:
484 case ValueType::FIXED_VALUE:
486 case ValueType::AT_LOWER_BOUND:
488 case ValueType::AT_UPPER_BOUND:
490 case ValueType::FREE:
496template <
typename IndexType,
typename ValueType>
498 absl::Span<const int64_t> ids_in_order,
499 const absl::flat_hash_map<int64_t, IndexType>& id_map,
502 for (
const int64_t variable_id : ids_in_order) {
503 const ValueType value = values[id_map.at(variable_id)];
511template <
typename ValueType>
513 switch (basis_status) {
515 return ValueType::BASIC;
517 return ValueType::FIXED_VALUE;
519 return ValueType::AT_LOWER_BOUND;
521 return ValueType::AT_UPPER_BOUND;
523 return ValueType::FREE;
525 LOG(FATAL) <<
"Unexpected invalid initial_basis.";
526 return ValueType::FREE;
532 const absl::flat_hash_map<int64_t, T>& id_map) {
533 std::vector<int64_t> sorted;
534 sorted.reserve(id_map.size());
535 for (
const auto& entry : id_map) {
536 sorted.emplace_back(entry.first);
538 std::sort(sorted.begin(), sorted.end());
547 const absl::flat_hash_map<int64_t, T>& id_map) {
549 constexpr int64_t kEmptyId = -1;
551 for (
const auto& [
id, index] : id_map) {
552 CHECK(index >= 0 && index < index_to_id.
size()) << index;
553 CHECK_EQ(index_to_id[index], kEmptyId);
554 index_to_id[index] = id;
564InvertedBounds GlopSolver::ListInvertedBounds()
const {
566 std::vector<glop::ColIndex> inverted_columns;
567 const glop::ColIndex num_cols = linear_program_.num_variables();
568 for (glop::ColIndex col(0); col < num_cols; ++col) {
569 if (linear_program_.variable_lower_bounds()[col] >
570 linear_program_.variable_upper_bounds()[col]) {
571 inverted_columns.push_back(col);
574 std::vector<glop::RowIndex> inverted_rows;
575 const glop::RowIndex num_rows = linear_program_.num_constraints();
576 for (glop::RowIndex row(0); row < num_rows; ++row) {
577 if (linear_program_.constraint_lower_bounds()[row] >
578 linear_program_.constraint_upper_bounds()[row]) {
579 inverted_rows.push_back(row);
585 InvertedBounds inverted_bounds;
586 if (!inverted_columns.empty()) {
587 const glop::StrictITIVector<glop::ColIndex, int64_t> ids =
589 CHECK_EQ(ids.size(), num_cols);
590 inverted_bounds.variables.reserve(inverted_columns.size());
591 for (
const glop::ColIndex col : inverted_columns) {
592 inverted_bounds.variables.push_back(ids[col]);
595 if (!inverted_rows.empty()) {
596 const glop::StrictITIVector<glop::RowIndex, int64_t> ids =
598 CHECK_EQ(ids.size(), num_rows);
599 inverted_bounds.linear_constraints.reserve(inverted_rows.size());
600 for (
const glop::RowIndex row : inverted_rows) {
601 inverted_bounds.linear_constraints.push_back(ids[row]);
605 return inverted_bounds;
608void GlopSolver::FillSolution(
const glop::ProblemStatus status,
609 const ModelSolveParametersProto& model_parameters,
610 SolveResultProto& solve_result) {
615 const bool phase_I_solution_available =
616 (status == glop::ProblemStatus::INIT) &&
617 (lp_solver_.GetNumberOfSimplexIterations() > 0);
618 if (status != glop::ProblemStatus::OPTIMAL &&
619 status != glop::ProblemStatus::PRIMAL_FEASIBLE &&
620 status != glop::ProblemStatus::DUAL_FEASIBLE &&
621 status != glop::ProblemStatus::PRIMAL_UNBOUNDED &&
622 status != glop::ProblemStatus::DUAL_UNBOUNDED &&
623 !phase_I_solution_available) {
627 auto sorted_constraints =
GetSortedIs(linear_constraints_);
628 SolutionProto*
const solution = solve_result.add_solutions();
629 BasisProto*
const basis =
solution->mutable_basis();
631 solution->mutable_primal_solution();
632 DualSolutionProto*
const dual_solution =
solution->mutable_dual_solution();
637 if (status == glop::ProblemStatus::OPTIMAL) {
639 basis->set_basic_dual_feasibility(SOLUTION_STATUS_FEASIBLE);
640 dual_solution->set_feasibility_status(SOLUTION_STATUS_FEASIBLE);
641 }
else if (status == glop::ProblemStatus::PRIMAL_FEASIBLE) {
646 dual_solution->set_feasibility_status(SOLUTION_STATUS_UNDETERMINED);
647 basis->set_basic_dual_feasibility(SOLUTION_STATUS_INFEASIBLE);
648 }
else if (status == glop::ProblemStatus::DUAL_FEASIBLE) {
655 dual_solution->set_feasibility_status(SOLUTION_STATUS_FEASIBLE);
656 basis->set_basic_dual_feasibility(SOLUTION_STATUS_FEASIBLE);
659 if (lp_solver_.GetParameters().use_dual_simplex()) {
664 dual_solution->set_feasibility_status(SOLUTION_STATUS_INFEASIBLE);
665 basis->set_basic_dual_feasibility(SOLUTION_STATUS_INFEASIBLE);
669 dual_solution->set_feasibility_status(SOLUTION_STATUS_UNDETERMINED);
670 basis->set_basic_dual_feasibility(SOLUTION_STATUS_UNDETERMINED);
676 if (basis->basic_dual_feasibility() == SOLUTION_STATUS_FEASIBLE) {
678 dual_solution->set_objective_value(
primal_solution->objective_value());
682 *basis->mutable_constraint_status() = *basis->mutable_variable_status() =
684 lp_solver_.variable_statuses());
685 *basis->mutable_constraint_status() =
687 lp_solver_.constraint_statuses());
690 sorted_variables, variables_, lp_solver_.variable_values(),
691 model_parameters.variable_values_filter());
694 sorted_constraints, linear_constraints_, lp_solver_.dual_values(),
695 model_parameters.dual_values_filter());
697 sorted_variables, variables_, lp_solver_.reduced_costs(),
698 model_parameters.reduced_costs_filter());
700 if (!lp_solver_.primal_ray().empty()) {
701 PrimalRayProto*
const primal_ray = solve_result.add_primal_rays();
704 sorted_variables, variables_, lp_solver_.primal_ray(),
705 model_parameters.variable_values_filter());
707 if (!lp_solver_.constraints_dual_ray().empty() &&
708 !lp_solver_.variable_bounds_dual_ray().empty()) {
709 DualRayProto*
const dual_ray = solve_result.add_dual_rays();
710 *dual_ray->mutable_dual_values() =
712 lp_solver_.constraints_dual_ray(),
713 model_parameters.dual_values_filter());
715 sorted_variables, variables_, lp_solver_.variable_bounds_dual_ray(),
716 model_parameters.reduced_costs_filter());
720absl::Status GlopSolver::FillSolveStats(
const absl::Duration solve_time,
721 SolveStatsProto& solve_stats) {
723 solve_stats.set_simplex_iterations(lp_solver_.GetNumberOfSimplexIterations());
725 solve_time, solve_stats.mutable_solve_time()));
727 return absl::OkStatus();
730absl::StatusOr<SolveResultProto> GlopSolver::MakeSolveResult(
731 const glop::ProblemStatus status,
732 const ModelSolveParametersProto& model_parameters,
733 const SolveInterrupter*
const interrupter,
734 const absl::Duration solve_time) {
735 SolveResultProto solve_result;
737 BuildTermination(status, interrupter,
738 linear_program_.IsMaximizationProblem(),
739 lp_solver_.GetObjectiveValue()));
740 FillSolution(status, model_parameters, solve_result);
742 FillSolveStats(solve_time, *solve_result.mutable_solve_stats()));
746void GlopSolver::SetGlopBasis(
const BasisProto& basis) {
747 glop::VariableStatusRow variable_statuses(linear_program_.num_variables());
748 for (
const auto [
id, value] :
MakeView(basis.variable_status())) {
749 variable_statuses[variables_.at(
id)] =
750 ToGlopBasisStatus<glop::VariableStatus>(
753 glop::ConstraintStatusColumn constraint_statuses(
754 linear_program_.num_constraints());
755 for (
const auto [
id, value] :
MakeView(basis.constraint_status())) {
756 constraint_statuses[linear_constraints_.at(
id)] =
757 ToGlopBasisStatus<glop::ConstraintStatus>(
760 lp_solver_.SetInitialBasis(variable_statuses, constraint_statuses);
770 model_parameters, kGlopSupportedStructures,
"Glop"));
774 const absl::Time start = absl::Now();
780 message_cb !=
nullptr,
781 linear_program_.IsMaximizationProblem()));
782 lp_solver_.SetParameters(glop_parameters);
788 std::atomic<bool> interrupt_solve =
false;
791 time_limit->RegisterExternalBooleanAsLimit(&interrupt_solve);
794 CHECK_NE(interrupter,
nullptr);
795 interrupt_solve =
true;
798 if (message_cb !=
nullptr) {
806 CHECK_EQ(lp_solver_.GetSolverLogger().NumInfoLoggingCallbacks(), 0);
807 lp_solver_.GetSolverLogger().AddInfoLoggingCallback(
808 [&](absl::string_view message) {
809 message_cb(absl::StrSplit(message,
'\n'));
812 const auto message_cb_cleanup = absl::MakeCleanup([&]() {
813 if (message_cb !=
nullptr) {
815 CHECK_EQ(lp_solver_.GetSolverLogger().NumInfoLoggingCallbacks(), 1);
816 lp_solver_.GetSolverLogger().ClearInfoLoggingCallbacks();
826 lp_solver_.SolveWithTimeLimit(linear_program_,
time_limit.get());
827 const absl::Duration solve_time = absl::Now() - start;
828 return MakeSolveResult(status, model_parameters, interrupter, solve_time);
834 auto solver = absl::WrapUnique(
new GlopSolver);
838 solver->linear_program_.SetDcheckBounds(
false);
840 solver->linear_program_.SetName(model.
name());
842 solver->linear_program_.SetObjectiveOffset(model.
objective().
offset());
845 solver->SetOrUpdateObjectiveCoefficients(
850 solver->linear_program_.CleanUp();
860 linear_program_.SetMaximizationProblem(
864 linear_program_.SetObjectiveOffset(
871 SetOrUpdateObjectiveCoefficients(
881 linear_program_.CleanUp();
886absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
890 return absl::UnimplementedError(
891 "GLOP does not implement a method to compute an infeasible subsystem");
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static std::unique_ptr< TimeLimit > FromParameters(const Parameters ¶meters)
bool has_random_seed() const
optional int32 random_seed = 43 [default = 1];
bool has_objective_lower_limit() const
optional double objective_lower_limit = 40 [default = -inf];
bool has_log_search_progress() const
optional bool log_search_progress = 61 [default = false];
bool has_use_scaling() const
optional bool use_scaling = 16 [default = true];
static constexpr ScalingAlgorithm EQUILIBRATION
void set_log_to_stdout(bool value)
bool has_scaling_method() const
optional .operations_research.glop.GlopParameters.ScalingAlgorithm scaling_method = 57 [default = EQU...
void set_scaling_method(::operations_research::glop::GlopParameters_ScalingAlgorithm value)
void set_num_omp_threads(::int32_t value)
void set_objective_lower_limit(double value)
bool has_objective_upper_limit() const
optional double objective_upper_limit = 41 [default = inf];
bool has_num_omp_threads() const
optional int32 num_omp_threads = 44 [default = 1];
void set_random_seed(::int32_t value)
void set_use_dual_simplex(bool value)
bool has_max_time_in_seconds() const
optional double max_time_in_seconds = 26 [default = inf];
bool has_max_number_of_iterations() const
optional int64 max_number_of_iterations = 27 [default = -1];
void set_max_time_in_seconds(double value)
bool has_use_dual_simplex() const
optional bool use_dual_simplex = 31 [default = false];
void set_max_number_of_iterations(::int64_t value)
bool has_use_preprocessing() const
optional bool use_preprocessing = 34 [default = true];
void set_objective_upper_limit(double value)
void set_log_search_progress(bool value)
void set_use_scaling(bool value)
void set_use_preprocessing(bool value)
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update) override
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto ¶meters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *interrupter) override
absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto ¶meters, MessageCallback message_cb, const SolveInterrupter *interrupter) override
static absl::StatusOr< glop::GlopParameters > MergeSolveParameters(const SolveParametersProto &solve_parameters, bool setting_initial_basis, bool has_message_callback, bool is_maximization)
static absl::StatusOr< std::unique_ptr< SolverInterface > > New(const ModelProto &model, const InitArgs &init_args)
const ::operations_research::math_opt::VariablesProto & variables() const
const ::operations_research::math_opt::LinearConstraintsProto & linear_constraints() const
const ::std::string & name() const
const ::operations_research::math_opt::ObjectiveProto & objective() const
const ::operations_research::math_opt::SparseDoubleMatrixProto & linear_constraint_matrix() const
const ::operations_research::math_opt::BasisProto & initial_basis() const
bool has_initial_basis() const
.operations_research.math_opt.BasisProto initial_basis = 4;
::int64_t deleted_linear_constraint_ids(int index) const
const ::operations_research::math_opt::SparseDoubleMatrixProto & linear_constraint_matrix_updates() const
const ::operations_research::math_opt::LinearConstraintsProto & new_linear_constraints() const
const ::operations_research::math_opt::VariableUpdatesProto & variable_updates() const
const ::operations_research::math_opt::ObjectiveUpdatesProto & objective_updates() const
const ::operations_research::math_opt::LinearConstraintUpdatesProto & linear_constraint_updates() const
::int64_t deleted_variable_ids(int index) const
const ::operations_research::math_opt::VariablesProto & new_variables() const
const ::operations_research::math_opt::SparseDoubleVectorProto & linear_coefficients() const
double offset_update() const
const ::operations_research::math_opt::SparseDoubleVectorProto & linear_coefficients() const
bool direction_update() const
bool has_direction_update() const
optional bool direction_update = 1;
bool has_offset_update() const
optional double offset_update = 2;
::operations_research::math_opt::EmphasisProto presolve() const
bool has_cutoff_limit() const
optional double cutoff_limit = 20;
::int32_t threads() const
bool has_objective_limit() const
optional double objective_limit = 21;
bool has_random_seed() const
optional int32 random_seed = 5;
bool has_solution_limit() const
optional int32 solution_limit = 23;
const ::operations_research::glop::GlopParameters & glop() const
::operations_research::math_opt::EmphasisProto scaling() const
::int32_t random_seed() const
::operations_research::math_opt::EmphasisProto heuristics() const
bool has_node_limit() const
optional int64 node_limit = 24;
double objective_limit() const
bool enable_output() const
double best_bound_limit() const
::operations_research::math_opt::LPAlgorithmProto lp_algorithm() const
::int64_t iteration_limit() const
bool has_best_bound_limit() const
optional double best_bound_limit = 22;
bool has_threads() const
optional int32 threads = 4;
const ::google::protobuf::Duration & time_limit() const
bool has_time_limit() const
.google.protobuf.Duration time_limit = 1;
::operations_research::math_opt::EmphasisProto cuts() const
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >( const CallbackDataProto &)> Callback
void add_values(::operations_research::math_opt::BasisStatusProto value)
void add_ids(::int64_t value)
void add_ids(::int64_t value)
void add_values(double value)
bool AcceptsAndUpdate(int64_t id, const Value &value)
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
std::string ValidateParameters(const GlopParameters ¶ms)
ProblemStatus
Different statuses for a given problem.
@ INFEASIBLE_OR_UNBOUNDED
@ ABNORMAL
An error occurred during the solving process.
@ INVALID_PROBLEM
The input problem was invalid (see LinearProgram.IsValid()).
@ INIT
The solver didn't had a chance to prove anything.
std::string GetProblemStatusString(ProblemStatus problem_status)
Returns the string representation of the ProblemStatus enum.
An object oriented wrapper for quadratic constraints in ModelStorage.
TerminationProto TerminateForReason(const TerminationReasonProto reason, const absl::string_view detail)
SparseDoubleVectorProto FillSparseDoubleVector(absl::Span< const int64_t > ids_in_order, const absl::flat_hash_map< int64_t, IndexType > &id_map, const glop::StrictITIVector< IndexType, glop::Fractional > &values, const SparseVectorFilterProto &filter)
absl::Status ModelIsSupported(const ModelProto &model, const SupportedProblemStructures &support_menu, const absl::string_view solver_name)
@ TERMINATION_REASON_IMPRECISE
absl::Status ModelSolveParametersAreSupported(const ModelSolveParametersProto &model_parameters, const SupportedProblemStructures &support_menu, const absl::string_view solver_name)
int NumMatrixNonzeros(const SparseDoubleMatrixProto &matrix)
void UpdateIdIndexMap(glop::StrictITIVector< IndexType, bool > indices_to_delete, IndexType num_indices, absl::flat_hash_map< int64_t, IndexType > &id_index_map)
int NumVariables(const VariablesProto &variables)
@ LP_ALGORITHM_DUAL_SIMPLEX
@ LP_ALGORITHM_UNSPECIFIED
@ LP_ALGORITHM_PRIMAL_SIMPLEX
TerminationProto OptimalTerminationProto(const double finite_primal_objective, const double dual_objective, const absl::string_view detail)
@ FEASIBILITY_STATUS_FEASIBLE
@ FEASIBILITY_STATUS_UNDETERMINED
@ FEASIBILITY_STATUS_INFEASIBLE
TerminationProto InfeasibleOrUnboundedTerminationProto(bool is_maximize, const FeasibilityStatusProto dual_feasibility_status, const absl::string_view detail)
bool UpdateIsSupported(const ModelUpdateProto &update, const SupportedProblemStructures &support_menu)
BasisStatusProto FromGlopBasisStatus(const ValueType glop_basis_status)
ValueType should be glop's VariableStatus or ConstraintStatus.
ValueType ToGlopBasisStatus(const BasisStatusProto basis_status)
ValueType should be glop's VariableStatus or ConstraintStatus.
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)
glop::StrictITIVector< T, int64_t > IndexToId(const absl::flat_hash_map< int64_t, T > &id_map)
TerminationProto NoSolutionFoundTerminationProto(const bool is_maximize, const LimitProto limit, const std::optional< double > optional_dual_objective, const absl::string_view detail)
std::vector< int64_t > GetSortedIs(const absl::flat_hash_map< int64_t, T > &id_map)
absl::Status CheckRegisteredCallbackEvents(const CallbackRegistrationProto ®istration, const absl::flat_hash_set< CallbackEventProto > &supported_events)
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
int NumConstraints(const LinearConstraintsProto &linear_constraints)
@ BASIS_STATUS_AT_UPPER_BOUND
@ BASIS_STATUS_FIXED_VALUE
@ BASIS_STATUS_UNSPECIFIED
@ BASIS_STATUS_AT_LOWER_BOUND
TerminationProto InfeasibleTerminationProto(bool is_maximize, const FeasibilityStatusProto dual_feasibility_status, const absl::string_view detail)
TerminationProto UnboundedTerminationProto(const bool is_maximize, const absl::string_view detail)
SparseBasisStatusVector FillSparseBasisStatusVector(absl::Span< const int64_t > ids_in_order, const absl::flat_hash_map< int64_t, IndexType > &id_map, const glop::StrictITIVector< IndexType, ValueType > &values)
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
std::string ProtoEnumToString(ProtoEnumType enum_value)
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
inline ::absl::StatusOr< google::protobuf::Duration > EncodeGoogleApiProto(absl::Duration d)
StatusBuilder InvalidArgumentErrorBuilder()
#define MATH_OPT_REGISTER_SOLVER(solver_type, solver_factory)
Initialization arguments.