OR-Tools  8.1
linear_solver.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 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 
14 //
15 
17 
18 #if !defined(_MSC_VER)
19 #include <unistd.h>
20 #endif
21 
22 #include <cmath>
23 #include <cstddef>
24 #include <utility>
25 
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/strings/ascii.h"
29 #include "absl/strings/match.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/str_format.h"
32 #include "absl/strings/str_replace.h"
33 #include "absl/synchronization/mutex.h"
37 #include "ortools/base/logging.h"
38 #include "ortools/base/map_util.h"
40 #include "ortools/base/stl_util.h"
44 #include "ortools/port/file.h"
45 #include "ortools/util/fp_utils.h"
46 
47 ABSL_FLAG(bool, verify_solution, false,
48  "Systematically verify the solution when calling Solve()"
49  ", and change the return value of Solve() to ABNORMAL if"
50  " an error was detected.");
51 ABSL_FLAG(bool, log_verification_errors, true,
52  "If --verify_solution is set: LOG(ERROR) all errors detected"
53  " during the verification of the solution.");
54 ABSL_FLAG(bool, linear_solver_enable_verbose_output, false,
55  "If set, enables verbose output for the solver. Setting this flag"
56  " is the same as calling MPSolver::EnableOutput().");
57 
58 ABSL_FLAG(bool, mpsolver_bypass_model_validation, false,
59  "If set, the user-provided Model won't be verified before Solve()."
60  " Invalid models will typically trigger various error responses"
61  " from the underlying solvers; sometimes crashes.");
62 
63 namespace operations_research {
64 
65 bool SolverTypeIsMip(MPModelRequest::SolverType solver_type) {
66  switch (solver_type) {
67  case MPModelRequest::GLOP_LINEAR_PROGRAMMING:
68  case MPModelRequest::CLP_LINEAR_PROGRAMMING:
69  case MPModelRequest::GLPK_LINEAR_PROGRAMMING:
70  case MPModelRequest::GUROBI_LINEAR_PROGRAMMING:
71  case MPModelRequest::XPRESS_LINEAR_PROGRAMMING:
72  case MPModelRequest::CPLEX_LINEAR_PROGRAMMING:
73  return false;
74 
75  case MPModelRequest::SCIP_MIXED_INTEGER_PROGRAMMING:
76  case MPModelRequest::GLPK_MIXED_INTEGER_PROGRAMMING:
77  case MPModelRequest::CBC_MIXED_INTEGER_PROGRAMMING:
78  case MPModelRequest::GUROBI_MIXED_INTEGER_PROGRAMMING:
79  case MPModelRequest::KNAPSACK_MIXED_INTEGER_PROGRAMMING:
80  case MPModelRequest::BOP_INTEGER_PROGRAMMING:
81  case MPModelRequest::SAT_INTEGER_PROGRAMMING:
82  case MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING:
83  case MPModelRequest::CPLEX_MIXED_INTEGER_PROGRAMMING:
84  return true;
85  }
86  LOG(DFATAL) << "Invalid SolverType: " << solver_type;
87  return false;
88 }
89 
90 double MPConstraint::GetCoefficient(const MPVariable* const var) const {
91  DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var;
92  if (var == nullptr) return 0.0;
93  return gtl::FindWithDefault(coefficients_, var, 0.0);
94 }
95 
96 void MPConstraint::SetCoefficient(const MPVariable* const var, double coeff) {
97  DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var;
98  if (var == nullptr) return;
99  if (coeff == 0.0) {
100  auto it = coefficients_.find(var);
101  // If setting a coefficient to 0 when this coefficient did not
102  // exist or was already 0, do nothing: skip
103  // interface_->SetCoefficient() and do not store a coefficient in
104  // the map. Note that if the coefficient being set to 0 did exist
105  // and was not 0, we do have to keep a 0 in the coefficients_ map,
106  // because the extraction of the constraint might rely on it,
107  // depending on the underlying solver.
108  if (it != coefficients_.end() && it->second != 0.0) {
109  const double old_value = it->second;
110  it->second = 0.0;
111  interface_->SetCoefficient(this, var, 0.0, old_value);
112  }
113  return;
114  }
115  auto insertion_result = coefficients_.insert(std::make_pair(var, coeff));
116  const double old_value =
117  insertion_result.second ? 0.0 : insertion_result.first->second;
118  insertion_result.first->second = coeff;
119  interface_->SetCoefficient(this, var, coeff, old_value);
120 }
121 
123  interface_->ClearConstraint(this);
124  coefficients_.clear();
125 }
126 
127 void MPConstraint::SetBounds(double lb, double ub) {
128  const bool change = lb != lb_ || ub != ub_;
129  lb_ = lb;
130  ub_ = ub;
131  if (change && interface_->constraint_is_extracted(index_)) {
132  interface_->SetConstraintBounds(index_, lb_, ub_);
133  }
134 }
135 
136 double MPConstraint::dual_value() const {
137  if (!interface_->IsContinuous()) {
138  LOG(DFATAL) << "Dual value only available for continuous problems";
139  return 0.0;
140  }
141  if (!interface_->CheckSolutionIsSynchronizedAndExists()) return 0.0;
142  return dual_value_;
143 }
144 
146  if (!interface_->IsContinuous()) {
147  LOG(DFATAL) << "Basis status only available for continuous problems";
148  return MPSolver::FREE;
149  }
150  if (!interface_->CheckSolutionIsSynchronizedAndExists()) {
151  return MPSolver::FREE;
152  }
153  // This is done lazily as this method is expected to be rarely used.
154  return interface_->row_status(index_);
155 }
156 
157 bool MPConstraint::ContainsNewVariables() {
158  const int last_variable_index = interface_->last_variable_index();
159  for (const auto& entry : coefficients_) {
160  const int variable_index = entry.first->index();
161  if (variable_index >= last_variable_index ||
162  !interface_->variable_is_extracted(variable_index)) {
163  return true;
164  }
165  }
166  return false;
167 }
168 
169 // ----- MPObjective -----
170 
171 double MPObjective::GetCoefficient(const MPVariable* const var) const {
172  DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var;
173  if (var == nullptr) return 0.0;
174  return gtl::FindWithDefault(coefficients_, var, 0.0);
175 }
176 
177 void MPObjective::SetCoefficient(const MPVariable* const var, double coeff) {
178  DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var;
179  if (var == nullptr) return;
180  if (coeff == 0.0) {
181  auto it = coefficients_.find(var);
182  // See the discussion on MPConstraint::SetCoefficient() for 0 coefficients,
183  // the same reasoning applies here.
184  if (it == coefficients_.end() || it->second == 0.0) return;
185  it->second = 0.0;
186  } else {
187  coefficients_[var] = coeff;
188  }
189  interface_->SetObjectiveCoefficient(var, coeff);
190 }
191 
193  offset_ = value;
194  interface_->SetObjectiveOffset(offset_);
195 }
196 
197 namespace {
198 void CheckLinearExpr(const MPSolver& solver, const LinearExpr& linear_expr) {
199  for (auto var_value_pair : linear_expr.terms()) {
200  CHECK(solver.OwnsVariable(var_value_pair.first))
201  << "Bad MPVariable* in LinearExpr, did you try adding an integer to an "
202  "MPVariable* directly?";
203  }
204 }
205 } // namespace
206 
208  bool is_maximization) {
209  CheckLinearExpr(*interface_->solver_, linear_expr);
210  interface_->ClearObjective();
211  coefficients_.clear();
212  SetOffset(linear_expr.offset());
213  for (const auto& kv : linear_expr.terms()) {
214  SetCoefficient(kv.first, kv.second);
215  }
216  SetOptimizationDirection(is_maximization);
217 }
218 
219 void MPObjective::AddLinearExpr(const LinearExpr& linear_expr) {
220  CheckLinearExpr(*interface_->solver_, linear_expr);
221  SetOffset(offset_ + linear_expr.offset());
222  for (const auto& kv : linear_expr.terms()) {
223  SetCoefficient(kv.first, GetCoefficient(kv.first) + kv.second);
224  }
225 }
226 
228  interface_->ClearObjective();
229  coefficients_.clear();
230  offset_ = 0.0;
231  SetMinimization();
232 }
233 
235  // Note(user): The maximize_ bool would more naturally belong to the
236  // MPObjective, but it actually has to be a member of MPSolverInterface,
237  // because some implementations (such as GLPK) need that bool for the
238  // MPSolverInterface constructor, i.e at a time when the MPObjective is not
239  // constructed yet (MPSolverInterface is always built before MPObjective
240  // when a new MPSolver is constructed).
241  interface_->maximize_ = maximize;
242  interface_->SetOptimizationDirection(maximize);
243 }
244 
245 bool MPObjective::maximization() const { return interface_->maximize_; }
246 
247 bool MPObjective::minimization() const { return !interface_->maximize_; }
248 
249 double MPObjective::Value() const {
250  // Note(user): implementation-wise, the objective value belongs more
251  // naturally to the MPSolverInterface, since all of its implementations write
252  // to it directly.
253  return interface_->objective_value();
254 }
255 
256 double MPObjective::BestBound() const {
257  // Note(user): the best objective bound belongs to the interface for the
258  // same reasons as the objective value does.
259  return interface_->best_objective_bound();
260 }
261 
262 // ----- MPVariable -----
263 
265  if (!interface_->CheckSolutionIsSynchronizedAndExists()) return 0.0;
266  // If the underlying solver supports integer variables, and this is an integer
267  // variable, we round the solution value (i.e., clients usually expect precise
268  // integer values for integer variables).
269  return (integer_ && interface_->IsMIP()) ? round(solution_value_)
270  : solution_value_;
271 }
272 
274  if (!interface_->CheckSolutionIsSynchronizedAndExists()) return 0.0;
275  return solution_value_;
276 }
277 
278 double MPVariable::reduced_cost() const {
279  if (!interface_->IsContinuous()) {
280  LOG(DFATAL) << "Reduced cost only available for continuous problems";
281  return 0.0;
282  }
283  if (!interface_->CheckSolutionIsSynchronizedAndExists()) return 0.0;
284  return reduced_cost_;
285 }
286 
288  if (!interface_->IsContinuous()) {
289  LOG(DFATAL) << "Basis status only available for continuous problems";
290  return MPSolver::FREE;
291  }
292  if (!interface_->CheckSolutionIsSynchronizedAndExists()) {
293  return MPSolver::FREE;
294  }
295  // This is done lazily as this method is expected to be rarely used.
296  return interface_->column_status(index_);
297 }
298 
299 void MPVariable::SetBounds(double lb, double ub) {
300  const bool change = lb != lb_ || ub != ub_;
301  lb_ = lb;
302  ub_ = ub;
303  if (change && interface_->variable_is_extracted(index_)) {
304  interface_->SetVariableBounds(index_, lb_, ub_);
305  }
306 }
307 
308 void MPVariable::SetInteger(bool integer) {
309  if (integer_ != integer) {
310  integer_ = integer;
311  if (interface_->variable_is_extracted(index_)) {
312  interface_->SetVariableInteger(index_, integer);
313  }
314  }
315 }
316 
318  if (priority == branching_priority_) return;
319  branching_priority_ = priority;
320  interface_->BranchingPriorityChangedForVariable(index_);
321 }
322 
323 // ----- Interface shortcuts -----
324 
325 bool MPSolver::IsMIP() const { return interface_->IsMIP(); }
326 
327 std::string MPSolver::SolverVersion() const {
328  return interface_->SolverVersion();
329 }
330 
331 void* MPSolver::underlying_solver() { return interface_->underlying_solver(); }
332 
333 // ---- Solver-specific parameters ----
334 
335 absl::Status MPSolver::SetNumThreads(int num_threads) {
336  if (num_threads < 1) {
337  return absl::InvalidArgumentError("num_threads must be a positive number.");
338  }
339  const absl::Status status = interface_->SetNumThreads(num_threads);
340  if (status.ok()) {
341  num_threads_ = num_threads;
342  }
343  return status;
344 }
345 
347  const std::string& parameters) {
348  solver_specific_parameter_string_ = parameters;
349  return interface_->SetSolverSpecificParametersAsString(parameters);
350 }
351 
352 // ----- Solver -----
353 
354 #if defined(USE_CLP) || defined(USE_CBC)
355 extern MPSolverInterface* BuildCLPInterface(MPSolver* const solver);
356 #endif
357 #if defined(USE_CBC)
358 extern MPSolverInterface* BuildCBCInterface(MPSolver* const solver);
359 #endif
360 #if defined(USE_GLPK)
361 extern MPSolverInterface* BuildGLPKInterface(bool mip, MPSolver* const solver);
362 #endif
363 extern MPSolverInterface* BuildBopInterface(MPSolver* const solver);
364 extern MPSolverInterface* BuildGLOPInterface(MPSolver* const solver);
365 extern MPSolverInterface* BuildSatInterface(MPSolver* const solver);
366 #if defined(USE_SCIP)
367 extern MPSolverInterface* BuildSCIPInterface(MPSolver* const solver);
368 #endif
369 extern MPSolverInterface* BuildGurobiInterface(bool mip,
370  MPSolver* const solver);
371 #if defined(USE_CPLEX)
372 extern MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver);
373 
374 extern MPSolverInterface* BuildGLOPInterface(MPSolver* const solver);
375 #endif
376 #if defined(USE_XPRESS)
377 extern MPSolverInterface* BuildXpressInterface(bool mip,
378  MPSolver* const solver);
379 #endif
380 
381 namespace {
382 MPSolverInterface* BuildSolverInterface(MPSolver* const solver) {
383  DCHECK(solver != nullptr);
384  switch (solver->ProblemType()) {
386  return BuildBopInterface(solver);
388  return BuildSatInterface(solver);
390  return BuildGLOPInterface(solver);
391 #if defined(USE_GLPK)
393  return BuildGLPKInterface(false, solver);
395  return BuildGLPKInterface(true, solver);
396 #endif
397 #if defined(USE_CLP) || defined(USE_CBC)
399  return BuildCLPInterface(solver);
400 #endif
401 #if defined(USE_CBC)
403  return BuildCBCInterface(solver);
404 #endif
405 #if defined(USE_SCIP)
407  return BuildSCIPInterface(solver);
408 #endif
410  return BuildGurobiInterface(false, solver);
412  return BuildGurobiInterface(true, solver);
413 #if defined(USE_CPLEX)
415  return BuildCplexInterface(false, solver);
417  return BuildCplexInterface(true, solver);
418 #endif
419 #if defined(USE_XPRESS)
421  return BuildXpressInterface(true, solver);
423  return BuildXpressInterface(false, solver);
424 #endif
425  default:
426  // TODO(user): Revert to the best *available* interface.
427  LOG(FATAL) << "Linear solver not recognized.";
428  }
429  return nullptr;
430 }
431 } // namespace
432 
433 namespace {
434 int NumDigits(int n) {
435 // Number of digits needed to write a non-negative integer in base 10.
436 // Note(user): max(1, log(0) + 1) == max(1, -inf) == 1.
437 #if defined(_MSC_VER)
438  return static_cast<int>(std::max(1.0L, log(1.0L * n) / log(10.0L) + 1.0));
439 #else
440  return static_cast<int>(std::max(1.0, log10(static_cast<double>(n)) + 1.0));
441 #endif
442 }
443 } // namespace
444 
445 MPSolver::MPSolver(const std::string& name,
447  : name_(name),
448  problem_type_(problem_type),
449  construction_time_(absl::Now()) {
450  interface_.reset(BuildSolverInterface(this));
451  if (absl::GetFlag(FLAGS_linear_solver_enable_verbose_output)) {
452  EnableOutput();
453  }
454  objective_.reset(new MPObjective(interface_.get()));
455 }
456 
458 
459 // static
461 #ifdef USE_CLP
462  if (problem_type == CLP_LINEAR_PROGRAMMING) return true;
463 #endif
464 #ifdef USE_GLPK
467  return true;
468  }
469 #endif
470  if (problem_type == BOP_INTEGER_PROGRAMMING) return true;
471  if (problem_type == SAT_INTEGER_PROGRAMMING) return true;
472  if (problem_type == GLOP_LINEAR_PROGRAMMING) return true;
475  return MPSolver::GurobiIsCorrectlyInstalled();
476  }
477 #ifdef USE_SCIP
478  if (problem_type == SCIP_MIXED_INTEGER_PROGRAMMING) return true;
479 #endif
480 #ifdef USE_CBC
481  if (problem_type == CBC_MIXED_INTEGER_PROGRAMMING) return true;
482 #endif
483 #ifdef USE_XPRESS
486  return true;
487  }
488 #endif
489 #ifdef USE_CPLEX
492  return true;
493  }
494 #endif
495  return false;
496 }
497 
498 // TODO(user): post c++ 14, instead use
499 // std::pair<MPSolver::OptimizationProblemType, const absl::string_view>
500 // once pair gets a constexpr constructor.
501 namespace {
502 struct NamedOptimizationProblemType {
504  absl::string_view name;
505 };
506 } // namespace
507 
508 #if defined(_MSC_VER)
509 const
510 #else
511 constexpr
512 #endif
513  NamedOptimizationProblemType kOptimizationProblemTypeNames[] = {
529 
530 };
531 // static
532 bool MPSolver::ParseSolverType(absl::string_view solver_id,
534  // Normalize the solver id.
535  const std::string id =
536  absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{"-", "_"}});
537 
538  // Support the full enum name
539  MPModelRequest::SolverType solver_type;
540  if (MPModelRequest::SolverType_Parse(id, &solver_type)) {
541  *type = static_cast<MPSolver::OptimizationProblemType>(solver_type);
542  return true;
543  }
544 
545  // Names are stored in lower case.
546  std::string lower_id = absl::AsciiStrToLower(id);
547 
548  // Remove any "_mip" suffix, since they are optional.
549  if (absl::EndsWith(lower_id, "_mip")) {
550  lower_id = lower_id.substr(0, lower_id.size() - 4);
551  }
552 
553  // Rewrite CP-SAT into SAT.
554  if (lower_id == "cp_sat") {
555  lower_id = "sat";
556  }
557 
558  // Reverse lookup in the kOptimizationProblemTypeNames[] array.
559  for (auto& named_solver : kOptimizationProblemTypeNames) {
560  if (named_solver.name == lower_id) {
561  *type = named_solver.problem_type;
562  return true;
563  }
564  }
565 
566  return false;
567 }
568 
569 const absl::string_view ToString(
570  MPSolver::OptimizationProblemType optimization_problem_type) {
571  for (const auto& named_solver : kOptimizationProblemTypeNames) {
572  if (named_solver.problem_type == optimization_problem_type) {
573  return named_solver.name;
574  }
575  }
576  LOG(FATAL) << "Unrecognized solver type: "
577  << static_cast<int>(optimization_problem_type);
578  return "";
579 }
580 
581 bool AbslParseFlag(const absl::string_view text,
583  std::string* error) {
584  DCHECK(solver_type != nullptr);
585  DCHECK(error != nullptr);
586  const bool result = MPSolver::ParseSolverType(text, solver_type);
587  if (!result) {
588  *error = absl::StrCat("Solver type: ", text, " does not exist.");
589  }
590  return result;
591 }
592 
593 /* static */
595  const std::string& solver_id) {
597  CHECK(MPSolver::ParseSolverType(solver_id, &problem_type)) << solver_id;
598  return problem_type;
599 }
600 
601 /* static */
602 MPSolver* MPSolver::CreateSolver(const std::string& solver_id) {
604  if (!MPSolver::ParseSolverType(solver_id, &problem_type)) {
605  LOG(WARNING) << "Unrecognized solver type: " << solver_id;
606  return nullptr;
607  }
609  LOG(WARNING) << "Support for " << solver_id
610  << " not linked in, or the license was not found.";
611  return nullptr;
612  }
613  return new MPSolver("", problem_type);
614 }
615 
616 MPVariable* MPSolver::LookupVariableOrNull(const std::string& var_name) const {
617  if (!variable_name_to_index_) GenerateVariableNameIndex();
618 
619  absl::flat_hash_map<std::string, int>::const_iterator it =
620  variable_name_to_index_->find(var_name);
621  if (it == variable_name_to_index_->end()) return nullptr;
622  return variables_[it->second];
623 }
624 
626  const std::string& constraint_name) const {
627  if (!constraint_name_to_index_) GenerateConstraintNameIndex();
628 
629  const auto it = constraint_name_to_index_->find(constraint_name);
630  if (it == constraint_name_to_index_->end()) return nullptr;
631  return constraints_[it->second];
632 }
633 
634 // ----- Methods using protocol buffers -----
635 
637  const MPModelProto& input_model, std::string* error_message) {
638  // The variable and constraint names are dropped, because we allow
639  // duplicate names in the proto (they're not considered as 'ids'),
640  // unlike the MPSolver C++ API which crashes if there are duplicate names.
641  // Clearing the names makes the MPSolver generate unique names.
642  return LoadModelFromProtoInternal(input_model, /*clear_names=*/true,
643  /*check_model_validity=*/true,
644  error_message);
645 }
646 
648  const MPModelProto& input_model, std::string* error_message) {
649  // Force variable and constraint name indexing (which CHECKs name uniqueness).
650  GenerateVariableNameIndex();
651  GenerateConstraintNameIndex();
652 
653  return LoadModelFromProtoInternal(input_model, /*clear_names=*/false,
654  /*check_model_validity=*/true,
655  error_message);
656 }
657 
658 MPSolverResponseStatus MPSolver::LoadModelFromProtoInternal(
659  const MPModelProto& input_model, bool clear_names,
660  bool check_model_validity, std::string* error_message) {
661  CHECK(error_message != nullptr);
662  if (check_model_validity) {
663  const std::string error = FindErrorInMPModelProto(input_model);
664  if (!error.empty()) {
665  *error_message = error;
667  << "Invalid model given to LoadModelFromProto(): " << error;
668  if (absl::GetFlag(FLAGS_mpsolver_bypass_model_validation)) {
670  << "Ignoring the model error(s) because of"
671  << " --mpsolver_bypass_model_validation.";
672  } else {
673  return absl::StrContains(error, "Infeasible") ? MPSOLVER_INFEASIBLE
675  }
676  }
677  }
678 
679  if (input_model.has_quadratic_objective()) {
680  *error_message =
681  "Optimizing a quadratic objective is only supported through direct "
682  "proto solves. Please use MPSolver::SolveWithProto, or the solver's "
683  "direct proto solve function.";
684  return MPSOLVER_MODEL_INVALID;
685  }
686 
687  MPObjective* const objective = MutableObjective();
688  // Passing empty names makes the MPSolver generate unique names.
689  const std::string empty;
690  for (int i = 0; i < input_model.variable_size(); ++i) {
691  const MPVariableProto& var_proto = input_model.variable(i);
692  MPVariable* variable =
693  MakeNumVar(var_proto.lower_bound(), var_proto.upper_bound(),
694  clear_names ? empty : var_proto.name());
695  variable->SetInteger(var_proto.is_integer());
696  if (var_proto.branching_priority() != 0) {
697  variable->SetBranchingPriority(var_proto.branching_priority());
698  }
699  objective->SetCoefficient(variable, var_proto.objective_coefficient());
700  }
701 
702  for (const MPConstraintProto& ct_proto : input_model.constraint()) {
703  if (ct_proto.lower_bound() == -infinity() &&
704  ct_proto.upper_bound() == infinity()) {
705  continue;
706  }
707 
708  MPConstraint* const ct =
709  MakeRowConstraint(ct_proto.lower_bound(), ct_proto.upper_bound(),
710  clear_names ? empty : ct_proto.name());
711  ct->set_is_lazy(ct_proto.is_lazy());
712  for (int j = 0; j < ct_proto.var_index_size(); ++j) {
713  ct->SetCoefficient(variables_[ct_proto.var_index(j)],
714  ct_proto.coefficient(j));
715  }
716  }
717 
718  for (const MPGeneralConstraintProto& general_constraint :
719  input_model.general_constraint()) {
720  switch (general_constraint.general_constraint_case()) {
721  case MPGeneralConstraintProto::kIndicatorConstraint: {
722  const auto& proto =
723  general_constraint.indicator_constraint().constraint();
724  if (proto.lower_bound() == -infinity() &&
725  proto.upper_bound() == infinity()) {
726  continue;
727  }
728 
729  const int constraint_index = NumConstraints();
730  MPConstraint* const constraint = new MPConstraint(
731  constraint_index, proto.lower_bound(), proto.upper_bound(),
732  clear_names ? "" : proto.name(), interface_.get());
733  if (constraint_name_to_index_) {
734  gtl::InsertOrDie(&*constraint_name_to_index_, constraint->name(),
735  constraint_index);
736  }
737  constraints_.push_back(constraint);
738  constraint_is_extracted_.push_back(false);
739 
740  constraint->set_is_lazy(proto.is_lazy());
741  for (int j = 0; j < proto.var_index_size(); ++j) {
742  constraint->SetCoefficient(variables_[proto.var_index(j)],
743  proto.coefficient(j));
744  }
745 
746  MPVariable* const variable =
747  variables_[general_constraint.indicator_constraint().var_index()];
748  constraint->indicator_variable_ = variable;
749  constraint->indicator_value_ =
750  general_constraint.indicator_constraint().var_value();
751 
752  if (!interface_->AddIndicatorConstraint(constraint)) {
753  *error_message = "Solver doesn't support indicator constraints";
754  return MPSOLVER_MODEL_INVALID;
755  }
756  break;
757  }
758  default:
759  *error_message = absl::StrFormat(
760  "Optimizing general constraints of type %i is only supported "
761  "through direct proto solves. Please use MPSolver::SolveWithProto, "
762  "or the solver's direct proto solve function.",
763  general_constraint.general_constraint_case());
764  return MPSOLVER_MODEL_INVALID;
765  }
766  }
767 
768  objective->SetOptimizationDirection(input_model.maximize());
769  if (input_model.has_objective_offset()) {
770  objective->SetOffset(input_model.objective_offset());
771  }
772 
773  // Stores any hints about where to start the solve.
774  solution_hint_.clear();
775  for (int i = 0; i < input_model.solution_hint().var_index_size(); ++i) {
776  solution_hint_.push_back(
777  std::make_pair(variables_[input_model.solution_hint().var_index(i)],
778  input_model.solution_hint().var_value(i)));
779  }
781 }
782 
783 namespace {
784 MPSolverResponseStatus ResultStatusToMPSolverResponseStatus(
785  MPSolver::ResultStatus status) {
786  switch (status) {
787  case MPSolver::OPTIMAL:
788  return MPSOLVER_OPTIMAL;
789  case MPSolver::FEASIBLE:
790  return MPSOLVER_FEASIBLE;
792  return MPSOLVER_INFEASIBLE;
793  case MPSolver::UNBOUNDED:
794  return MPSOLVER_UNBOUNDED;
795  case MPSolver::ABNORMAL:
796  return MPSOLVER_ABNORMAL;
798  return MPSOLVER_MODEL_INVALID;
800  return MPSOLVER_NOT_SOLVED;
801  }
803 }
804 } // namespace
805 
806 void MPSolver::FillSolutionResponseProto(MPSolutionResponse* response) const {
807  CHECK(response != nullptr);
808  response->Clear();
809  response->set_status(
810  ResultStatusToMPSolverResponseStatus(interface_->result_status_));
811  if (interface_->result_status_ == MPSolver::OPTIMAL ||
812  interface_->result_status_ == MPSolver::FEASIBLE) {
813  response->set_objective_value(Objective().Value());
814  for (int i = 0; i < variables_.size(); ++i) {
815  response->add_variable_value(variables_[i]->solution_value());
816  }
817 
818  if (interface_->IsMIP()) {
819  response->set_best_objective_bound(interface_->best_objective_bound());
820  } else {
821  // Dual values have no meaning in MIP.
822  for (int j = 0; j < constraints_.size(); ++j) {
823  response->add_dual_value(constraints_[j]->dual_value());
824  }
825  // Reduced cost have no meaning in MIP.
826  for (int i = 0; i < variables_.size(); ++i) {
827  response->add_reduced_cost(variables_[i]->reduced_cost());
828  }
829  }
830  }
831 }
832 
833 // static
834 void MPSolver::SolveWithProto(const MPModelRequest& model_request,
835  MPSolutionResponse* response) {
836  CHECK(response != nullptr);
837  MPSolver solver(model_request.model().name(),
839  model_request.solver_type()));
840  if (model_request.enable_internal_solver_output()) {
841  solver.EnableOutput();
842  }
843 
844  auto optional_response = solver.interface_->DirectlySolveProto(model_request);
845  if (optional_response) {
846  *response = std::move(optional_response).value();
847  return;
848  }
849 
850  const absl::optional<LazyMutableCopy<MPModelProto>> optional_model =
852  if (!optional_model) {
853  LOG_IF(WARNING, model_request.enable_internal_solver_output())
854  << "Failed to extract a valid model from protocol buffer. Status: "
855  << ProtoEnumToString<MPSolverResponseStatus>(response->status()) << " ("
856  << response->status() << "): " << response->status_str();
857  return;
858  }
859  std::string error_message;
860  response->set_status(solver.LoadModelFromProtoInternal(
861  optional_model->get(), /*clear_names=*/true,
862  /*check_model_validity=*/false, &error_message));
863  // Even though we don't re-check model validity here, there can be some
864  // problems found by LoadModelFromProto, eg. unsupported features.
865  if (response->status() != MPSOLVER_MODEL_IS_VALID) {
866  response->set_status_str(error_message);
867  LOG_IF(WARNING, model_request.enable_internal_solver_output())
868  << "LoadModelFromProtoInternal() failed even though the model was "
869  << "valid! Status: "
870  << ProtoEnumToString<MPSolverResponseStatus>(response->status()) << " ("
871  << response->status() << "); Error: " << error_message;
872  return;
873  }
874  if (model_request.has_solver_time_limit_seconds()) {
875  solver.SetTimeLimit(
876  absl::Seconds(model_request.solver_time_limit_seconds()));
877  }
878  std::string warning_message;
879  if (model_request.has_solver_specific_parameters()) {
881  model_request.solver_specific_parameters())) {
882  if (model_request.ignore_solver_specific_parameters_failure()) {
883  // We'll add a warning message in status_str after the solve.
884  warning_message =
885  "Warning: the solver specific parameters were not successfully "
886  "applied";
887  } else {
889  return;
890  }
891  }
892  }
893  solver.Solve();
895  if (!warning_message.empty()) {
896  response->set_status_str(absl::StrCat(
897  response->status_str(), (response->status_str().empty() ? "" : "\n"),
898  warning_message));
899  }
900 }
901 
902 void MPSolver::ExportModelToProto(MPModelProto* output_model) const {
903  DCHECK(output_model != nullptr);
904  output_model->Clear();
905  // Name
906  output_model->set_name(Name());
907  // Variables
908  for (int j = 0; j < variables_.size(); ++j) {
909  const MPVariable* const var = variables_[j];
910  MPVariableProto* const variable_proto = output_model->add_variable();
911  // TODO(user): Add option to avoid filling the var name to avoid overly
912  // large protocol buffers.
913  variable_proto->set_name(var->name());
914  variable_proto->set_lower_bound(var->lb());
915  variable_proto->set_upper_bound(var->ub());
916  variable_proto->set_is_integer(var->integer());
917  if (objective_->GetCoefficient(var) != 0.0) {
918  variable_proto->set_objective_coefficient(
919  objective_->GetCoefficient(var));
920  }
921  if (var->branching_priority() != 0) {
922  variable_proto->set_branching_priority(var->branching_priority());
923  }
924  }
925 
926  // Map the variables to their indices. This is needed to output the
927  // variables in the order they were created, which in turn is needed to have
928  // repeatable results with ExportModelAsLpFormat and ExportModelAsMpsFormat.
929  // This step is needed as long as the variable indices are given by the
930  // underlying solver at the time of model extraction.
931  // TODO(user): remove this step.
932  absl::flat_hash_map<const MPVariable*, int> var_to_index;
933  for (int j = 0; j < variables_.size(); ++j) {
934  var_to_index[variables_[j]] = j;
935  }
936 
937  // Constraints
938  for (int i = 0; i < constraints_.size(); ++i) {
939  MPConstraint* const constraint = constraints_[i];
940  MPConstraintProto* constraint_proto;
941  if (constraint->indicator_variable() != nullptr) {
942  MPGeneralConstraintProto* const general_constraint_proto =
943  output_model->add_general_constraint();
944  general_constraint_proto->set_name(constraint->name());
945  MPIndicatorConstraint* const indicator_constraint_proto =
946  general_constraint_proto->mutable_indicator_constraint();
947  indicator_constraint_proto->set_var_index(
948  constraint->indicator_variable()->index());
949  indicator_constraint_proto->set_var_value(constraint->indicator_value());
950  constraint_proto = indicator_constraint_proto->mutable_constraint();
951  } else {
952  constraint_proto = output_model->add_constraint();
953  }
954  constraint_proto->set_name(constraint->name());
955  constraint_proto->set_lower_bound(constraint->lb());
956  constraint_proto->set_upper_bound(constraint->ub());
957  constraint_proto->set_is_lazy(constraint->is_lazy());
958  // Vector linear_term will contain pairs (variable index, coeff), that will
959  // be sorted by variable index.
960  std::vector<std::pair<int, double>> linear_term;
961  for (const auto& entry : constraint->coefficients_) {
962  const MPVariable* const var = entry.first;
963  const int var_index = gtl::FindWithDefault(var_to_index, var, -1);
964  DCHECK_NE(-1, var_index);
965  const double coeff = entry.second;
966  linear_term.push_back(std::pair<int, double>(var_index, coeff));
967  }
968  // The cost of sort is expected to be low as constraints usually have very
969  // few terms.
970  std::sort(linear_term.begin(), linear_term.end());
971  // Now use linear term.
972  for (const std::pair<int, double>& var_and_coeff : linear_term) {
973  constraint_proto->add_var_index(var_and_coeff.first);
974  constraint_proto->add_coefficient(var_and_coeff.second);
975  }
976  }
977 
978  output_model->set_maximize(Objective().maximization());
979  output_model->set_objective_offset(Objective().offset());
980 
981  if (!solution_hint_.empty()) {
982  PartialVariableAssignment* const hint =
983  output_model->mutable_solution_hint();
984  for (const auto& var_value_pair : solution_hint_) {
985  hint->add_var_index(var_value_pair.first->index());
986  hint->add_var_value(var_value_pair.second);
987  }
988  }
989 }
990 
991 absl::Status MPSolver::LoadSolutionFromProto(const MPSolutionResponse& response,
992  double tolerance) {
993  interface_->result_status_ = static_cast<ResultStatus>(response.status());
994  if (response.status() != MPSOLVER_OPTIMAL &&
995  response.status() != MPSOLVER_FEASIBLE) {
996  return absl::InvalidArgumentError(absl::StrCat(
997  "Cannot load a solution unless its status is OPTIMAL or FEASIBLE"
998  " (status was: ",
999  ProtoEnumToString<MPSolverResponseStatus>(response.status()), ")"));
1000  }
1001  // Before touching the variables, verify that the solution looks legit:
1002  // each variable of the MPSolver must have its value listed exactly once, and
1003  // each listed solution should correspond to a known variable.
1004  if (response.variable_value_size() != variables_.size()) {
1005  return absl::InvalidArgumentError(absl::StrCat(
1006  "Trying to load a solution whose number of variables (",
1007  response.variable_value_size(),
1008  ") does not correspond to the Solver's (", variables_.size(), ")"));
1009  }
1010  interface_->ExtractModel();
1011 
1012  if (tolerance != infinity()) {
1013  // Look further: verify that the variable values are within the bounds.
1014  double largest_error = 0;
1015  int num_vars_out_of_bounds = 0;
1016  int last_offending_var = -1;
1017  for (int i = 0; i < response.variable_value_size(); ++i) {
1018  const double var_value = response.variable_value(i);
1019  MPVariable* var = variables_[i];
1020  // TODO(user): Use parameter when they become available in this class.
1021  const double lb_error = var->lb() - var_value;
1022  const double ub_error = var_value - var->ub();
1023  if (lb_error > tolerance || ub_error > tolerance) {
1024  ++num_vars_out_of_bounds;
1025  largest_error = std::max(largest_error, std::max(lb_error, ub_error));
1026  last_offending_var = i;
1027  }
1028  }
1029  if (num_vars_out_of_bounds > 0) {
1030  return absl::InvalidArgumentError(absl::StrCat(
1031  "Loaded a solution whose variables matched the solver's, but ",
1032  num_vars_out_of_bounds, " of ", variables_.size(),
1033  " variables were out of their bounds, by more than the primal"
1034  " tolerance which is: ",
1035  tolerance, ". Max error: ", largest_error, ", last offender var is #",
1036  last_offending_var, ": '", variables_[last_offending_var]->name(),
1037  "'"));
1038  }
1039  }
1040  // TODO(user): Load the reduced costs too, if available.
1041  for (int i = 0; i < response.variable_value_size(); ++i) {
1042  variables_[i]->set_solution_value(response.variable_value(i));
1043  }
1044  // Set the objective value, if is known.
1045  // NOTE(user): We do not verify the objective, even though we could!
1046  if (response.has_objective_value()) {
1047  interface_->objective_value_ = response.objective_value();
1048  }
1049  if (response.has_best_objective_bound()) {
1050  interface_->best_objective_bound_ = response.best_objective_bound();
1051  }
1052  // Mark the status as SOLUTION_SYNCHRONIZED, so that users may inspect the
1053  // solution normally.
1054  interface_->sync_status_ = MPSolverInterface::SOLUTION_SYNCHRONIZED;
1055  return absl::OkStatus();
1056 }
1057 
1059  MutableObjective()->Clear();
1060  gtl::STLDeleteElements(&variables_);
1061  gtl::STLDeleteElements(&constraints_);
1062  variables_.clear();
1063  if (variable_name_to_index_) {
1064  variable_name_to_index_->clear();
1065  }
1066  variable_is_extracted_.clear();
1067  constraints_.clear();
1068  if (constraint_name_to_index_) {
1069  constraint_name_to_index_->clear();
1070  }
1071  constraint_is_extracted_.clear();
1072  interface_->Reset();
1073  solution_hint_.clear();
1074 }
1075 
1076 void MPSolver::Reset() { interface_->Reset(); }
1077 
1078 bool MPSolver::InterruptSolve() { return interface_->InterruptSolve(); }
1079 
1081  const std::vector<BasisStatus>& variable_statuses,
1082  const std::vector<BasisStatus>& constraint_statuses) {
1083  interface_->SetStartingLpBasis(variable_statuses, constraint_statuses);
1084 }
1085 
1086 MPVariable* MPSolver::MakeVar(double lb, double ub, bool integer,
1087  const std::string& name) {
1088  const int var_index = NumVariables();
1089  MPVariable* v =
1090  new MPVariable(var_index, lb, ub, integer, name, interface_.get());
1091  if (variable_name_to_index_) {
1092  gtl::InsertOrDie(&*variable_name_to_index_, v->name(), var_index);
1093  }
1094  variables_.push_back(v);
1095  variable_is_extracted_.push_back(false);
1096  interface_->AddVariable(v);
1097  return v;
1098 }
1099 
1100 MPVariable* MPSolver::MakeNumVar(double lb, double ub,
1101  const std::string& name) {
1102  return MakeVar(lb, ub, false, name);
1103 }
1104 
1105 MPVariable* MPSolver::MakeIntVar(double lb, double ub,
1106  const std::string& name) {
1107  return MakeVar(lb, ub, true, name);
1108 }
1109 
1110 MPVariable* MPSolver::MakeBoolVar(const std::string& name) {
1111  return MakeVar(0.0, 1.0, true, name);
1112 }
1113 
1114 void MPSolver::MakeVarArray(int nb, double lb, double ub, bool integer,
1115  const std::string& name,
1116  std::vector<MPVariable*>* vars) {
1117  DCHECK_GE(nb, 0);
1118  if (nb <= 0) return;
1119  const int num_digits = NumDigits(nb);
1120  for (int i = 0; i < nb; ++i) {
1121  if (name.empty()) {
1122  vars->push_back(MakeVar(lb, ub, integer, name));
1123  } else {
1124  std::string vname =
1125  absl::StrFormat("%s%0*d", name.c_str(), num_digits, i);
1126  vars->push_back(MakeVar(lb, ub, integer, vname));
1127  }
1128  }
1129 }
1130 
1131 void MPSolver::MakeNumVarArray(int nb, double lb, double ub,
1132  const std::string& name,
1133  std::vector<MPVariable*>* vars) {
1134  MakeVarArray(nb, lb, ub, false, name, vars);
1135 }
1136 
1137 void MPSolver::MakeIntVarArray(int nb, double lb, double ub,
1138  const std::string& name,
1139  std::vector<MPVariable*>* vars) {
1140  MakeVarArray(nb, lb, ub, true, name, vars);
1141 }
1142 
1143 void MPSolver::MakeBoolVarArray(int nb, const std::string& name,
1144  std::vector<MPVariable*>* vars) {
1145  MakeVarArray(nb, 0.0, 1.0, true, name, vars);
1146 }
1147 
1149  return MakeRowConstraint(lb, ub, "");
1150 }
1151 
1153  return MakeRowConstraint(-infinity(), infinity(), "");
1154 }
1155 
1157  const std::string& name) {
1158  const int constraint_index = NumConstraints();
1159  MPConstraint* const constraint =
1160  new MPConstraint(constraint_index, lb, ub, name, interface_.get());
1161  if (constraint_name_to_index_) {
1162  gtl::InsertOrDie(&*constraint_name_to_index_, constraint->name(),
1163  constraint_index);
1164  }
1165  constraints_.push_back(constraint);
1166  constraint_is_extracted_.push_back(false);
1167  interface_->AddRowConstraint(constraint);
1168  return constraint;
1169 }
1170 
1172  return MakeRowConstraint(-infinity(), infinity(), name);
1173 }
1174 
1176  return MakeRowConstraint(range, "");
1177 }
1178 
1180  const std::string& name) {
1181  CheckLinearExpr(*this, range.linear_expr());
1182  MPConstraint* constraint =
1183  MakeRowConstraint(range.lower_bound(), range.upper_bound(), name);
1184  for (const auto& kv : range.linear_expr().terms()) {
1185  constraint->SetCoefficient(kv.first, kv.second);
1186  }
1187  return constraint;
1188 }
1189 
1190 int MPSolver::ComputeMaxConstraintSize(int min_constraint_index,
1191  int max_constraint_index) const {
1192  int max_constraint_size = 0;
1193  DCHECK_GE(min_constraint_index, 0);
1194  DCHECK_LE(max_constraint_index, constraints_.size());
1195  for (int i = min_constraint_index; i < max_constraint_index; ++i) {
1196  MPConstraint* const ct = constraints_[i];
1197  if (ct->coefficients_.size() > max_constraint_size) {
1198  max_constraint_size = ct->coefficients_.size();
1199  }
1200  }
1201  return max_constraint_size;
1202 }
1203 
1204 bool MPSolver::HasInfeasibleConstraints() const {
1205  bool hasInfeasibleConstraints = false;
1206  for (int i = 0; i < constraints_.size(); ++i) {
1207  if (constraints_[i]->lb() > constraints_[i]->ub()) {
1208  LOG(WARNING) << "Constraint " << constraints_[i]->name() << " (" << i
1209  << ") has contradictory bounds:"
1210  << " lower bound = " << constraints_[i]->lb()
1211  << " upper bound = " << constraints_[i]->ub();
1212  hasInfeasibleConstraints = true;
1213  }
1214  }
1215  return hasInfeasibleConstraints;
1216 }
1217 
1218 bool MPSolver::HasIntegerVariables() const {
1219  for (const MPVariable* const variable : variables_) {
1220  if (variable->integer()) return true;
1221  }
1222  return false;
1223 }
1224 
1226  MPSolverParameters default_param;
1227  return Solve(default_param);
1228 }
1229 
1231  // Special case for infeasible constraints so that all solvers have
1232  // the same behavior.
1233  // TODO(user): replace this by model extraction to proto + proto validation
1234  // (the proto has very low overhead compared to the wrapper, both in
1235  // performance and memory, so it's ok).
1236  if (HasInfeasibleConstraints()) {
1237  interface_->result_status_ = MPSolver::INFEASIBLE;
1238  return interface_->result_status_;
1239  }
1240 
1241  MPSolver::ResultStatus status = interface_->Solve(param);
1242  if (absl::GetFlag(FLAGS_verify_solution)) {
1243  if (status != MPSolver::OPTIMAL && status != MPSolver::FEASIBLE) {
1244  VLOG(1) << "--verify_solution enabled, but the solver did not find a"
1245  << " solution: skipping the verification.";
1246  } else if (!VerifySolution(
1248  absl::GetFlag(FLAGS_log_verification_errors))) {
1249  status = MPSolver::ABNORMAL;
1250  interface_->result_status_ = status;
1251  }
1252  }
1253  DCHECK_EQ(interface_->result_status_, status);
1254  return status;
1255 }
1256 
1257 void MPSolver::Write(const std::string& file_name) {
1258  interface_->Write(file_name);
1259 }
1260 
1261 namespace {
1262 std::string PrettyPrintVar(const MPVariable& var) {
1263  const std::string prefix = "Variable '" + var.name() + "': domain = ";
1264  if (var.lb() >= MPSolver::infinity() || var.ub() <= -MPSolver::infinity() ||
1265  var.lb() > var.ub()) {
1266  return prefix + "∅"; // Empty set.
1267  }
1268  // Special case: integer variable with at most two possible values
1269  // (and potentially none).
1270  if (var.integer() && var.ub() - var.lb() <= 1) {
1271  const int64 lb = static_cast<int64>(ceil(var.lb()));
1272  const int64 ub = static_cast<int64>(floor(var.ub()));
1273  if (lb > ub) {
1274  return prefix + "∅";
1275  } else if (lb == ub) {
1276  return absl::StrFormat("%s{ %d }", prefix.c_str(), lb);
1277  } else {
1278  return absl::StrFormat("%s{ %d, %d }", prefix.c_str(), lb, ub);
1279  }
1280  }
1281  // Special case: single (non-infinite) real value.
1282  if (var.lb() == var.ub()) {
1283  return absl::StrFormat("%s{ %f }", prefix.c_str(), var.lb());
1284  }
1285  return prefix + (var.integer() ? "Integer" : "Real") + " in " +
1286  (var.lb() <= -MPSolver::infinity()
1287  ? std::string("]-∞")
1288  : absl::StrFormat("[%f", var.lb())) +
1289  ", " +
1290  (var.ub() >= MPSolver::infinity() ? std::string("+∞[")
1291  : absl::StrFormat("%f]", var.ub()));
1292 }
1293 
1294 std::string PrettyPrintConstraint(const MPConstraint& constraint) {
1295  std::string prefix = "Constraint '" + constraint.name() + "': ";
1296  if (constraint.lb() >= MPSolver::infinity() ||
1297  constraint.ub() <= -MPSolver::infinity() ||
1298  constraint.lb() > constraint.ub()) {
1299  return prefix + "ALWAYS FALSE";
1300  }
1301  if (constraint.lb() <= -MPSolver::infinity() &&
1302  constraint.ub() >= MPSolver::infinity()) {
1303  return prefix + "ALWAYS TRUE";
1304  }
1305  prefix += "<linear expr>";
1306  // Equality.
1307  if (constraint.lb() == constraint.ub()) {
1308  return absl::StrFormat("%s = %f", prefix.c_str(), constraint.lb());
1309  }
1310  // Inequalities.
1311  if (constraint.lb() <= -MPSolver::infinity()) {
1312  return absl::StrFormat("%s ≤ %f", prefix.c_str(), constraint.ub());
1313  }
1314  if (constraint.ub() >= MPSolver::infinity()) {
1315  return absl::StrFormat("%s ≥ %f", prefix.c_str(), constraint.lb());
1316  }
1317  return absl::StrFormat("%s ∈ [%f, %f]", prefix.c_str(), constraint.lb(),
1318  constraint.ub());
1319 }
1320 } // namespace
1321 
1323  interface_->ExtractModel();
1324  for (MPVariable* const variable : variables_) {
1325  const double value = variable->solution_value();
1326  if (std::isnan(value)) {
1327  return absl::InvalidArgumentError(
1328  absl::StrCat("NaN value for ", PrettyPrintVar(*variable)));
1329  }
1330  if (value < variable->lb()) {
1331  variable->set_solution_value(variable->lb());
1332  } else if (value > variable->ub()) {
1333  variable->set_solution_value(variable->ub());
1334  }
1335  }
1336  interface_->sync_status_ = MPSolverInterface::SOLUTION_SYNCHRONIZED;
1337  return absl::OkStatus();
1338 }
1339 
1340 std::vector<double> MPSolver::ComputeConstraintActivities() const {
1341  // TODO(user): test this failure case.
1342  if (!interface_->CheckSolutionIsSynchronizedAndExists()) return {};
1343  std::vector<double> activities(constraints_.size(), 0.0);
1344  for (int i = 0; i < constraints_.size(); ++i) {
1345  const MPConstraint& constraint = *constraints_[i];
1346  AccurateSum<double> sum;
1347  for (const auto& entry : constraint.coefficients_) {
1348  sum.Add(entry.first->solution_value() * entry.second);
1349  }
1350  activities[i] = sum.Value();
1351  }
1352  return activities;
1353 }
1354 
1355 // TODO(user): split.
1356 bool MPSolver::VerifySolution(double tolerance, bool log_errors) const {
1357  double max_observed_error = 0;
1358  if (tolerance < 0) tolerance = infinity();
1359  int num_errors = 0;
1360 
1361  // Verify variables.
1362  for (int i = 0; i < variables_.size(); ++i) {
1363  const MPVariable& var = *variables_[i];
1364  const double value = var.solution_value();
1365  // Check for NaN.
1366  if (std::isnan(value)) {
1367  ++num_errors;
1368  max_observed_error = infinity();
1369  LOG_IF(ERROR, log_errors) << "NaN value for " << PrettyPrintVar(var);
1370  continue;
1371  }
1372  // Check lower bound.
1373  if (var.lb() != -infinity()) {
1374  if (value < var.lb() - tolerance) {
1375  ++num_errors;
1376  max_observed_error = std::max(max_observed_error, var.lb() - value);
1377  LOG_IF(ERROR, log_errors)
1378  << "Value " << value << " too low for " << PrettyPrintVar(var);
1379  }
1380  }
1381  // Check upper bound.
1382  if (var.ub() != infinity()) {
1383  if (value > var.ub() + tolerance) {
1384  ++num_errors;
1385  max_observed_error = std::max(max_observed_error, value - var.ub());
1386  LOG_IF(ERROR, log_errors)
1387  << "Value " << value << " too high for " << PrettyPrintVar(var);
1388  }
1389  }
1390  // Check integrality.
1391  if (IsMIP() && var.integer()) {
1392  if (fabs(value - round(value)) > tolerance) {
1393  ++num_errors;
1394  max_observed_error =
1395  std::max(max_observed_error, fabs(value - round(value)));
1396  LOG_IF(ERROR, log_errors)
1397  << "Non-integer value " << value << " for " << PrettyPrintVar(var);
1398  }
1399  }
1400  }
1401  if (!IsMIP() && HasIntegerVariables()) {
1402  LOG_IF(INFO, log_errors) << "Skipped variable integrality check, because "
1403  << "a continuous relaxation of the model was "
1404  << "solved (i.e., the selected solver does not "
1405  << "support integer variables).";
1406  }
1407 
1408  // Verify constraints.
1409  const std::vector<double> activities = ComputeConstraintActivities();
1410  for (int i = 0; i < constraints_.size(); ++i) {
1411  const MPConstraint& constraint = *constraints_[i];
1412  const double activity = activities[i];
1413  // Re-compute the activity with a inaccurate summing algorithm.
1414  double inaccurate_activity = 0.0;
1415  for (const auto& entry : constraint.coefficients_) {
1416  inaccurate_activity += entry.first->solution_value() * entry.second;
1417  }
1418  // Catch NaNs.
1419  if (std::isnan(activity) || std::isnan(inaccurate_activity)) {
1420  ++num_errors;
1421  max_observed_error = infinity();
1422  LOG_IF(ERROR, log_errors)
1423  << "NaN value for " << PrettyPrintConstraint(constraint);
1424  continue;
1425  }
1426  // Check bounds.
1427  if (constraint.indicator_variable() == nullptr ||
1428  std::round(constraint.indicator_variable()->solution_value()) ==
1429  constraint.indicator_value()) {
1430  if (constraint.lb() != -infinity()) {
1431  if (activity < constraint.lb() - tolerance) {
1432  ++num_errors;
1433  max_observed_error =
1434  std::max(max_observed_error, constraint.lb() - activity);
1435  LOG_IF(ERROR, log_errors)
1436  << "Activity " << activity << " too low for "
1437  << PrettyPrintConstraint(constraint);
1438  } else if (inaccurate_activity < constraint.lb() - tolerance) {
1439  LOG_IF(WARNING, log_errors)
1440  << "Activity " << activity << ", computed with the (inaccurate)"
1441  << " standard sum of its terms, is too low for "
1442  << PrettyPrintConstraint(constraint);
1443  }
1444  }
1445  if (constraint.ub() != infinity()) {
1446  if (activity > constraint.ub() + tolerance) {
1447  ++num_errors;
1448  max_observed_error =
1449  std::max(max_observed_error, activity - constraint.ub());
1450  LOG_IF(ERROR, log_errors)
1451  << "Activity " << activity << " too high for "
1452  << PrettyPrintConstraint(constraint);
1453  } else if (inaccurate_activity > constraint.ub() + tolerance) {
1454  LOG_IF(WARNING, log_errors)
1455  << "Activity " << activity << ", computed with the (inaccurate)"
1456  << " standard sum of its terms, is too high for "
1457  << PrettyPrintConstraint(constraint);
1458  }
1459  }
1460  }
1461  }
1462 
1463  // Verify that the objective value wasn't reported incorrectly.
1464  const MPObjective& objective = Objective();
1465  AccurateSum<double> objective_sum;
1466  objective_sum.Add(objective.offset());
1467  double inaccurate_objective_value = objective.offset();
1468  for (const auto& entry : objective.coefficients_) {
1469  const double term = entry.first->solution_value() * entry.second;
1470  objective_sum.Add(term);
1471  inaccurate_objective_value += term;
1472  }
1473  const double actual_objective_value = objective_sum.Value();
1475  objective.Value(), actual_objective_value, tolerance, tolerance)) {
1476  ++num_errors;
1477  max_observed_error = std::max(
1478  max_observed_error, fabs(actual_objective_value - objective.Value()));
1479  LOG_IF(ERROR, log_errors)
1480  << "Objective value " << objective.Value() << " isn't accurate"
1481  << ", it should be " << actual_objective_value
1482  << " (delta=" << actual_objective_value - objective.Value() << ").";
1483  } else if (!AreWithinAbsoluteOrRelativeTolerances(objective.Value(),
1484  inaccurate_objective_value,
1485  tolerance, tolerance)) {
1486  LOG_IF(WARNING, log_errors)
1487  << "Objective value " << objective.Value() << " doesn't correspond"
1488  << " to the value computed with the standard (and therefore inaccurate)"
1489  << " sum of its terms.";
1490  }
1491  if (num_errors > 0) {
1492  LOG_IF(ERROR, log_errors)
1493  << "There were " << num_errors << " errors above the tolerance ("
1494  << tolerance << "), the largest was " << max_observed_error;
1495  return false;
1496  }
1497  return true;
1498 }
1499 
1500 bool MPSolver::OutputIsEnabled() const { return !interface_->quiet(); }
1501 
1502 void MPSolver::EnableOutput() { interface_->set_quiet(false); }
1503 
1504 void MPSolver::SuppressOutput() { interface_->set_quiet(true); }
1505 
1506 int64 MPSolver::iterations() const { return interface_->iterations(); }
1507 
1508 int64 MPSolver::nodes() const { return interface_->nodes(); }
1509 
1511  return interface_->ComputeExactConditionNumber();
1512 }
1513 
1515  if (var == nullptr) return false;
1516  if (var->index() >= 0 && var->index() < variables_.size()) {
1517  // Then, verify that the variable with this index has the same address.
1518  return variables_[var->index()] == var;
1519  }
1520  return false;
1521 }
1522 
1524  std::string* model_str) const {
1525  MPModelProto proto;
1527  MPModelExportOptions options;
1528  options.obfuscate = obfuscate;
1529  const auto status_or =
1531  *model_str = status_or.value_or("");
1532  return status_or.ok();
1533 }
1534 
1535 bool MPSolver::ExportModelAsMpsFormat(bool fixed_format, bool obfuscate,
1536  std::string* model_str) const {
1537  // if (fixed_format) {
1538  // LOG_EVERY_N_SEC(WARNING, 10)
1539  // << "Fixed format is deprecated. Using free format instead.";
1540  //
1541 
1542  MPModelProto proto;
1544  MPModelExportOptions options;
1545  options.obfuscate = obfuscate;
1546  const auto status_or =
1548  *model_str = status_or.value_or("");
1549  return status_or.ok();
1550 }
1551 
1552 void MPSolver::SetHint(std::vector<std::pair<const MPVariable*, double>> hint) {
1553  for (const auto& var_value_pair : hint) {
1554  CHECK(OwnsVariable(var_value_pair.first))
1555  << "hint variable does not belong to this solver";
1556  }
1557  solution_hint_ = std::move(hint);
1558 }
1559 
1560 void MPSolver::GenerateVariableNameIndex() const {
1561  if (variable_name_to_index_) return;
1562  variable_name_to_index_ = absl::flat_hash_map<std::string, int>();
1563  for (const MPVariable* const var : variables_) {
1564  gtl::InsertOrDie(&*variable_name_to_index_, var->name(), var->index());
1565  }
1566 }
1567 
1568 void MPSolver::GenerateConstraintNameIndex() const {
1569  if (constraint_name_to_index_) return;
1570  constraint_name_to_index_ = absl::flat_hash_map<std::string, int>();
1571  for (const MPConstraint* const cst : constraints_) {
1572  gtl::InsertOrDie(&*constraint_name_to_index_, cst->name(), cst->index());
1573  }
1574 }
1575 
1576 bool MPSolver::NextSolution() { return interface_->NextSolution(); }
1577 
1578 void MPSolver::SetCallback(MPCallback* mp_callback) {
1579  interface_->SetCallback(mp_callback);
1580 }
1581 
1583  return interface_->SupportsCallbacks();
1584 }
1585 
1587  switch (status) {
1588  // Cases that don't yield an RPC error when they happen on the server.
1589  case MPSOLVER_OPTIMAL:
1590  case MPSOLVER_FEASIBLE:
1591  case MPSOLVER_INFEASIBLE:
1592  case MPSOLVER_NOT_SOLVED:
1593  case MPSOLVER_UNBOUNDED:
1594  case MPSOLVER_ABNORMAL:
1596  return false;
1597  // Cases that should never happen with the linear solver server. We prefer
1598  // to consider those as "not RPC errors".
1600  return false;
1601  // Cases that yield an RPC error when they happen on the server.
1606  return true;
1607  }
1608  LOG(DFATAL)
1609  << "MPSolverResponseStatusIsRpcError() called with invalid status "
1610  << "(value: " << status << ")";
1611  return false;
1612 }
1613 
1614 // ---------- MPSolverInterface ----------
1615 
1617 
1618 // TODO(user): Initialize objective value and bound to +/- inf (depending on
1619 // optimization direction).
1621  : solver_(solver),
1622  sync_status_(MODEL_SYNCHRONIZED),
1623  result_status_(MPSolver::NOT_SOLVED),
1624  maximize_(false),
1625  last_constraint_index_(0),
1626  last_variable_index_(0),
1627  objective_value_(0.0),
1628  best_objective_bound_(0.0),
1629  quiet_(true) {}
1630 
1632 
1633 void MPSolverInterface::Write(const std::string& filename) {
1634  LOG(WARNING) << "Writing model not implemented in this solver interface.";
1635 }
1636 
1638  switch (sync_status_) {
1639  case MUST_RELOAD: {
1642  ExtractObjective();
1643 
1644  last_constraint_index_ = solver_->constraints_.size();
1645  last_variable_index_ = solver_->variables_.size();
1647  break;
1648  }
1649  case MODEL_SYNCHRONIZED: {
1650  // Everything has already been extracted.
1651  DCHECK_EQ(last_constraint_index_, solver_->constraints_.size());
1652  DCHECK_EQ(last_variable_index_, solver_->variables_.size());
1653  break;
1654  }
1655  case SOLUTION_SYNCHRONIZED: {
1656  // Nothing has changed since last solve.
1657  DCHECK_EQ(last_constraint_index_, solver_->constraints_.size());
1658  DCHECK_EQ(last_variable_index_, solver_->variables_.size());
1659  break;
1660  }
1661  }
1662 }
1663 
1664 // TODO(user): remove this method.
1669  solver_->variable_is_extracted_.assign(solver_->variables_.size(), false);
1670  solver_->constraint_is_extracted_.assign(solver_->constraints_.size(), false);
1671 }
1672 
1675  LOG(DFATAL)
1676  << "The model has been changed since the solution was last computed."
1677  << " MPSolverInterface::sync_status_ = " << sync_status_;
1678  return false;
1679  }
1680  return true;
1681 }
1682 
1683 // Default version that can be overwritten by a solver-specific
1684 // version to accommodate for the quirks of each solver.
1688  LOG(DFATAL) << "No solution exists. MPSolverInterface::result_status_ = "
1689  << result_status_;
1690  return false;
1691  }
1692  return true;
1693 }
1694 
1696  if (!CheckSolutionIsSynchronizedAndExists()) return 0;
1697  return objective_value_;
1698 }
1699 
1701  const double trivial_worst_bound =
1702  maximize_ ? -std::numeric_limits<double>::infinity()
1703  : std::numeric_limits<double>::infinity();
1704  if (!IsMIP()) {
1705  LOG(DFATAL) << "Best objective bound only available for discrete problems.";
1706  return trivial_worst_bound;
1707  }
1708  if (!CheckSolutionIsSynchronized()) {
1709  return trivial_worst_bound;
1710  }
1711  // Special case for empty model.
1712  if (solver_->variables_.empty() && solver_->constraints_.empty()) {
1713  return solver_->Objective().offset();
1714  }
1715  return best_objective_bound_;
1716 }
1717 
1721  }
1722 }
1723 
1725  // Override this method in interfaces that actually support it.
1726  LOG(DFATAL) << "ComputeExactConditionNumber not implemented for "
1727  << ProtoEnumToString<MPModelRequest::SolverType>(
1728  static_cast<MPModelRequest::SolverType>(
1729  solver_->ProblemType()));
1730  return 0.0;
1731 }
1732 
1734  // TODO(user): Overhaul the code that sets parameters to enable changing
1735  // GLOP parameters without issuing warnings.
1736  // By default, we let GLOP keep its own default tolerance, much more accurate
1737  // than for the rest of the solvers.
1738  //
1743  }
1745  // TODO(user): In the future, we could distinguish between the
1746  // algorithm to solve the root LP and the algorithm to solve node
1747  // LPs. Not sure if underlying solvers support it.
1751  }
1752 }
1753 
1758  }
1759 }
1760 
1763  LOG(WARNING) << "Trying to set an unsupported parameter: " << param << ".";
1764 }
1767  LOG(WARNING) << "Trying to set an unsupported parameter: " << param << ".";
1768 }
1770  MPSolverParameters::DoubleParam param, double value) {
1771  LOG(WARNING) << "Trying to set a supported parameter: " << param
1772  << " to an unsupported value: " << value;
1773 }
1776  LOG(WARNING) << "Trying to set a supported parameter: " << param
1777  << " to an unsupported value: " << value;
1778 }
1779 
1780 absl::Status MPSolverInterface::SetNumThreads(int num_threads) {
1781  return absl::UnimplementedError(
1782  absl::StrFormat("SetNumThreads() not supported by %s.", SolverVersion()));
1783 }
1784 
1786  const std::string& parameters) {
1787  // Note(user): this method needs to return a success/failure boolean
1788  // immediately, so we also perform the actual parameter parsing right away.
1789  // Some implementations will keep them forever and won't need to re-parse
1790  // them; some (eg. Gurobi) need to re-parse the parameters every time they do
1791  // Solve(). We just store the parameters string anyway.
1792  //
1793  // Note(user): This is not implemented on Android because there is no
1794  // temporary directory to write files to without a pointer to the Java
1795  // environment.
1796  if (parameters.empty()) return true;
1797 
1798  std::string extension = ValidFileExtensionForParameterFile();
1799  std::string filename;
1800  bool no_error_so_far = PortableTemporaryFile(nullptr, &filename);
1801  filename += extension;
1802  if (no_error_so_far) {
1803  no_error_so_far = PortableFileSetContents(filename, parameters).ok();
1804  }
1805  if (no_error_so_far) {
1806  no_error_so_far = ReadParameterFile(filename);
1807  // We need to clean up the file even if ReadParameterFile() returned
1808  // false. In production we can continue even if the deletion failed.
1809  if (!PortableDeleteFile(filename).ok()) {
1810  LOG(DFATAL) << "Couldn't delete temporary parameters file: " << filename;
1811  }
1812  }
1813  if (!no_error_so_far) {
1814  LOG(WARNING) << "Error in SetSolverSpecificParametersAsString() "
1815  << "for solver type: "
1816  << ProtoEnumToString<MPModelRequest::SolverType>(
1817  static_cast<MPModelRequest::SolverType>(
1818  solver_->ProblemType()));
1819  }
1820  return no_error_so_far;
1821 }
1822 
1823 bool MPSolverInterface::ReadParameterFile(const std::string& filename) {
1824  LOG(WARNING) << "ReadParameterFile() not supported by this solver.";
1825  return false;
1826 }
1827 
1829  return ".tmp";
1830 }
1831 
1832 // ---------- MPSolverParameters ----------
1833 
1834 const double MPSolverParameters::kDefaultRelativeMipGap = 1e-4;
1835 // For the primal and dual tolerances, choose the same default as CLP and GLPK.
1838 const double MPSolverParameters::kDefaultDualTolerance = 1e-7;
1844 
1849 
1850 // The constructor sets all parameters to their default value.
1852  : relative_mip_gap_value_(kDefaultRelativeMipGap),
1853  primal_tolerance_value_(kDefaultPrimalTolerance),
1854  dual_tolerance_value_(kDefaultDualTolerance),
1855  presolve_value_(kDefaultPresolve),
1856  scaling_value_(kDefaultIntegerParamValue),
1857  lp_algorithm_value_(kDefaultIntegerParamValue),
1858  incrementality_value_(kDefaultIncrementality),
1859  lp_algorithm_is_default_(true) {}
1860 
1862  double value) {
1863  switch (param) {
1864  case RELATIVE_MIP_GAP: {
1865  relative_mip_gap_value_ = value;
1866  break;
1867  }
1868  case PRIMAL_TOLERANCE: {
1869  primal_tolerance_value_ = value;
1870  break;
1871  }
1872  case DUAL_TOLERANCE: {
1873  dual_tolerance_value_ = value;
1874  break;
1875  }
1876  default: {
1877  LOG(ERROR) << "Trying to set an unknown parameter: " << param << ".";
1878  }
1879  }
1880 }
1881 
1883  int value) {
1884  switch (param) {
1885  case PRESOLVE: {
1886  if (value != PRESOLVE_OFF && value != PRESOLVE_ON) {
1887  LOG(ERROR) << "Trying to set a supported parameter: " << param
1888  << " to an unknown value: " << value;
1889  }
1890  presolve_value_ = value;
1891  break;
1892  }
1893  case SCALING: {
1894  if (value != SCALING_OFF && value != SCALING_ON) {
1895  LOG(ERROR) << "Trying to set a supported parameter: " << param
1896  << " to an unknown value: " << value;
1897  }
1898  scaling_value_ = value;
1899  break;
1900  }
1901  case LP_ALGORITHM: {
1902  if (value != DUAL && value != PRIMAL && value != BARRIER) {
1903  LOG(ERROR) << "Trying to set a supported parameter: " << param
1904  << " to an unknown value: " << value;
1905  }
1906  lp_algorithm_value_ = value;
1907  lp_algorithm_is_default_ = false;
1908  break;
1909  }
1910  case INCREMENTALITY: {
1912  LOG(ERROR) << "Trying to set a supported parameter: " << param
1913  << " to an unknown value: " << value;
1914  }
1915  incrementality_value_ = value;
1916  break;
1917  }
1918  default: {
1919  LOG(ERROR) << "Trying to set an unknown parameter: " << param << ".";
1920  }
1921  }
1922 }
1923 
1926  switch (param) {
1927  case RELATIVE_MIP_GAP: {
1928  relative_mip_gap_value_ = kDefaultRelativeMipGap;
1929  break;
1930  }
1931  case PRIMAL_TOLERANCE: {
1932  primal_tolerance_value_ = kDefaultPrimalTolerance;
1933  break;
1934  }
1935  case DUAL_TOLERANCE: {
1936  dual_tolerance_value_ = kDefaultDualTolerance;
1937  break;
1938  }
1939  default: {
1940  LOG(ERROR) << "Trying to reset an unknown parameter: " << param << ".";
1941  }
1942  }
1943 }
1944 
1947  switch (param) {
1948  case PRESOLVE: {
1949  presolve_value_ = kDefaultPresolve;
1950  break;
1951  }
1952  case SCALING: {
1953  scaling_value_ = kDefaultIntegerParamValue;
1954  break;
1955  }
1956  case LP_ALGORITHM: {
1957  lp_algorithm_is_default_ = true;
1958  break;
1959  }
1960  case INCREMENTALITY: {
1961  incrementality_value_ = kDefaultIncrementality;
1962  break;
1963  }
1964  default: {
1965  LOG(ERROR) << "Trying to reset an unknown parameter: " << param << ".";
1966  }
1967  }
1968 }
1969 
1978 }
1979 
1981  MPSolverParameters::DoubleParam param) const {
1982  switch (param) {
1983  case RELATIVE_MIP_GAP: {
1984  return relative_mip_gap_value_;
1985  }
1986  case PRIMAL_TOLERANCE: {
1987  return primal_tolerance_value_;
1988  }
1989  case DUAL_TOLERANCE: {
1990  return dual_tolerance_value_;
1991  }
1992  default: {
1993  LOG(ERROR) << "Trying to get an unknown parameter: " << param << ".";
1994  return kUnknownDoubleParamValue;
1995  }
1996  }
1997 }
1998 
2000  MPSolverParameters::IntegerParam param) const {
2001  switch (param) {
2002  case PRESOLVE: {
2003  return presolve_value_;
2004  }
2005  case LP_ALGORITHM: {
2006  if (lp_algorithm_is_default_) return kDefaultIntegerParamValue;
2007  return lp_algorithm_value_;
2008  }
2009  case INCREMENTALITY: {
2010  return incrementality_value_;
2011  }
2012  case SCALING: {
2013  return scaling_value_;
2014  }
2015  default: {
2016  LOG(ERROR) << "Trying to get an unknown parameter: " << param << ".";
2018  }
2019  }
2020 }
2021 
2022 } // namespace operations_research
operations_research::MPSolverInterface::ExtractObjective
virtual void ExtractObjective()=0
operations_research::MPSOLVER_UNKNOWN_STATUS
@ MPSOLVER_UNKNOWN_STATUS
Definition: linear_solver.pb.h:235
var
IntVar * var
Definition: expr_array.cc:1858
operations_research::MPSolverInterface::SetDoubleParamToUnsupportedValue
void SetDoubleParamToUnsupportedValue(MPSolverParameters::DoubleParam param, double value)
Definition: linear_solver.cc:1769
operations_research::MPSolver::SuppressOutput
void SuppressOutput()
Suppresses solver logging.
Definition: linear_solver.cc:1504
INFO
const int INFO
Definition: log_severity.h:31
operations_research::MPCallback
Definition: linear_solver_callback.h:140
operations_research::MPSolver::MakeIntVar
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
Definition: linear_solver.cc:1105
operations_research::SolverTypeIsMip
bool SolverTypeIsMip(MPModelRequest::SolverType solver_type)
Definition: linear_solver.cc:65
response
SharedResponseManager * response
Definition: cp_model_solver.cc:2105
problem_type
MPSolver::OptimizationProblemType problem_type
Definition: linear_solver.cc:503
integral_types.h
map_util.h
operations_research::MPSolverParameters::kDefaultIntegerParamValue
static const int kDefaultIntegerParamValue
Definition: linear_solver.h:1431
operations_research::LinearExpr
LinearExpr models a quantity that is linear in the decision variables (MPVariable) of an optimization...
Definition: linear_expr.h:114
VLOG
#define VLOG(verboselevel)
Definition: base/logging.h:978
operations_research::PropagationBaseObject::name
virtual std::string name() const
Object naming.
Definition: constraint_solver.cc:2505
operations_research::MPSolver::ExportModelAsLpFormat
bool ExportModelAsLpFormat(bool obfuscate, std::string *model_str) const
Shortcuts to the homonymous MPModelProtoExporter methods, via exporting to a MPModelProto with Export...
Definition: linear_solver.cc:1523
operations_research::MPSolver::CBC_MIXED_INTEGER_PROGRAMMING
@ CBC_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:198
operations_research::MPVariable::SetBounds
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
Definition: linear_solver.cc:299
operations_research::MPObjective::BestBound
double BestBound() const
Returns the best objective bound.
Definition: linear_solver.cc:256
max
int64 max
Definition: alldiff_cst.cc:139
operations_research::MPObjective::Value
double Value() const
Returns the objective value of the best solution found so far.
Definition: linear_solver.cc:249
operations_research::MPVariable::SetInteger
void SetInteger(bool integer)
Sets the integrality requirement of the variable.
Definition: linear_solver.cc:308
operations_research::MPSolverInterface::column_status
virtual MPSolver::BasisStatus column_status(int variable_index) const =0
operations_research::MPConstraint::basis_status
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the constraint.
Definition: linear_solver.cc:145
operations_research::MPSolver::GLOP_LINEAR_PROGRAMMING
@ GLOP_LINEAR_PROGRAMMING
Definition: linear_solver.h:192
operations_research::MPSolverResponseStatus
MPSolverResponseStatus
Definition: linear_solver.pb.h:227
operations_research::MPSolver::NumVariables
int NumVariables() const
Returns the number of variables.
Definition: linear_solver.h:296
operations_research::MPSolverInterface::SetObjectiveOffset
virtual void SetObjectiveOffset(double value)=0
operations_research::MPSolver::SupportsCallbacks
bool SupportsCallbacks() const
Definition: linear_solver.cc:1582
operations_research::MPSolverInterface::MPSolverInterface
MPSolverInterface(MPSolver *const solver)
Definition: linear_solver.cc:1620
operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING
@ XPRESS_LINEAR_PROGRAMMING
Definition: linear_solver.h:205
LOG
#define LOG(severity)
Definition: base/logging.h:420
ERROR
const int ERROR
Definition: log_severity.h:32
operations_research::MPSolverParameters::DUAL_TOLERANCE
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
Definition: linear_solver.h:1375
linear_solver.pb.h
operations_research::MPSolver::ProblemType
virtual OptimizationProblemType ProblemType() const
Returns the optimization problem type set at construction.
Definition: linear_solver.h:284
operations_research::MPSolver::OPTIMAL
@ OPTIMAL
optimal.
Definition: linear_solver.h:429
operations_research::MPModelExportOptions
Export options.
Definition: model_exporter.h:29
operations_research::AccurateSum::Add
void Add(const FpNumber &value)
Definition: accurate_sum.h:29
operations_research::MPVariable::integer
bool integer() const
Returns the integrality requirement of the variable.
Definition: linear_solver.h:1061
operations_research::MPSolverParameters::LP_ALGORITHM
@ LP_ALGORITHM
Algorithm to solve linear programs.
Definition: linear_solver.h:1383
operations_research::MPConstraint::SetBounds
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
Definition: linear_solver.cc:127
FATAL
const int FATAL
Definition: log_severity.h:32
operations_research::MPVariable::index
int index() const
Returns the index of the variable in the MPSolver::variables_.
Definition: linear_solver.h:1073
operations_research::MPObjective::SetMinimization
void SetMinimization()
Sets the optimization direction to minimize.
Definition: linear_solver.h:985
operations_research::MPSolver::Objective
const MPObjective & Objective() const
Returns the objective object.
Definition: linear_solver.h:416
operations_research::ExportModelAsLpFormat
absl::StatusOr< std::string > ExportModelAsLpFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in the so-called "C...
Definition: model_exporter.cc:214
operations_research::MPSolver::UNBOUNDED
@ UNBOUNDED
proven unbounded.
Definition: linear_solver.h:435
operations_research::MPObjective::GetCoefficient
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
Definition: linear_solver.cc:171
operations_research::MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING
@ CPLEX_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:204
operations_research::MPSolverInterface::BranchingPriorityChangedForVariable
virtual void BranchingPriorityChangedForVariable(int var_index)
Definition: linear_solver.h:1607
operations_research::MPSOLVER_MODEL_INVALID_SOLUTION_HINT
@ MPSOLVER_MODEL_INVALID_SOLUTION_HINT
Definition: linear_solver.pb.h:237
operations_research::MPSolverParameters::MPSolverParameters
MPSolverParameters()
The constructor sets all parameters to their default value.
Definition: linear_solver.cc:1851
operations_research::MPSolver::ExportModelAsMpsFormat
bool ExportModelAsMpsFormat(bool fixed_format, bool obfuscate, std::string *model_str) const
Definition: linear_solver.cc:1535
operations_research::FindErrorInMPModelProto
std::string FindErrorInMPModelProto(const MPModelProto &model, double abs_value_threshold)
Returns an empty string iff the model is valid and not trivially infeasible.
Definition: model_validator.cc:416
logging.h
operations_research::MPObjective::OptimizeLinearExpr
void OptimizeLinearExpr(const LinearExpr &linear_expr, bool is_maximization)
Resets the current objective to take the value of linear_expr, and sets the objective direction to ma...
Definition: linear_solver.cc:207
operations_research::MPSolverInterface::last_constraint_index_
int last_constraint_index_
Definition: linear_solver.h:1724
operations_research::MPSolver
This mathematical programming (MP) solver class is the main class though which users build and solve ...
Definition: linear_solver.h:179
operations_research::LinearExpr::offset
double offset() const
Definition: linear_expr.h:142
operations_research::MPSolver::Reset
void Reset()
Advanced usage: resets extracted model to solve from scratch.
Definition: linear_solver.cc:1076
value
int64 value
Definition: demon_profiler.cc:43
operations_research::MPSolver::SolverVersion
std::string SolverVersion() const
Returns a string describing the underlying solver and its version.
Definition: linear_solver.cc:327
operations_research::MPSOLVER_ABNORMAL
@ MPSOLVER_ABNORMAL
Definition: linear_solver.pb.h:232
operations_research::MPSolverInterface::MODEL_SYNCHRONIZED
@ MODEL_SYNCHRONIZED
Definition: linear_solver.h:1525
operations_research::MPObjective::AddLinearExpr
void AddLinearExpr(const LinearExpr &linear_expr)
Adds linear_expr to the current objective, does not change the direction.
Definition: linear_solver.cc:219
operations_research::MPSolver::MutableObjective
MPObjective * MutableObjective()
Returns the mutable objective object.
Definition: linear_solver.h:419
operations_research::MPVariable::name
const std::string & name() const
Returns the name of the variable.
Definition: linear_solver.h:1055
operations_research::MPSolver::LookupVariableOrNull
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
Definition: linear_solver.cc:616
operations_research::MPSolver::InterruptSolve
bool InterruptSolve()
Interrupts the Solve() execution to terminate processing if possible.
Definition: linear_solver.cc:1078
gtl::FindWithDefault
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
Definition: map_util.h:26
operations_research::MPSolver::ComputeExactConditionNumber
double ComputeExactConditionNumber() const
Advanced usage: computes the exact condition number of the current scaled basis: L1norm(B) * L1norm(i...
Definition: linear_solver.cc:1510
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::MPObjective::offset
double offset() const
Gets the constant term in the objective.
Definition: linear_solver.h:961
operations_research::MPSolverParameters::kDefaultRelativeMipGap
static const double kDefaultRelativeMipGap
Definition: linear_solver.h:1442
operations_research::AccurateSum::Value
FpNumber Value() const
Definition: accurate_sum.h:37
operations_research::MPSolver::ClampSolutionWithinBounds
absl::Status ClampSolutionWithinBounds()
Resets values of out of bound variables to the corresponding bound and returns an error if any of the...
Definition: linear_solver.cc:1322
operations_research::MPSolverInterface::ClearObjective
virtual void ClearObjective()=0
operations_research::MPSolverParameters::kUnknownIntegerParamValue
static const int kUnknownIntegerParamValue
Definition: linear_solver.h:1435
WARNING
const int WARNING
Definition: log_severity.h:31
operations_research::MPObjective::maximization
bool maximization() const
Is the optimization direction set to maximize?
Definition: linear_solver.cc:245
operations_research::MPSolverInterface::InvalidateSolutionSynchronization
void InvalidateSolutionSynchronization()
Definition: linear_solver.cc:1718
operations_research::MPSolver::MODEL_INVALID
@ MODEL_INVALID
the model is trivially invalid (NaN coefficients, etc).
Definition: linear_solver.h:439
operations_research::MPSolverInterface
Definition: linear_solver.h:1516
operations_research::MPVariable::unrounded_solution_value
double unrounded_solution_value() const
Advanced usage: unrounded solution value.
Definition: linear_solver.cc:273
operations_research::MPSolver::Name
const std::string & Name() const
Returns the name of the model set at construction.
Definition: linear_solver.h:279
operations_research::MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING
@ GLPK_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:197
operations_research::MPSolverParameters::SCALING_OFF
@ SCALING_OFF
Scaling is off.
Definition: linear_solver.h:1423
operations_research::MPSolver::ABNORMAL
@ ABNORMAL
abnormal, i.e., error of some kind.
Definition: linear_solver.h:437
operations_research::MPConstraint::ub
double ub() const
Returns the upper bound.
Definition: linear_solver.h:1212
int64
int64_t int64
Definition: integral_types.h:34
operations_research::MPVariable::solution_value
double solution_value() const
Returns the value of the variable in the current solution.
Definition: linear_solver.cc:264
operations_research::MPConstraint::indicator_variable
const MPVariable * indicator_variable() const
Definition: linear_solver.h:1241
operations_research::ToString
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
Definition: linear_solver.cc:569
operations_research::MPSolverParameters::kUnknownDoubleParamValue
static const double kUnknownDoubleParamValue
Definition: linear_solver.h:1434
operations_research::MPConstraint::name
const std::string & name() const
Returns the name of the constraint.
Definition: linear_solver.h:1180
operations_research::MPObjective::SetCoefficient
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
Definition: linear_solver.cc:177
operations_research::MPSolverParameters
This class stores parameter settings for LP and MIP solvers.
Definition: linear_solver.h:1360
accurate_sum.h
operations_research::MPConstraint
The class for constraints of a Mathematical Programming (MP) model.
Definition: linear_solver.h:1177
file.h
operations_research::MPConstraint::GetCoefficient
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable on the constraint (which is 0 if the variable does not appea...
Definition: linear_solver.cc:90
operations_research::BuildBopInterface
MPSolverInterface * BuildBopInterface(MPSolver *const solver)
Definition: bop_interface.cc:383
operations_research::MPSolverInterface::constraint_is_extracted
bool constraint_is_extracted(int ct_index) const
Definition: linear_solver.h:1660
operations_research::MPVariable::basis_status
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the variable in the current solution (only available for ...
Definition: linear_solver.cc:287
operations_research::MPSolver::NextSolution
ABSL_MUST_USE_RESULT bool NextSolution()
Some solvers (MIP only, not LP) can produce multiple solutions to the problem.
Definition: linear_solver.cc:1576
operations_research::MPSolverParameters::PresolveValues
PresolveValues
For each categorical parameter, enumeration of possible values.
Definition: linear_solver.h:1391
operations_research::MPSolverParameters::PRESOLVE_ON
@ PRESOLVE_ON
Presolve is on.
Definition: linear_solver.h:1395
DCHECK_NE
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:886
operations_research::kOptimizationProblemTypeNames
constexpr NamedOptimizationProblemType kOptimizationProblemTypeNames[]
Definition: linear_solver.cc:513
operations_research::BuildSatInterface
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
Definition: sat_interface.cc:298
operations_research::MPSolverInterface::SetLpAlgorithm
virtual void SetLpAlgorithm(int value)=0
operations_research::ExtractValidMPModelOrPopulateResponseStatus
absl::optional< LazyMutableCopy< MPModelProto > > ExtractValidMPModelOrPopulateResponseStatus(const MPModelRequest &request, MPSolutionResponse *response)
If the model is valid and non-empty, returns it (possibly after extracting the model_delta).
Definition: model_validator.cc:531
operations_research::MPSolverInterface::objective_value_
double objective_value_
Definition: linear_solver.h:1729
operations_research::AbslParseFlag
bool AbslParseFlag(const absl::string_view text, MPSolver::OptimizationProblemType *solver_type, std::string *error)
Definition: linear_solver.cc:581
operations_research::BuildCBCInterface
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)
Definition: cbc_interface.cc:533
operations_research::MPSolverInterface::last_variable_index
int last_variable_index() const
Definition: linear_solver.h:1652
operations_research::MPSOLVER_FEASIBLE
@ MPSOLVER_FEASIBLE
Definition: linear_solver.pb.h:229
operations_research::MPSolver::OutputIsEnabled
bool OutputIsEnabled() const
Controls (or queries) the amount of output produced by the underlying solver.
Definition: linear_solver.cc:1500
operations_research::MPSolverParameters::GetIntegerParam
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
Definition: linear_solver.cc:1999
operations_research::MPSolverInterface::objective_value
double objective_value() const
Definition: linear_solver.cc:1695
operations_research::MPSolver::MakeIntVarArray
void MakeIntVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of integer variables.
Definition: linear_solver.cc:1137
operations_research::MPSolver::MakeBoolVar
MPVariable * MakeBoolVar(const std::string &name)
Creates a boolean variable.
Definition: linear_solver.cc:1110
operations_research::MPSolverParameters::SCALING_ON
@ SCALING_ON
Scaling is on.
Definition: linear_solver.h:1425
operations_research::MPSolverInterface::SetPresolveMode
virtual void SetPresolveMode(int value)=0
operations_research::MPSolverInterface::SetConstraintBounds
virtual void SetConstraintBounds(int index, double lb, double ub)=0
operations_research::MPSolverInterface::Write
virtual void Write(const std::string &filename)
Definition: linear_solver.cc:1633
operations_research::MPObjective::SetOffset
void SetOffset(double value)
Sets the constant term in the objective.
Definition: linear_solver.cc:192
operations_research::MPSolverInterface::ResetExtractionInformation
void ResetExtractionInformation()
Definition: linear_solver.cc:1665
operations_research::MPSolverParameters::INCREMENTALITY_ON
@ INCREMENTALITY_ON
Reuse results from previous solve as much as the underlying solver allows.
Definition: linear_solver.h:1417
operations_research::MPSolver::LoadModelFromProto
MPSolverResponseStatus LoadModelFromProto(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
Definition: linear_solver.cc:636
operations_research::MPSolverInterface::solver_
MPSolver *const solver_
Definition: linear_solver.h:1714
operations_research::MPSolverInterface::IsContinuous
virtual bool IsContinuous() const =0
operations_research::MPSolverInterface::IsMIP
virtual bool IsMIP() const =0
operations_research::MPSOLVER_UNBOUNDED
@ MPSOLVER_UNBOUNDED
Definition: linear_solver.pb.h:231
operations_research::MPSolverInterface::SetUnsupportedDoubleParam
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
Definition: linear_solver.cc:1761
operations_research::MPSolver::GLPK_LINEAR_PROGRAMMING
@ GLPK_LINEAR_PROGRAMMING
Definition: linear_solver.h:191
operations_research::MPSolver::NumConstraints
int NumConstraints() const
Returns the number of constraints.
Definition: linear_solver.h:361
operations_research::MPSolver::infinity
static double infinity()
Infinity.
Definition: linear_solver.h:670
operations_research::MPSolver::NOT_SOLVED
@ NOT_SOLVED
not been solved yet.
Definition: linear_solver.h:441
operations_research::BuildSCIPInterface
MPSolverInterface * BuildSCIPInterface(MPSolver *const solver)
Definition: scip_interface.cc:1103
operations_research::MPSolver::BOP_INTEGER_PROGRAMMING
@ BOP_INTEGER_PROGRAMMING
Definition: linear_solver.h:210
operations_research::MPSolver::SetSolverSpecificParametersAsString
bool SetSolverSpecificParametersAsString(const std::string &parameters)
Advanced usage: pass solver specific parameters in text format.
Definition: linear_solver.cc:346
operations_research::MPSolverParameters::PRESOLVE
@ PRESOLVE
Advanced usage: presolve mode.
Definition: linear_solver.h:1381
operations_research::MPSolver::KNAPSACK_MIXED_INTEGER_PROGRAMMING
@ KNAPSACK_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:218
operations_research::MPSolver::FREE
@ FREE
Definition: linear_solver.h:643
operations_research::MPSolver::MakeNumVar
MPVariable * MakeNumVar(double lb, double ub, const std::string &name)
Creates a continuous variable.
Definition: linear_solver.cc:1100
operations_research::MPSolverParameters::kDefaultPresolve
static const PresolveValues kDefaultPresolve
Definition: linear_solver.h:1445
operations_research::MPSolverInterface::ValidFileExtensionForParameterFile
virtual std::string ValidFileExtensionForParameterFile() const
Definition: linear_solver.cc:1828
operations_research::MPSolverInterface::SetVariableBounds
virtual void SetVariableBounds(int index, double lb, double ub)=0
fp_utils.h
operations_research::MPSolverInterface::SOLUTION_SYNCHRONIZED
@ SOLUTION_SYNCHRONIZED
Definition: linear_solver.h:1528
operations_research::MPSolverParameters::ResetIntegerParam
void ResetIntegerParam(MPSolverParameters::IntegerParam param)
Sets an integer parameter to its default value (default value defined in MPSolverParameters if it exi...
Definition: linear_solver.cc:1945
operations_research::MPSolverInterface::SetDualTolerance
virtual void SetDualTolerance(double value)=0
operations_research::MPSolver::SetTimeLimit
void SetTimeLimit(absl::Duration time_limit)
Definition: linear_solver.h:689
operations_research::MPSOLVER_MODEL_IS_VALID
@ MPSOLVER_MODEL_IS_VALID
Definition: linear_solver.pb.h:234
operations_research::MPSolverInterface::SetSolverSpecificParametersAsString
virtual bool SetSolverSpecificParametersAsString(const std::string &parameters)
Definition: linear_solver.cc:1785
operations_research::MPSolverParameters::Reset
void Reset()
Sets all parameters to their default value.
Definition: linear_solver.cc:1970
operations_research::LinearRange::lower_bound
double lower_bound() const
Definition: linear_expr.h:205
operations_research::MPSolverParameters::kDefaultIncrementality
static const IncrementalityValues kDefaultIncrementality
Definition: linear_solver.h:1446
operations_research::MPSolverParameters::kDefaultDoubleParamValue
static const double kDefaultDoubleParamValue
Definition: linear_solver.h:1430
operations_research::MPSOLVER_SOLVER_TYPE_UNAVAILABLE
@ MPSOLVER_SOLVER_TYPE_UNAVAILABLE
Definition: linear_solver.pb.h:239
operations_research::MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS
@ MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS
Definition: linear_solver.pb.h:238
operations_research::MPSolver::MakeVar
MPVariable * MakeVar(double lb, double ub, bool integer, const std::string &name)
Creates a variable with the given bounds, integrality requirement and name.
Definition: linear_solver.cc:1086
operations_research::MPObjective::minimization
bool minimization() const
Is the optimization direction set to minimize?
Definition: linear_solver.cc:247
operations_research::MPSolver::Write
void Write(const std::string &file_name)
Writes the model using the solver internal write function.
Definition: linear_solver.cc:1257
operations_research::MPSolver::Solve
ResultStatus Solve()
Solves the problem using the default parameter values.
Definition: linear_solver.cc:1225
operations_research::MPSolverInterface::SetIntegerParamToUnsupportedValue
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
Definition: linear_solver.cc:1774
operations_research::MPSolverInterface::ComputeExactConditionNumber
virtual double ComputeExactConditionNumber() const
Definition: linear_solver.cc:1724
operations_research::MPSolverInterface::ReadParameterFile
virtual bool ReadParameterFile(const std::string &filename)
Definition: linear_solver.cc:1823
ABSL_FLAG
ABSL_FLAG(bool, verify_solution, false, "Systematically verify the solution when calling Solve()" ", and change the return value of Solve() to ABNORMAL if" " an error was detected.")
operations_research::MPSolver::BasisStatus
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
Definition: linear_solver.h:642
operations_research::MPSolverInterface::CheckSolutionIsSynchronizedAndExists
bool CheckSolutionIsSynchronizedAndExists() const
Definition: linear_solver.h:1634
operations_research::MPSolver::LookupConstraintOrNull
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
Definition: linear_solver.cc:625
operations_research::MPSolverParameters::kDefaultPrimalTolerance
static const double kDefaultPrimalTolerance
Definition: linear_solver.h:1443
operations_research::BuildCLPInterface
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
Definition: clp_interface.cc:626
status_macros.h
operations_research::MPObjective::Clear
void Clear()
Clears the offset, all variables and coefficients, and the optimization direction.
Definition: linear_solver.cc:227
operations_research::MPSolverParameters::SetDoubleParam
void SetDoubleParam(MPSolverParameters::DoubleParam param, double value)
Sets a double parameter to a specific value.
Definition: linear_solver.cc:1861
operations_research::MPVariable::lb
double lb() const
Returns the lower bound.
Definition: linear_solver.h:1076
ct
const Constraint * ct
Definition: demon_profiler.cc:42
operations_research::MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING
@ SCIP_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:196
operations_research::MPSolverInterface::SetUnsupportedIntegerParam
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
Definition: linear_solver.cc:1765
operations_research::MPSolver::MPSolver
MPSolver(const std::string &name, OptimizationProblemType problem_type)
Create a solver with the given name and underlying solver backend.
Definition: linear_solver.cc:445
operations_research::MPSolverInterface::SetOptimizationDirection
virtual void SetOptimizationDirection(bool maximize)=0
operations_research::MPSolverInterface::SetObjectiveCoefficient
virtual void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient)=0
operations_research::sat::Value
std::function< int64(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1470
operations_research::MPSolverParameters::INCREMENTALITY_OFF
@ INCREMENTALITY_OFF
Start solve from scratch.
Definition: linear_solver.h:1411
operations_research::MPSolver::iterations
int64 iterations() const
Returns the number of simplex iterations.
Definition: linear_solver.cc:1506
operations_research::MPVariable::ub
double ub() const
Returns the upper bound.
Definition: linear_solver.h:1079
operations_research::MPSolverInterface::sync_status_
SynchronizationStatus sync_status_
Definition: linear_solver.h:1716
LOG_IF
#define LOG_IF(severity, condition)
Definition: base/logging.h:479
DCHECK
#define DCHECK(condition)
Definition: base/logging.h:884
operations_research::LinearRange
An expression of the form:
Definition: linear_expr.h:192
operations_research::MPSolver::SetCallback
void SetCallback(MPCallback *mp_callback)
Definition: linear_solver.cc:1578
operations_research::MPSolver::MakeNumVarArray
void MakeNumVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of continuous variables.
Definition: linear_solver.cc:1131
operations_research::MPSolver::SetNumThreads
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
Definition: linear_solver.cc:335
operations_research::MPSolverInterface::SetRelativeMipGap
virtual void SetRelativeMipGap(double value)=0
operations_research::MPSolver::GUROBI_LINEAR_PROGRAMMING
@ GUROBI_LINEAR_PROGRAMMING
Definition: linear_solver.h:201
operations_research::MPSolverInterface::SolverVersion
virtual std::string SolverVersion() const =0
operations_research::MPSolverParameters::PRIMAL_TOLERANCE
@ PRIMAL_TOLERANCE
Advanced usage: tolerance for primal feasibility of basic solutions.
Definition: linear_solver.h:1373
operations_research::MPSolverParameters::IncrementalityValues
IncrementalityValues
Advanced usage: Incrementality options.
Definition: linear_solver.h:1409
operations_research::MPSOLVER_NOT_SOLVED
@ MPSOLVER_NOT_SOLVED
Definition: linear_solver.pb.h:233
operations_research::MPSolver::ResultStatus
ResultStatus
The status of solving the problem.
Definition: linear_solver.h:427
operations_research::MPSolverInterface::variable_is_extracted
bool variable_is_extracted(int var_index) const
Definition: linear_solver.h:1654
model_validator.h
operations_research::MPSolver::SetStartingLpBasis
void SetStartingLpBasis(const std::vector< MPSolver::BasisStatus > &variable_statuses, const std::vector< MPSolver::BasisStatus > &constraint_statuses)
Advanced usage: Incrementality.
Definition: linear_solver.cc:1080
operations_research::MPSolver::VerifySolution
bool VerifySolution(double tolerance, bool log_errors) const
Advanced usage: Verifies the correctness of the solution.
Definition: linear_solver.cc:1356
DCHECK_GE
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:889
operations_research::LinearExpr::terms
const absl::flat_hash_map< const MPVariable *, double > & terms() const
Definition: linear_expr.h:143
operations_research::MPSolverInterface::ExtractModel
void ExtractModel()
Definition: linear_solver.cc:1637
operations_research::PortableDeleteFile
::absl::Status PortableDeleteFile(absl::string_view file_name)
Definition: file_nonport.cc:55
operations_research::MPSolverInterface::SetVariableInteger
virtual void SetVariableInteger(int index, bool integer)=0
operations_research::MPSolverInterface::SetMIPParameters
void SetMIPParameters(const MPSolverParameters &param)
Definition: linear_solver.cc:1754
operations_research::MPSolverParameters::GetDoubleParam
double GetDoubleParam(MPSolverParameters::DoubleParam param) const
Returns the value of a double parameter.
Definition: linear_solver.cc:1980
operations_research::MPSolver::EnableOutput
void EnableOutput()
Enables solver logging.
Definition: linear_solver.cc:1502
operations_research::MPSolverParameters::kDefaultDualTolerance
static const double kDefaultDualTolerance
Definition: linear_solver.h:1444
operations_research::MPSolver::MakeRowConstraint
MPConstraint * MakeRowConstraint()
Creates a constraint with -infinity and +infinity bounds.
Definition: linear_solver.cc:1152
operations_research::MPSolver::LoadSolutionFromProto
absl::Status LoadSolutionFromProto(const MPSolutionResponse &response, double tolerance=kDefaultPrimalTolerance)
Load a solution encoded in a protocol buffer onto this solver for easy access via the MPSolver interf...
Definition: linear_solver.cc:991
operations_research::MPConstraint::lb
double lb() const
Returns the lower bound.
Definition: linear_solver.h:1209
operations_research::MPSolver::SAT_INTEGER_PROGRAMMING
@ SAT_INTEGER_PROGRAMMING
Definition: linear_solver.h:215
operations_research::MPSolver::nodes
int64 nodes() const
Returns the number of branch-and-bound nodes evaluated during the solve.
Definition: linear_solver.cc:1508
operations_research::MPSolverInterface::row_status
virtual MPSolver::BasisStatus row_status(int constraint_index) const =0
operations_research::MPSolverInterface::ExtractNewConstraints
virtual void ExtractNewConstraints()=0
operations_research::MPSolver::SolveWithProto
static void SolveWithProto(const MPModelRequest &model_request, MPSolutionResponse *response)
Solves the model encoded by a MPModelRequest protocol buffer and fills the solution encoded as a MPSo...
Definition: linear_solver.cc:834
operations_research::MPSOLVER_MODEL_INVALID
@ MPSOLVER_MODEL_INVALID
Definition: linear_solver.pb.h:236
operations_research::MPSolverParameters::SCALING
@ SCALING
Advanced usage: enable or disable matrix scaling.
Definition: linear_solver.h:1387
operations_research::MPSolver::IsMIP
bool IsMIP() const
Definition: linear_solver.cc:325
operations_research::MPSolver::ComputeConstraintActivities
std::vector< double > ComputeConstraintActivities() const
Advanced usage: compute the "activities" of all constraints, which are the sums of their linear terms...
Definition: linear_solver.cc:1340
operations_research::MPModelExportOptions::obfuscate
bool obfuscate
Obfuscates variable and constraint names.
Definition: model_exporter.h:33
operations_research::MPSolver::~MPSolver
virtual ~MPSolver()
Definition: linear_solver.cc:457
operations_research::MPSolverParameters::IntegerParam
IntegerParam
Enumeration of parameters that take integer or categorical values.
Definition: linear_solver.h:1379
operations_research::MPConstraint::is_lazy
bool is_lazy() const
Advanced usage: returns true if the constraint is "lazy" (see below).
Definition: linear_solver.h:1224
operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING
@ CPLEX_LINEAR_PROGRAMMING
Definition: linear_solver.h:203
operations_research::MPSolver::MakeVarArray
void MakeVarArray(int nb, double lb, double ub, bool integer, const std::string &name_prefix, std::vector< MPVariable * > *vars)
Creates an array of variables.
Definition: linear_solver.cc:1114
stl_util.h
gtl::InsertOrDie
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
Definition: map_util.h:135
operations_research::MPSolverParameters::ResetDoubleParam
void ResetDoubleParam(MPSolverParameters::DoubleParam param)
Sets a double parameter to its default value (default value defined in MPSolverParameters if it exist...
Definition: linear_solver.cc:1924
operations_research::MPSolverInterface::ExtractNewVariables
virtual void ExtractNewVariables()=0
operations_research::MPConstraint::indicator_value
bool indicator_value() const
Definition: linear_solver.h:1242
operations_research::MPSolverInterface::last_variable_index_
int last_variable_index_
Definition: linear_solver.h:1726
operations_research::MPSolver::underlying_solver
void * underlying_solver()
Advanced usage: returns the underlying solver.
Definition: linear_solver.cc:331
operations_research::MPSolverParameters::RELATIVE_MIP_GAP
@ RELATIVE_MIP_GAP
Limit for relative MIP gap.
Definition: linear_solver.h:1365
operations_research::MPSOLVER_INFEASIBLE
@ MPSOLVER_INFEASIBLE
Definition: linear_solver.pb.h:230
operations_research::MPSolver::CLP_LINEAR_PROGRAMMING
@ CLP_LINEAR_PROGRAMMING
Definition: linear_solver.h:190
operations_research::MPSolverParameters::INCREMENTALITY
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
Definition: linear_solver.h:1385
operations_research::MPSolverInterface::best_objective_bound
double best_objective_bound() const
Definition: linear_solver.cc:1700
operations_research::MPSolverInterface::SetPrimalTolerance
virtual void SetPrimalTolerance(double value)=0
operations_research::MPVariable
The class for variables of a Mathematical Programming (MP) model.
Definition: linear_solver.h:1052
DCHECK_EQ
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:885
operations_research::MPSolver::FillSolutionResponseProto
void FillSolutionResponseProto(MPSolutionResponse *response) const
Encodes the current solution in a solution response protocol buffer.
Definition: linear_solver.cc:806
operations_research::MPSolver::OptimizationProblemType
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
Definition: linear_solver.h:187
maximize_
const bool maximize_
Definition: search.cc:2499
operations_research::MPSolver::ExportModelToProto
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
Definition: linear_solver.cc:902
linear_solver.h
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
operations_research::PortableTemporaryFile
bool PortableTemporaryFile(const char *directory_prefix, std::string *filename_out)
Definition: file_nonport.cc:37
operations_research::MPSolverInterface::ClearConstraint
virtual void ClearConstraint(MPConstraint *const constraint)=0
name
absl::string_view name
Definition: linear_solver.cc:504
operations_research::MPSOLVER_OPTIMAL
@ MPSOLVER_OPTIMAL
Definition: linear_solver.pb.h:228
operations_research::BuildGLOPInterface
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
Definition: glop_interface.cc:427
operations_research::MPSolverInterface::SetCommonParameters
void SetCommonParameters(const MPSolverParameters &param)
Definition: linear_solver.cc:1733
operations_research::MPConstraint::SetCoefficient
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable on the constraint.
Definition: linear_solver.cc:96
operations_research::MPSolverInterface::SetNumThreads
virtual absl::Status SetNumThreads(int num_threads)
Definition: linear_solver.cc:1780
operations_research::MPConstraint::dual_value
double dual_value() const
Advanced usage: returns the dual value of the constraint in the current solution (only available for ...
Definition: linear_solver.cc:136
operations_research::MPObjective::SetOptimizationDirection
void SetOptimizationDirection(bool maximize)
Sets the optimization direction (maximize: true or minimize: false).
Definition: linear_solver.cc:234
operations_research::MPSolver::ParseSolverType
static bool ParseSolverType(absl::string_view solver_id, OptimizationProblemType *type)
Parses the name of the solver.
Definition: linear_solver.cc:532
operations_research::MPSolver::INFEASIBLE
@ INFEASIBLE
proven infeasible.
Definition: linear_solver.h:433
operations_research::MPSolverInterface::SetCoefficient
virtual void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value)=0
DLOG_IF
#define DLOG_IF(severity, condition)
Definition: base/logging.h:877
operations_research::BuildGurobiInterface
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
Definition: gurobi_interface.cc:1371
absl
Definition: cleanup.h:22
gtl::STLDeleteElements
void STLDeleteElements(T *container)
Definition: stl_util.h:372
operations_research::MPSolver::CreateSolver
static MPSolver * CreateSolver(const std::string &solver_id)
Recommended factory method to create a MPSolver instance, especially in non C++ languages.
Definition: linear_solver.cc:602
proto
CpModelProto proto
Definition: cp_model_fz_solver.cc:107
operations_research::MPSolverResponseStatusIsRpcError
bool MPSolverResponseStatusIsRpcError(MPSolverResponseStatus status)
Definition: linear_solver.cc:1586
operations_research::MPSolver::MakeBoolVarArray
void MakeBoolVarArray(int nb, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of boolean variables.
Definition: linear_solver.cc:1143
operations_research::MPSolverParameters::PRIMAL
@ PRIMAL
Primal simplex.
Definition: linear_solver.h:1403
operations_research::kDefaultPrimalTolerance
constexpr double kDefaultPrimalTolerance
Definition: linear_solver.h:164
operations_research::MPSolverParameters::DoubleParam
DoubleParam
Enumeration of parameters that take continuous values.
Definition: linear_solver.h:1363
operations_research::PortableFileSetContents
::absl::Status PortableFileSetContents(absl::string_view file_name, absl::string_view content)
Definition: file_nonport.cc:27
operations_research::MPSolverParameters::PRESOLVE_OFF
@ PRESOLVE_OFF
Presolve is off.
Definition: linear_solver.h:1393
operations_research::MPSolver::LoadModelFromProtoWithUniqueNamesOrDie
MPSolverResponseStatus LoadModelFromProtoWithUniqueNamesOrDie(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
Definition: linear_solver.cc:647
operations_research::MPConstraint::Clear
void Clear()
Clears all variables and coefficients. Does not clear the bounds.
Definition: linear_solver.cc:122
model_exporter.h
operations_research::MPSolverInterface::CheckSolutionExists
virtual bool CheckSolutionExists() const
Definition: linear_solver.cc:1685
DCHECK_LE
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:887
operations_research::MPSolverInterface::MUST_RELOAD
@ MUST_RELOAD
Definition: linear_solver.h:1521
operations_research::MPSolver::Clear
void Clear()
Clears the objective (including the optimization direction), all variables and constraints.
Definition: linear_solver.cc:1058
operations_research::MPSolver::SetHint
void SetHint(std::vector< std::pair< const MPVariable *, double > > hint)
Sets a hint for solution.
Definition: linear_solver.cc:1552
operations_research::MPSolverParameters::SetIntegerParam
void SetIntegerParam(MPSolverParameters::IntegerParam param, int value)
Sets a integer parameter to a specific value.
Definition: linear_solver.cc:1882
operations_research::MPSolverInterface::kDummyVariableIndex
static const int kDummyVariableIndex
Definition: linear_solver.h:1739
operations_research::MPSolver::OwnsVariable
bool OwnsVariable(const MPVariable *var) const
Definition: linear_solver.cc:1514
operations_research::MPSolverInterface::CheckSolutionIsSynchronized
bool CheckSolutionIsSynchronized() const
Definition: linear_solver.cc:1673
operations_research::AccurateSum
Definition: accurate_sum.h:23
operations_research::MPObjective
A class to express a linear objective.
Definition: linear_solver.h:925
operations_research::MPVariable::SetBranchingPriority
void SetBranchingPriority(int priority)
Definition: linear_solver.cc:317
operations_research::MPSolverInterface::result_status_
MPSolver::ResultStatus result_status_
Definition: linear_solver.h:1719
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
operations_research::MPSolverInterface::maximize_
bool maximize_
Definition: linear_solver.h:1721
commandlineflags.h
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:108
operations_research::MPSolver::SupportsProblemType
static bool SupportsProblemType(OptimizationProblemType problem_type)
Whether the given problem type is supported (this will depend on the targets that you linked).
Definition: linear_solver.cc:460
operations_research::MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING
@ XPRESS_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:206
operations_research::LinearRange::upper_bound
double upper_bound() const
Definition: linear_expr.h:207
operations_research::MPSolver::ParseSolverTypeOrDie
static OptimizationProblemType ParseSolverTypeOrDie(const std::string &solver_id)
Parses the name of the solver and returns the correct optimization type or dies.
Definition: linear_solver.cc:594
operations_research::MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING
@ GUROBI_MIXED_INTEGER_PROGRAMMING
Definition: linear_solver.h:202
operations_research::LinearRange::linear_expr
const LinearExpr & linear_expr() const
Definition: linear_expr.h:206
operations_research::AreWithinAbsoluteOrRelativeTolerances
bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)
Definition: fp_utils.h:120
operations_research::MPVariable::reduced_cost
double reduced_cost() const
Advanced usage: returns the reduced cost of the variable in the current solution (only available for ...
Definition: linear_solver.cc:278
operations_research::MPSolverParameters::DUAL
@ DUAL
Dual simplex.
Definition: linear_solver.h:1401
operations_research::MPSolverParameters::BARRIER
@ BARRIER
Barrier algorithm.
Definition: linear_solver.h:1405
operations_research::MPSolver::FEASIBLE
@ FEASIBLE
feasible, or stopped by limit.
Definition: linear_solver.h:431
operations_research::MPSolverInterface::~MPSolverInterface
virtual ~MPSolverInterface()
Definition: linear_solver.cc:1631
operations_research::MPSolverInterface::best_objective_bound_
double best_objective_bound_
Definition: linear_solver.h:1732
operations_research::ExportModelAsMpsFormat
absl::StatusOr< std::string > ExportModelAsMpsFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in MPS file format,...
Definition: model_exporter.cc:231