OR-Tools  9.0
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 
37 namespace 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.
70  int eager_frequency = 10;
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,
87  bool is_pseudo_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.
118 template <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.
162 template <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.
180 template <typename ConstraintData>
181 void 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 
189 namespace internal {
190 
192  public:
193  virtual ~ScipCallbackRunner() {}
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 
207 template <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 
248 void 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 
255 template <typename ConstraintData>
257  SCIP* scip) {
259  handler->description(),
261  handler),
262  scip);
263 }
264 
265 template <typename ConstraintData>
266 void 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 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)