OR-Tools  8.1
gurobi_interface.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 // Gurobi backend to MPSolver.
15 //
16 // Implementation Notes:
17 //
18 // Incrementalism (last updated June 29, 2020): For solving both LPs and MIPs,
19 // Gurobi attempts to reuse information from previous solves, potentially
20 // giving a faster solve time. MPSolver supports this for the following problem
21 // modification types:
22 // * Adding a variable,
23 // * Adding a linear constraint,
24 // * Updating a variable bound,
25 // * Updating an objective coefficient or the objective offset (note that in
26 // Gurobi 7.5 LP solver, there is a bug if you update only the objective
27 // offset and nothing else).
28 // * Updating a coefficient in the constraint matrix.
29 // * Updating the type of variable (integer, continuous)
30 // * Changing the optimization direction.
31 // Updates of the following types will force a resolve from scratch:
32 // * Updating the upper or lower bounds of a linear constraint. Note that in
33 // MPSolver's model, this includes updating the sense (le, ge, eq, range) of
34 // a linear constraint.
35 // * Clearing a constraint
36 // Any model containing indicator constraints is considered "non-incremental"
37 // and will always solve from scratch.
38 //
39 // The above limitations are largely due MPSolver and this file, not Gurobi.
40 //
41 // Warning(rander): the interactions between callbacks and incrementalism are
42 // poorly tested, proceed with caution.
43 //
44 
45 #include <cmath>
46 #include <cstddef>
47 #include <limits>
48 #include <memory>
49 #include <stdexcept>
50 #include <string>
51 #include <utility>
52 #include <vector>
53 
54 #include "absl/status/status.h"
55 #include "absl/strings/match.h"
56 #include "absl/strings/str_format.h"
59 #include "ortools/base/logging.h"
60 #include "ortools/base/map_util.h"
61 #include "ortools/base/timer.h"
66 
67 ABSL_FLAG(int, num_gurobi_threads, 4,
68  "Number of threads available for Gurobi.");
69 
70 namespace operations_research {
71 
73  public:
74  // Constructor that takes a name for the underlying GRB solver.
75  explicit GurobiInterface(MPSolver* const solver, bool mip);
76  ~GurobiInterface() override;
77 
78  // Sets the optimization direction (min/max).
79  void SetOptimizationDirection(bool maximize) override;
80 
81  // ----- Solve -----
82  // Solves the problem using the parameter values specified.
83  MPSolver::ResultStatus Solve(const MPSolverParameters& param) override;
84  absl::optional<MPSolutionResponse> DirectlySolveProto(
85  const MPModelRequest& request) override;
86 
87  // Writes the model.
88  void Write(const std::string& filename) override;
89 
90  // ----- Model modifications and extraction -----
91  // Resets extracted model
92  void Reset() override;
93 
94  // Modifies bounds.
95  void SetVariableBounds(int var_index, double lb, double ub) override;
96  void SetVariableInteger(int var_index, bool integer) override;
97  void SetConstraintBounds(int row_index, double lb, double ub) override;
98 
99  // Adds Constraint incrementally.
100  void AddRowConstraint(MPConstraint* const ct) override;
101  bool AddIndicatorConstraint(MPConstraint* const ct) override;
102  // Adds variable incrementally.
103  void AddVariable(MPVariable* const var) override;
104  // Changes a coefficient in a constraint.
105  void SetCoefficient(MPConstraint* const constraint,
106  const MPVariable* const variable, double new_value,
107  double old_value) override;
108  // Clears a constraint from all its terms.
109  void ClearConstraint(MPConstraint* const constraint) override;
110  // Changes a coefficient in the linear objective
111  void SetObjectiveCoefficient(const MPVariable* const variable,
112  double coefficient) override;
113  // Changes the constant term in the linear objective.
114  void SetObjectiveOffset(double value) override;
115  // Clears the objective from all its terms.
116  void ClearObjective() override;
117  void BranchingPriorityChangedForVariable(int var_index) override;
118 
119  // ------ Query statistics on the solution and the solve ------
120  // Number of simplex or interior-point iterations
121  int64 iterations() const override;
122  // Number of branch-and-bound nodes. Only available for discrete problems.
123  int64 nodes() const override;
124 
125  // Returns the basis status of a row.
126  MPSolver::BasisStatus row_status(int constraint_index) const override;
127  // Returns the basis status of a column.
128  MPSolver::BasisStatus column_status(int variable_index) const override;
129 
130  // ----- Misc -----
131  // Queries problem type.
132  bool IsContinuous() const override { return IsLP(); }
133  bool IsLP() const override { return !mip_; }
134  bool IsMIP() const override { return mip_; }
135 
136  void ExtractNewVariables() override;
137  void ExtractNewConstraints() override;
138  void ExtractObjective() override;
139 
140  std::string SolverVersion() const override {
141  int major, minor, technical;
142  GRBversion(&major, &minor, &technical);
143  return absl::StrFormat("Gurobi library version %d.%d.%d\n", major, minor,
144  technical);
145  }
146 
147  bool InterruptSolve() override {
148  if (model_ != nullptr) GRBterminate(model_);
149  return true;
150  }
151 
152  void* underlying_solver() override { return reinterpret_cast<void*>(model_); }
153 
154  double ComputeExactConditionNumber() const override {
155  if (!IsContinuous()) {
156  LOG(DFATAL) << "ComputeExactConditionNumber not implemented for"
157  << " GUROBI_MIXED_INTEGER_PROGRAMMING";
158  return 0.0;
159  }
160 
161  // TODO(user,user): Not yet working.
162  LOG(DFATAL) << "ComputeExactConditionNumber not implemented for"
163  << " GUROBI_LINEAR_PROGRAMMING";
164  return 0.0;
165 
166  // double cond = 0.0;
167  // const int status = GRBgetdblattr(model_, GRB_DBL_ATTR_KAPPA, &cond);
168  // if (0 == status) {
169  // return cond;
170  // } else {
171  // LOG(DFATAL) << "Condition number only available for "
172  // << "continuous problems";
173  // return 0.0;
174  // }
175  }
176 
177  // Iterates through the solutions in Gurobi's solution pool.
178  bool NextSolution() override;
179 
180  void SetCallback(MPCallback* mp_callback) override;
181  bool SupportsCallbacks() const override { return true; }
182 
183  private:
184  // Sets all parameters in the underlying solver.
185  void SetParameters(const MPSolverParameters& param) override;
186  // Sets solver-specific parameters (avoiding using files). The previous
187  // implementations supported multi-line strings of the form:
188  // parameter_i value_i\n
189  // We extend support for strings of the form:
190  // parameter1=value1,....,parametern=valuen
191  // or for strings of the form:
192  // parameter1 value1, ... ,parametern valuen
193  // which are easier to set in the command line.
194  // This implementations relies on SetSolverSpecificParameters, which has the
195  // extra benefit of unifying the way we handle specific parameters for both
196  // proto-based solves and for MPModel solves.
197  bool SetSolverSpecificParametersAsString(
198  const std::string& parameters) override;
199  // Sets each parameter in the underlying solver.
200  void SetRelativeMipGap(double value) override;
201  void SetPrimalTolerance(double value) override;
202  void SetDualTolerance(double value) override;
203  void SetPresolveMode(int value) override;
204  void SetScalingMode(int value) override;
205  void SetLpAlgorithm(int value) override;
206 
207  bool ReadParameterFile(const std::string& filename) override;
208  std::string ValidFileExtensionForParameterFile() const override;
209 
210  MPSolver::BasisStatus TransformGRBVarBasisStatus(
211  int gurobi_basis_status) const;
212  MPSolver::BasisStatus TransformGRBConstraintBasisStatus(
213  int gurobi_basis_status, int constraint_index) const;
214 
215  // See the implementation note at the top of file on incrementalism.
216  bool ModelIsNonincremental() const;
217 
218  void SetIntAttr(const char* name, int value);
219  int GetIntAttr(const char* name) const;
220  void SetDoubleAttr(const char* name, double value);
221  double GetDoubleAttr(const char* name) const;
222  void SetIntAttrElement(const char* name, int index, int value);
223  int GetIntAttrElement(const char* name, int index) const;
224  void SetDoubleAttrElement(const char* name, int index, double value);
225  double GetDoubleAttrElement(const char* name, int index) const;
226  std::vector<double> GetDoubleAttrArray(const char* name, int elements);
227  void SetCharAttrElement(const char* name, int index, char value);
228  char GetCharAttrElement(const char* name, int index) const;
229 
230  void CheckedGurobiCall(int err) const;
231 
232  int SolutionCount() const;
233 
234  GRBmodel* model_;
235  GRBenv* env_;
236  bool mip_;
237  int current_solution_index_;
238  MPCallback* callback_ = nullptr;
239  bool update_branching_priorities_ = false;
240  // Has length equal to the number of MPVariables in
241  // MPSolverInterface::solver_. Values are the index of the corresponding
242  // Gurobi variable. Note that Gurobi may have additional auxiliary variables
243  // not represented by MPVariables, such as those created by two-sided range
244  // constraints.
245  std::vector<int> mp_var_to_gurobi_var_;
246  // Has length equal to the number of MPConstraints in
247  // MPSolverInterface::solver_. Values are the index of the corresponding
248  // linear (or range) constraint in Gurobi, or -1 if no such constraint exists
249  // (e.g. for indicator constraints).
250  std::vector<int> mp_cons_to_gurobi_linear_cons_;
251  // Should match the Gurobi model after it is updated.
252  int num_gurobi_vars_ = 0;
253  // Should match the Gurobi model after it is updated.
254  // NOTE(user): indicator constraints are not counted below.
255  int num_gurobi_linear_cons_ = 0;
256  // See the implementation note at the top of file on incrementalism.
257  bool had_nonincremental_change_ = false;
258 };
259 
260 namespace {
261 
262 void CheckedGurobiCall(int err, GRBenv* const env) {
263  CHECK_EQ(0, err) << "Fatal error with code " << err << ", due to "
264  << GRBgeterrormsg(env);
265 }
266 
267 // For interacting directly with the Gurobi C API for callbacks.
268 struct GurobiInternalCallbackContext {
271  int where;
272 };
273 
274 class GurobiMPCallbackContext : public MPCallbackContext {
275  public:
276  GurobiMPCallbackContext(GRBenv* env,
277  const std::vector<int>* mp_var_to_gurobi_var,
278  int num_gurobi_vars, bool might_add_cuts,
279  bool might_add_lazy_constraints);
280 
281  // Implementation of the interface.
282  MPCallbackEvent Event() override;
283  bool CanQueryVariableValues() override;
284  double VariableValue(const MPVariable* variable) override;
285  void AddCut(const LinearRange& cutting_plane) override;
286  void AddLazyConstraint(const LinearRange& lazy_constraint) override;
287  double SuggestSolution(
288  const absl::flat_hash_map<const MPVariable*, double>& solution) override;
289  int64 NumExploredNodes() override;
290 
291  // Call this method to update the internal state of the callback context
292  // before passing it to MPCallback::RunCallback().
293  void UpdateFromGurobiState(
294  const GurobiInternalCallbackContext& gurobi_internal_context);
295 
296  private:
297  // Wraps GRBcbget(), used to query the state of the solver. See
298  // http://www.gurobi.com/documentation/8.0/refman/callback_codes.html#sec:CallbackCodes
299  // for callback_code values.
300  template <typename T>
301  T GurobiCallbackGet(
302  const GurobiInternalCallbackContext& gurobi_internal_context,
303  int callback_code);
304  void CheckedGurobiCall(int gurobi_error_code) const;
305 
306  template <typename GRBConstraintFunction>
307  void AddGeneratedConstraint(const LinearRange& linear_range,
308  GRBConstraintFunction grb_constraint_function);
309 
310  GRBenv* const env_;
311  const std::vector<int>* const mp_var_to_gurobi_var_;
312  const int num_gurobi_vars_;
313 
314  const bool might_add_cuts_;
315  const bool might_add_lazy_constraints_;
316 
317  // Stateful, updated before each call to the callback.
318  GurobiInternalCallbackContext current_gurobi_internal_callback_context_;
319  bool variable_values_extracted_ = false;
320  std::vector<double> gurobi_variable_values_;
321 };
322 
323 void GurobiMPCallbackContext::CheckedGurobiCall(int gurobi_error_code) const {
324  ::operations_research::CheckedGurobiCall(gurobi_error_code, env_);
325 }
326 
327 GurobiMPCallbackContext::GurobiMPCallbackContext(
328  GRBenv* env, const std::vector<int>* mp_var_to_gurobi_var,
329  int num_gurobi_vars, bool might_add_cuts, bool might_add_lazy_constraints)
330  : env_(ABSL_DIE_IF_NULL(env)),
331  mp_var_to_gurobi_var_(ABSL_DIE_IF_NULL(mp_var_to_gurobi_var)),
332  num_gurobi_vars_(num_gurobi_vars),
333  might_add_cuts_(might_add_cuts),
334  might_add_lazy_constraints_(might_add_lazy_constraints) {}
335 
336 void GurobiMPCallbackContext::UpdateFromGurobiState(
337  const GurobiInternalCallbackContext& gurobi_internal_context) {
338  current_gurobi_internal_callback_context_ = gurobi_internal_context;
339  variable_values_extracted_ = false;
340 }
341 
342 int64 GurobiMPCallbackContext::NumExploredNodes() {
343  switch (Event()) {
344  case MPCallbackEvent::kMipNode:
345  return static_cast<int64>(GurobiCallbackGet<double>(
346  current_gurobi_internal_callback_context_, GRB_CB_MIPNODE_NODCNT));
347  case MPCallbackEvent::kMipSolution:
348  return static_cast<int64>(GurobiCallbackGet<double>(
349  current_gurobi_internal_callback_context_, GRB_CB_MIPSOL_NODCNT));
350  default:
351  LOG(FATAL) << "Node count is supported only for callback events MIP_NODE "
352  "and MIP_SOL, but was requested at: "
353  << ToString(Event());
354  }
355 }
356 
357 template <typename T>
358 T GurobiMPCallbackContext::GurobiCallbackGet(
359  const GurobiInternalCallbackContext& gurobi_internal_context,
360  const int callback_code) {
361  T result = 0;
362  CheckedGurobiCall(
363  GRBcbget(gurobi_internal_context.gurobi_internal_callback_data,
364  gurobi_internal_context.where, callback_code,
365  static_cast<void*>(&result)));
366  return result;
367 }
368 
369 MPCallbackEvent GurobiMPCallbackContext::Event() {
370  switch (current_gurobi_internal_callback_context_.where) {
371  case GRB_CB_POLLING:
372  return MPCallbackEvent::kPolling;
373  case GRB_CB_PRESOLVE:
374  return MPCallbackEvent::kPresolve;
375  case GRB_CB_SIMPLEX:
376  return MPCallbackEvent::kSimplex;
377  case GRB_CB_MIP:
378  return MPCallbackEvent::kMip;
379  case GRB_CB_MIPSOL:
380  return MPCallbackEvent::kMipSolution;
381  case GRB_CB_MIPNODE:
382  return MPCallbackEvent::kMipNode;
383  case GRB_CB_MESSAGE:
384  return MPCallbackEvent::kMessage;
385  case GRB_CB_BARRIER:
386  return MPCallbackEvent::kBarrier;
387  // TODO(b/112427356): in Gurobi 8.0, there is a new callback location.
388  // case GRB_CB_MULTIOBJ:
389  // return MPCallbackEvent::kMultiObj;
390  default:
391  LOG_FIRST_N(ERROR, 1) << "Gurobi callback at unknown where="
392  << current_gurobi_internal_callback_context_.where;
393  return MPCallbackEvent::kUnknown;
394  }
395 }
396 
397 bool GurobiMPCallbackContext::CanQueryVariableValues() {
398  const MPCallbackEvent where = Event();
399  if (where == MPCallbackEvent::kMipSolution) {
400  return true;
401  }
402  if (where == MPCallbackEvent::kMipNode) {
403  const int gurobi_node_status = GurobiCallbackGet<int>(
404  current_gurobi_internal_callback_context_, GRB_CB_MIPNODE_STATUS);
405  return gurobi_node_status == GRB_OPTIMAL;
406  }
407  return false;
408 }
409 
410 double GurobiMPCallbackContext::VariableValue(const MPVariable* variable) {
411  CHECK(variable != nullptr);
412  if (!variable_values_extracted_) {
413  const MPCallbackEvent where = Event();
414  CHECK(where == MPCallbackEvent::kMipSolution ||
415  where == MPCallbackEvent::kMipNode)
416  << "You can only call VariableValue at "
417  << ToString(MPCallbackEvent::kMipSolution) << " or "
418  << ToString(MPCallbackEvent::kMipNode)
419  << " but called from: " << ToString(where);
420  const int gurobi_get_var_param = where == MPCallbackEvent::kMipNode
423 
424  gurobi_variable_values_.resize(num_gurobi_vars_);
425  CheckedGurobiCall(GRBcbget(
426  current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
427  current_gurobi_internal_callback_context_.where, gurobi_get_var_param,
428  static_cast<void*>(gurobi_variable_values_.data())));
429  variable_values_extracted_ = true;
430  }
431  return gurobi_variable_values_[mp_var_to_gurobi_var_->at(variable->index())];
432 }
433 
434 template <typename GRBConstraintFunction>
435 void GurobiMPCallbackContext::AddGeneratedConstraint(
436  const LinearRange& linear_range,
437  GRBConstraintFunction grb_constraint_function) {
438  std::vector<int> variable_indices;
439  std::vector<double> variable_coefficients;
440  const int num_terms = linear_range.linear_expr().terms().size();
441  variable_indices.reserve(num_terms);
442  variable_coefficients.reserve(num_terms);
443  for (const auto& var_coef_pair : linear_range.linear_expr().terms()) {
444  variable_indices.push_back(
445  mp_var_to_gurobi_var_->at(var_coef_pair.first->index()));
446  variable_coefficients.push_back(var_coef_pair.second);
447  }
448  if (std::isfinite(linear_range.upper_bound())) {
449  CheckedGurobiCall(grb_constraint_function(
450  current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
451  variable_indices.size(), variable_indices.data(),
452  variable_coefficients.data(), GRB_LESS_EQUAL,
453  linear_range.upper_bound()));
454  }
455  if (std::isfinite(linear_range.lower_bound())) {
456  CheckedGurobiCall(grb_constraint_function(
457  current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
458  variable_indices.size(), variable_indices.data(),
459  variable_coefficients.data(), GRB_GREATER_EQUAL,
460  linear_range.lower_bound()));
461  }
462 }
463 
464 void GurobiMPCallbackContext::AddCut(const LinearRange& cutting_plane) {
465  CHECK(might_add_cuts_);
466  const MPCallbackEvent where = Event();
467  CHECK(where == MPCallbackEvent::kMipNode)
468  << "Cuts can only be added at MIP_NODE, tried to add cut at: "
469  << ToString(where);
470  AddGeneratedConstraint(cutting_plane, GRBcbcut);
471 }
472 
473 void GurobiMPCallbackContext::AddLazyConstraint(
474  const LinearRange& lazy_constraint) {
475  CHECK(might_add_lazy_constraints_);
476  const MPCallbackEvent where = Event();
477  CHECK(where == MPCallbackEvent::kMipNode ||
478  where == MPCallbackEvent::kMipSolution)
479  << "Lazy constraints can only be added at MIP_NODE or MIP_SOL, tried to "
480  "add lazy constraint at: "
481  << ToString(where);
482  AddGeneratedConstraint(lazy_constraint, GRBcblazy);
483 }
484 
485 double GurobiMPCallbackContext::SuggestSolution(
486  const absl::flat_hash_map<const MPVariable*, double>& solution) {
487  const MPCallbackEvent where = Event();
488  CHECK(where == MPCallbackEvent::kMipNode)
489  << "Feasible solutions can only be added at MIP_NODE, tried to add "
490  "solution at: "
491  << ToString(where);
492 
493  std::vector<double> full_solution(num_gurobi_vars_, GRB_UNDEFINED);
494  for (const auto& variable_value : solution) {
495  const MPVariable* var = variable_value.first;
496  full_solution[mp_var_to_gurobi_var_->at(var->index())] =
497  variable_value.second;
498  }
499 
500  double objval;
501  CheckedGurobiCall(GRBcbsolution(
502  current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
503  full_solution.data(), &objval));
504 
505  return objval;
506 }
507 
508 struct MPCallbackWithGurobiContext {
509  GurobiMPCallbackContext* context;
510  MPCallback* callback;
511 };
512 
513 // NOTE(user): This function must have this exact API, because we are passing
514 // it to Gurobi as a callback.
515 int STDCALL CallbackImpl(GRBmodel* model, void* gurobi_internal_callback_data,
516  int where, void* raw_model_and_callback) {
517  MPCallbackWithGurobiContext* const callback_with_context =
518  static_cast<MPCallbackWithGurobiContext*>(raw_model_and_callback);
519  CHECK(callback_with_context != nullptr);
520  CHECK(callback_with_context->context != nullptr);
521  CHECK(callback_with_context->callback != nullptr);
522  GurobiInternalCallbackContext gurobi_internal_context{
524  callback_with_context->context->UpdateFromGurobiState(
525  gurobi_internal_context);
526  callback_with_context->callback->RunCallback(callback_with_context->context);
527  return 0;
528 }
529 
530 } // namespace
531 
532 void GurobiInterface::CheckedGurobiCall(int err) const {
533  ::operations_research::CheckedGurobiCall(err, env_);
534 }
535 
536 void GurobiInterface::SetIntAttr(const char* name, int value) {
537  CheckedGurobiCall(GRBsetintattr(model_, name, value));
538 }
539 
540 int GurobiInterface::GetIntAttr(const char* name) const {
541  int value;
542  CheckedGurobiCall(GRBgetintattr(model_, name, &value));
543  return value;
544 }
545 
546 void GurobiInterface::SetDoubleAttr(const char* name, double value) {
547  CheckedGurobiCall(GRBsetdblattr(model_, name, value));
548 }
549 
550 double GurobiInterface::GetDoubleAttr(const char* name) const {
551  double value;
552  CheckedGurobiCall(GRBgetdblattr(model_, name, &value));
553  return value;
554 }
555 
556 void GurobiInterface::SetIntAttrElement(const char* name, int index,
557  int value) {
558  CheckedGurobiCall(GRBsetintattrelement(model_, name, index, value));
559 }
560 
561 int GurobiInterface::GetIntAttrElement(const char* name, int index) const {
562  int value;
563  CheckedGurobiCall(GRBgetintattrelement(model_, name, index, &value));
564  return value;
565 }
566 
567 void GurobiInterface::SetDoubleAttrElement(const char* name, int index,
568  double value) {
569  CheckedGurobiCall(GRBsetdblattrelement(model_, name, index, value));
570 }
571 double GurobiInterface::GetDoubleAttrElement(const char* name,
572  int index) const {
573  double value;
574  CheckedGurobiCall(GRBgetdblattrelement(model_, name, index, &value));
575  return value;
576 }
577 
578 std::vector<double> GurobiInterface::GetDoubleAttrArray(const char* name,
579  int elements) {
580  std::vector<double> results(elements);
581  CheckedGurobiCall(
582  GRBgetdblattrarray(model_, name, 0, elements, results.data()));
583  return results;
584 }
585 
586 void GurobiInterface::SetCharAttrElement(const char* name, int index,
587  char value) {
588  CheckedGurobiCall(GRBsetcharattrelement(model_, name, index, value));
589 }
590 char GurobiInterface::GetCharAttrElement(const char* name, int index) const {
591  char value;
592  CheckedGurobiCall(GRBgetcharattrelement(model_, name, index, &value));
593  return value;
594 }
595 
596 // Creates a LP/MIP instance with the specified name and minimization objective.
597 GurobiInterface::GurobiInterface(MPSolver* const solver, bool mip)
598  : MPSolverInterface(solver),
599  model_(nullptr),
600  env_(nullptr),
601  mip_(mip),
602  current_solution_index_(0) {
604  CheckedGurobiCall(GRBnewmodel(env_, &model_, solver_->name_.c_str(),
605  0, // numvars
606  nullptr, // obj
607  nullptr, // lb
608  nullptr, // ub
609  nullptr, // vtype
610  nullptr)); // varnanes
612  CheckedGurobiCall(GRBsetintparam(env_, GRB_INT_PAR_THREADS,
613  absl::GetFlag(FLAGS_num_gurobi_threads)));
614 }
615 
617  CheckedGurobiCall(GRBfreemodel(model_));
618  GRBfreeenv(env_);
619 }
620 
621 // ------ Model modifications and extraction -----
622 
624  CheckedGurobiCall(GRBfreemodel(model_));
625  CheckedGurobiCall(GRBnewmodel(env_, &model_, solver_->name_.c_str(),
626  0, // numvars
627  nullptr, // obj
628  nullptr, // lb
629  nullptr, // ub
630  nullptr, // vtype
631  nullptr)); // varnames
633  mp_var_to_gurobi_var_.clear();
634  mp_cons_to_gurobi_linear_cons_.clear();
635  num_gurobi_vars_ = 0;
636  num_gurobi_linear_cons_ = 0;
637  had_nonincremental_change_ = false;
638 }
639 
643 }
644 
645 void GurobiInterface::SetVariableBounds(int var_index, double lb, double ub) {
647  if (!had_nonincremental_change_ && variable_is_extracted(var_index)) {
648  SetDoubleAttrElement(GRB_DBL_ATTR_LB, mp_var_to_gurobi_var_.at(var_index),
649  lb);
650  SetDoubleAttrElement(GRB_DBL_ATTR_UB, mp_var_to_gurobi_var_.at(var_index),
651  ub);
652  } else {
654  }
655 }
656 
659  if (!had_nonincremental_change_ && variable_is_extracted(index)) {
660  char type_var;
661  if (integer) {
662  type_var = GRB_INTEGER;
663  } else {
664  type_var = GRB_CONTINUOUS;
665  }
666  SetCharAttrElement(GRB_CHAR_ATTR_VTYPE, mp_var_to_gurobi_var_.at(index),
667  type_var);
668  } else {
670  }
671 }
672 
673 void GurobiInterface::SetConstraintBounds(int index, double lb, double ub) {
676  had_nonincremental_change_ = true;
677  }
678  // TODO(user): this is nontrivial to make incremental:
679  // 1. Make sure it is a linear constraint (not an indicator or indicator
680  // range constraint).
681  // 2. Check if the sense of the constraint changes. If it was previously a
682  // range constraint, we can do nothing, and if it becomes a range
683  // constraint, we can do nothing. We could support range constraints if
684  // we tracked the auxiliary variable that is added with range
685  // constraints.
686 }
687 
690 }
691 
693  had_nonincremental_change_ = true;
695  return !IsContinuous();
696 }
697 
700 }
701 
703  const MPVariable* const variable,
704  double new_value, double old_value) {
706  if (!had_nonincremental_change_ && variable_is_extracted(variable->index()) &&
707  constraint_is_extracted(constraint->index())) {
708  // Cannot be const, GRBchgcoeffs needs non-const pointer.
709  int grb_var = mp_var_to_gurobi_var_.at(variable->index());
710  int grb_cons = mp_cons_to_gurobi_linear_cons_.at(constraint->index());
711  if (grb_cons < 0) {
712  had_nonincremental_change_ = true;
714  } else {
715  // TODO(user): investigate if this has bad performance.
716  CheckedGurobiCall(
717  GRBchgcoeffs(model_, 1, &grb_cons, &grb_var, &new_value));
718  }
719  } else {
721  }
722 }
723 
725  had_nonincremental_change_ = true;
727  // TODO(user): this is difficult to make incremental, like
728  // SetConstraintBounds(), because of the auxiliary Gurobi variables that
729  // range constraints introduce.
730 }
731 
733  double coefficient) {
735  if (!had_nonincremental_change_ && variable_is_extracted(variable->index())) {
736  SetDoubleAttrElement(GRB_DBL_ATTR_OBJ,
737  mp_var_to_gurobi_var_.at(variable->index()),
738  coefficient);
739  } else {
741  }
742 }
743 
746  if (!had_nonincremental_change_) {
747  SetDoubleAttr(GRB_DBL_ATTR_OBJCON, value);
748  } else {
750  }
751 }
752 
755  if (!had_nonincremental_change_) {
756  SetObjectiveOffset(0.0);
757  for (const auto& entry : solver_->objective_->coefficients_) {
758  SetObjectiveCoefficient(entry.first, 0.0);
759  }
760  } else {
762  }
763 }
764 
766  update_branching_priorities_ = true;
767 }
768 
769 // ------ Query statistics on the solution and the solve ------
770 
772  double iter;
774  CheckedGurobiCall(GRBgetdblattr(model_, GRB_DBL_ATTR_ITERCOUNT, &iter));
775  return static_cast<int64>(iter);
776 }
777 
779  if (mip_) {
781  return static_cast<int64>(GetDoubleAttr(GRB_DBL_ATTR_NODECOUNT));
782  } else {
783  LOG(DFATAL) << "Number of nodes only available for discrete problems.";
784  return kUnknownNumberOfNodes;
785  }
786 }
787 
788 MPSolver::BasisStatus GurobiInterface::TransformGRBVarBasisStatus(
789  int gurobi_basis_status) const {
790  switch (gurobi_basis_status) {
791  case GRB_BASIC:
792  return MPSolver::BASIC;
793  case GRB_NONBASIC_LOWER:
795  case GRB_NONBASIC_UPPER:
797  case GRB_SUPERBASIC:
798  return MPSolver::FREE;
799  default:
800  LOG(DFATAL) << "Unknown GRB basis status.";
801  return MPSolver::FREE;
802  }
803 }
804 
805 MPSolver::BasisStatus GurobiInterface::TransformGRBConstraintBasisStatus(
806  int gurobi_basis_status, int constraint_index) const {
807  const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
808  if (grb_index < 0) {
809  LOG(DFATAL) << "Basis status not available for nonlinear constraints.";
810  return MPSolver::FREE;
811  }
812  switch (gurobi_basis_status) {
813  case GRB_BASIC:
814  return MPSolver::BASIC;
815  default: {
816  // Non basic.
817  double tolerance = 0.0;
818  CheckedGurobiCall(GRBgetdblparam(GRBgetenv(model_),
819  GRB_DBL_PAR_FEASIBILITYTOL, &tolerance));
820  const double slack = GetDoubleAttrElement(GRB_DBL_ATTR_SLACK, grb_index);
821  const char sense = GetCharAttrElement(GRB_CHAR_ATTR_SENSE, grb_index);
822  VLOG(4) << "constraint " << constraint_index << " , slack = " << slack
823  << " , sense = " << sense;
824  if (fabs(slack) <= tolerance) {
825  switch (sense) {
826  case GRB_EQUAL:
827  case GRB_LESS_EQUAL:
829  case GRB_GREATER_EQUAL:
831  default:
832  return MPSolver::FREE;
833  }
834  } else {
835  return MPSolver::FREE;
836  }
837  }
838  }
839 }
840 
841 // Returns the basis status of a row.
843  const int optim_status = GetIntAttr(GRB_INT_ATTR_STATUS);
844  if (optim_status != GRB_OPTIMAL && optim_status != GRB_SUBOPTIMAL) {
845  LOG(DFATAL) << "Basis status only available after a solution has "
846  << "been found.";
847  return MPSolver::FREE;
848  }
849  if (mip_) {
850  LOG(DFATAL) << "Basis status only available for continuous problems.";
851  return MPSolver::FREE;
852  }
853  const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
854  if (grb_index < 0) {
855  LOG(DFATAL) << "Basis status not available for nonlinear constraints.";
856  return MPSolver::FREE;
857  }
858  const int gurobi_basis_status =
859  GetIntAttrElement(GRB_INT_ATTR_CBASIS, grb_index);
860  return TransformGRBConstraintBasisStatus(gurobi_basis_status,
861  constraint_index);
862 }
863 
864 // Returns the basis status of a column.
866  const int optim_status = GetIntAttr(GRB_INT_ATTR_STATUS);
867  if (optim_status != GRB_OPTIMAL && optim_status != GRB_SUBOPTIMAL) {
868  LOG(DFATAL) << "Basis status only available after a solution has "
869  << "been found.";
870  return MPSolver::FREE;
871  }
872  if (mip_) {
873  LOG(DFATAL) << "Basis status only available for continuous problems.";
874  return MPSolver::FREE;
875  }
876  const int grb_index = mp_var_to_gurobi_var_.at(variable_index);
877  const int gurobi_basis_status =
878  GetIntAttrElement(GRB_INT_ATTR_VBASIS, grb_index);
879  return TransformGRBVarBasisStatus(gurobi_basis_status);
880 }
881 
882 // Extracts new variables.
884  const int total_num_vars = solver_->variables_.size();
885  if (total_num_vars > last_variable_index_) {
886  // Define new variables.
887  for (int j = last_variable_index_; j < total_num_vars; ++j) {
888  const MPVariable* const var = solver_->variables_.at(j);
889  set_variable_as_extracted(var->index(), true);
890  CheckedGurobiCall(GRBaddvar(
891  model_, 0, // numnz
892  nullptr, // vind
893  nullptr, // vval
894  solver_->objective_->GetCoefficient(var), var->lb(), var->ub(),
895  var->integer() && mip_ ? GRB_INTEGER : GRB_CONTINUOUS,
896  var->name().empty() ? nullptr : var->name().c_str()));
897  mp_var_to_gurobi_var_.push_back(num_gurobi_vars_++);
898  }
899  CheckedGurobiCall(GRBupdatemodel(model_));
900  // Add new variables to existing constraints.
901  std::vector<int> grb_cons_ind;
902  std::vector<int> grb_var_ind;
903  std::vector<double> coef;
904  for (int i = 0; i < last_constraint_index_; ++i) {
905  // If there was a nonincremental change/the model is not incremental (e.g.
906  // there is an indicator constraint), we should never enter this loop, as
907  // last_variable_index_ will be reset to zero before ExtractNewVariables()
908  // is called.
909  MPConstraint* const ct = solver_->constraints_[i];
910  const int grb_ct_idx = mp_cons_to_gurobi_linear_cons_.at(ct->index());
911  DCHECK_GE(grb_ct_idx, 0);
912  DCHECK(ct->indicator_variable() == nullptr);
913  for (const auto& entry : ct->coefficients_) {
914  const int var_index = entry.first->index();
915  DCHECK(variable_is_extracted(var_index));
916 
917  if (var_index >= last_variable_index_) {
918  grb_cons_ind.push_back(grb_ct_idx);
919  grb_var_ind.push_back(mp_var_to_gurobi_var_.at(var_index));
920  coef.push_back(entry.second);
921  }
922  }
923  }
924  if (!grb_cons_ind.empty()) {
925  CheckedGurobiCall(GRBchgcoeffs(model_, grb_cons_ind.size(),
926  grb_cons_ind.data(), grb_var_ind.data(),
927  coef.data()));
928  }
929  }
930  CheckedGurobiCall(GRBupdatemodel(model_));
931  DCHECK_EQ(GetIntAttr(GRB_INT_ATTR_NUMVARS), num_gurobi_vars_);
932 }
933 
935  int total_num_rows = solver_->constraints_.size();
936  if (last_constraint_index_ < total_num_rows) {
937  // Add each new constraint.
938  for (int row = last_constraint_index_; row < total_num_rows; ++row) {
939  MPConstraint* const ct = solver_->constraints_[row];
941  const int size = ct->coefficients_.size();
942  std::vector<int> grb_vars;
943  std::vector<double> coefs;
944  grb_vars.reserve(size);
945  coefs.reserve(size);
946  for (const auto& entry : ct->coefficients_) {
947  const int var_index = entry.first->index();
948  CHECK(variable_is_extracted(var_index));
949  grb_vars.push_back(mp_var_to_gurobi_var_.at(var_index));
950  coefs.push_back(entry.second);
951  }
952  char* const name =
953  ct->name().empty() ? nullptr : const_cast<char*>(ct->name().c_str());
954  if (ct->indicator_variable() != nullptr) {
955  const int grb_ind_var =
956  mp_var_to_gurobi_var_.at(ct->indicator_variable()->index());
957  if (ct->lb() > -std::numeric_limits<double>::infinity()) {
958  CheckedGurobiCall(GRBaddgenconstrIndicator(
959  model_, name, grb_ind_var, ct->indicator_value(), size,
960  grb_vars.data(), coefs.data(),
961  ct->ub() == ct->lb() ? GRB_EQUAL : GRB_GREATER_EQUAL, ct->lb()));
962  }
963  if (ct->ub() < std::numeric_limits<double>::infinity() &&
964  ct->lb() != ct->ub()) {
965  CheckedGurobiCall(GRBaddgenconstrIndicator(
966  model_, name, grb_ind_var, ct->indicator_value(), size,
967  grb_vars.data(), coefs.data(), GRB_LESS_EQUAL, ct->ub()));
968  }
969  mp_cons_to_gurobi_linear_cons_.push_back(-1);
970  } else {
971  // Using GRBaddrangeconstr for constraints that don't require it adds
972  // a slack which is not always removed by presolve.
973  if (ct->lb() == ct->ub()) {
974  CheckedGurobiCall(GRBaddconstr(model_, size, grb_vars.data(),
975  coefs.data(), GRB_EQUAL, ct->lb(),
976  name));
977  } else if (ct->lb() == -std::numeric_limits<double>::infinity()) {
978  CheckedGurobiCall(GRBaddconstr(model_, size, grb_vars.data(),
979  coefs.data(), GRB_LESS_EQUAL, ct->ub(),
980  name));
981  } else if (ct->ub() == std::numeric_limits<double>::infinity()) {
982  CheckedGurobiCall(GRBaddconstr(model_, size, grb_vars.data(),
983  coefs.data(), GRB_GREATER_EQUAL,
984  ct->lb(), name));
985  } else {
986  CheckedGurobiCall(GRBaddrangeconstr(model_, size, grb_vars.data(),
987  coefs.data(), ct->lb(), ct->ub(),
988  name));
989  // NOTE(user): range constraints implicitly add an extra variable
990  // to the model.
991  num_gurobi_vars_++;
992  }
993  mp_cons_to_gurobi_linear_cons_.push_back(num_gurobi_linear_cons_++);
994  }
995  }
996  }
997  CheckedGurobiCall(GRBupdatemodel(model_));
998  DCHECK_EQ(GetIntAttr(GRB_INT_ATTR_NUMCONSTRS), num_gurobi_linear_cons_);
999 }
1000 
1003  SetDoubleAttr(GRB_DBL_ATTR_OBJCON, solver_->Objective().offset());
1004 }
1005 
1006 // ------ Parameters -----
1007 
1008 void GurobiInterface::SetParameters(const MPSolverParameters& param) {
1009  SetCommonParameters(param);
1010  if (mip_) {
1011  SetMIPParameters(param);
1012  }
1013 }
1014 
1015 bool GurobiInterface::SetSolverSpecificParametersAsString(
1016  const std::string& parameters) {
1017  return SetSolverSpecificParameters(parameters, GRBgetenv(model_)).ok();
1018 }
1019 
1020 void GurobiInterface::SetRelativeMipGap(double value) {
1021  if (mip_) {
1022  CheckedGurobiCall(
1024  } else {
1025  LOG(WARNING) << "The relative MIP gap is only available "
1026  << "for discrete problems.";
1027  }
1028 }
1029 
1030 // Gurobi has two different types of primal tolerance (feasibility tolerance):
1031 // constraint and integrality. We need to set them both.
1032 // See:
1033 // http://www.gurobi.com/documentation/6.0/refman/feasibilitytol.html
1034 // and
1035 // http://www.gurobi.com/documentation/6.0/refman/intfeastol.html
1036 void GurobiInterface::SetPrimalTolerance(double value) {
1037  CheckedGurobiCall(
1039  CheckedGurobiCall(
1041 }
1042 
1043 // As opposed to primal (feasibility) tolerance, the dual (optimality) tolerance
1044 // applies only to the reduced costs in the improving direction.
1045 // See:
1046 // http://www.gurobi.com/documentation/6.0/refman/optimalitytol.html
1047 void GurobiInterface::SetDualTolerance(double value) {
1048  CheckedGurobiCall(
1050 }
1051 
1052 void GurobiInterface::SetPresolveMode(int value) {
1053  switch (value) {
1055  CheckedGurobiCall(
1056  GRBsetintparam(GRBgetenv(model_), GRB_INT_PAR_PRESOLVE, false));
1057  break;
1058  }
1060  CheckedGurobiCall(
1062  break;
1063  }
1064  default: {
1066  }
1067  }
1068 }
1069 
1070 // Sets the scaling mode.
1071 void GurobiInterface::SetScalingMode(int value) {
1072  switch (value) {
1074  CheckedGurobiCall(
1076  break;
1078  CheckedGurobiCall(
1080  CheckedGurobiCall(
1082  break;
1083  default:
1084  // Leave the parameters untouched.
1085  break;
1086  }
1087 }
1088 
1089 // Sets the LP algorithm : primal, dual or barrier. Note that GRB
1090 // offers automatic selection
1091 void GurobiInterface::SetLpAlgorithm(int value) {
1092  switch (value) {
1094  CheckedGurobiCall(GRBsetintparam(GRBgetenv(model_), GRB_INT_PAR_METHOD,
1095  GRB_METHOD_DUAL));
1096  break;
1098  CheckedGurobiCall(GRBsetintparam(GRBgetenv(model_), GRB_INT_PAR_METHOD,
1100  break;
1102  CheckedGurobiCall(GRBsetintparam(GRBgetenv(model_), GRB_INT_PAR_METHOD,
1104  break;
1105  default:
1107  value);
1108  }
1109 }
1110 
1111 int GurobiInterface::SolutionCount() const {
1112  return GetIntAttr(GRB_INT_ATTR_SOLCOUNT);
1113 }
1114 
1115 bool GurobiInterface::ModelIsNonincremental() const {
1116  for (const MPConstraint* c : solver_->constraints()) {
1117  if (c->indicator_variable() != nullptr) {
1118  return true;
1119  }
1120  }
1121  return false;
1122 }
1123 
1125  WallTimer timer;
1126  timer.Start();
1127 
1130  ModelIsNonincremental() || had_nonincremental_change_) {
1131  Reset();
1132  }
1133 
1134  // Set log level.
1135  CheckedGurobiCall(
1137 
1138  ExtractModel();
1139  // Sync solver.
1140  CheckedGurobiCall(GRBupdatemodel(model_));
1141  VLOG(1) << absl::StrFormat("Model built in %s.",
1142  absl::FormatDuration(timer.GetDuration()));
1143 
1144  // Set solution hints if any.
1145  for (const std::pair<const MPVariable*, double>& p :
1146  solver_->solution_hint_) {
1147  SetDoubleAttrElement(GRB_DBL_ATTR_START,
1148  mp_var_to_gurobi_var_.at(p.first->index()), p.second);
1149  }
1150 
1151  // Pass branching priority annotations if at least one has been updated.
1152  if (update_branching_priorities_) {
1153  for (const MPVariable* var : solver_->variables_) {
1154  SetIntAttrElement(GRB_INT_ATTR_BRANCHPRIORITY,
1155  mp_var_to_gurobi_var_.at(var->index()),
1156  var->branching_priority());
1157  }
1158  update_branching_priorities_ = false;
1159  }
1160 
1161  // Time limit.
1162  if (solver_->time_limit() != 0) {
1163  VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
1164  CheckedGurobiCall(GRBsetdblparam(GRBgetenv(model_), GRB_DBL_PAR_TIMELIMIT,
1166  }
1167 
1168  // We first set our internal MPSolverParameters from 'param' and then set
1169  // any user-specified internal solver parameters via
1170  // solver_specific_parameter_string_.
1171  // Default MPSolverParameters can override custom parameters (for example for
1172  // presolving) and therefore we apply MPSolverParameters first.
1173  SetParameters(param);
1175  solver_->solver_specific_parameter_string_);
1176 
1177  std::unique_ptr<GurobiMPCallbackContext> gurobi_context;
1178  MPCallbackWithGurobiContext mp_callback_with_context;
1179  int gurobi_precrush = 0;
1180  int gurobi_lazy_constraint = 0;
1181  if (callback_ == nullptr) {
1182  CheckedGurobiCall(GRBsetcallbackfunc(model_, nullptr, nullptr));
1183  } else {
1184  gurobi_context = absl::make_unique<GurobiMPCallbackContext>(
1185  env_, &mp_var_to_gurobi_var_, num_gurobi_vars_,
1186  callback_->might_add_cuts(), callback_->might_add_lazy_constraints());
1187  mp_callback_with_context.context = gurobi_context.get();
1188  mp_callback_with_context.callback = callback_;
1189  CheckedGurobiCall(GRBsetcallbackfunc(
1190  model_, CallbackImpl, static_cast<void*>(&mp_callback_with_context)));
1191  gurobi_precrush = callback_->might_add_cuts();
1192  gurobi_lazy_constraint = callback_->might_add_lazy_constraints();
1193  }
1194  CheckedGurobiCall(
1195  GRBsetintparam(GRBgetenv(model_), GRB_INT_PAR_PRECRUSH, gurobi_precrush));
1196  CheckedGurobiCall(GRBsetintparam(
1197  GRBgetenv(model_), GRB_INT_PAR_LAZYCONSTRAINTS, gurobi_lazy_constraint));
1198 
1199  // Solve
1200  timer.Restart();
1201  const int status = GRBoptimize(model_);
1202 
1203  if (status) {
1204  VLOG(1) << "Failed to optimize MIP." << GRBgeterrormsg(env_);
1205  } else {
1206  VLOG(1) << absl::StrFormat("Solved in %s.",
1207  absl::FormatDuration(timer.GetDuration()));
1208  }
1209 
1210  // Get the status.
1211  const int optimization_status = GetIntAttr(GRB_INT_ATTR_STATUS);
1212  VLOG(1) << absl::StrFormat("Solution status %d.\n", optimization_status);
1213  const int solution_count = SolutionCount();
1214 
1215  switch (optimization_status) {
1216  case GRB_OPTIMAL:
1218  break;
1219  case GRB_INFEASIBLE:
1221  break;
1222  case GRB_UNBOUNDED:
1224  break;
1225  case GRB_INF_OR_UNBD:
1226  // TODO(user,user): We could introduce our own "infeasible or
1227  // unbounded" status.
1229  break;
1230  default: {
1231  if (solution_count > 0) {
1233  } else {
1235  }
1236  break;
1237  }
1238  }
1239 
1240  if (IsMIP() && (result_status_ != MPSolver::UNBOUNDED &&
1242  const int error =
1244  LOG_IF(WARNING, error != 0)
1245  << "Best objective bound is not available, error=" << error
1246  << ", message=" << GRBgeterrormsg(env_);
1247  VLOG(1) << "best bound = " << best_objective_bound_;
1248  }
1249 
1250  if (solution_count > 0 && (result_status_ == MPSolver::FEASIBLE ||
1252  current_solution_index_ = 0;
1253  // Get the results.
1254  objective_value_ = GetDoubleAttr(GRB_DBL_ATTR_OBJVAL);
1255  VLOG(1) << "objective = " << objective_value_;
1256 
1257  {
1258  const std::vector<double> grb_variable_values =
1259  GetDoubleAttrArray(GRB_DBL_ATTR_X, num_gurobi_vars_);
1260  for (int i = 0; i < solver_->variables_.size(); ++i) {
1261  MPVariable* const var = solver_->variables_[i];
1262  const double val = grb_variable_values.at(mp_var_to_gurobi_var_.at(i));
1263  var->set_solution_value(val);
1264  VLOG(3) << var->name() << ", value = " << val;
1265  }
1266  }
1267  if (!mip_) {
1268  {
1269  const std::vector<double> grb_reduced_costs =
1270  GetDoubleAttrArray(GRB_DBL_ATTR_RC, num_gurobi_vars_);
1271  for (int i = 0; i < solver_->variables_.size(); ++i) {
1272  MPVariable* const var = solver_->variables_[i];
1273  const double rc = grb_reduced_costs.at(mp_var_to_gurobi_var_.at(i));
1274  var->set_reduced_cost(rc);
1275  VLOG(4) << var->name() << ", reduced cost = " << rc;
1276  }
1277  }
1278 
1279  {
1280  std::vector<double> grb_dual_values =
1281  GetDoubleAttrArray(GRB_DBL_ATTR_PI, num_gurobi_linear_cons_);
1282  for (int i = 0; i < solver_->constraints_.size(); ++i) {
1283  MPConstraint* const ct = solver_->constraints_[i];
1284  const double dual_value =
1285  grb_dual_values.at(mp_cons_to_gurobi_linear_cons_.at(i));
1286  ct->set_dual_value(dual_value);
1287  VLOG(4) << "row " << ct->index() << ", dual value = " << dual_value;
1288  }
1289  }
1290  }
1291  }
1292 
1294  GRBresetparams(GRBgetenv(model_));
1295  return result_status_;
1296 }
1297 
1298 absl::optional<MPSolutionResponse> GurobiInterface::DirectlySolveProto(
1299  const MPModelRequest& request) {
1300  // Here we reuse the Gurobi environment to support single-use license that
1301  // forbids creating a second environment if one already exists.
1302  const auto status_or = GurobiSolveProto(request, env_);
1303  if (status_or.ok()) return status_or.value();
1304  // Special case: if something is not implemented yet, fall back to solving
1305  // through MPSolver.
1306  if (absl::IsUnimplemented(status_or.status())) return absl::nullopt;
1307 
1308  if (request.enable_internal_solver_output()) {
1309  LOG(INFO) << "Invalid Gurobi status: " << status_or.status();
1310  }
1311  MPSolutionResponse response;
1312  response.set_status(MPSOLVER_NOT_SOLVED);
1313  response.set_status_str(status_or.status().ToString());
1314  return response;
1315 }
1316 
1318  // Next solution only supported for MIP
1319  if (!mip_) return false;
1320 
1321  // Make sure we have successfully solved the problem and not modified it.
1323  return false;
1324  }
1325  // Check if we are out of solutions.
1326  if (current_solution_index_ + 1 >= SolutionCount()) {
1327  return false;
1328  }
1329  current_solution_index_++;
1330 
1331  CheckedGurobiCall(GRBsetintparam(
1332  GRBgetenv(model_), GRB_INT_PAR_SOLUTIONNUMBER, current_solution_index_));
1333 
1334  objective_value_ = GetDoubleAttr(GRB_DBL_ATTR_POOLOBJVAL);
1335  const std::vector<double> grb_variable_values =
1336  GetDoubleAttrArray(GRB_DBL_ATTR_XN, num_gurobi_vars_);
1337 
1338  for (int i = 0; i < solver_->variables_.size(); ++i) {
1339  MPVariable* const var = solver_->variables_[i];
1340  var->set_solution_value(
1341  grb_variable_values.at(mp_var_to_gurobi_var_.at(i)));
1342  }
1343  // TODO(user,user): This reset may not be necessary, investigate.
1344  GRBresetparams(GRBgetenv(model_));
1345  return true;
1346 }
1347 
1348 void GurobiInterface::Write(const std::string& filename) {
1349  if (sync_status_ == MUST_RELOAD) {
1350  Reset();
1351  }
1352  ExtractModel();
1353  // Sync solver.
1354  CheckedGurobiCall(GRBupdatemodel(model_));
1355  VLOG(1) << "Writing Gurobi model file \"" << filename << "\".";
1356  const int status = GRBwrite(model_, filename.c_str());
1357  if (status) {
1358  LOG(WARNING) << "Failed to write MIP." << GRBgeterrormsg(env_);
1359  }
1360 }
1361 
1362 bool GurobiInterface::ReadParameterFile(const std::string& filename) {
1363  // A non-zero return value indicates that a problem occurred.
1364  return GRBreadparams(GRBgetenv(model_), filename.c_str()) == 0;
1365 }
1366 
1367 std::string GurobiInterface::ValidFileExtensionForParameterFile() const {
1368  return ".prm";
1369 }
1370 
1372  return new GurobiInterface(solver, mip);
1373 }
1374 
1376  callback_ = mp_callback;
1377 }
1378 
1379 } // namespace operations_research
operations_research::GurobiInterface::SetConstraintBounds
void SetConstraintBounds(int row_index, double lb, double ub) override
Definition: gurobi_interface.cc:673
operations_research::GurobiInterface::NextSolution
bool NextSolution() override
Definition: gurobi_interface.cc:1317
GRB_UNBOUNDED
#define GRB_UNBOUNDED
Definition: gurobi_environment.h:474
var
IntVar * var
Definition: expr_array.cc:1858
GRB_DBL_ATTR_OBJBOUND
#define GRB_DBL_ATTR_OBJBOUND
Definition: gurobi_environment.h:284
GRB_DBL_PAR_FEASIBILITYTOL
#define GRB_DBL_PAR_FEASIBILITYTOL
Definition: gurobi_environment.h:497
INFO
const int INFO
Definition: log_severity.h:31
GRB_MAXIMIZE
#define GRB_MAXIMIZE
Definition: gurobi_environment.h:183
operations_research::MPCallback
Definition: linear_solver_callback.h:140
response
SharedResponseManager * response
Definition: cp_model_solver.cc:2105
integral_types.h
map_util.h
CHECK_OK
#define CHECK_OK(x)
Definition: base/logging.h:40
VLOG
#define VLOG(verboselevel)
Definition: base/logging.h:978
STDCALL
#define STDCALL
Definition: gurobi_environment.h:25
operations_research::GurobiInterface::row_status
MPSolver::BasisStatus row_status(int constraint_index) const override
Definition: gurobi_interface.cc:842
GRB_METHOD_DUAL
#define GRB_METHOD_DUAL
Definition: gurobi_environment.h:657
operations_research::GRBaddgenconstrIndicator
std::function< int(GRBmodel *model, const char *name, int binvar, int binval, int nvars, const int *vars, const double *vals, char sense, double rhs)> GRBaddgenconstrIndicator
Definition: gurobi_environment.cc:101
GRB_INFEASIBLE
#define GRB_INFEASIBLE
Definition: gurobi_environment.h:472
operations_research::GurobiInterface::SetVariableInteger
void SetVariableInteger(int var_index, bool integer) override
Definition: gurobi_interface.cc:657
operations_research::GurobiSolveProto
absl::StatusOr< MPSolutionResponse > GurobiSolveProto(const MPModelRequest &request, GRBenv *gurobi_env)
Definition: gurobi_proto_solver.cc:262
where
int where
Definition: gurobi_interface.cc:271
GRB_DBL_ATTR_OBJCON
#define GRB_DBL_ATTR_OBJCON
Definition: gurobi_environment.h:210
GRB_INT_PAR_PRECRUSH
#define GRB_INT_PAR_PRECRUSH
Definition: gurobi_environment.h:607
GRB_INT_PAR_METHOD
#define GRB_INT_PAR_METHOD
Definition: gurobi_environment.h:504
operations_research::GurobiInterface::ExtractNewVariables
void ExtractNewVariables() override
Definition: gurobi_interface.cc:883
LOG
#define LOG(severity)
Definition: base/logging.h:420
GRB_DBL_PAR_MIPGAP
#define GRB_DBL_PAR_MIPGAP
Definition: gurobi_environment.h:500
GRB_CB_MIPSOL_NODCNT
#define GRB_CB_MIPSOL_NODCNT
Definition: gurobi_environment.h:445
ERROR
const int ERROR
Definition: log_severity.h:32
operations_research::MPSolverInterface::MPConstraint
friend class MPConstraint
Definition: linear_solver.h:1710
operations_research::MPSolver::OPTIMAL
@ OPTIMAL
optimal.
Definition: linear_solver.h:429
GRB_INT_ATTR_VBASIS
#define GRB_INT_ATTR_VBASIS
Definition: gurobi_environment.h:304
GRB_DBL_ATTR_X
#define GRB_DBL_ATTR_X
Definition: gurobi_environment.h:299
operations_research::MPSolverParameters::LP_ALGORITHM
@ LP_ALGORITHM
Algorithm to solve linear programs.
Definition: linear_solver.h:1383
FATAL
const int FATAL
Definition: log_severity.h:32
operations_research::MPVariable::index
int index() const
Returns the index of the variable in the MPSolver::variables_.
Definition: linear_solver.h:1073
operations_research::MPSolver::Objective
const MPObjective & Objective() const
Returns the objective object.
Definition: linear_solver.h:416
GRB_MINIMIZE
#define GRB_MINIMIZE
Definition: gurobi_environment.h:182
operations_research::MPSolver::UNBOUNDED
@ UNBOUNDED
proven unbounded.
Definition: linear_solver.h:435
GRB_DBL_ATTR_RC
#define GRB_DBL_ATTR_RC
Definition: gurobi_environment.h:302
GRB_CB_SIMPLEX
#define GRB_CB_SIMPLEX
Definition: gurobi_environment.h:416
operations_research::GRBsetcallbackfunc
std::function< int(GRBmodel *model, int(STDCALL *cb)(CB_ARGS), void *usrdata)> GRBsetcallbackfunc
Definition: gurobi_environment.cc:106
operations_research::GurobiInterface::nodes
int64 nodes() const override
Definition: gurobi_interface.cc:778
operations_research::GRBsetintparam
std::function< int(GRBenv *, const char *, int)> GRBsetintparam
Definition: gurobi_environment.cc:80
logging.h
operations_research::MPSolverInterface::quiet_
bool quiet_
Definition: linear_solver.h:1735
operations_research::MPSolverInterface::last_constraint_index_
int last_constraint_index_
Definition: linear_solver.h:1724
GRB_CHAR_ATTR_VTYPE
#define GRB_CHAR_ATTR_VTYPE
Definition: gurobi_environment.h:229
operations_research::MPSolver
This mathematical programming (MP) solver class is the main class though which users build and solve ...
Definition: linear_solver.h:179
GRB_DBL_ATTR_NODECOUNT
#define GRB_DBL_ATTR_NODECOUNT
Definition: gurobi_environment.h:295
GRB_METHOD_PRIMAL
#define GRB_METHOD_PRIMAL
Definition: gurobi_environment.h:656
GRB_CB_POLLING
#define GRB_CB_POLLING
Definition: gurobi_environment.h:414
operations_research::GurobiInterface::SetCallback
void SetCallback(MPCallback *mp_callback) override
Definition: gurobi_interface.cc:1375
operations_research::GRBcbget
std::function< int(void *cbdata, int where, int what, void *resultP)> GRBcbget
Definition: gurobi_environment.cc:85
GRB_NONBASIC_LOWER
#define GRB_NONBASIC_LOWER
Definition: gurobi_environment.h:486
operations_research::GRBcblazy
std::function< int(void *cbdata, int lazylen, const int *lazyind, const double *lazyval, char lazysense, double lazyrhs)> GRBcblazy
Definition: gurobi_environment.cc:92
GRB_INT_ATTR_SOLCOUNT
#define GRB_INT_ATTR_SOLCOUNT
Definition: gurobi_environment.h:291
value
int64 value
Definition: demon_profiler.cc:43
GRB_DBL_ATTR_LB
#define GRB_DBL_ATTR_LB
Definition: gurobi_environment.h:226
GRB_CB_MIPSOL
#define GRB_CB_MIPSOL
Definition: gurobi_environment.h:418
GRB_GREATER_EQUAL
#define GRB_GREATER_EQUAL
Definition: gurobi_environment.h:175
GRB_INF_OR_UNBD
#define GRB_INF_OR_UNBD
Definition: gurobi_environment.h:473
GRB_CB_MIPNODE
#define GRB_CB_MIPNODE
Definition: gurobi_environment.h:419
GRB_CB_MIPSOL_SOL
#define GRB_CB_MIPSOL_SOL
Definition: gurobi_environment.h:441
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::GurobiInterface::SupportsCallbacks
bool SupportsCallbacks() const override
Definition: gurobi_interface.cc:181
GRB_BASIC
#define GRB_BASIC
Definition: gurobi_environment.h:485
operations_research::MPObjective::offset
double offset() const
Gets the constant term in the objective.
Definition: linear_solver.h:961
operations_research::GRBgeterrormsg
std::function< char *(GRBenv *)> GRBgeterrormsg
Definition: gurobi_environment.cc:62
WARNING
const int WARNING
Definition: log_severity.h:31
operations_research::MPSolverInterface::InvalidateSolutionSynchronization
void InvalidateSolutionSynchronization()
Definition: linear_solver.cc:1718
GRB_CHAR_ATTR_SENSE
#define GRB_CHAR_ATTR_SENSE
Definition: gurobi_environment.h:242
operations_research::LoadGurobiEnvironment
absl::Status LoadGurobiEnvironment(GRBenv **env)
Definition: gurobi_environment.cc:26
operations_research::GurobiInterface::AddVariable
void AddVariable(MPVariable *const var) override
Definition: gurobi_interface.cc:698
GRB_INTEGER
#define GRB_INTEGER
Definition: gurobi_environment.h:179
operations_research::MPSolverInterface
Definition: linear_solver.h:1516
operations_research::GRBwrite
std::function< int(GRBmodel *, const char *)> GRBwrite
Definition: gurobi_environment.cc:84
operations_research::MPSolverParameters::SCALING_OFF
@ SCALING_OFF
Scaling is off.
Definition: linear_solver.h:1423
operations_research::GRBreadparams
std::function< int(GRBenv *, const char *)> GRBreadparams
Definition: gurobi_environment.cc:71
WallTimer::Restart
void Restart()
Definition: timer.h:35
int64
int64_t int64
Definition: integral_types.h:34
operations_research::MPConstraint::index
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
Definition: linear_solver.h:1245
operations_research::GRBgetdblparam
std::function< int(GRBenv *, const char *, double *)> GRBgetdblparam
Definition: gurobi_environment.cc:60
GRB_UNDEFINED
#define GRB_UNDEFINED
Definition: gurobi_environment.h:187
operations_research::ToString
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
Definition: linear_solver.cc:569
operations_research::GurobiInterface::SetObjectiveOffset
void SetObjectiveOffset(double value) override
Definition: gurobi_interface.cc:744
index
int index
Definition: pack.cc:508
operations_research::MPSolverParameters
This class stores parameter settings for LP and MIP solvers.
Definition: linear_solver.h:1360
operations_research::GurobiInterface::IsMIP
bool IsMIP() const override
Definition: gurobi_interface.cc:134
operations_research::MPConstraint
The class for constraints of a Mathematical Programming (MP) model.
Definition: linear_solver.h:1177
context
GurobiMPCallbackContext * context
Definition: gurobi_interface.cc:509
operations_research::GRBgetdblattr
std::function< int(GRBmodel *, const char *, double *)> GRBgetdblattr
Definition: gurobi_environment.cc:55
operations_research::MPSolverInterface::constraint_is_extracted
bool constraint_is_extracted(int ct_index) const
Definition: linear_solver.h:1660
operations_research::GurobiInterface::BranchingPriorityChangedForVariable
void BranchingPriorityChangedForVariable(int var_index) override
Definition: gurobi_interface.cc:765
operations_research::GRBfreemodel
std::function< int(GRBmodel *)> GRBfreemodel
Definition: gurobi_environment.cc:52
operations_research::GRBnewmodel
std::function< int(GRBenv *, GRBmodel **, const char *, int numvars, double *, double *, double *, char *, char **)> GRBnewmodel
Definition: gurobi_environment.cc:69
GRB_DBL_ATTR_PI
#define GRB_DBL_ATTR_PI
Definition: gurobi_environment.h:305
operations_research::GurobiInterface::ClearObjective
void ClearObjective() override
Definition: gurobi_interface.cc:753
operations_research::GurobiInterface::Reset
void Reset() override
Definition: gurobi_interface.cc:623
operations_research::GurobiInterface::SetObjectiveCoefficient
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
Definition: gurobi_interface.cc:732
operations_research::MPSolverParameters::PRESOLVE_ON
@ PRESOLVE_ON
Presolve is on.
Definition: linear_solver.h:1395
operations_research::GRBsetintattr
std::function< int(GRBmodel *, const char *, int)> GRBsetintattr
Definition: gurobi_environment.cc:79
operations_research::GRBresetparams
std::function< int(GRBenv *)> GRBresetparams
Definition: gurobi_environment.cc:72
operations_research::GRBgetdblattrarray
std::function< int(GRBmodel *, const char *, int, int, double *)> GRBgetdblattrarray
Definition: gurobi_environment.cc:57
GRB_INT_ATTR_MODELSENSE
#define GRB_INT_ATTR_MODELSENSE
Definition: gurobi_environment.h:209
operations_research::MPSolverInterface::objective_value_
double objective_value_
Definition: linear_solver.h:1729
operations_research::GRBcbcut
std::function< int(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs)> GRBcbcut
Definition: gurobi_environment.cc:89
operations_research::MPCallback::might_add_cuts
bool might_add_cuts() const
Definition: linear_solver_callback.h:155
operations_research::MPSolverParameters::GetIntegerParam
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
Definition: linear_solver.cc:1999
operations_research::MPSolverParameters::SCALING_ON
@ SCALING_ON
Scaling is on.
Definition: linear_solver.h:1425
WallTimer::Start
void Start()
Definition: timer.h:31
GRB_DBL_ATTR_START
#define GRB_DBL_ATTR_START
Definition: gurobi_environment.h:230
operations_research::GRBchgcoeffs
std::function< int(GRBmodel *model, int numchgs, int *cind, int *vind, double *val)> GRBchgcoeffs
Definition: gurobi_environment.cc:50
GRB_NONBASIC_UPPER
#define GRB_NONBASIC_UPPER
Definition: gurobi_environment.h:487
GRB_CB_PRESOLVE
#define GRB_CB_PRESOLVE
Definition: gurobi_environment.h:415
operations_research::MPSolverInterface::ResetExtractionInformation
void ResetExtractionInformation()
Definition: linear_solver.cc:1665
operations_research::MPCallbackEvent
MPCallbackEvent
Definition: linear_solver_callback.h:35
operations_research::MPSolver::BASIC
@ BASIC
Definition: linear_solver.h:647
operations_research::MPSolverInterface::kUnknownNumberOfIterations
static constexpr int64 kUnknownNumberOfIterations
Definition: linear_solver.h:1533
operations_research::MPSolverInterface::solver_
MPSolver *const solver_
Definition: linear_solver.h:1714
GRB_INT_PAR_LAZYCONSTRAINTS
#define GRB_INT_PAR_LAZYCONSTRAINTS
Definition: gurobi_environment.h:600
operations_research::GRBsetintattrelement
std::function< int(GRBmodel *model, const char *attrname, int element, int newvalue)> GRBsetintattrelement
Definition: gurobi_environment.cc:104
operations_research::MPSolver::constraints
const std::vector< MPConstraint * > & constraints() const
Returns the array of constraints handled by the MPSolver.
Definition: linear_solver.h:368
GRB_EQUAL
#define GRB_EQUAL
Definition: gurobi_environment.h:176
operations_research::MPSolver::NOT_SOLVED
@ NOT_SOLVED
not been solved yet.
Definition: linear_solver.h:441
GRB_INT_PAR_OUTPUTFLAG
#define GRB_INT_PAR_OUTPUTFLAG
Definition: gurobi_environment.h:606
operations_research::GurobiInterface::InterruptSolve
bool InterruptSolve() override
Definition: gurobi_interface.cc:147
operations_research::GurobiInterface::iterations
int64 iterations() const override
Definition: gurobi_interface.cc:771
GRB_DBL_ATTR_ITERCOUNT
#define GRB_DBL_ATTR_ITERCOUNT
Definition: gurobi_environment.h:292
operations_research::MPSolverInterface::kUnknownNumberOfNodes
static constexpr int64 kUnknownNumberOfNodes
Definition: linear_solver.h:1536
operations_research::GRBsetcharattrelement
std::function< int(GRBmodel *, const char *, int, char)> GRBsetcharattrelement
Definition: gurobi_environment.cc:73
operations_research::MPSolver::SetSolverSpecificParametersAsString
bool SetSolverSpecificParametersAsString(const std::string &parameters)
Advanced usage: pass solver specific parameters in text format.
Definition: linear_solver.cc:346
timer.h
operations_research::MPSolverParameters::PRESOLVE
@ PRESOLVE
Advanced usage: presolve mode.
Definition: linear_solver.h:1381
operations_research::MPSolver::FREE
@ FREE
Definition: linear_solver.h:643
GRB_INT_PAR_PRESOLVE
#define GRB_INT_PAR_PRESOLVE
Definition: gurobi_environment.h:612
operations_research::MPSolverInterface::SOLUTION_SYNCHRONIZED
@ SOLUTION_SYNCHRONIZED
Definition: linear_solver.h:1528
operations_research::GRBsetdblattrelement
std::function< int(GRBmodel *, const char *, int, double)> GRBsetdblattrelement
Definition: gurobi_environment.cc:76
operations_research::GurobiInterface::AddIndicatorConstraint
bool AddIndicatorConstraint(MPConstraint *const ct) override
Definition: gurobi_interface.cc:692
GRB_DBL_ATTR_XN
#define GRB_DBL_ATTR_XN
Definition: gurobi_environment.h:300
GRB_INT_PAR_SCALEFLAG
#define GRB_INT_PAR_SCALEFLAG
Definition: gurobi_environment.h:507
GRB_DBL_PAR_OPTIMALITYTOL
#define GRB_DBL_PAR_OPTIMALITYTOL
Definition: gurobi_environment.h:502
operations_research::GurobiInterface::~GurobiInterface
~GurobiInterface() override
Definition: gurobi_interface.cc:616
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
operations_research::GRBversion
std::function< void(int *, int *, int *)> GRBversion
Definition: gurobi_environment.cc:83
GRB_DBL_PAR_TIMELIMIT
#define GRB_DBL_PAR_TIMELIMIT
Definition: gurobi_environment.h:494
operations_research::GurobiInterface::SolverVersion
std::string SolverVersion() const override
Definition: gurobi_interface.cc:140
operations_research::MPSolverInterface::SetIntegerParamToUnsupportedValue
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
Definition: linear_solver.cc:1774
operations_research::MPSolver::time_limit
int64 time_limit() const
Definition: linear_solver.h:779
operations_research::MPSolver::BasisStatus
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
Definition: linear_solver.h:642
operations_research::MPSolverInterface::CheckSolutionIsSynchronizedAndExists
bool CheckSolutionIsSynchronizedAndExists() const
Definition: linear_solver.h:1634
GRB_SUBOPTIMAL
#define GRB_SUBOPTIMAL
Definition: gurobi_environment.h:482
operations_research::GurobiInterface::Write
void Write(const std::string &filename) override
Definition: gurobi_interface.cc:1348
GRB_OPTIMAL
#define GRB_OPTIMAL
Definition: gurobi_environment.h:471
GRB_INT_PAR_THREADS
#define GRB_INT_PAR_THREADS
Definition: gurobi_environment.h:621
GRB_CB_MIP
#define GRB_CB_MIP
Definition: gurobi_environment.h:417
operations_research::GRBsetdblattr
std::function< int(GRBmodel *, const char *, double)> GRBsetdblattr
Definition: gurobi_environment.cc:75
ct
const Constraint * ct
Definition: demon_profiler.cc:42
WallTimer
Definition: timer.h:23
GRB_CB_BARRIER
#define GRB_CB_BARRIER
Definition: gurobi_environment.h:421
operations_research::MPSolverParameters::INCREMENTALITY_OFF
@ INCREMENTALITY_OFF
Start solve from scratch.
Definition: linear_solver.h:1411
operations_research::GRBaddrangeconstr
std::function< int(GRBmodel *, int, int *, double *, double, double, const char *)> GRBaddrangeconstr
Definition: gurobi_environment.cc:40
GRB_METHOD_BARRIER
#define GRB_METHOD_BARRIER
Definition: gurobi_environment.h:658
operations_research::MPSolver::AT_UPPER_BOUND
@ AT_UPPER_BOUND
Definition: linear_solver.h:645
operations_research::MPSolverInterface::sync_status_
SynchronizationStatus sync_status_
Definition: linear_solver.h:1716
LOG_IF
#define LOG_IF(severity, condition)
Definition: base/logging.h:479
DCHECK
#define DCHECK(condition)
Definition: base/logging.h:884
GRB_CB_MIPNODE_NODCNT
#define GRB_CB_MIPNODE_NODCNT
Definition: gurobi_environment.h:452
operations_research::GRBcbsolution
std::function< int(void *cbdata, const double *solution, double *objvalP)> GRBcbsolution
Definition: gurobi_environment.cc:94
GRB_SUPERBASIC
#define GRB_SUPERBASIC
Definition: gurobi_environment.h:488
operations_research::GurobiInterface::ExtractObjective
void ExtractObjective() override
Definition: gurobi_interface.cc:1001
operations_research::GRBgetintattr
std::function< int(GRBmodel *, const char *, int *)> GRBgetintattr
Definition: gurobi_environment.cc:63
operations_research::GurobiInterface::IsLP
bool IsLP() const override
Definition: gurobi_interface.cc:133
operations_research::MPSolver::time_limit_in_secs
double time_limit_in_secs() const
Definition: linear_solver.h:789
LOG_FIRST_N
#define LOG_FIRST_N(severity, n)
Definition: base/logging.h:849
operations_research::MPSOLVER_NOT_SOLVED
@ MPSOLVER_NOT_SOLVED
Definition: linear_solver.pb.h:233
operations_research::MPSolver::ResultStatus
ResultStatus
The status of solving the problem.
Definition: linear_solver.h:427
operations_research::MPSolverInterface::variable_is_extracted
bool variable_is_extracted(int var_index) const
Definition: linear_solver.h:1654
GRB_INT_PAR_SOLUTIONNUMBER
#define GRB_INT_PAR_SOLUTIONNUMBER
Definition: gurobi_environment.h:540
operations_research::GurobiInterface::AddRowConstraint
void AddRowConstraint(MPConstraint *const ct) override
Definition: gurobi_interface.cc:688
GRB_DBL_ATTR_POOLOBJVAL
#define GRB_DBL_ATTR_POOLOBJVAL
Definition: gurobi_environment.h:288
GRB_INT_ATTR_NUMVARS
#define GRB_INT_ATTR_NUMVARS
Definition: gurobi_environment.h:194
operations_research::MPCallback::might_add_lazy_constraints
bool might_add_lazy_constraints() const
Definition: linear_solver_callback.h:156
callback
MPCallback * callback
Definition: gurobi_interface.cc:510
GRBenv
struct _GRBenv GRBenv
Definition: gurobi_environment.h:30
GRB_INT_ATTR_NUMCONSTRS
#define GRB_INT_ATTR_NUMCONSTRS
Definition: gurobi_environment.h:193
DCHECK_GE
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:889
model
GRBmodel * model
Definition: gurobi_interface.cc:269
operations_research::MPSolverInterface::ExtractModel
void ExtractModel()
Definition: linear_solver.cc:1637
operations_research::MPSolverInterface::SetMIPParameters
void SetMIPParameters(const MPSolverParameters &param)
Definition: linear_solver.cc:1754
operations_research::GRBoptimize
std::function< int(GRBmodel *)> GRBoptimize
Definition: gurobi_environment.cc:70
GRB_DBL_PAR_INTFEASTOL
#define GRB_DBL_PAR_INTFEASTOL
Definition: gurobi_environment.h:498
GRB_LESS_EQUAL
#define GRB_LESS_EQUAL
Definition: gurobi_environment.h:174
coef
int64 coef
Definition: expr_array.cc:1859
operations_research::MPSolverInterface::set_variable_as_extracted
void set_variable_as_extracted(int var_index, bool extracted)
Definition: linear_solver.h:1657
operations_research::GRBaddvar
std::function< int(GRBmodel *model, int numnz, int *vind, double *vval, double obj, double lb, double ub, char vtype, const char *varname)> GRBaddvar
Definition: gurobi_environment.cc:44
operations_research::GurobiInterface::column_status
MPSolver::BasisStatus column_status(int variable_index) const override
Definition: gurobi_interface.cc:865
coefficient
int64 coefficient
Definition: routing_search.cc:972
operations_research::GurobiInterface::Solve
MPSolver::ResultStatus Solve(const MPSolverParameters &param) override
Definition: gurobi_interface.cc:1124
GRB_DBL_ATTR_SLACK
#define GRB_DBL_ATTR_SLACK
Definition: gurobi_environment.h:307
ABSL_DIE_IF_NULL
#define ABSL_DIE_IF_NULL
Definition: base/logging.h:39
row
RowIndex row
Definition: markowitz.cc:175
operations_research::GurobiInterface::GurobiInterface
GurobiInterface(MPSolver *const solver, bool mip)
Definition: gurobi_interface.cc:597
gurobi_internal_callback_data
void * gurobi_internal_callback_data
Definition: gurobi_interface.cc:270
operations_research::MPSolverInterface::last_variable_index_
int last_variable_index_
Definition: linear_solver.h:1726
GRB_CONTINUOUS
#define GRB_CONTINUOUS
Definition: gurobi_environment.h:177
operations_research::GurobiInterface::SetVariableBounds
void SetVariableBounds(int var_index, double lb, double ub) override
Definition: gurobi_interface.cc:645
operations_research::MPSolverParameters::INCREMENTALITY
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
Definition: linear_solver.h:1385
gurobi_environment.h
GRB_CB_MIPNODE_STATUS
#define GRB_CB_MIPNODE_STATUS
Definition: gurobi_environment.h:448
operations_research::MPVariable
The class for variables of a Mathematical Programming (MP) model.
Definition: linear_solver.h:1052
DCHECK_EQ
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:885
operations_research::GRBgetenv
std::function< GRBenv *(GRBmodel *)> GRBgetenv
Definition: gurobi_environment.cc:61
GRB_DBL_ATTR_OBJVAL
#define GRB_DBL_ATTR_OBJVAL
Definition: gurobi_environment.h:283
operations_research::GurobiInterface::ClearConstraint
void ClearConstraint(MPConstraint *const constraint) override
Definition: gurobi_interface.cc:724
linear_solver.h
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
GRB_DBL_PAR_OBJSCALE
#define GRB_DBL_PAR_OBJSCALE
Definition: gurobi_environment.h:506
operations_research::GurobiInterface::DirectlySolveProto
absl::optional< MPSolutionResponse > DirectlySolveProto(const MPModelRequest &request) override
Definition: gurobi_interface.cc:1298
GRB_CB_MESSAGE
#define GRB_CB_MESSAGE
Definition: gurobi_environment.h:420
operations_research::GRBupdatemodel
std::function< int(GRBmodel *)> GRBupdatemodel
Definition: gurobi_environment.cc:82
operations_research::MPSolverInterface::SetCommonParameters
void SetCommonParameters(const MPSolverParameters &param)
Definition: linear_solver.cc:1733
WallTimer::GetDuration
absl::Duration GetDuration() const
Definition: timer.h:48
operations_research::GRBgetcharattrelement
std::function< int(GRBmodel *, const char *, int, char *)> GRBgetcharattrelement
Definition: gurobi_environment.cc:53
operations_research::MPSolver::INFEASIBLE
@ INFEASIBLE
proven infeasible.
Definition: linear_solver.h:433
operations_research::BuildGurobiInterface
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
Definition: gurobi_interface.cc:1371
linear_solver_callback.h
GRBmodel
struct _GRBmodel GRBmodel
Definition: gurobi_environment.h:29
operations_research::GRBsetdblparam
std::function< int(GRBenv *, const char *, double)> GRBsetdblparam
Definition: gurobi_environment.cc:78
operations_research::MPSolverParameters::PRIMAL
@ PRIMAL
Primal simplex.
Definition: linear_solver.h:1403
operations_research::GRBgetdblattrelement
std::function< int(GRBmodel *, const char *, int, double *)> GRBgetdblattrelement
Definition: gurobi_environment.cc:58
operations_research::MPSolverParameters::PRESOLVE_OFF
@ PRESOLVE_OFF
Presolve is off.
Definition: linear_solver.h:1393
operations_research::GRBgetintattrelement
std::function< int(GRBmodel *, const char *, int, int *)> GRBgetintattrelement
Definition: gurobi_environment.cc:64
operations_research::MPSolverInterface::MUST_RELOAD
@ MUST_RELOAD
Definition: linear_solver.h:1521
GRB_DBL_ATTR_UB
#define GRB_DBL_ATTR_UB
Definition: gurobi_environment.h:227
GRB_DBL_ATTR_OBJ
#define GRB_DBL_ATTR_OBJ
Definition: gurobi_environment.h:228
operations_research::MPSolverInterface::CheckSolutionIsSynchronized
bool CheckSolutionIsSynchronized() const
Definition: linear_solver.cc:1673
operations_research::GRBterminate
std::function< void(GRBmodel *)> GRBterminate
Definition: gurobi_environment.cc:81
operations_research::GurobiInterface::ExtractNewConstraints
void ExtractNewConstraints() override
Definition: gurobi_interface.cc:934
operations_research::GurobiInterface
Definition: gurobi_interface.cc:72
operations_research::MPSolver::AT_LOWER_BOUND
@ AT_LOWER_BOUND
Definition: linear_solver.h:644
operations_research::MPSolverInterface::result_status_
MPSolver::ResultStatus result_status_
Definition: linear_solver.h:1719
operations_research::GurobiInterface::ComputeExactConditionNumber
double ComputeExactConditionNumber() const override
Definition: gurobi_interface.cc:154
operations_research::GRBfreeenv
std::function< void(GRBenv *)> GRBfreeenv
Definition: gurobi_environment.cc:51
ABSL_FLAG
ABSL_FLAG(int, num_gurobi_threads, 4, "Number of threads available for Gurobi.")
gurobi_proto_solver.h
operations_research::GRBaddconstr
std::function< int(GRBmodel *model, int numnz, int *cind, double *cval, char sense, double rhs, const char *constrname)> GRBaddconstr
Definition: gurobi_environment.cc:97
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
operations_research::MPSolverInterface::maximize_
bool maximize_
Definition: linear_solver.h:1721
commandlineflags.h
operations_research::MPSolverInterface::set_constraint_as_extracted
void set_constraint_as_extracted(int ct_index, bool extracted)
Definition: linear_solver.h:1663
operations_research::GurobiInterface::IsContinuous
bool IsContinuous() const override
Definition: gurobi_interface.cc:132
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:108
name
const std::string name
Definition: default_search.cc:808
operations_research::SetSolverSpecificParameters
absl::Status SetSolverSpecificParameters(const std::string &parameters, GRBenv *gurobi)
Definition: gurobi_proto_solver.cc:222
operations_research::GurobiInterface::SetOptimizationDirection
void SetOptimizationDirection(bool maximize) override
Definition: gurobi_interface.cc:640
operations_research::MPSolverParameters::DUAL
@ DUAL
Dual simplex.
Definition: linear_solver.h:1401
GRB_INT_ATTR_STATUS
#define GRB_INT_ATTR_STATUS
Definition: gurobi_environment.h:282
operations_research::MPSolver::FEASIBLE
@ FEASIBLE
feasible, or stopped by limit.
Definition: linear_solver.h:431
operations_research::MPSolverParameters::BARRIER
@ BARRIER
Barrier algorithm.
Definition: linear_solver.h:1405
GRB_CB_MIPNODE_REL
#define GRB_CB_MIPNODE_REL
Definition: gurobi_environment.h:449
operations_research::GurobiInterface::underlying_solver
void * underlying_solver() override
Definition: gurobi_interface.cc:152
operations_research::MPSolverInterface::best_objective_bound_
double best_objective_bound_
Definition: linear_solver.h:1732
GRB_INT_ATTR_CBASIS
#define GRB_INT_ATTR_CBASIS
Definition: gurobi_environment.h:310
GRB_INT_ATTR_BRANCHPRIORITY
#define GRB_INT_ATTR_BRANCHPRIORITY
Definition: gurobi_environment.h:232
operations_research::GurobiInterface::SetCoefficient
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
Definition: gurobi_interface.cc:702