OR-Tools  8.1
linear_solver_callback.h
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 // See go/mpsolver-callbacks for documentation on how to use this file.
15 
16 #ifndef OR_TOOLS_LINEAR_SOLVER_LINEAR_SOLVER_CALLBACK_H_
17 #define OR_TOOLS_LINEAR_SOLVER_LINEAR_SOLVER_CALLBACK_H_
18 
19 #include <string>
20 
21 #include "absl/container/flat_hash_map.h"
23 
24 namespace operations_research {
25 
26 class MPVariable;
27 class LinearExpr;
28 class LinearRange;
29 
30 // The current state of the solver when the callback is invoked.
31 //
32 // For Gurobi, similar to the int 'where' in the Gurobi callback API.
33 // See http://www.gurobi.com/documentation/8.0/refman/callback_codes.html
34 // for details.
35 enum class MPCallbackEvent {
36  kUnknown,
37  // For regaining control of the main thread in single threaded applications,
38  // not for interacting with the solver.
39  kPolling,
40  // The solver is currently running presolve.
41  kPresolve,
42  // The solver is currently running the simplex method.
43  kSimplex,
44  // The solver is in the MIP loop (called periodically before starting a new
45  // node). Useful to early termination.
46  kMip,
47  // Called every time a new MIP incumbent is found.
48  kMipSolution,
49  // Called once per pass of the cut loop inside each MIP node.
50  kMipNode,
51  // Called in each iterate of IPM/barrier method.
52  kBarrier,
53  // The solver is about to log out a message, use this callback to capture it.
54  kMessage,
55  // The solver is in multi-objective optimization.
56  kMultiObj,
57 };
58 
59 std::string ToString(MPCallbackEvent event);
60 
61 // When querying solution values or modifying the model during a callback, use
62 // this API, rather than manipulating MPSolver directly. You should only
63 // interact with this object from within MPCallback::RunCallback().
65  public:
66  virtual ~MPCallbackContext() {}
67 
68  // What the solver is currently doing. How you can interact with the solver
69  // from the callback depends on this value.
70  virtual MPCallbackEvent Event() = 0;
71 
72  // Always false if event is not kMipSolution or kMipNode, otherwise behavior
73  // may be solver dependent.
74  //
75  // For Gurobi, under kMipNode, may be false if the node was not solved to
76  // optimality, see MIPNODE_REL here for details:
77  // http://www.gurobi.com/documentation/8.0/refman/callback_codes.html
78  virtual bool CanQueryVariableValues() = 0;
79 
80  // Returns the value of variable from the solver's current state.
81  //
82  // Call only when CanQueryVariableValues() is true.
83  //
84  // At kMipSolution, the solution is integer feasible, while at kMipNode, the
85  // solution solves the current node's LP relaxation (so integer variables may
86  // be fractional).
87  virtual double VariableValue(const MPVariable* variable) = 0;
88 
89  // Adds a constraint to the model that strengths the LP relaxation.
90  //
91  // Call only when the event is kMipNode.
92  //
93  // Requires that MPCallback::might_add_cuts() is true.
94  //
95  // This constraint must not cut off integer solutions, it should only
96  // strengthen the LP (behavior is undefined otherwise). Use
97  // MPCallbackContext::AddLazyConstriant() if you are cutting off integer
98  // solutions.
99  virtual void AddCut(const LinearRange& cutting_plane) = 0;
100 
101  // Adds a constraint to the model that cuts off an undesired integer solution.
102  //
103  // Call only when the event is kMipSolution or kMipNode.
104  //
105  // Requires that MPCallback::might_add_lazy_constraints() is true.
106  //
107  // Use this to avoid adding a large number of constraints to the model where
108  // most are expected to not be needed.
109  //
110  // Given an integral solution, AddLazyConstraint() MUST be able to detect if
111  // there is a violated constraint, and it is guaranteed that every integer
112  // solution will be checked by AddLazyConstraint().
113  //
114  // Warning(rander): in some solvers, e.g. Gurobi, an integer solution may not
115  // respect a previously added lazy constraint, so you may need to add a
116  // constraint more than once (e.g. due to threading issues).
117  virtual void AddLazyConstraint(const LinearRange& lazy_constraint) = 0;
118 
119  // Suggests a (potentially partial) variable assignment to the solver, to be
120  // used as a feasible solution (or part of one). If the assignment is partial,
121  // certain solvers (e.g. Gurobi) will try to compute a feasible solution from
122  // the partial assignment. Returns the objective value of the solution if the
123  // solver supports it.
124  //
125  // Call only when the event is kMipNode.
126  virtual double SuggestSolution(
127  const absl::flat_hash_map<const MPVariable*, double>& solution) = 0;
128 
129  // Returns the number of nodes explored so far in the branch and bound tree,
130  // which 0 at the root node and > 0 otherwise.
131  //
132  // Call only when the event is kMipSolution or kMipNode.
133  virtual int64 NumExploredNodes() = 0;
134 };
135 
136 // Extend this class with model specific logic, and register through
137 // MPSolver::SetCallback, passing a pointer to this object.
138 //
139 // See go/mpsolver-callbacks for additional documentation.
140 class MPCallback {
141  public:
142  // If you intend to call call MPCallbackContext::AddCut(), you must set
143  // might_add_cuts below to be true. Likewise for
144  // MPCallbackContext::AddLazyConstraint() and might_add_lazy_constraints.
146  : might_add_cuts_(might_add_cuts),
147  might_add_lazy_constraints_(might_add_lazy_constraints) {}
148  virtual ~MPCallback() {}
149 
150  // Threading behavior may be solver dependent:
151  // * Gurobi: RunCallback always runs on the same thread that you called
152  // MPSolver::Solve() on, even when Gurobi uses multiple threads.
153  virtual void RunCallback(MPCallbackContext* callback_context) = 0;
154 
155  bool might_add_cuts() const { return might_add_cuts_; }
157  return might_add_lazy_constraints_;
158  }
159 
160  private:
161  bool might_add_cuts_;
162  bool might_add_lazy_constraints_;
163 };
164 
165 // Single callback that runs the list of callbacks given at construction, in
166 // sequence.
167 class MPCallbackList : public MPCallback {
168  public:
169  explicit MPCallbackList(const std::vector<MPCallback*>& callbacks);
170 
171  // Runs all callbacks from the list given at construction, in sequence.
172  void RunCallback(MPCallbackContext* context) override;
173 
174  private:
175  const std::vector<MPCallback*> callbacks_;
176 };
177 
178 } // namespace operations_research
179 
180 #endif // OR_TOOLS_LINEAR_SOLVER_LINEAR_SOLVER_CALLBACK_H_
operations_research::MPCallbackList::MPCallbackList
MPCallbackList(const std::vector< MPCallback * > &callbacks)
Definition: linear_solver_callback.cc:72
operations_research::MPCallback::MPCallback
MPCallback(bool might_add_cuts, bool might_add_lazy_constraints)
Definition: linear_solver_callback.h:145
operations_research::MPCallback
Definition: linear_solver_callback.h:140
operations_research::MPCallbackContext::Event
virtual MPCallbackEvent Event()=0
integral_types.h
operations_research::MPCallbackContext
Definition: linear_solver_callback.h:64
operations_research::MPCallback::RunCallback
virtual void RunCallback(MPCallbackContext *callback_context)=0
operations_research::MPCallbackContext::~MPCallbackContext
virtual ~MPCallbackContext()
Definition: linear_solver_callback.h:66
operations_research::MPCallbackContext::AddLazyConstraint
virtual void AddLazyConstraint(const LinearRange &lazy_constraint)=0
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
int64
int64_t int64
Definition: integral_types.h:34
operations_research::ToString
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
Definition: linear_solver.cc:569
operations_research::MPCallbackContext::AddCut
virtual void AddCut(const LinearRange &cutting_plane)=0
context
GurobiMPCallbackContext * context
Definition: gurobi_interface.cc:509
operations_research::MPCallbackContext::VariableValue
virtual double VariableValue(const MPVariable *variable)=0
operations_research::MPCallbackEvent::kUnknown
@ kUnknown
operations_research::MPCallback::might_add_cuts
bool might_add_cuts() const
Definition: linear_solver_callback.h:155
operations_research::MPCallbackEvent
MPCallbackEvent
Definition: linear_solver_callback.h:35
operations_research::MPCallbackList
Definition: linear_solver_callback.h:167
operations_research::MPCallbackContext::SuggestSolution
virtual double SuggestSolution(const absl::flat_hash_map< const MPVariable *, double > &solution)=0
operations_research::MPCallbackContext::NumExploredNodes
virtual int64 NumExploredNodes()=0
operations_research::LinearRange
An expression of the form:
Definition: linear_expr.h:192
operations_research::MPCallback::might_add_lazy_constraints
bool might_add_lazy_constraints() const
Definition: linear_solver_callback.h:156
operations_research::MPVariable
The class for variables of a Mathematical Programming (MP) model.
Definition: linear_solver.h:1050
operations_research::MPCallbackContext::CanQueryVariableValues
virtual bool CanQueryVariableValues()=0
operations_research::MPCallbackList::RunCallback
void RunCallback(MPCallbackContext *context) override
Definition: linear_solver_callback.cc:77
operations_research::MPCallback::~MPCallback
virtual ~MPCallback()
Definition: linear_solver_callback.h:148