120 absl::Span<SCIP_CONS*> constraints,
124 for (SCIP_CONS* constraint : constraints) {
125 SCIP_CONSDATA* consdata = SCIPconsGetData(constraint);
126 CHECK(consdata !=
nullptr);
127 std::vector<CallbackRangeConstraint> user_suggested_constraints;
129 user_suggested_constraints =
132 user_suggested_constraints =
135 int num_constraints_added = 0;
137 user_suggested_constraints) {
139 user_suggested_constraint.range)) {
142 num_constraints_added++;
144 if (user_suggested_constraint.is_cut) {
145 SCIP_ROW*
row =
nullptr;
146 constexpr bool kModifiable =
false;
147 constexpr bool kRemovable =
true;
149 scip, &
row, constraint, user_suggested_constraint.name.c_str(),
150 user_suggested_constraint.range.lower_bound(),
151 user_suggested_constraint.range.upper_bound(),
152 user_suggested_constraint.local, kModifiable, kRemovable)));
154 for (
const auto& coef_pair :
155 user_suggested_constraint.range.linear_expr().terms()) {
158 SCIP_VAR*
var = ScipGetVar(scip, coef_pair.first->index());
159 const double coef = coef_pair.second;
163 SCIP_Bool infeasible;
164 constexpr bool kForceCut =
false;
179 std::vector<SCIP_VAR*> vars;
180 std::vector<double> coefs;
181 for (
const auto& coef_pair :
182 user_suggested_constraint.range.linear_expr().terms()) {
185 vars.push_back(ScipGetVar(scip, coef_pair.first->index()));
186 coefs.push_back(coef_pair.second);
189 const int num_vars = vars.size();
190 SCIP_CONS* scip_cons;
194 scip, &scip_cons, user_suggested_constraint.name.c_str(), num_vars,
195 vars.data(), coefs.data(),
196 user_suggested_constraint.range.lower_bound(),
197 user_suggested_constraint.range.upper_bound(),
true,
199 true, user_suggested_constraint.local,
202 if (user_suggested_constraint.local) {
203 CHECK_OK(
SCIP_TO_STATUS(SCIPaddConsLocal(scip, scip_cons,
nullptr)));
403 const int num_vars = operations_research::ScipNumVars(scip);
404 for (
int i = 0; i < num_vars; ++i) {
405 SCIP_VAR*
var = operations_research::ScipGetVar(scip, i);
406 SCIP_CALL(SCIPaddVarLocksType(scip,
var, locktype, nlockspos + nlocksneg,
407 nlockspos + nlocksneg));
418 std::unique_ptr<ScipCallbackRunner> runner,
SCIP* scip) {
419 SCIP_CONSHDLR* c_scip_handler;
420 SCIP_CONSHDLRDATA* scip_handler_data =
new SCIP_CONSHDLRDATA;
421 scip_handler_data->runner = std::move(runner);
424 scip, &c_scip_handler, description.
name.c_str(),
428 CheckFeasibilityC, VariableRoundingLockC, scip_handler_data)));
429 CHECK(c_scip_handler !=
nullptr);
431 scip, c_scip_handler, SeparateLpC, SeparatePrimalSolutionC,
435 SCIPsetConshdlrFree(scip, c_scip_handler, ConstraintHandlerFreeC)));
437 SCIPsetConshdlrDelete(scip, c_scip_handler, ConstraintHandlerDeleteC)));
441 const std::string& constraint_name,
442 void* constraint_data,
444 SCIP_CONSHDLR* conshdlr = SCIPfindConshdlr(scip, handler_name.c_str());
445 CHECK(conshdlr !=
nullptr)
446 <<
"Constraint handler " << handler_name <<
" not registered with scip.";
448 consdata->
data = constraint_data;
449 SCIP_CONS* constraint =
nullptr;
451 scip, &constraint, constraint_name.c_str(), conshdlr, consdata,
455 CHECK(constraint !=
nullptr);
int64_t CurrentNodeId() const
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.
int64_t NumNodesProcessed() const