21 #include "absl/container/flat_hash_set.h" 22 #include "absl/memory/memory.h" 23 #include "absl/status/status.h" 24 #include "absl/status/statusor.h" 25 #include "absl/strings/string_view.h" 26 #include "absl/synchronization/mutex.h" 27 #include "absl/time/clock.h" 28 #include "absl/time/time.h" 29 #include "absl/types/optional.h" 30 #include "scip/scip.h" 31 #include "scip/type_scip.h" 34 #include "ortools/math_opt/callback.pb.h" 44 std::unique_ptr<GScipSolverCallbackHandler>
46 const CallbackRegistrationProto& callback_registration,
50 const absl::flat_hash_set<CallbackEventProto> events =
52 if (!events.contains(CALLBACK_EVENT_MESSAGE)) {
56 return absl::WrapUnique(
64 solve_start_(std::move(solve_start)),
68 return std::bind(&GScipSolverCallbackHandler::MessageCallback,
this,
69 std::placeholders::_1, std::placeholders::_2);
82 const absl::MutexLock lock(&message_mutex_);
84 absl::optional<CallbackDataProto> data = message_callback_data_.Flush();
87 absl::Now() - solve_start_, data->mutable_runtime()))
88 <<
"Failed to encode the time.";
89 CallUserCallback(*data);
93 const absl::MutexLock lock(&callback_mutex_);
97 void GScipSolverCallbackHandler::MessageCallback(
105 const absl::MutexLock lock(&message_mutex_);
107 absl::optional<CallbackDataProto> data =
108 message_callback_data_.Parse(
message);
114 absl::Now() - solve_start_, data->mutable_runtime());
115 if (!runtime_status.ok()) {
116 absl::MutexLock lock(&callback_mutex_);
122 <<
"Failed to encode the time.";
126 const auto interrupt_status =
SCIP_TO_STATUS(SCIPinterruptSolve(scip_));
127 LOG_IF(ERROR, !interrupt_status.ok())
128 <<
"Failed to interrupt the solve on error: " << interrupt_status;
135 CallUserCallback(*data);
138 absl::optional<CallbackResultProto>
139 GScipSolverCallbackHandler::CallUserCallback(
140 const CallbackDataProto& callback_data) {
159 absl::MutexLock lock(&callback_mutex_);
161 return absl::nullopt;
164 absl::StatusOr<CallbackResultProto> result_or = callback_(callback_data);
165 status_ = result_or.status();
166 if (!result_or.ok() || result_or->terminate()) {
170 const auto interrupt_status =
SCIP_TO_STATUS(SCIPinterruptSolve(scip_));
171 if (!interrupt_status.ok()) {
173 status_ = interrupt_status;
175 LOG(ERROR) <<
"Failed to interrupt the solve on error: " 179 return absl::nullopt;
182 return *std::move(result_or);
#define SCIP_TO_STATUS(x)
inline ::absl::StatusOr< google::protobuf::Duration > EncodeGoogleApiProto(absl::Duration d)
static std::unique_ptr< GScipSolverCallbackHandler > RegisterIfNeeded(const CallbackRegistrationProto &callback_registration, SolverInterface::Callback callback, absl::Time solve_start, SCIP *scip)
GScipSolverCallbackHandler(const GScipSolverCallbackHandler &)=delete
absl::flat_hash_set< CallbackEventProto > EventSet(const CallbackRegistrationProto &callback_registration)
GScipMessageHandler MessageHandler()
#define LOG_IF(severity, condition)
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
Collection of objects used to extend the Constraint Solver library.
#define RETURN_IF_ERROR(expr)
std::function< void(GScipMessageType type, absl::string_view message)> GScipMessageHandler