Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
gscip_event_handler.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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
15
16#include <string>
17#include <vector>
18
19#include "absl/status/status.h"
21#include "ortools/gscip/gscip.h"
23#include "scip/def.h"
24#include "scip/scip.h"
25#include "scip/scip_event.h"
26#include "scip/type_event.h"
27
30 operations_research::GScip* gscip = nullptr;
31};
32
33// SCIP callback implementation
34
35static SCIP_DECL_EVENTEXEC(EventExec) {
36 VLOG(3) << "EventExec";
37 CHECK_NE(scip, nullptr);
38 CHECK_NE(eventhdlr, nullptr);
39 CHECK_NE(event, nullptr);
40
41 SCIP_EVENTHDLRDATA* const event_handler_data =
42 SCIPeventhdlrGetData(eventhdlr);
43 CHECK_NE(event_handler_data, nullptr);
44
45 return event_handler_data->handler->Execute(
46 {event_handler_data->gscip, SCIPeventGetType(event)});
47}
48
49static SCIP_DECL_EVENTINIT(EventInit) {
50 VLOG(3) << "EventInit";
51 CHECK_NE(scip, nullptr);
52 CHECK_NE(eventhdlr, nullptr);
53
54 SCIP_EVENTHDLRDATA* const event_handler_data =
55 SCIPeventhdlrGetData(eventhdlr);
56 CHECK_NE(event_handler_data, nullptr);
57
58 return event_handler_data->handler->Init(event_handler_data->gscip);
59}
60
61static SCIP_DECL_EVENTEXIT(EventExit) {
62 VLOG(3) << "EventExit";
63 CHECK_NE(scip, nullptr);
64 CHECK_NE(eventhdlr, nullptr);
65
66 SCIP_EVENTHDLRDATA* const event_handler_data =
67 SCIPeventhdlrGetData(eventhdlr);
68 CHECK_NE(event_handler_data, nullptr);
69
70 SCIP_CALL(DropAllEvents(*event_handler_data->handler));
71
72 return event_handler_data->handler->Exit(event_handler_data->gscip);
73}
74
75static SCIP_DECL_EVENTFREE(EventFree) {
76 VLOG(3) << "EventFree";
77 CHECK_NE(scip, nullptr);
78 CHECK_NE(eventhdlr, nullptr);
79
80 SCIP_EVENTHDLRDATA* const event_handler_data =
81 SCIPeventhdlrGetData(eventhdlr);
82 CHECK_NE(event_handler_data, nullptr);
83
84 delete event_handler_data;
85 SCIPeventhdlrSetData(eventhdlr, nullptr);
86
87 return SCIP_OKAY;
88}
89
90namespace operations_research {
91
92absl::Status GScipEventHandler::Register(GScip* const gscip) {
93 if (gscip_ != nullptr || event_handler_ != nullptr) {
94 return absl::InternalError("Already registered");
95 }
96
97 gscip_ = gscip;
98
99 // event_handler_data is freed in EventFree.
100 SCIP_EVENTHDLRDATA* const event_handler_data = new SCIP_EVENTHDLRDATA;
101 event_handler_data->gscip = gscip;
102 event_handler_data->handler = this;
103
104 RETURN_IF_SCIP_ERROR(SCIPincludeEventhdlrBasic(
105 gscip->scip(), &event_handler_, description_.name.c_str(),
106 description_.description.c_str(), EventExec, event_handler_data));
107 if (event_handler_ == nullptr) {
108 // This is only defensive: SCIP should return a SCIP error above instead.
109 return absl::InternalError("SCIP failed to create event handler");
110 }
111
113 SCIPsetEventhdlrInit(gscip->scip(), event_handler_, EventInit));
115 SCIPsetEventhdlrExit(gscip->scip(), event_handler_, EventExit));
117 SCIPsetEventhdlrFree(gscip->scip(), event_handler_, EventFree));
118 return absl::OkStatus();
119}
120
121SCIP_RETCODE GScipEventHandler::CatchEvent(const SCIP_EVENTTYPE event_type) {
122 int filter_pos = -1;
123
124 SCIP_CALL(SCIPcatchEvent(gscip_->scip(), event_type, event_handler_,
125 /*eventdata=*/nullptr, &filter_pos));
126 CHECK_GE(filter_pos, 0);
127
128 caught_events_.emplace_back(event_type, filter_pos);
129
130 return SCIP_OKAY;
131}
132
133SCIP_RETCODE DropAllEvents(GScipEventHandler& handler) {
134 for (const GScipEventHandler::CaughtEvent& caught_event :
135 handler.caught_events_) {
136 SCIP_CALL(SCIPdropEvent(handler.gscip_->scip(), caught_event.event_type,
137 handler.event_handler_,
138 /*eventdata=*/nullptr, caught_event.filter_pos));
139 }
140
141 handler.caught_events_.clear();
142
143 return SCIP_OKAY;
144}
145
146} // namespace operations_research
SCIP_RETCODE CatchEvent(SCIP_EVENTTYPE event_type)
static SCIP_DECL_EVENTEXIT(EventExit)
static SCIP_DECL_EVENTFREE(EventFree)
static SCIP_DECL_EVENTEXEC(EventExec)
SCIP callback implementation.
static SCIP_DECL_EVENTINIT(EventInit)
In SWIG mode, we don't want anything besides these top-level includes.
SCIP_RETCODE DropAllEvents(GScipEventHandler &handler)
#define RETURN_IF_SCIP_ERROR(x)
operations_research::GScip * gscip
operations_research::GScipEventHandler * handler
std::string name
See CONSHDLR_NAME in SCIP documentation above.
std::string description
See CONSHDLR_DESC in SCIP documentation above.