23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/str_format.h"
36 #ifndef __PORTABLE_PLATFORM__
41 "Tells whether do dump the problem to a protobuf file.");
43 "Whether the proto dump file is compressed.");
45 "Whether the proto dump file is binary.");
47 "Number for the dump file, in the form name-000048.pb. "
48 "If < 0, the file is automatically numbered from the number of "
49 "calls to LPSolver::Solve().");
51 "Directory where dump files are written.");
53 "Base name for dump files. LinearProgram::name_ is used if "
54 "lp_dump_file_basename is empty. If LinearProgram::name_ is "
55 "empty, \"linear_program_dump_file\" is used.");
57 "Override any user parameters with the value of this flag. This is "
58 "interpreted as a GlopParameters proto in text format.");
71 void DumpLinearProgramIfRequiredByFlags(
const LinearProgram& linear_program,
73 if (!absl::GetFlag(FLAGS_lp_dump_to_proto_file))
return;
74 #ifdef __PORTABLE_PLATFORM__
75 LOG(WARNING) <<
"DumpLinearProgramIfRequiredByFlags(linear_program, num) "
76 "requested for linear_program.name()='"
77 << linear_program.name() <<
"', num=" << num
78 <<
" but is not implemented for this platform.";
80 std::string filename = absl::GetFlag(FLAGS_lp_dump_file_basename);
81 if (filename.empty()) {
82 if (linear_program.name().empty()) {
83 filename =
"linear_program_dump";
85 filename = linear_program.name();
88 const int file_num = absl::GetFlag(FLAGS_lp_dump_file_number) >= 0
89 ? absl::GetFlag(FLAGS_lp_dump_file_number)
91 absl::StrAppendFormat(&filename,
"-%06d.pb", file_num);
92 const std::string filespec =
93 absl::StrCat(absl::GetFlag(FLAGS_lp_dump_dir),
"/", filename);
96 const ProtoWriteFormat write_format = absl::GetFlag(FLAGS_lp_dump_binary_file)
100 absl::GetFlag(FLAGS_lp_dump_compressed_file))) {
101 LOG(DFATAL) <<
"Could not write " << filespec;
120 #ifndef __PORTABLE_PLATFORM__
121 if (!absl::GetFlag(FLAGS_glop_params).empty()) {
122 GlopParameters flag_params;
123 CHECK(google::protobuf::TextFormat::ParseFromString(
124 absl::GetFlag(FLAGS_glop_params), &flag_params));
125 parameters_.MergeFrom(flag_params);
145 LOG(DFATAL) <<
"SolveWithTimeLimit() called with a nullptr time_limit.";
149 num_revised_simplex_iterations_ = 0;
150 DumpLinearProgramIfRequiredByFlags(lp, num_solves_);
154 <<
"\n******************************************************************"
155 "\n* WARNING: Glop will be very slow because it will use DCHECKs *"
156 "\n* to verify the results and the precision of the solver. *"
157 "\n* You can gain at least an order of magnitude speedup by *"
158 "\n* compiling with optimizations enabled and by defining NDEBUG. *"
159 "\n******************************************************************";
164 if (!parameters_.log_search_progress() &&
VLOG_IS_ON(1)) {
179 LOG(DFATAL) <<
"The columns of the given linear program should be ordered "
180 <<
"by row and contain no zero coefficients. Call CleanUp() "
181 <<
"on it before calling Solve().";
189 if (!lp.
IsValid(parameters_.max_valid_magnitude())) {
191 "The given linear program is invalid. It contains NaNs, "
192 "coefficients too large or invalid bounds specification.");
205 const bool postsolve_is_needed =
preprocessor.Run(¤t_linear_program_);
231 constraints_dual_ray_.
clear();
232 variable_bounds_dual_ray_.
clear();
238 RunRevisedSimplexIfNeeded(&solution,
time_limit);
240 if (postsolve_is_needed)
preprocessor.DestructiveRecoverSolution(&solution);
257 ResizeSolution(RowIndex(0), ColIndex(0));
258 revised_simplex_.reset(
nullptr);
288 if (revised_simplex_ ==
nullptr) {
289 revised_simplex_ = std::make_unique<RevisedSimplex>();
290 revised_simplex_->SetLogger(&logger_);
292 revised_simplex_->LoadStateForNextSolve(state);
293 if (parameters_.use_preprocessing()) {
294 LOG(WARNING) <<
"In GLOP, SetInitialBasis() was called but the parameter "
295 "use_preprocessing is true, this will likely not result in "
319 SOLVER_LOG(&logger_,
"Final unscaled solution:");
321 if (!IsProblemSolutionConsistent(lp, solution)) {
322 SOLVER_LOG(&logger_,
"Inconsistency detected in the solution.");
337 ComputeReducedCosts(lp);
338 const Fractional primal_objective_value = ComputeObjective(lp);
339 const Fractional dual_objective_value = ComputeDualObjective(lp);
340 SOLVER_LOG(&logger_,
"Primal objective (before moving primal/dual values) = ",
342 "%.15E", ProblemObjectiveValue(lp, primal_objective_value)));
343 SOLVER_LOG(&logger_,
"Dual objective (before moving primal/dual values) = ",
344 absl::StrFormat(
"%.15E",
345 ProblemObjectiveValue(lp, dual_objective_value)));
349 parameters_.provide_strong_optimal_guarantee()) {
350 MovePrimalValuesWithinBounds(lp);
351 MoveDualValuesWithinBounds(lp);
355 problem_objective_value_ = ProblemObjectiveValue(lp, ComputeObjective(lp));
356 SOLVER_LOG(&logger_,
"Primal objective (after moving primal/dual values) = ",
357 absl::StrFormat(
"%.15E", problem_objective_value_));
359 ComputeReducedCosts(lp);
360 ComputeConstraintActivities(lp);
370 bool rhs_perturbation_is_too_large =
false;
371 bool cost_perturbation_is_too_large =
false;
372 bool primal_infeasibility_is_too_large =
false;
373 bool dual_infeasibility_is_too_large =
false;
374 bool primal_residual_is_too_large =
false;
375 bool dual_residual_is_too_large =
false;
378 ComputeMaxRhsPerturbationToEnforceOptimality(lp,
379 &rhs_perturbation_is_too_large);
380 ComputeMaxCostPerturbationToEnforceOptimality(
381 lp, &cost_perturbation_is_too_large);
382 const double primal_infeasibility =
383 ComputePrimalValueInfeasibility(lp, &primal_infeasibility_is_too_large);
384 const double dual_infeasibility =
385 ComputeDualValueInfeasibility(lp, &dual_infeasibility_is_too_large);
386 const double primal_residual =
387 ComputeActivityInfeasibility(lp, &primal_residual_is_too_large);
388 const double dual_residual =
389 ComputeReducedCostInfeasibility(lp, &dual_residual_is_too_large);
394 max_absolute_primal_infeasibility_ =
395 std::max(primal_infeasibility, primal_residual);
396 max_absolute_dual_infeasibility_ =
397 std::max(dual_infeasibility, dual_residual);
398 SOLVER_LOG(&logger_,
"Max. primal infeasibility = ",
399 max_absolute_primal_infeasibility_);
401 "Max. dual infeasibility = ", max_absolute_dual_infeasibility_);
406 const double objective_error_ub = ComputeMaxExpectedObjectiveError(lp);
407 SOLVER_LOG(&logger_,
"Objective error <= ", objective_error_ub);
410 parameters_.provide_strong_optimal_guarantee()) {
413 if (primal_infeasibility != 0.0 || dual_infeasibility != 0.0) {
414 LOG(ERROR) <<
"Primal/dual values have been moved to their bounds. "
415 <<
"Therefore the primal/dual infeasibilities should be "
416 <<
"exactly zero (but not the residuals). If this message "
417 <<
"appears, there is probably a bug in "
418 <<
"MovePrimalValuesWithinBounds() or in "
419 <<
"MoveDualValuesWithinBounds().";
421 if (rhs_perturbation_is_too_large) {
422 SOLVER_LOG(&logger_,
"The needed rhs perturbation is too large !!");
423 if (parameters_.change_status_to_imprecise()) {
427 if (cost_perturbation_is_too_large) {
428 SOLVER_LOG(&logger_,
"The needed cost perturbation is too large !!");
429 if (parameters_.change_status_to_imprecise()) {
439 if (std::abs(primal_objective_value - dual_objective_value) >
440 objective_error_ub) {
442 "The objective gap of the final solution is too large.");
443 if (parameters_.change_status_to_imprecise()) {
450 (primal_residual_is_too_large || primal_infeasibility_is_too_large)) {
452 "The primal infeasibility of the final solution is too large.");
453 if (parameters_.change_status_to_imprecise()) {
459 (dual_residual_is_too_large || dual_infeasibility_is_too_large)) {
461 "The dual infeasibility of the final solution is too large.");
462 if (parameters_.change_status_to_imprecise()) {
467 may_have_multiple_solutions_ =
472 bool LPSolver::IsOptimalSolutionOnFacet(
const LinearProgram& lp) {
477 const double kReducedCostTolerance = 1e-9;
478 const double kBoundTolerance = 1e-7;
480 for (ColIndex
col(0);
col < num_cols; ++
col) {
486 kReducedCostTolerance) &&
493 for (RowIndex
row(0);
row < num_rows; ++
row) {
499 kReducedCostTolerance) &&
509 return problem_objective_value_;
513 return max_absolute_primal_infeasibility_;
517 return max_absolute_dual_infeasibility_;
521 return may_have_multiple_solutions_;
525 return num_revised_simplex_iterations_;
529 return revised_simplex_ ==
nullptr ? 0.0
530 : revised_simplex_->DeterministicTime();
533 void LPSolver::MovePrimalValuesWithinBounds(
const LinearProgram& lp) {
535 DCHECK_EQ(num_cols, primal_values_.
size());
537 for (ColIndex
col(0);
col < num_cols; ++
col) {
547 SOLVER_LOG(&logger_,
"Max. primal values move = ", error);
550 void LPSolver::MoveDualValuesWithinBounds(
const LinearProgram& lp) {
551 const RowIndex num_rows = lp.num_constraints();
552 DCHECK_EQ(num_rows, dual_values_.
size());
553 const Fractional optimization_sign = lp.IsMaximizationProblem() ? -1.0 : 1.0;
555 for (RowIndex
row(0);
row < num_rows; ++
row) {
560 Fractional minimization_dual_value = optimization_sign * dual_values_[
row];
562 error =
std::max(error, minimization_dual_value);
563 minimization_dual_value = 0.0;
566 error =
std::max(error, -minimization_dual_value);
567 minimization_dual_value = 0.0;
569 dual_values_[
row] = optimization_sign * minimization_dual_value;
571 SOLVER_LOG(&logger_,
"Max. dual values move = ", error);
574 void LPSolver::ResizeSolution(RowIndex num_rows, ColIndex num_cols) {
575 primal_values_.
resize(num_cols, 0.0);
576 reduced_costs_.
resize(num_cols, 0.0);
579 dual_values_.resize(num_rows, 0.0);
580 constraint_activities_.
resize(num_rows, 0.0);
584 void LPSolver::RunRevisedSimplexIfNeeded(ProblemSolution* solution,
595 if (revised_simplex_ ==
nullptr) {
596 revised_simplex_ = std::make_unique<RevisedSimplex>();
597 revised_simplex_->SetLogger(&logger_);
599 revised_simplex_->SetParameters(parameters_);
600 if (revised_simplex_->Solve(current_linear_program_,
time_limit).ok()) {
601 num_revised_simplex_iterations_ = revised_simplex_->GetNumberOfIterations();
602 solution->status = revised_simplex_->GetProblemStatus();
605 const ColIndex num_cols = solution->primal_values.size();
606 DCHECK_LE(num_cols, revised_simplex_->GetProblemNumCols());
607 for (ColIndex
col(0);
col < num_cols; ++
col) {
608 solution->primal_values[
col] = revised_simplex_->GetVariableValue(
col);
609 solution->variable_statuses[
col] =
610 revised_simplex_->GetVariableStatus(
col);
612 const RowIndex num_rows = revised_simplex_->GetProblemNumRows();
613 DCHECK_EQ(solution->dual_values.size(), num_rows);
614 for (RowIndex
row(0);
row < num_rows; ++
row) {
615 solution->dual_values[
row] = revised_simplex_->GetDualValue(
row);
616 solution->constraint_statuses[
row] =
617 revised_simplex_->GetConstraintStatus(
row);
619 if (!parameters_.use_preprocessing() && !parameters_.use_scaling()) {
621 primal_ray_ = revised_simplex_->GetPrimalRay();
623 primal_ray_.
resize(num_cols);
625 constraints_dual_ray_ = revised_simplex_->GetDualRay();
626 variable_bounds_dual_ray_ =
627 revised_simplex_->GetDualRayRowCombination();
629 variable_bounds_dual_ray_.
resize(num_cols);
648 SOLVER_LOG(&logger_,
"Error during the revised simplex algorithm.");
658 VLOG(1) <<
"Variable " <<
col <<
" status is "
660 <<
" and its bounds are [" << lb <<
", " << ub <<
"].";
665 VLOG(1) <<
"Constraint " <<
row <<
" status is "
667 <<
", " << ub <<
"].";
672 bool LPSolver::IsProblemSolutionConsistent(
673 const LinearProgram& lp,
const ProblemSolution& solution)
const {
674 const RowIndex num_rows = lp.num_constraints();
675 const ColIndex num_cols = lp.num_variables();
676 if (solution.variable_statuses.size() != num_cols)
return false;
677 if (solution.constraint_statuses.size() != num_rows)
return false;
678 if (solution.primal_values.size() != num_cols)
return false;
679 if (solution.dual_values.size() != num_rows)
return false;
688 RowIndex num_basic_variables(0);
689 for (ColIndex
col(0);
col < num_cols; ++
col) {
694 switch (solution.variable_statuses[
col]) {
698 ++num_basic_variables;
716 if (
value != lb || lb == ub) {
737 for (RowIndex
row(0);
row < num_rows; ++
row) {
748 if (dual_value != 0.0) {
749 VLOG(1) <<
"Constraint " <<
row <<
" is BASIC, but its dual value is "
750 << dual_value <<
" instead of 0.";
753 ++num_basic_variables;
759 if (ub - lb > 1e-12) {
760 LogConstraintStatusError(
row,
status, lb, ub);
766 LogConstraintStatusError(
row,
status, lb, ub);
772 LogConstraintStatusError(
row,
status, lb, ub);
777 if (dual_value != 0.0) {
778 VLOG(1) <<
"Constraint " <<
row <<
" is FREE, but its dual value is "
779 << dual_value <<
" instead of 0.";
783 LogConstraintStatusError(
row,
status, lb, ub);
792 if (num_basic_variables != num_rows) {
793 VLOG(1) <<
"Wrong number of basic variables: " << num_basic_variables;
803 Fractional LPSolver::ComputeMaxCostPerturbationToEnforceOptimality(
804 const LinearProgram& lp,
bool* is_too_large) {
806 const ColIndex num_cols = lp.num_variables();
807 const Fractional optimization_sign = lp.IsMaximizationProblem() ? -1.0 : 1.0;
808 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
809 for (ColIndex
col(0);
col < num_cols; ++
col) {
813 const Fractional reduced_cost = optimization_sign * reduced_costs_[
col];
818 max_cost_correction =
819 std::max(max_cost_correction, std::abs(reduced_cost));
821 std::abs(reduced_cost) >
822 AllowedError(tolerance, lp.objective_coefficients()[
col]);
825 SOLVER_LOG(&logger_,
"Max. cost perturbation = ", max_cost_correction);
826 return max_cost_correction;
831 Fractional LPSolver::ComputeMaxRhsPerturbationToEnforceOptimality(
832 const LinearProgram& lp,
bool* is_too_large) {
834 const RowIndex num_rows = lp.num_constraints();
835 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
836 for (RowIndex
row(0);
row < num_rows; ++
row) {
846 allowed_error = AllowedError(tolerance,
lower_bound);
850 allowed_error = AllowedError(tolerance,
upper_bound);
852 max_rhs_correction =
std::max(max_rhs_correction, rhs_error);
853 *is_too_large |= rhs_error > allowed_error;
855 SOLVER_LOG(&logger_,
"Max. rhs perturbation = ", max_rhs_correction);
856 return max_rhs_correction;
859 void LPSolver::ComputeConstraintActivities(
const LinearProgram& lp) {
860 const RowIndex num_rows = lp.num_constraints();
861 const ColIndex num_cols = lp.num_variables();
862 DCHECK_EQ(num_cols, primal_values_.
size());
863 constraint_activities_.
assign(num_rows, 0.0);
864 for (ColIndex
col(0);
col < num_cols; ++
col) {
865 lp.GetSparseColumn(
col).AddMultipleToDenseVector(primal_values_[
col],
866 &constraint_activities_);
870 void LPSolver::ComputeReducedCosts(
const LinearProgram& lp) {
871 const RowIndex num_rows = lp.num_constraints();
872 const ColIndex num_cols = lp.num_variables();
873 DCHECK_EQ(num_rows, dual_values_.size());
874 reduced_costs_.resize(num_cols, 0.0);
875 for (ColIndex
col(0);
col < num_cols; ++
col) {
876 reduced_costs_[
col] = lp.objective_coefficients()[
col] -
881 double LPSolver::ComputeObjective(
const LinearProgram& lp) {
882 const ColIndex num_cols = lp.num_variables();
883 DCHECK_EQ(num_cols, primal_values_.
size());
885 for (ColIndex
col(0);
col < num_cols; ++
col) {
886 sum.
Add(lp.objective_coefficients()[
col] * primal_values_[
col]);
907 double LPSolver::ComputeDualObjective(
const LinearProgram& lp) {
911 const RowIndex num_rows = lp.num_constraints();
912 const Fractional optimization_sign = lp.IsMaximizationProblem() ? -1.0 : 1.0;
913 for (RowIndex
row(0);
row < num_rows; ++
row) {
918 const Fractional corrected_value = optimization_sign * dual_values_[
row];
943 const ColIndex num_cols = lp.num_variables();
944 for (ColIndex
col(0);
col < num_cols; ++
col) {
950 const Fractional reduced_cost = optimization_sign * reduced_costs_[
col];
956 reduced_cost > 0.0) {
959 reduced_cost < 0.0) {
965 dual_objective.Add(optimization_sign * correction);
967 return dual_objective.Value();
970 double LPSolver::ComputeMaxExpectedObjectiveError(
const LinearProgram& lp) {
971 const ColIndex num_cols = lp.num_variables();
972 DCHECK_EQ(num_cols, primal_values_.
size());
973 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
975 for (ColIndex
col(0);
col < num_cols; ++
col) {
979 primal_objective_error += std::abs(lp.objective_coefficients()[
col]) *
980 AllowedError(tolerance, primal_values_[
col]);
982 return primal_objective_error;
985 double LPSolver::ComputePrimalValueInfeasibility(
const LinearProgram& lp,
986 bool* is_too_large) {
987 double infeasibility = 0.0;
988 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
989 const ColIndex num_cols = lp.num_variables();
990 for (ColIndex
col(0);
col < num_cols; ++
col) {
997 infeasibility =
std::max(infeasibility, error);
998 *is_too_large |= error > AllowedError(tolerance,
upper_bound);
1003 infeasibility =
std::max(infeasibility, error);
1004 *is_too_large |= error > AllowedError(tolerance,
upper_bound);
1008 infeasibility =
std::max(infeasibility, error);
1009 *is_too_large |= error > AllowedError(tolerance,
lower_bound);
1012 return infeasibility;
1015 double LPSolver::ComputeActivityInfeasibility(
const LinearProgram& lp,
1016 bool* is_too_large) {
1017 double infeasibility = 0.0;
1018 int num_problematic_rows(0);
1019 const RowIndex num_rows = lp.num_constraints();
1020 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
1021 for (RowIndex
row(0);
row < num_rows; ++
row) {
1030 VLOG(2) <<
"Row " <<
row.value() <<
" has activity " << activity
1031 <<
" which is different from " <<
upper_bound <<
" by "
1033 ++num_problematic_rows;
1040 if (row_excess > AllowedError(tolerance,
upper_bound)) {
1041 VLOG(2) <<
"Row " <<
row.value() <<
" has activity " << activity
1042 <<
", exceeding its upper bound " <<
upper_bound <<
" by "
1044 ++num_problematic_rows;
1046 infeasibility =
std::max(infeasibility, row_excess);
1050 if (row_deficit > AllowedError(tolerance,
lower_bound)) {
1051 VLOG(2) <<
"Row " <<
row.value() <<
" has activity " << activity
1052 <<
", below its lower bound " <<
lower_bound <<
" by "
1054 ++num_problematic_rows;
1056 infeasibility =
std::max(infeasibility, row_deficit);
1059 if (num_problematic_rows > 0) {
1060 *is_too_large =
true;
1061 VLOG(1) <<
"Number of infeasible rows = " << num_problematic_rows;
1063 return infeasibility;
1066 double LPSolver::ComputeDualValueInfeasibility(
const LinearProgram& lp,
1067 bool* is_too_large) {
1068 const Fractional allowed_error = parameters_.solution_feasibility_tolerance();
1069 const Fractional optimization_sign = lp.IsMaximizationProblem() ? -1.0 : 1.0;
1070 double infeasibility = 0.0;
1071 const RowIndex num_rows = lp.num_constraints();
1072 for (RowIndex
row(0);
row < num_rows; ++
row) {
1077 const Fractional minimization_dual_value = optimization_sign * dual_value;
1079 *is_too_large |= minimization_dual_value > allowed_error;
1080 infeasibility =
std::max(infeasibility, minimization_dual_value);
1083 *is_too_large |= -minimization_dual_value > allowed_error;
1084 infeasibility =
std::max(infeasibility, -minimization_dual_value);
1087 return infeasibility;
1090 double LPSolver::ComputeReducedCostInfeasibility(
const LinearProgram& lp,
1091 bool* is_too_large) {
1092 const Fractional optimization_sign = lp.IsMaximizationProblem() ? -1.0 : 1.0;
1093 double infeasibility = 0.0;
1094 const ColIndex num_cols = lp.num_variables();
1095 const Fractional tolerance = parameters_.solution_feasibility_tolerance();
1096 for (ColIndex
col(0);
col < num_cols; ++
col) {
1102 optimization_sign * reduced_cost;
1104 AllowedError(tolerance, lp.objective_coefficients()[
col]);
1106 *is_too_large |= minimization_reduced_cost > allowed_error;
1107 infeasibility =
std::max(infeasibility, minimization_reduced_cost);
1110 *is_too_large |= -minimization_reduced_cost > allowed_error;
1111 infeasibility =
std::max(infeasibility, -minimization_reduced_cost);
1114 return infeasibility;
void push_back(const value_type &x)
void Add(const FpNumber &value)
void SetLogToStdOut(bool enable)
bool LoggingIsEnabled() const
void EnableLogging(bool enable)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
static std::unique_ptr< TimeLimit > FromParameters(const Parameters ¶meters)
Creates a time limit object initialized from an object that provides methods max_time_in_seconds() an...
const GlopParameters & GetParameters() const
SolverLogger & GetSolverLogger()
static std::string GlopVersion()
void SetInitialBasis(const VariableStatusRow &variable_statuses, const ConstraintStatusColumn &constraint_statuses)
const ConstraintStatusColumn & constraint_statuses() const
bool MayHaveMultipleOptimalSolutions() const
const VariableStatusRow & variable_statuses() const
GlopParameters * GetMutableParameters()
Fractional GetMaximumDualInfeasibility() const
Fractional GetMaximumPrimalInfeasibility() const
Fractional GetObjectiveValue() const
ProblemStatus LoadAndVerifySolution(const LinearProgram &lp, const ProblemSolution &solution)
ABSL_MUST_USE_RESULT ProblemStatus Solve(const LinearProgram &lp)
ABSL_MUST_USE_RESULT ProblemStatus SolveWithTimeLimit(const LinearProgram &lp, TimeLimit *time_limit)
void SetParameters(const GlopParameters ¶meters)
double DeterministicTime() const
int GetNumberOfSimplexIterations() const
std::string GetObjectiveStatsString() const
void PopulateFromLinearProgram(const LinearProgram &linear_program)
void ClearTransposeMatrix()
const DenseRow & variable_lower_bounds() const
const DenseColumn & constraint_lower_bounds() const
std::string GetBoundsStatsString() const
bool IsValid(Fractional max_valid_magnitude=kInfinity) const
Fractional objective_offset() const
const DenseColumn & constraint_upper_bounds() const
bool IsMaximizationProblem() const
const DenseRow & variable_upper_bounds() const
ColIndex num_variables() const
std::string GetDimensionString() const
Fractional objective_scaling_factor() const
RowIndex num_constraints() const
void resize(IntType size)
void assign(IntType size, const T &v)
ModelSharedTimeLimit * time_limit
ABSL_FLAG(bool, lp_dump_to_proto_file, false, "Tells whether do dump the problem to a protobuf file.")
AccurateSum< Fractional > KahanSum
Fractional ScalarProduct(const DenseRowOrColumn1 &u, const DenseRowOrColumn2 &v)
std::string GetProblemStatusString(ProblemStatus problem_status)
constexpr double kInfinity
std::string GetConstraintStatusString(ConstraintStatus status)
void LinearProgramToMPModelProto(const LinearProgram &input, MPModelProto *output)
bool IsFinite(Fractional value)
void ChangeSign(StrictITIVector< IndexType, Fractional > *data)
std::string GetVariableStatusString(VariableStatus status)
Collection of objects used to extend the Constraint Solver library.
bool WriteProtoToFile(absl::string_view filename, const google::protobuf::Message &proto, ProtoWriteFormat proto_write_format, bool gzipped, bool append_extension_to_file_name)
std::string OrToolsVersionString()
bool AreWithinAbsoluteTolerance(FloatType x, FloatType y, FloatType absolute_tolerance)
glop::MainLpPreprocessor preprocessor
VariableStatusRow statuses
VariableStatusRow variable_statuses
ConstraintStatusColumn constraint_statuses
#define SOLVER_LOG(logger,...)
#define VLOG(verboselevel)
#define VLOG_IS_ON(verboselevel)