18#ifndef OR_TOOLS_GSCIP_GSCIP_CONSTRAINT_HANDLER_H_
19#define OR_TOOLS_GSCIP_GSCIP_CONSTRAINT_HANDLER_H_
27#include "absl/status/status.h"
28#include "absl/status/statusor.h"
31#include "scip/type_cons.h"
32#include "scip/type_sol.h"
33#include "scip/type_var.h"
181 SCIP_CONSHDLR* current_handler,
182 SCIP_SOL* current_solution)
185 current_handler_(current_handler),
186 current_solution_(current_solution) {}
201 absl::StatusOr<GScipCallbackResult>
AddCut(
202 const GScipLinearRange&
range,
const std::string&
name,
214 const GScipLinearRange&
range,
const std::string&
name,
236 SCIP_CONSHDLR* current_handler_;
237 SCIP_SOL* current_solution_;
285template <
typename Constra
intData>
317 GScip* gscip,
const std::string& constraint_name,
318 const ConstraintData* constraint_data,
335 const ConstraintData& constraint_data,
bool solution_infeasible);
355 const ConstraintData& constraint_data,
bool solution_infeasible,
356 bool objective_infeasible);
378 const ConstraintData& constraint_data,
bool check_integrality,
379 bool check_lp_rows,
bool print_reason,
bool check_completely);
394 virtual std::vector<std::pair<SCIP_VAR*, RoundingLockDirection>>
RoundingLock(
395 GScip* gscip,
const ConstraintData& constraint_data,
396 bool lock_type_is_model);
405 const ConstraintData& constraint_data);
415 const ConstraintData& constraint_data);
420 const ConstraintData& constraint_data,
421 bool solution_infeasible);
425 const ConstraintData& constraint_data,
bool solution_infeasible,
426 bool objective_infeasible);
429 const ConstraintData& constraint_data,
430 bool check_integrality,
431 bool check_lp_rows,
bool print_reason,
432 bool check_completely);
435 const ConstraintData& constraint_data);
439 const ConstraintData& constraint_data);
446 absl::StatusOr<GScipCallbackResult> result,
494class UntypedGScipConstraintHandler :
public GScipConstraintHandler<void*> {
501template <
typename Constra
intData>
502class UntypedGScipConstraintHandlerImpl :
public UntypedGScipConstraintHandler {
507 actual_handler_(constraint_handler) {}
509 absl::StatusOr<GScipCallbackResult>
EnforceLp(
511 bool solution_infeasible)
override {
512 return actual_handler_->EnforceLp(
513 context, *
static_cast<const ConstraintData*
>(constraint_data),
514 solution_infeasible);
519 bool solution_infeasible,
bool objective_infeasible)
override {
520 return actual_handler_->EnforcePseudoSolution(
521 context, *
static_cast<const ConstraintData*
>(constraint_data),
522 solution_infeasible, objective_infeasible);
526 void*
const& constraint_data,
527 bool check_integrality,
528 bool check_lp_rows,
bool print_reason,
529 bool completely)
override {
530 return actual_handler_->CheckIsFeasible(
531 context, *
static_cast<const ConstraintData*
>(constraint_data),
532 check_integrality, check_lp_rows, print_reason, completely);
535 std::vector<std::pair<SCIP_VAR*, RoundingLockDirection>>
RoundingLock(
536 GScip* gscip,
void*
const& constraint_data,
537 bool lock_type_is_model)
override {
538 return actual_handler_->RoundingLock(
539 gscip, *
static_cast<const ConstraintData*
>(constraint_data),
543 absl::StatusOr<GScipCallbackResult>
SeparateLp(
545 void*
const& constraint_data)
override {
546 return actual_handler_->SeparateLp(
547 context, *
static_cast<const ConstraintData*
>(constraint_data));
552 void*
const& constraint_data)
override {
553 return actual_handler_->SeparateSolution(
554 context, *
static_cast<const ConstraintData*
>(constraint_data));
563 std::unique_ptr<UntypedGScipConstraintHandler> constraint_handler);
566 GScip* gscip,
const std::string& handler_name,
567 const std::string& constraint_name,
void* constraint_data,
568 const GScipConstraintOptions& options);
574template <
typename Constra
intData>
582template <
typename Constra
intData>
583absl::StatusOr<SCIP_CONS*>
585 GScip* gscip,
const std::string& constraint_name,
586 const ConstraintData* constraint_data,
587 const GScipConstraintOptions& options) {
589 gscip, properties().
name, constraint_name,
590 static_cast<void*
>(
const_cast<ConstraintData*
>(constraint_data)),
596template <
typename Constra
intData>
597absl::StatusOr<GScipCallbackResult>
600 const ConstraintData& ,
bool ) {
604template <
typename Constra
intData>
605absl::StatusOr<GScipCallbackResult>
608 const ConstraintData& ,
bool ,
613template <
typename Constra
intData>
616 const ConstraintData& ,
bool ,
617 bool ,
bool ,
bool ) {
621template <
typename Constra
intData>
622std::vector<std::pair<SCIP_VAR*, RoundingLockDirection>>
624 GScip* gscip,
const ConstraintData& ,
626 std::vector<std::pair<SCIP_VAR*, RoundingLockDirection>> result;
627 for (SCIP_VAR*
var : gscip->variables()) {
633template <
typename Constra
intData>
634absl::StatusOr<GScipCallbackResult>
637 const ConstraintData& ) {
641template <
typename Constra
intData>
642absl::StatusOr<GScipCallbackResult>
645 const ConstraintData& ) {
651template <
typename Constra
intData>
654 const absl::StatusOr<GScipCallbackResult> result,
658 context.gscip()->InterruptSolveFromCallbackOnCallbackError(result.status());
659 return default_callback_result;
661 return result.value();
664template <
typename Constra
intData>
666 GScipConstraintHandlerContext
context,
667 const ConstraintData& constraint_data,
bool solution_infeasible) {
668 return HandleCallbackStatus(
669 EnforceLp(
context, constraint_data, solution_infeasible),
context,
673template <
typename Constra
intData>
677 const ConstraintData& constraint_data,
bool solution_infeasible,
678 bool objective_infeasible) {
679 return HandleCallbackStatus(
680 EnforcePseudoSolution(
context, constraint_data, solution_infeasible,
681 objective_infeasible),
685template <
typename Constra
intData>
688 const ConstraintData& constraint_data,
bool check_integrality,
689 bool check_lp_rows,
bool print_reason,
bool check_completely) {
690 const absl::StatusOr<bool> result =
691 CheckIsFeasible(
context, constraint_data, check_integrality,
692 check_lp_rows, print_reason, check_completely);
694 return HandleCallbackStatus(result.status(),
context,
703template <
typename Constra
intData>
706 const ConstraintData& constraint_data) {
707 return HandleCallbackStatus(SeparateLp(
context, constraint_data),
context,
711template <
typename Constra
intData>
715 const ConstraintData& constraint_data) {
716 return HandleCallbackStatus(SeparateSolution(
context, constraint_data),
double VariableValue(SCIP_VAR *variable) const
const GScipCallbackStats & stats() const
double GlobalVarUb(SCIP_VAR *var) const
absl::Status SetLocalVarLb(SCIP_VAR *var, double value)
GScipConstraintHandlerContext(GScip *gscip, const GScipCallbackStats *stats, SCIP_CONSHDLR *current_handler, SCIP_SOL *current_solution)
absl::StatusOr< GScipCallbackResult > AddCut(const GScipLinearRange &range, const std::string &name, const GScipCutOptions &options=GScipCutOptions())
double GlobalVarLb(SCIP_VAR *var) const
absl::Status SetGlobalVarUb(SCIP_VAR *var, double value)
absl::Status AddLazyLinearConstraint(const GScipLinearRange &range, const std::string &name, const GScipLazyConstraintOptions &options=GScipLazyConstraintOptions())
absl::Status SetLocalVarUb(SCIP_VAR *var, double value)
double LocalVarLb(SCIP_VAR *var) const
double LocalVarUb(SCIP_VAR *var) const
absl::Status SetGlobalVarLb(SCIP_VAR *var, double value)
virtual std::vector< std::pair< SCIP_VAR *, RoundingLockDirection > > RoundingLock(GScip *gscip, const ConstraintData &constraint_data, bool lock_type_is_model)
GScipCallbackResult CallEnforcePseudoSolution(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool solution_infeasible, bool objective_infeasible)
const GScipConstraintHandlerProperties & properties() const
virtual absl::StatusOr< GScipCallbackResult > SeparateSolution(GScipConstraintHandlerContext context, const ConstraintData &constraint_data)
virtual absl::StatusOr< GScipCallbackResult > EnforceLp(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool solution_infeasible)
Default callback implementations.
GScipCallbackResult CallEnforceLp(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool solution_infeasible)
The functions below wrap each callback function to manage status.
absl::Status Register(GScip *gscip)
Template implementations.
GScipCallbackResult CallCheckIsFeasible(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool check_integrality, bool check_lp_rows, bool print_reason, bool check_completely)
absl::StatusOr< SCIP_CONS * > AddCallbackConstraint(GScip *gscip, const std::string &constraint_name, const ConstraintData *constraint_data, const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
virtual absl::StatusOr< GScipCallbackResult > SeparateLp(GScipConstraintHandlerContext context, const ConstraintData &constraint_data)
virtual ~GScipConstraintHandler()=default
virtual absl::StatusOr< GScipCallbackResult > EnforcePseudoSolution(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool solution_infeasible, bool objective_infeasible)
virtual absl::StatusOr< bool > CheckIsFeasible(GScipConstraintHandlerContext context, const ConstraintData &constraint_data, bool check_integrality, bool check_lp_rows, bool print_reason, bool check_completely)
GScipCallbackResult CallSeparateLp(GScipConstraintHandlerContext context, const ConstraintData &constraint_data)
GScipCallbackResult CallSeparateSolution(GScipConstraintHandlerContext context, const ConstraintData &constraint_data)
GScipConstraintHandler(const GScipConstraintHandlerProperties &properties)
absl::StatusOr< bool > CheckIsFeasible(GScipConstraintHandlerContext context, void *const &constraint_data, bool check_integrality, bool check_lp_rows, bool print_reason, bool completely) override
absl::StatusOr< GScipCallbackResult > SeparateSolution(GScipConstraintHandlerContext context, void *const &constraint_data) override
absl::StatusOr< GScipCallbackResult > EnforceLp(GScipConstraintHandlerContext context, void *const &constraint_data, bool solution_infeasible) override
Default callback implementations.
UntypedGScipConstraintHandlerImpl(GScipConstraintHandler< ConstraintData > *constraint_handler)
absl::StatusOr< GScipCallbackResult > SeparateLp(GScipConstraintHandlerContext context, void *const &constraint_data) override
absl::StatusOr< GScipCallbackResult > EnforcePseudoSolution(GScipConstraintHandlerContext context, void *const &constraint_data, bool solution_infeasible, bool objective_infeasible) override
std::vector< std::pair< SCIP_VAR *, RoundingLockDirection > > RoundingLock(GScip *gscip, void *const &constraint_data, bool lock_type_is_model) override
UntypedGScipConstraintHandler(const GScipConstraintHandlerProperties &properties)
const std::string name
A name for logging purposes.
GurobiMPCallbackContext * context
absl::StatusOr< SCIP_CONS * > AddCallbackConstraint(GScip *gscip, const std::string &handler_name, const std::string &constraint_name, void *constraint_data, const GScipConstraintOptions &options)
absl::Status RegisterConstraintHandler(GScip *gscip, std::unique_ptr< UntypedGScipConstraintHandler > constraint_handler)
In SWIG mode, we don't want anything besides these top-level includes.
const GScipConstraintOptions & DefaultGScipConstraintOptions()
int ConstraintHandlerResultPriority(const GScipCallbackResult result, const ConstraintHandlerCallbackType callback_type)
ConstraintHandlerCallbackType
@ kEnfoPs
Unsupported: kEnfoRelax, ///< CONSENFORELAX.
GScipCallbackResult
Equivalent to type_result.h in SCIP.
GScipCallbackResult MergeConstraintHandlerResults(const GScipCallbackResult result1, const GScipCallbackResult result2, const ConstraintHandlerCallbackType callback_type)
const std::optional< Range > & range
double dual_bound
The global dual bound on the problem. See SCIPgetDualBound().
int64_t num_processed_nodes
int32_t num_solutions_found
int64_t num_processed_nodes_total
double primal_bound
The global primal bound on the problem. See SCIPgetPrimalBound().
int64_t dual_simplex_iterations
int64_t num_nodes_left
The number of open nodes left in the current run. See SCIPgetNNodesLeft().
int64_t primal_simplex_iterations
int feasibility_check_priority
Options passed to SCIP when adding a cut.
bool local
Cut is only valid for the current subtree.
bool removable
Cut can be removed from the LP due to aging or cleanup.
bool force_cut
Cut is forced to enter the LP.
bool modifiable
Cut is modifiable during node processing (subject to column generation).
Options passed to SCIP when adding a lazy constraint.
bool local
Cut is only valid for the current subtree.
bool dynamic
Constraint is subject to aging.