OR-Tools  9.2
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 MathOpt.
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 MathOpt::Callback as an optional argument to MathOpt::Solve(). This
19 // function is called periodically throughout the solve process. This file
20 // defines the data types needed to use this callback.
21 //
22 // The example below registers a callback that listens for feasible solutions
23 // the solvers finds along the way and accumulates them in a list for analysis
24 // after the solve.
25 //
26 // using ::operations_research::math_opt::CallbackData;
27 // using ::operations_research::math_opt::CallbackRegistration;
28 // using ::operations_research::math_opt::CallbackResult;
29 // using ::operations_research::math_opt::MathOpt;
30 // using ::operations_research::math_opt::Result;
31 // using ::operations_research::math_opt::Variable;
32 // using ::operations_research::math_opt::VariableMap;
33 //
34 // MathOpt model(operations_research::math_opt::SOLVER_TYPE_GUROBI);
35 // Variable x = model.AddBinaryVariable();
36 // model.objective().Maximize(x);
37 // CallbackRegistration cb_reg;
38 // cb_reg.events = {
39 // operations_research::math_opt::CALLBACK_EVENT_MIP_SOLUTION};
40 // std::vector<VariableMap<double>> solutions;
41 // auto cb = [&solutions](const CallbackData& cb_data) {
42 // // NOTE: this assumes the callback is always called from the same thread.
43 // // Gurobi always does this, multi-threaded SCIP does not.
44 // solutions.push_back(*cb_data.solution);
45 // return CallbackResult();
46 // };
47 // absl::StatusOr<Result> result = opt.Solve({}, {}, cb_reb, cb);
48 //
49 // At the termination of the example, solutions will have {{x, 1.0}}, and
50 // possibly {{x, 0.0}} as well.
51 //
52 // If the callback argument to MathOpt::Solve() is not null, it will be invoked
53 // on the events specified by the callback_registration argument (and when the
54 // callback is null, callback_registration must not request any events or will
55 // CHECK fail). Some solvers do not support callbacks or certain events, in this
56 // case the callback is ignored. TODO(b/180617976): change this behavior.
57 //
58 // Some solvers may call callback from multiple threads (SCIP will, Gurobi
59 // will not). You should either solve with one thread (see
60 // solver_parameters.common_parameters.threads), write a threadsafe callback,
61 // or consult the documentation of your underlying solver.
62 #ifndef OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
63 #define OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
64 
65 #include <string>
66 #include <utility>
67 #include <vector>
68 
69 #include "absl/container/flat_hash_set.h"
70 #include "absl/time/time.h"
71 #include "absl/types/optional.h"
72 #include "ortools/math_opt/callback.pb.h"
76 
77 namespace operations_research {
78 namespace math_opt {
79 
80 // The input to the MathOpt::Callback function.
81 //
82 // The information available depends on the current event.
83 struct CallbackData {
84  // Users will typically not need this function.
85  // Will CHECK fail if proto is not valid.
86  CallbackData(IndexedModel* model, const CallbackDataProto& proto);
87  CallbackData() = default;
88 
89  // The current state of the underlying solver.
90  CallbackEventProto event = CALLBACK_EVENT_UNSPECIFIED;
91 
92  // If event == CALLBACK_EVENT_MIP_NODE, the primal_solution contains the
93  // primal solution to the current LP-node relaxation. In some cases, no
94  // solution will be available (e.g. because LP was infeasible or the solve
95  // was imprecise).
96  // If event == CALLBACK_EVENT_MIP_SOLUTION, the primal_solution contains the
97  // newly found primal (integer) feasible solution. The solution is always
98  // present.
99  // Otherwise, the primal_solution is not available.
100  absl::optional<VariableMap<double>> solution;
101 
102  // If event == CALLBACK_EVENT_MESSAGE, contains the messages from the solver.
103  // Each message represents a single output line from the solver, and each
104  // message does not contain any '\n' characters.
105  // Otherwise, messages is empty.
106  std::vector<std::string> messages;
107 
108  // Time since `Solve()` was called. Available for all events except
109  // CALLBACK_EVENT_POLLING.
110  absl::Duration runtime;
111 
112  // Only available for event == CALLBACK_EVENT_PRESOLVE.
113  CallbackDataProto::PresolveStats presolve_stats;
114 
115  // Only available for event == CALLBACK_EVENT_SIMPLEX.
116  CallbackDataProto::SimplexStats simplex_stats;
117 
118  // Only available for event == CALLBACK_EVENT_BARRIER.
119  CallbackDataProto::BarrierStats barrier_stats;
120 
121  // Only available for event of CALLBACK_EVENT_MIP, CALLBACK_EVENT_MIP_NODE, or
122  // CALLBACK_EVENT_MIP_SOLUTION.
123  CallbackDataProto::MipStats mip_stats;
124 };
125 
126 // Provided with a callback at the start of a Solve() to inform the solver:
127 // * what information the callback needs,
128 // * how the callback might alter the solve process.
130  // Will CHECK fail if referenced variables are not from the same model.
131  CallbackRegistrationProto Proto() const;
132 
133  // Returns the model referenced variables, or null if no variables are
134  // referenced. Will CHECK fail if variables are not from the same model.
135  IndexedModel* model() const;
136 
137  // The events the solver should invoke the callback at.
138  absl::flat_hash_set<CallbackEventProto> events;
139 
140  // Restricts the variable returned in CallbackData.solution for event
141  // CALLBACK_EVENT_MIP_SOLUTION. This can improve performance.
143 
144  // Restricts the variable returned in CallbackData.solution for event
145  // CALLBACK_EVENT_MIP_NODE. This can improve performance.
147 
148  // If the callback will ever add "user cuts" at event CALLBACK_EVENT_MIP_NODE
149  // during the solve process (a linear constraint that excludes the current LP
150  // solution but does not cut off any integer points).
151  bool add_cuts = false;
152 
153  // If the callback will ever add "lazy constraints" at event
154  // CALLBACK_EVENT_MIP_NODE or CALLBACK_EVENT_MIP_SOLUTION during the solve
155  // process (a linear constraint that excludes integer points).
156  bool add_lazy_constraints = false;
157 };
158 
159 // The value returned by the MathOpt::Callback function.
161  // Prefer AddUserCut and AddLazyConstraint below instead of using this
162  // directly.
165  bool is_lazy = false;
166 
168  };
169 
170  // Adds a "user cut," a linear constraint that excludes the current LP
171  // solution but does not cut off any integer points. Use only for
172  // CALLBACK_EVENT_MIP_NODE.
173  void AddUserCut(BoundedLinearExpression linear_constraint) {
174  new_constraints.push_back({std::move(linear_constraint), false});
175  }
176 
177  // Adds a "lazy constraint," a linear constraint that excludes integer points.
178  // Use only for CALLBACK_EVENT_MIP_NODE and CALLBACK_EVENT_MIP_SOLUTION.
179  void AddLazyConstraint(BoundedLinearExpression linear_constraint) {
180  new_constraints.push_back({std::move(linear_constraint), true});
181  }
182 
183  // Will CHECK fail if referenced variables are not from the same model.
184  CallbackResultProto Proto() const;
185 
186  // Returns the model referenced variables, or null if no variables are
187  // referenced. Will CHECK fail if variables are not from the same model.
188  //
189  // Runs in O(num constraints + num suggested solutions).
190  IndexedModel* model() const;
191 
192  // Stop the solve process and return early. Can be called from any event.
193  bool terminate = false;
194 
195  // The user cuts and lazy constraints added. Prefer AddUserCut() and
196  // AddLazyConstraint() to modifying this directly.
197  std::vector<GeneratedLinearConstraint> new_constraints;
198 
199  // A solution or partially defined solution to give to the solver.
200  std::vector<VariableMap<double>> suggested_solutions;
201 };
202 
203 } // namespace math_opt
204 } // namespace operations_research
205 
206 #endif // OR_TOOLS_MATH_OPT_CPP_CALLBACK_H_
void AddLazyConstraint(BoundedLinearExpression linear_constraint)
Definition: callback.h:179
std::vector< VariableMap< double > > suggested_solutions
Definition: callback.h:200
void AddUserCut(BoundedLinearExpression linear_constraint)
Definition: callback.h:173
absl::optional< VariableMap< double > > solution
Definition: callback.h:100
GRBmodel * model
std::vector< GeneratedLinearConstraint > new_constraints
Definition: callback.h:197
CallbackResultProto Proto() const
Definition: callback.cc:120
absl::flat_hash_set< CallbackEventProto > events
Definition: callback.h:138
CpModelProto proto
CallbackDataProto::PresolveStats presolve_stats
Definition: callback.h:113
CallbackRegistrationProto Proto() const
Definition: callback.cc:98
CallbackDataProto::MipStats mip_stats
Definition: callback.h:123
CallbackDataProto::BarrierStats barrier_stats
Definition: callback.h:119
CallbackDataProto::SimplexStats simplex_stats
Definition: callback.h:116
Collection of objects used to extend the Constraint Solver library.
std::vector< std::string > messages
Definition: callback.h:106