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