OR-Tools  9.6
scip_callback.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <memory>
26 #include <string>
27 #include <vector>
28 
29 #include "absl/memory/memory.h"
32 #include "scip/scip_sol.h"
33 #include "scip/type_cons.h"
34 #include "scip/type_scip.h"
35 #include "scip/type_sol.h"
36 #include "scip/type_var.h"
37 
38 namespace operations_research {
39 
40 // See https://scip.zib.de/doc-6.0.2/html/CONS.php#CONS_PROPERTIES for details.
41 // For member below, the corresponding SCIP constraint handler property name is
42 // provided.
43 //
44 // TODO(user): no effort has been made to optimize the default values of
45 // enforcement_priority, feasibility_check_priority, eager_frequency, or
46 // separation_priority.
48  // See CONSHDLR_NAME in SCIP documentation above.
49  std::string name;
50 
51  // See CONSHDLR_DESC in SCIP documentation above.
52  std::string description;
53 
54  // See CONSHDLR_ENFOPRIORITY in the SCIP documentation above. Determines the
55  // order this constraint class is checked at each LP node.
56  //
57  // WARNING(rander): Assumed that enforcement_priority < 0. (This enforcement
58  // runs after integrality enforcement, so CONSENFOLP always runs on integral
59  // solutions.)
61 
62  // See CONSHDLR_CHECKPRIORITY: in the SCIP documentation above. Determines the
63  // order this constraint class runs in when testing solution feasibility.
64  //
65  // WARNING(rander): Assumed that feasibility_check_priority < 0. (This check
66  // runs after the integrality check, so CONSCHECK always runs on integral
67  // solutions.)
69 
70  // See CONSHDLR_EAGERFREQ in SCIP documentation above.
71  int eager_frequency = 10;
72 
73  // See CONSHDLR_NEEDSCONS in SCIP documentation above.
74  bool needs_constraints = false;
75 
76  // See CONSHDLR_SEPAPRIORITY in SCIP documentation above. Determines the
77  // order this constraint class runs in the cut loop.
79 
80  // See CONSHDLR_SEPAFREQ in the SCIP documentation above.
82 };
83 
85  public:
86  // A value of nullptr for solution means to use the current LP solution.
87  ScipConstraintHandlerContext(SCIP* scip, SCIP_SOL* solution,
88  bool is_pseudo_solution);
89  double VariableValue(const MPVariable* variable) const;
90 
91  int64_t CurrentNodeId() const;
92  int64_t NumNodesProcessed() const;
93 
94  SCIP* scip() const { return scip_; }
95 
96  // Pseudo solutions may not be LP feasible. Duals/reduced costs are not
97  // available (the LP solver failed at this node).
98  //
99  // Do not add "user cuts" here (that strengthen LP solution but don't change
100  // feasible region), add only "lazy constraints" (cut off integer solutions).
101  //
102  // TODO(user): maybe this can be abstracted away.
103  bool is_pseudo_solution() const { return is_pseudo_solution_; }
104 
105  private:
106  SCIP* scip_;
107  SCIP_SOL* solution_;
108  bool is_pseudo_solution_;
109 };
110 
113  bool is_cut = false; // Does not remove any integer points.
114  std::string name; // can be empty
115  bool local = false;
116 };
117 
118 // See go/scip-callbacks for additional documentation.
119 template <typename Constraint>
121  public:
124  : description_(description) {}
127  return description_;
128  }
129 
130  // Unless SeparateIntegerSolution() below is overridden, this must find a
131  // violated lazy constraint if one exists when given an integral solution.
132  virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
134  const Constraint& constraint) = 0;
135 
136  // This MUST find a violated lazy constraint if one exists.
137  // All constraints returned must have is_cut as false.
138  virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
140  const Constraint& constraint) {
141  return SeparateFractionalSolution(context, constraint);
142  }
143 
144  // Returns true if no constraints are violated.
147  const Constraint& constraint) {
148  return SeparateFractionalSolution(context, constraint).empty();
149  }
150 
151  // This MUST find a violated constraint if one exists.
154  const Constraint& constraint) {
155  return SeparateIntegerSolution(context, constraint).empty();
156  }
157 
158  private:
160 };
161 
162 // handler is not owned but held.
163 template <typename Constraint>
165  SCIP* scip);
166 
168  bool initial = true;
169  bool separate = true;
170  bool enforce = true;
171  bool check = true;
172  bool propagate = true;
173  bool local = false;
174  bool modifiable = false;
175  bool dynamic = false;
176  bool removable = true;
177  bool stickingatnodes = false;
178 };
179 
180 // constraint_data is not owned but held.
181 template <typename ConstraintData>
182 void AddCallbackConstraint(SCIP* scip,
184  const std::string& constraint_name,
185  const ConstraintData* constraint_data,
186  const ScipCallbackConstraintOptions& options);
187 
188 // Implementation details, here and below.
189 
190 namespace internal {
191 
193  public:
194  virtual ~ScipCallbackRunner() {}
195  virtual std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
196  const ScipConstraintHandlerContext& context, void* constraint) = 0;
197 
198  virtual std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
199  const ScipConstraintHandlerContext& context, void* constraint) = 0;
200 
202  const ScipConstraintHandlerContext& context, void* constraint) = 0;
203 
205  const ScipConstraintHandlerContext& context, void* constraint) = 0;
206 };
207 
208 template <typename ConstraintData>
210  public:
213  : handler_(handler) {}
214 
215  std::vector<CallbackRangeConstraint> SeparateFractionalSolution(
217  void* constraint_data) override {
218  return handler_->SeparateFractionalSolution(
219  context, *static_cast<ConstraintData*>(constraint_data));
220  }
221 
222  std::vector<CallbackRangeConstraint> SeparateIntegerSolution(
224  void* constraint_data) override {
225  return handler_->SeparateIntegerSolution(
226  context, *static_cast<ConstraintData*>(constraint_data));
227  }
228 
230  void* constraint_data) override {
231  return handler_->FractionalSolutionFeasible(
232  context, *static_cast<ConstraintData*>(constraint_data));
233  }
234 
236  void* constraint_data) override {
237  return handler_->IntegerSolutionFeasible(
238  context, *static_cast<ConstraintData*>(constraint_data));
239  }
240 
241  private:
243 };
244 
246  const ScipConstraintHandlerDescription& description,
247  std::unique_ptr<ScipCallbackRunner> runner, SCIP* scip);
248 
249 void AddCallbackConstraintImpl(SCIP* scip, const std::string& handler_name,
250  const std::string& constraint_name,
251  void* constraint_data,
252  const ScipCallbackConstraintOptions& options);
253 
254 } // namespace internal
255 
256 template <typename ConstraintData>
258  SCIP* scip) {
260  handler->description(),
262  handler),
263  scip);
264 }
265 
266 template <typename ConstraintData>
267 void AddCallbackConstraint(SCIP* scip,
269  const std::string& constraint_name,
270  const ConstraintData* constraint_data,
271  const ScipCallbackConstraintOptions& options) {
273  scip, handler->description().name, constraint_name,
274  static_cast<void*>(const_cast<ConstraintData*>(constraint_data)),
275  options);
276 }
277 
278 } // namespace operations_research
279 
280 #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 bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, const Constraint &constraint)
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)=0
ScipConstraintHandler(const ScipConstraintHandlerDescription &description)
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, const Constraint &constraint)
const ScipConstraintHandlerDescription & description() const
virtual bool IntegerSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual bool FractionalSolutionFeasible(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
virtual std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint)=0
std::vector< CallbackRangeConstraint > SeparateFractionalSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
std::vector< CallbackRangeConstraint > SeparateIntegerSolution(const ScipConstraintHandlerContext &context, void *constraint_data) override
ScipCallbackRunnerImpl(ScipConstraintHandler< ConstraintData > *handler)
bool FractionalSolutionFeasible(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)