OR-Tools  9.1
scip_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// See go/scip-callbacks for documentation.
15//
16// This file provides a simplified C++ API for using callbacks with SCIP and
17// MPSolver. It can be used directly by users, although in most cases, the
18// mp_callback.h should be sufficient (in fact, SCIP's mp_callback.h
19// implementation is built on top of this). See also go/mpsolver-callbacks.
20
21#ifndef OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
22#define OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
23
24#include <cstdint>
25#include <string>
26#include <vector>
27
28#include "absl/memory/memory.h"
31#include "scip/scip_sol.h"
32#include "scip/type_cons.h"
33#include "scip/type_scip.h"
34#include "scip/type_sol.h"
35#include "scip/type_var.h"
36
37namespace operations_research {
38
39// See https://scip.zib.de/doc-6.0.2/html/CONS.php#CONS_PROPERTIES for details.
40// For member below, the corresponding SCIP constraint handler property name is
41// provided.
42//
43// TODO(user): no effort has been made to optimize the default values of
44// enforcement_priority, feasibility_check_priority, eager_frequency, or
45// separation_priority.
47 // See CONSHDLR_NAME in SCIP documentation above.
48 std::string name;
49
50 // See CONSHDLR_DESC in SCIP documentation above.
51 std::string description;
52
53 // See CONSHDLR_ENFOPRIORITY in the SCIP documentation above. Determines the
54 // order this constraint class is checked at each LP node.
55 //
56 // WARNING(rander): Assumed that enforcement_priority < 0. (This enforcement
57 // runs after integrality enforcement, so CONSENFOLP always runs on integral
58 // solutions.)
60
61 // See CONSHDLR_CHECKPRIORITY: in the SCIP documentation above. Determines the
62 // order this constraint class runs in when testing solution feasibility.
63 //
64 // WARNING(rander): Assumed that feasibility_check_priority < 0. (This check
65 // runs after the integrality check, so CONSCHECK always runs on integral
66 // solutions.)
68
69 // See CONSHDLR_EAGERFREQ in SCIP documentation above.
71
72 // See CONSHDLR_NEEDSCONS in SCIP documentation above.
73 bool needs_constraints = false;
74
75 // See CONSHDLR_SEPAPRIORITY in SCIP documentation above. Determines the
76 // order this constraint class runs in the cut loop.
78
79 // See CONSHDLR_SEPAFREQ in the SCIP documentation above.
81};
82
84 public:
85 // A value of nullptr for solution means to use the current LP solution.
86 ScipConstraintHandlerContext(SCIP* scip, SCIP_SOL* solution,
88 double VariableValue(const MPVariable* variable) const;
89
90 int64_t CurrentNodeId() const;
91 int64_t NumNodesProcessed() const;
92
93 SCIP* scip() const { return scip_; }
94
95 // Pseudo solutions may not be LP feasible. Duals/reduced costs are not
96 // available (the LP solver failed at this node).
97 //
98 // Do not add "user cuts" here (that strengthen LP solution but don't change
99 // feasible region), add only "lazy constraints" (cut off integer solutions).
100 //
101 // TODO(user): maybe this can be abstracted away.
102 bool is_pseudo_solution() const { return is_pseudo_solution_; }
103
104 private:
105 SCIP* scip_;
106 SCIP_SOL* solution_;
107 bool is_pseudo_solution_;
108};
109
112 bool is_cut = false; // Does not remove any integer points.
113 std::string name; // can be empty
114 bool local = false;
115};
116
117// See go/scip-callbacks for additional documentation.
118template <typename Constraint>
120 public:
123 : description_(description) {}
126 return description_;
127 }
128
129 // Unless SeparateIntegerSolution() below is overridden, this must find a
130 // violated lazy constraint if one exists when given an integral solution.
131 virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
133 const Constraint& constraint) = 0;
134
135 // This MUST find a violated lazy constraint if one exists.
136 // All constraints returned must have is_cut as false.
137 virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
139 const Constraint& constraint) {
140 return SeparateFractionalSolution(context, constraint);
141 }
142
143 // Returns true if no constraints are violated.
146 const Constraint& constraint) {
147 return SeparateFractionalSolution(context, constraint).empty();
148 }
149
150 // This MUST find a violated constraint if one exists.
153 const Constraint& constraint) {
154 return SeparateIntegerSolution(context, constraint).empty();
155 }
156
157 private:
159};
160
161// handler is not owned but held.
162template <typename Constraint>
164 SCIP* scip);
165
167 bool initial = true;
168 bool separate = true;
169 bool enforce = true;
170 bool check = true;
171 bool propagate = true;
172 bool local = false;
173 bool modifiable = false;
174 bool dynamic = false;
175 bool removable = true;
176 bool stickingatnodes = false;
177};
178
179// constraint_data is not owned but held.
180template <typename ConstraintData>
181void AddCallbackConstraint(SCIP* scip,
183 const std::string& constraint_name,
184 const ConstraintData* constraint_data,
185 const ScipCallbackConstraintOptions& options);
186
187// Implementation details, here and below.
188
189namespace internal {
190
192 public:
194 virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
195 const ScipConstraintHandlerContext& context, void* constraint) = 0;
196
197 virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
198 const ScipConstraintHandlerContext& context, void* constraint) = 0;
199
201 const ScipConstraintHandlerContext& context, void* constraint) = 0;
202
204 const ScipConstraintHandlerContext& context, void* constraint) = 0;
205};
206
207template <typename ConstraintData>
209 public:
212 : handler_(handler) {}
213
214 std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
216 void* constraint_data) override {
217 return handler_->SeparateFractionalSolution(
218 context, *static_cast<ConstraintData*>(constraint_data));
219 }
220
221 std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
223 void* constraint_data) override {
224 return handler_->SeparateIntegerSolution(
225 context, *static_cast<ConstraintData*>(constraint_data));
226 }
227
229 void* constraint_data) override {
230 return handler_->FractionalSolutionFeasible(
231 context, *static_cast<ConstraintData*>(constraint_data));
232 }
233
235 void* constraint_data) override {
236 return handler_->IntegerSolutionFeasible(
237 context, *static_cast<ConstraintData*>(constraint_data));
238 }
239
240 private:
242};
243
245 const ScipConstraintHandlerDescription& description,
246 std::unique_ptr<ScipCallbackRunner> runner, SCIP* scip);
247
248void AddCallbackConstraintImpl(SCIP* scip, const std::string& handler_name,
249 const std::string& constraint_name,
250 void* constraint_data,
251 const ScipCallbackConstraintOptions& options);
252
253} // namespace internal
254
255template <typename ConstraintData>
257 SCIP* scip) {
259 handler->description(),
261 handler),
262 scip);
263}
264
265template <typename ConstraintData>
266void AddCallbackConstraint(SCIP* scip,
268 const std::string& constraint_name,
269 const ConstraintData* constraint_data,
270 const ScipCallbackConstraintOptions& options) {
272 scip, handler->description().name, constraint_name,
273 static_cast<void*>(const_cast<ConstraintData*>(constraint_data)),
274 options);
275}
276
277} // namespace operations_research
278
279#endif // OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
A constraint is the main modeling object.
An expression of the form:
Definition: linear_expr.h:192
The class for variables of a Mathematical Programming (MP) model.
double VariableValue(const MPVariable *variable) const
ScipConstraintHandlerContext(SCIP *scip, SCIP_SOL *solution, bool is_pseudo_solution)
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)=0
virtual bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
const ScipConstraintHandlerDescription & description() const
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
ScipConstraintHandler(const ScipConstraintHandlerDescription &description)
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)
virtual bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
ScipCallbackRunnerImpl(ScipConstraintHandler< ConstraintData > *handler)
bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint_data) override
std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint_data) override
GurobiMPCallbackContext * context
This file allows you to write natural code (like a mathematical equation) to model optimization probl...
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void AddConstraintHandlerImpl(const ScipConstraintHandlerDescription &description, std::unique_ptr< ScipCallbackRunner > runner, SCIP *scip)
void AddCallbackConstraintImpl(SCIP *scip, const std::string &handler_name, const std::string &constraint_name, void *constraint_data, const ScipCallbackConstraintOptions &options)
Collection of objects used to extend the Constraint Solver library.
void RegisterConstraintHandler(ScipConstraintHandler< Constraint > *handler, SCIP *scip)
void AddCallbackConstraint(SCIP *scip, ScipConstraintHandler< ConstraintData > *handler, const std::string &constraint_name, const ConstraintData *constraint_data, const ScipCallbackConstraintOptions &options)