20 #include "absl/strings/str_cat.h"
21 #include "absl/types/span.h"
24 #include "scip/cons_linear.h"
26 #include "scip/pub_cons.h"
27 #include "scip/scip.h"
28 #include "scip/scip_cons.h"
29 #include "scip/scip_cut.h"
30 #include "scip/scip_general.h"
31 #include "scip/scip_lp.h"
32 #include "scip/scip_param.h"
33 #include "scip/scip_prob.h"
34 #include "scip/scip_sol.h"
35 #include "scip/scip_solvingstats.h"
36 #include "scip/scip_tree.h"
37 #include "scip/scipdefplugins.h"
38 #include "scip/struct_cons.h"
39 #include "scip/struct_tree.h"
40 #include "scip/struct_var.h"
41 #include "scip/type_cons.h"
42 #include "scip/type_lp.h"
43 #include "scip/type_result.h"
44 #include "scip/type_retcode.h"
45 #include "scip/type_scip.h"
46 #include "scip/type_sol.h"
47 #include "scip/type_tree.h"
48 #include "scip/type_var.h"
51 std::unique_ptr<operations_research::internal::ScipCallbackRunner>
runner;
61 int ScipNumVars(SCIP* scip) {
return SCIPgetNOrigVars(scip); }
63 SCIP_VAR* ScipGetVar(SCIP* scip,
int var_index) {
66 return SCIPgetOrigVars(scip)[var_index];
72 SCIP* scip, SCIP_SOL* solution,
bool is_pseudo_solution)
75 is_pseudo_solution_(is_pseudo_solution) {}
79 return SCIPgetSolVal(scip_, solution_, ScipGetVar(scip_, variable->
index()));
83 return SCIPgetNNodes(scip_);
87 return SCIPgetCurrentNode(scip_)->number;
100 a_times_x += coef_pair.second *
context.VariableValue(coef_pair.first);
104 return violation > 0;
115 absl::Span<SCIP_CONS*> constraints,
119 for (SCIP_CONS* constraint : constraints) {
120 SCIP_CONSDATA* consdata = SCIPconsGetData(constraint);
121 CHECK(consdata !=
nullptr);
122 std::vector<CallbackRangeConstraint> user_suggested_constraints;
124 user_suggested_constraints =
127 user_suggested_constraints =
130 int num_constraints_added = 0;
132 user_suggested_constraints) {
134 user_suggested_constraint.range)) {
137 num_constraints_added++;
139 if (user_suggested_constraint.is_cut) {
140 SCIP_ROW*
row =
nullptr;
141 constexpr
bool kModifiable =
false;
142 constexpr
bool kRemovable =
true;
144 scip, &
row, constraint, user_suggested_constraint.name.c_str(),
145 user_suggested_constraint.range.lower_bound(),
146 user_suggested_constraint.range.upper_bound(),
147 user_suggested_constraint.local, kModifiable, kRemovable)));
149 for (
const auto& coef_pair :
150 user_suggested_constraint.range.linear_expr().terms()) {
153 SCIP_VAR*
var = ScipGetVar(scip, coef_pair.first->index());
154 const double coef = coef_pair.second;
158 SCIP_Bool infeasible;
159 constexpr
bool kForceCut =
false;
174 std::vector<SCIP_VAR*> vars;
175 std::vector<double> coefs;
176 for (
const auto& coef_pair :
177 user_suggested_constraint.range.linear_expr().terms()) {
180 vars.push_back(ScipGetVar(scip, coef_pair.first->index()));
181 coefs.push_back(coef_pair.second);
184 const int num_vars = vars.size();
185 SCIP_CONS* scip_cons;
189 scip, &scip_cons, user_suggested_constraint.name.c_str(), num_vars,
190 vars.data(), coefs.data(),
191 user_suggested_constraint.range.lower_bound(),
192 user_suggested_constraint.range.upper_bound(),
true,
194 true, user_suggested_constraint.local,
197 if (user_suggested_constraint.local) {
218 int nconss,
int nusefulconss, SCIP_SOL* sol,
219 bool is_pseudo_solution)
222 context(scip, sol, is_pseudo_solution),
225 absl::MakeSpan(conss, nconss).subspan(nusefulconss)) {
238 CHECK(scip !=
nullptr);
239 SCIP_CONSHDLRDATA* scip_handler_data = SCIPconshdlrGetData(conshdlr);
240 CHECK(scip_handler_data !=
nullptr);
241 delete scip_handler_data;
242 SCIPconshdlrSetData(conshdlr,
nullptr);
247 VLOG(3) <<
"DeleteC";
248 CHECK(consdata !=
nullptr);
249 CHECK(*consdata !=
nullptr);
251 cons->consdata =
nullptr;
256 VLOG(3) <<
"EnforceC";
258 nusefulconss,
nullptr,
false);
263 if (separation_result ==
269 switch (separation_result) {
271 *result = SCIP_CONSADDED;
274 *result = SCIP_SEPARATED;
277 *result = SCIP_FEASIBLE;
284 VLOG(3) <<
"SeparateLpC";
286 nusefulconss,
nullptr,
false);
291 if (separation_result ==
297 switch (separation_result) {
299 *result = SCIP_CONSADDED;
302 *result = SCIP_SEPARATED;
305 *result = SCIP_DIDNOTFIND;
312 VLOG(3) <<
"SeparatePrimalC";
314 nusefulconss, sol,
false);
319 if (separation_result ==
325 switch (separation_result) {
327 *result = SCIP_CONSADDED;
330 LOG(
ERROR) <<
"Cutting planes cannot be added on integer solutions, "
331 "treating as a constraint.";
332 *result = SCIP_CONSADDED;
335 *result = SCIP_DIDNOTFIND;
342 VLOG(3) <<
"CheckFeasibilityC";
347 SCIP_CONSDATA* consdata = SCIPconsGetData(constraint);
348 CHECK(consdata !=
nullptr);
351 *result = SCIP_INFEASIBLE;
355 *result = SCIP_FEASIBLE;
359 VLOG(3) <<
"EnforcePseudoSolutionC";
363 nusefulconss,
nullptr,
true);
368 if (separation_result ==
374 switch (separation_result) {
376 *result = SCIP_CONSADDED;
379 LOG(
ERROR) <<
"Cutting planes cannot be added on pseudo solutions, "
380 "treating as a constraint.";
381 *result = SCIP_CONSADDED;
384 *result = SCIP_FEASIBLE;
398 const int num_vars = operations_research::ScipNumVars(scip);
399 for (
int i = 0; i < num_vars; ++i) {
400 SCIP_VAR*
var = operations_research::ScipGetVar(scip, i);
401 SCIP_CALL(SCIPaddVarLocksType(scip,
var, locktype, nlockspos + nlocksneg,
402 nlockspos + nlocksneg));
413 std::unique_ptr<ScipCallbackRunner> runner, SCIP* scip) {
414 SCIP_CONSHDLR* c_scip_handler;
415 SCIP_CONSHDLRDATA* scip_handler_data =
new SCIP_CONSHDLRDATA;
416 scip_handler_data->runner = std::move(runner);
419 scip, &c_scip_handler, description.
name.c_str(),
423 CheckFeasibilityC, VariableRoundingLockC, scip_handler_data)));
424 CHECK(c_scip_handler !=
nullptr);
426 scip, c_scip_handler, SeparateLpC, SeparatePrimalSolutionC,
430 SCIPsetConshdlrFree(scip, c_scip_handler, ConstraintHandlerFreeC)));
432 SCIPsetConshdlrDelete(scip, c_scip_handler, ConstraintHandlerDeleteC)));
436 const std::string& constraint_name,
437 void* constraint_data,
439 SCIP_CONSHDLR* conshdlr = SCIPfindConshdlr(scip, handler_name.c_str());
440 CHECK(conshdlr !=
nullptr)
441 <<
"Constraint handler " << handler_name <<
" not registered with scip.";
443 consdata->
data = constraint_data;
444 SCIP_CONS* constraint =
nullptr;
446 scip, &constraint, constraint_name.c_str(), conshdlr, consdata,
450 CHECK(constraint !=
nullptr);
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define VLOG(verboselevel)
const absl::flat_hash_map< const MPVariable *, double > & terms() const
An expression of the form:
double upper_bound() const
double lower_bound() const
const LinearExpr & linear_expr() const
The class for variables of a Mathematical Programming (MP) model.
int index() const
Returns the index of the variable in the MPSolver::variables_.
double VariableValue(const MPVariable *variable) const
ScipConstraintHandlerContext(SCIP *scip, SCIP_SOL *solution, bool is_pseudo_solution)
int64_t CurrentNodeId() const
int64_t NumNodesProcessed() const
virtual bool IntegerSolutionFeasible(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
GurobiMPCallbackContext * context
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.
bool LinearConstraintIsViolated(const ScipConstraintHandlerContext &context, const LinearRange &constraint)
ScipSeparationResult RunSeparation(internal::ScipCallbackRunner *runner, const ScipConstraintHandlerContext &context, absl::Span< SCIP_CONS * > constraints, bool is_integral)
static SCIP_DECL_CONSLOCK(VariableRoundingLockC)
static SCIP_DECL_CONSFREE(ConstraintHandlerFreeC)
destructor of constraint handler to free user data (called when SCIP is exiting)
static SCIP_DECL_CONSSEPASOL(SeparatePrimalSolutionC)
static SCIP_DECL_CONSENFOPS(EnforcePseudoSolutionC)
static SCIP_DECL_CONSSEPALP(SeparateLpC)
static SCIP_DECL_CONSENFOLP(EnforceLpC)
static SCIP_DECL_CONSDELETE(ConstraintHandlerDeleteC)
static SCIP_DECL_CONSCHECK(CheckFeasibilityC)
#define SCIP_TO_STATUS(x)
std::unique_ptr< operations_research::internal::ScipCallbackRunner > runner
internal::ScipCallbackRunner * callback_runner
absl::Span< SCIP_CONS * > unlikely_useful_constraints
CallbackSetup(SCIP *scip, SCIP_CONSHDLR *scip_handler, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, bool is_pseudo_solution)
absl::Span< SCIP_CONS * > useful_constraints
SCIP_CONSHDLRDATA * scip_handler_data
ScipConstraintHandlerContext context
int feasibility_check_priority