1// Copyright 2010-2024 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
6// http://www.apache.org/licenses/LICENSE-2.0
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.
14// Solver-Callback handling protos:
15// Callback functions allow for a fine-grain control, and ongoing interaction
16// with the solver during the solve process. The overall architecture is that
17// upon solve invocation the user will select what type of interactions to have
18// with the solver, and whenever the solver offers an interaction enabled by the
19// user, return the statistics collected up to that point, and any additional
20// information required by the user. Once done, the callback function must
21// return a message to the solver to continue with the solve process.
24package operations_research.math_opt;
26import "google/protobuf/duration.proto";
27import "ortools/math_opt/sparse_containers.proto";
29option java_package = "com.google.ortools.mathopt";
30option java_multiple_files = true;
32// The supported events during a solve for callbacks.
33enum CallbackEventProto {
34 CALLBACK_EVENT_UNSPECIFIED = 0;
36 // The solver is currently running presolve.
38 // This event is supported by SOLVER_TYPE_GUROBI only.
39 CALLBACK_EVENT_PRESOLVE = 1;
41 // The solver is currently running the simplex method.
43 // This event is supported by SOLVER_TYPE_GUROBI only.
44 CALLBACK_EVENT_SIMPLEX = 2;
46 // The solver is in the MIP loop (called periodically before starting a new
47 // node). Useful for early termination. Note that this event does not provide
48 // information on LP relaxations nor about new incumbent solutions.
50 // This event is supported for MIP models by SOLVER_TYPE_GUROBI only.
51 CALLBACK_EVENT_MIP = 3;
53 // Called every time a new MIP incumbent is found.
55 // This event is fully supported for MIP models by SOLVER_TYPE_GUROBI.
56 // SOLVER_TYPE_CP_SAT has partial support: you can view the solutions and
57 // request termination, but you cannot add lazy constraints. Other solvers
58 // don't support this event.
59 CALLBACK_EVENT_MIP_SOLUTION = 4;
61 // Called inside a MIP node. Note that there is no guarantee that the
62 // callback function will be called on every node. That behavior is
65 // Disabling cuts using SolveParametersProto may interfere with this event
66 // being called and/or adding cuts at this event, the behavior is solver
69 // This event is supported for MIP models by SOLVER_TYPE_GUROBI only.
70 CALLBACK_EVENT_MIP_NODE = 5;
72 // Called in each iterate of an interior point/barrier method.
74 // This event is supported for SOLVER_TYPE_GUROBI only.
75 CALLBACK_EVENT_BARRIER = 6;
78// The callback function input data.
79// Note that depending on the event, some information might be unavailable.
80message CallbackDataProto {
81 CallbackEventProto event = 1;
82 // if event == CALLBACK_EVENT_MIP_NODE, the primal_solution_vector contains
83 // the variable values of the primal solution for the current LP-node
84 // relaxation. In some cases, no solution will be available (e.g. because
85 // LP was infeasible or the solve was imprecise).
86 // if event == CALLBACK_EVENT_MIP_SOLUTION, the primal_solution_vector
87 // contains variable values for the newly found primal (integer) feasible
89 // Otherwise, the primal_solution_vector is not available.
91 // Note that, because of variable filters, it is possible that when a solution
92 // is found, it is empty. The message will be set but left empty in this case,
93 // while it will be unset when no solution is available.
94 SparseDoubleVectorProto primal_solution_vector = 2;
96 // Running time since the `Solve` call.
97 google.protobuf.Duration runtime = 3;
99 // Presolve stats. Only available during CALLBACK_EVENT_PRESOLVE.
100 message PresolveStats {
101 optional int64 removed_variables = 1;
102 optional int64 removed_constraints = 2;
103 optional int64 bound_changes = 3;
104 optional int64 coefficient_changes = 4;
106 PresolveStats presolve_stats = 4;
108 // Simplex stats. Only available during CALLBACK_EVENT_SIMPLEX.
109 message SimplexStats {
110 optional int64 iteration_count = 1;
111 optional double objective_value = 2;
112 optional double primal_infeasibility = 3;
113 optional double dual_infeasibility = 4;
114 optional bool is_pertubated = 5;
116 SimplexStats simplex_stats = 5;
118 // Barrier stats. Only available during CALLBACK_EVENT_BARRIER.
119 message BarrierStats {
120 optional int32 iteration_count = 1;
121 optional double primal_objective = 2;
122 optional double dual_objective = 3;
123 optional double complementarity = 4;
124 optional double primal_infeasibility = 5;
125 optional double dual_infeasibility = 6;
127 BarrierStats barrier_stats = 6;
129 // MIP B&B stats. Only available during CALLBACK_EVENT_MIPxxxx events.
130 // Not supported for CP-SAT.
132 optional double primal_bound = 1;
133 optional double dual_bound = 2;
134 optional int64 explored_nodes = 3;
135 optional int64 open_nodes = 4;
136 optional int64 simplex_iterations = 5;
137 optional int32 number_of_solutions_found = 6;
138 optional int32 cutting_planes_in_lp = 7;
140 MipStats mip_stats = 7;
143// Return value of a callback function.
144message CallbackResultProto {
145 message GeneratedLinearConstraint {
146 // This message encode linear constraints of the form
147 // lower_bound <= linear_expression <= upper_bound
148 SparseDoubleVectorProto linear_expression = 1;
149 double lower_bound = 2;
150 double upper_bound = 3;
152 // Two types of generated linear constraints are supported based on is_lazy:
153 // * The "lazy constraint" can remove integer points from the feasible
154 // region and can be added at event CALLBACK_EVENT_MIP_NODE or
155 // CALLBACK_EVENT_MIP_SOLUTION
156 // * The "user cut" (on is_lazy=false) strengthens the LP without removing
157 // integer points. It can only be added at CALLBACK_EVENT_MIP_NODE.
161 // Ends the solve early.
164 // TODO(b/172214608): SCIP allows to reject a feasible solution without
165 // providing a cut. This is something we might support at a later stage.
167 // Dynamically generated linear constraints to add to the MIP. See
168 // GeneratedLinearConstraint::is_lazy for details.
169 repeated GeneratedLinearConstraint cuts = 4;
171 // Use only for CALLBACK_EVENT_MIP_NODE.
173 // Note that some solvers (e.g. Gurobi) support partially-defined solutions.
174 // The most common use case is to specify a value for each variable in the
175 // model. If a variable is not present in the primal solution, its value is
176 // taken to be undefined, and is up to the underlying solver to deal with it.
177 // For example, Gurobi will try to solve a Sub-MIP to get a fully feasible
178 // solution if necessary.
179 repeated SparseDoubleVectorProto suggested_solutions = 5;
182// Provided with a callback at the start of a Solve() to inform the solver:
183// * what information the callback needs,
184// * how the callback might alter the solve process.
185message CallbackRegistrationProto {
186 // The events the solver should invoke the callback at.
188 // When a solver is called with registered events that are not supported,
189 // an InvalidArgument is returned. The supported events may depend on the
190 // model. For example registering for CALLBACK_EVENT_MIP with a model that
191 // only contains continuous variables will fail for most solvers. See the
192 // documentation of each event to see their supported solvers/model types.
193 repeated CallbackEventProto request_registration = 1;
195 // If CALLBACK_EVENT_MIP_SOLUTION is in `request_registration`, then
196 // the returned primal_solution information will be filtered according to
198 SparseVectorFilterProto mip_solution_filter = 2;
200 // If CALLBCK_EVENT_MIP_NODE is in `request_registration`, then the
201 // returned primal_solution information will be filtered according to this
203 SparseVectorFilterProto mip_node_filter = 3;
205 //////////////////////////////////////////////////////////////////////////////
206 // What might you do in your callback (typically some solver features need
207 // to be disabled before the solve starts to support these features).
208 //////////////////////////////////////////////////////////////////////////////
210 // Dynamically add linear constraints that strength the formulation but do not
211 // exclude integer points during CALLBACK_EVENT_MIP_NODE events.
213 // Dynamically add linear constraints that exclude integer points during
214 // CALLBACK_EVENT_MIP_NODE and/or CALLBACK_EVENT_MIP_SOLUTION events.
215 bool add_lazy_constraints = 5;