Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
scip_callback.h
Go to the documentation of this file.
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
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//
15// This file provides a simplified C++ API for using callbacks with SCIP and
16// MPSolver. It can be used directly by users, although in most cases, the
17// mp_callback.h should be sufficient (in fact, SCIP's mp_callback.h
18// implementation is built on top of this).
19
20#ifndef OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
21#define OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
22
23#include <cstdint>
24#include <memory>
25#include <string>
26#include <vector>
27
30#include "scip/type_scip.h"
31#include "scip/type_sol.h"
32
33namespace operations_research {
34
35// See https://scip.zib.de/doc-6.0.2/html/CONS.php#CONS_PROPERTIES for details.
36// For member below, the corresponding SCIP constraint handler property name is
37// provided.
38//
39// TODO(user): no effort has been made to optimize the default values of
40// enforcement_priority, feasibility_check_priority, eager_frequency, or
41// separation_priority.
43 // See CONSHDLR_NAME in SCIP documentation above.
44 std::string name;
45
46 // See CONSHDLR_DESC in SCIP documentation above.
47 std::string description;
48
49 // See CONSHDLR_ENFOPRIORITY in the SCIP documentation above. Determines the
50 // order this constraint class is checked at each LP node.
51 //
52 // WARNING(rander): Assumed that enforcement_priority < 0. (This enforcement
53 // runs after integrality enforcement, so CONSENFOLP always runs on integral
54 // solutions.)
56
57 // See CONSHDLR_CHECKPRIORITY: in the SCIP documentation above. Determines the
58 // order this constraint class runs in when testing solution feasibility.
59 //
60 // WARNING(rander): Assumed that feasibility_check_priority < 0. (This check
61 // runs after the integrality check, so CONSCHECK always runs on integral
62 // solutions.)
64
65 // See CONSHDLR_EAGERFREQ in SCIP documentation above.
67
68 // See CONSHDLR_NEEDSCONS in SCIP documentation above.
69 bool needs_constraints = false;
70
71 // See CONSHDLR_SEPAPRIORITY in SCIP documentation above. Determines the
72 // order this constraint class runs in the cut loop.
74
75 // See CONSHDLR_SEPAFREQ in the SCIP documentation above.
77};
78
80 public:
81 // A value of nullptr for solution means to use the current LP solution.
84 double VariableValue(const MPVariable* variable) const;
85
86 int64_t CurrentNodeId() const;
87 int64_t NumNodesProcessed() const;
88
89 SCIP* scip() const { return scip_; }
90
91 // Pseudo solutions may not be LP feasible. Duals/reduced costs are not
92 // available (the LP solver failed at this node).
93 //
94 // Do not add "user cuts" here (that strengthen LP solution but don't change
95 // feasible region), add only "lazy constraints" (cut off integer solutions).
96 //
97 // TODO(user): maybe this can be abstracted away.
98 bool is_pseudo_solution() const { return is_pseudo_solution_; }
99
100 private:
101 SCIP* scip_;
102 SCIP_SOL* solution_;
103 bool is_pseudo_solution_;
104};
105
108 bool is_cut = false; // Does not remove any integer points.
109 std::string name; // can be empty
110 bool local = false;
111};
112
113template <typename Constraint>
115 public:
121 return description_;
122 }
123
124 // Unless SeparateIntegerSolution() below is overridden, this must find a
125 // violated lazy constraint if one exists when given an integral solution.
126 virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
128 const Constraint& constraint) = 0;
129
130 // This MUST find a violated lazy constraint if one exists.
131 // All constraints returned must have is_cut as false.
132 virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
134 const Constraint& constraint) {
135 return SeparateFractionalSolution(context, constraint);
136 }
137
138 // Returns true if no constraints are violated.
141 const Constraint& constraint) {
142 return SeparateFractionalSolution(context, constraint).empty();
143 }
144
145 // This MUST find a violated constraint if one exists.
148 const Constraint& constraint) {
149 return SeparateIntegerSolution(context, constraint).empty();
150 }
151
152 private:
154};
155
156// handler is not owned but held.
157template <typename Constraint>
159 SCIP* scip);
160
162 bool initial = true;
163 bool separate = true;
164 bool enforce = true;
165 bool check = true;
166 bool propagate = true;
167 bool local = false;
168 bool modifiable = false;
169 bool dynamic = false;
170 bool removable = true;
171 bool stickingatnodes = false;
172};
173
174// constraint_data is not owned but held.
175template <typename ConstraintData>
176void AddCallbackConstraint(SCIP* scip,
178 const std::string& constraint_name,
179 const ConstraintData* constraint_data,
180 const ScipCallbackConstraintOptions& options);
181
182// Implementation details, here and below.
183
184namespace internal {
185
187 public:
189 virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
190 const ScipConstraintHandlerContext& context, void* constraint) = 0;
191
192 virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
193 const ScipConstraintHandlerContext& context, void* constraint) = 0;
194
196 const ScipConstraintHandlerContext& context, void* constraint) = 0;
197
199 const ScipConstraintHandlerContext& context, void* constraint) = 0;
200};
201
202template <typename ConstraintData>
204 public:
207 : handler_(handler) {}
208
209 std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
211 void* constraint_data) override {
212 return handler_->SeparateFractionalSolution(
213 context, *static_cast<ConstraintData*>(constraint_data));
214 }
215
216 std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
218 void* constraint_data) override {
219 return handler_->SeparateIntegerSolution(
220 context, *static_cast<ConstraintData*>(constraint_data));
221 }
222
224 void* constraint_data) override {
225 return handler_->FractionalSolutionFeasible(
226 context, *static_cast<ConstraintData*>(constraint_data));
227 }
228
230 void* constraint_data) override {
231 return handler_->IntegerSolutionFeasible(
232 context, *static_cast<ConstraintData*>(constraint_data));
233 }
234
235 private:
237};
238
240 const ScipConstraintHandlerDescription& description,
241 std::unique_ptr<ScipCallbackRunner> runner, SCIP* scip);
242
243void AddCallbackConstraintImpl(SCIP* scip, const std::string& handler_name,
244 const std::string& constraint_name,
245 void* constraint_data,
246 const ScipCallbackConstraintOptions& options);
247
248} // namespace internal
249
250template <typename ConstraintData>
259
260template <typename ConstraintData>
263 const std::string& constraint_name,
264 const ConstraintData* constraint_data,
265 const ScipCallbackConstraintOptions& options) {
267 scip, handler->description().name, constraint_name,
268 static_cast<void*>(const_cast<ConstraintData*>(constraint_data)),
269 options);
270}
271
272} // namespace operations_research
273
274#endif // OR_TOOLS_LINEAR_SOLVER_SCIP_CALLBACK_H_
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)
A value of nullptr for solution means to use the current LP solution.
ScipConstraintHandler(const ScipConstraintHandlerDescription &description)
const ScipConstraintHandlerDescription & description() const
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
Returns true if no constraints are violated.
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)=0
virtual bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
This MUST find a violated constraint if one exists.
std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
ScipCallbackRunnerImpl(ScipConstraintHandler< ConstraintData > *handler)
std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint_data) override
bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint_data) override
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
GurobiMPCallbackContext * context
double solution
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)
In SWIG mode, we don't want anything besides these top-level includes.
void AddCallbackConstraint(SCIP *scip, ScipConstraintHandler< ConstraintData > *handler, const std::string &constraint_name, const ConstraintData *constraint_data, const ScipCallbackConstraintOptions &options)
constraint_data is not owned but held.
void RegisterConstraintHandler(ScipConstraintHandler< Constraint > *handler, SCIP *scip)
handler is not owned but held.
bool needs_constraints
See CONSHDLR_NEEDSCONS in SCIP documentation above.
std::string name
See CONSHDLR_NAME in SCIP documentation above.
int eager_frequency
See CONSHDLR_EAGERFREQ in SCIP documentation above.
std::string description
See CONSHDLR_DESC in SCIP documentation above.
int separation_frequency
See CONSHDLR_SEPAFREQ in the SCIP documentation above.