OR-Tools  9.3
callback.h
Go to the documentation of this file.
1// Copyright 2010-2021 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// Data types for using callbacks with Solve() and IncrementalSolver.
15//
16// Callbacks allow to user to observe the progress of a solver and modify its
17// behavior mid solve. This is supported by allowing the user to a function of
18// type Callback as an optional argument to Solve() and
19// IncrementalSolver::Solve(). This function is called periodically throughout
20// the solve process. This file defines the data types needed to use this
21// callback.
22//
23// The example below registers a callback that listens for feasible solutions
24// the solvers finds along the way and accumulates them in a list for analysis
25// after the solve.
26//
27// using ::operations_research::math_opt::CallbackData;
28// using ::operations_research::math_opt::CallbackRegistration;
29// using ::operations_research::math_opt::CallbackResult;
30// using ::operations_research::math_opt::Model;
31// using ::operations_research::math_opt::SolveResult;
32// using ::operations_research::math_opt::Solve;
33// using ::operations_research::math_opt::Variable;
34// using ::operations_research::math_opt::VariableMap;
35//
36// Model model;
37// Variable x = model.AddBinaryVariable();
38// model.Maximize(x);
39// CallbackRegistration cb_reg;
40// cb_reg.events = {
41// operations_research::math_opt::CALLBACK_EVENT_MIP_SOLUTION};
42// std::vector<VariableMap<double>> solutions;
43// auto cb = [&solutions](const CallbackData& cb_data) {
44// // NOTE: this assumes the callback is always called from the same thread.
45// // Gurobi always does this, multi-threaded SCIP does not.
46// solutions.push_back(*cb_data.solution);
47// return CallbackResult();
48// };
49// absl::StatusOr<SolveResult> result = Solve(
50// model, operations_research::math_opt::SOLVER_TYPE_GUROBI,
51// /*parameters=*/{}, /*model_parameters=*/{}, cb_reb, cb);
52//
53// At the termination of the example, solutions will have {{x, 1.0}}, and
54// possibly {{x, 0.0}} as well.
55//
56// If the callback argument to Solve() is not null, it will be invoked on the
57// events specified by the callback_registration argument (and when the
58// callback is null, callback_registration must not request any events or will
59// CHECK fail). Some solvers do not support callbacks or certain events, in this
60// case the callback is ignored. TODO(b/180617976): change this behavior.
61//
62// Some solvers may call callback from multiple threads (SCIP will, Gurobi will
63// not). You should either solve with one thread (see
64// solver_parameters.threads), write a threadsafe callback, or consult
65// the documentation of your underlying solver.
66#ifndef OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
67#define OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
68
69#include <functional>
70#include <optional>
71#include <utility>
72#include <vector>
73
74#include "absl/container/flat_hash_set.h"
75#include "absl/time/time.h"
76#include "absl/types/span.h"
77#include "ortools/math_opt/callback.pb.h"
79#include "ortools/math_opt/cpp/enums.h" // IWYU pragma: export
82
83namespace operations_research {
84namespace math_opt {
85
86struct CallbackData;
87struct CallbackResult;
88
89using Callback = std::function<CallbackResult(const CallbackData&)>;
90
91// The supported events for LP/MIP callbacks.
92enum class CallbackEvent {
93 // The solver is currently running presolve.
94 //
95 // This event is supported for MIP & LP models by SolverType::kGurobi. Other
96 // solvers don't support this event.
97 kPresolve = CALLBACK_EVENT_PRESOLVE,
98
99 // The solver is currently running the simplex method.
100 //
101 // This event is supported for MIP & LP models by SolverType::kGurobi. Other
102 // solvers don't support this event.
103 kSimplex = CALLBACK_EVENT_SIMPLEX,
104
105 // The solver is in the MIP loop (called periodically before starting a new
106 // node). Useful for early termination. Note that this event does not provide
107 // information on LP relaxations nor about new incumbent solutions.
108 //
109 // This event is supported for MIP models only by SolverType::kGurobi. Other
110 // solvers don't support this event.
111 kMip = CALLBACK_EVENT_MIP,
112
113 // Called every time a new MIP incumbent is found.
114 //
115 // This event is fully supported for MIP models by SolverType::kGurobi. CP-SAT
116 // has partial support: you can view the solutions and request termination,
117 // but you cannot add lazy constraints. Other solvers don't support this
118 // event.
119 kMipSolution = CALLBACK_EVENT_MIP_SOLUTION,
120
121 // Called inside a MIP node. Note that there is no guarantee that the
122 // callback function will be called on every node. That behavior is
123 // solver-dependent.
124 //
125 // Disabling cuts using CommonSolveParameters may interfere with this event
126 // being called and/or adding cuts at this event, the behavior is solver
127 // specific.
128 //
129 // This event is supported for MIP models only by SolverType::kGurobi. Other
130 // solvers don't support this event.
131 kMipNode = CALLBACK_EVENT_MIP_NODE,
132
133 // Called in each iterate of an interior point/barrier method.
134 //
135 // This event is supported for LP models only by SolverType::kGurobi. Other
136 // solvers don't support this event.
137 kBarrier = CALLBACK_EVENT_BARRIER,
138};
139
140MATH_OPT_DEFINE_ENUM(CallbackEvent, CALLBACK_EVENT_UNSPECIFIED);
141
142// Provided with a callback at the start of a Solve() to inform the solver:
143// * what information the callback needs,
144// * how the callback might alter the solve process.
146 // Will CHECK fail if referenced variables are not from the same model.
147 CallbackRegistrationProto Proto() const;
148
149 // Returns the model referenced variables, or null if no variables are
150 // referenced. Will CHECK fail if variables are not from the same model.
151 const ModelStorage* storage() const;
152
153 // The events the solver should invoke the callback at.
154 //
155 // A solver will return an InvalidArgument status when called with registered
156 // events that are not supported for the selected solver and the type of
157 // model. For example registring for CallbackEvent::kMip with a model that
158 // only contains continuous variables will fail for most solvers (see the
159 // documentation of each event to see which solvers support them and in which
160 // case).
161 absl::flat_hash_set<CallbackEvent> events;
162
163 // Restricts the variable returned in CallbackData.solution for event
164 // CallbackEvent::kMipSolution. This can improve performance.
166
167 // Restricts the variable returned in CallbackData.solution for event
168 // CallbackEvent::kMipNode. This can improve performance.
170
171 // If the callback will ever add "user cuts" at event CallbackEvent::kMipNode
172 // during the solve process (a linear constraint that excludes the current LP
173 // solution but does not cut off any integer points).
174 bool add_cuts = false;
175
176 // If the callback will ever add "lazy constraints" at event
177 // CallbackEvent::kMipNode or CallbackEvent::kMipSolution during the solve
178 // process (a linear constraint that excludes integer points).
180};
181
182// The input to the Callback function.
183//
184// The information available depends on the current event.
186 // Users will typically not need this function.
187 // Will CHECK fail if proto is not valid.
188 CallbackData(const ModelStorage* storage, const CallbackDataProto& proto);
189
190 // The current state of the underlying solver.
192
193 // If event == CallbackEvent::kMipNode, the primal_solution contains the
194 // primal solution to the current LP-node relaxation. In some cases, no
195 // solution will be available (e.g. because LP was infeasible or the solve
196 // was imprecise).
197 // If event == CallbackEvent::kMipSolution, the primal_solution contains the
198 // newly found primal (integer) feasible solution. The solution is always
199 // present.
200 // Otherwise, the primal_solution is not available.
201 std::optional<VariableMap<double>> solution;
202
203 // Time since `Solve()` was called. Available for all events except
204 // CallbackEvent::kPolling.
205 absl::Duration runtime;
206
207 // Only available for event == CallbackEvent::kPresolve.
208 CallbackDataProto::PresolveStats presolve_stats;
209
210 // Only available for event == CallbackEvent::kSimplex.
211 CallbackDataProto::SimplexStats simplex_stats;
212
213 // Only available for event == CallbackEvent::kBarrier.
214 CallbackDataProto::BarrierStats barrier_stats;
215
216 // Only available for event of CallbackEvent::kMip, CallbackEvent::kMipNode,
217 // or CallbackEvent::kMipSolution.
218 CallbackDataProto::MipStats mip_stats;
219};
220
221// The value returned by the Callback function.
223 // Prefer AddUserCut and AddLazyConstraint below instead of using this
224 // directly.
227 bool is_lazy = false;
228
229 const ModelStorage* storage() const {
231 }
232 };
233
234 // Adds a "user cut," a linear constraint that excludes the current LP
235 // solution but does not cut off any integer points. Use only for
236 // CallbackEvent::kMipNode.
237 void AddUserCut(BoundedLinearExpression linear_constraint) {
238 new_constraints.push_back({std::move(linear_constraint), false});
239 }
240
241 // Adds a "lazy constraint," a linear constraint that excludes integer points.
242 // Use only for CallbackEvent::kMipNode and CallbackEvent::kMipSolution.
244 new_constraints.push_back({std::move(linear_constraint), true});
245 }
246
247 // Will CHECK fail if referenced variables are not from the same model.
248 CallbackResultProto Proto() const;
249
250 // Returns the model referenced variables, or null if no variables are
251 // referenced. Will CHECK fail if variables are not from the same model.
252 //
253 // Runs in O(num constraints + num suggested solutions).
254 const ModelStorage* storage() const;
255
256 // Stop the solve process and return early. Can be called from any event.
257 bool terminate = false;
258
259 // The user cuts and lazy constraints added. Prefer AddUserCut() and
260 // AddLazyConstraint() to modifying this directly.
261 std::vector<GeneratedLinearConstraint> new_constraints;
262
263 // A solution or partially defined solution to give to the solver.
264 std::vector<VariableMap<double>> suggested_solutions;
265};
266
267} // namespace math_opt
268} // namespace operations_research
269
270#endif // OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
CpModelProto proto
MATH_OPT_DEFINE_ENUM(CallbackEvent, CALLBACK_EVENT_UNSPECIFIED)
std::function< CallbackResult(const CallbackData &)> Callback
Definition: callback.h:89
Collection of objects used to extend the Constraint Solver library.
CallbackData(const ModelStorage *storage, const CallbackDataProto &proto)
Definition: callback.cc:103
CallbackDataProto::PresolveStats presolve_stats
Definition: callback.h:208
std::optional< VariableMap< double > > solution
Definition: callback.h:201
CallbackDataProto::SimplexStats simplex_stats
Definition: callback.h:211
CallbackDataProto::BarrierStats barrier_stats
Definition: callback.h:214
CallbackDataProto::MipStats mip_stats
Definition: callback.h:218
CallbackRegistrationProto Proto() const
Definition: callback.cc:127
absl::flat_hash_set< CallbackEvent > events
Definition: callback.h:161
std::vector< VariableMap< double > > suggested_solutions
Definition: callback.h:264
void AddLazyConstraint(BoundedLinearExpression linear_constraint)
Definition: callback.h:243
CallbackResultProto Proto() const
Definition: callback.cc:149
void AddUserCut(BoundedLinearExpression linear_constraint)
Definition: callback.h:237
const ModelStorage * storage() const
Definition: callback.cc:144
std::vector< GeneratedLinearConstraint > new_constraints
Definition: callback.h:261