OR-Tools  9.3
gscip_solver_callback.cc
Go to the documentation of this file.
1// Copyright 2010-2021 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 <memory>
17#include <optional>
18#include <utility>
19
20#include "absl/container/flat_hash_set.h"
21#include "absl/memory/memory.h"
22#include "absl/status/status.h"
23#include "absl/status/statusor.h"
24#include "absl/synchronization/mutex.h"
25#include "absl/time/time.h"
28#include "ortools/math_opt/callback.pb.h"
31#include "scip/scip.h"
32#include "scip/type_scip.h"
33
34namespace operations_research {
35namespace math_opt {
36
37std::unique_ptr<GScipSolverCallbackHandler>
39 const CallbackRegistrationProto& callback_registration,
40 const SolverInterface::Callback callback, const absl::Time solve_start,
41 SCIP* const scip) {
42 // TODO(b/180617976): Don't ignore unknown callbacks.
43 return nullptr;
44}
45
47 SolverInterface::Callback callback, absl::Time solve_start,
48 SCIP* const scip)
49 : callback_(std::move(ABSL_DIE_IF_NULL(callback))),
50 solve_start_(std::move(solve_start)),
51 scip_(ABSL_DIE_IF_NULL(scip)) {}
52
54 const absl::MutexLock lock(&callback_mutex_);
55 return status_;
56}
57
58std::optional<CallbackResultProto> GScipSolverCallbackHandler::CallUserCallback(
59 const CallbackDataProto& callback_data) {
60 // We hold the lock during the call of the user callback to ensure only one
61 // call execute at a time. Having multiple calls at once may be an issue when
62 // the user asks for termination since it may ask for it in one call while
63 // another thread is about to make its call for another callback.
64 //
65 // We don't expect any valid actions taken by the user is a callback to lead
66 // to another callback.
67 absl::MutexLock lock(&callback_mutex_);
68 if (!status_.ok()) {
69 return std::nullopt;
70 }
71
72 absl::StatusOr<CallbackResultProto> result_or = callback_(callback_data);
73 status_ = result_or.status();
74 if (!result_or.ok() || result_or->terminate()) {
75 // TODO(b/182919884): Make sure it is correct to use SCIPinterruptSolve()
76 // here and maybe migrate to the same architecture as the one used to
77 // interrupt the solve from foreign threads..
78 const auto interrupt_status = SCIP_TO_STATUS(SCIPinterruptSolve(scip_));
79 if (!interrupt_status.ok()) {
80 if (status_.ok()) {
81 status_ = interrupt_status;
82 } else {
83 LOG(ERROR) << "Failed to interrupt the solve on error: "
84 << interrupt_status;
85 }
86 }
87 return std::nullopt;
88 }
89
90 return *std::move(result_or);
91}
92
93} // namespace math_opt
94} // namespace operations_research
#define LOG(severity)
Definition: base/logging.h:420
#define ABSL_DIE_IF_NULL
Definition: base/logging.h:43
static std::unique_ptr< GScipSolverCallbackHandler > RegisterIfNeeded(const CallbackRegistrationProto &callback_registration, SolverInterface::Callback callback, absl::Time solve_start, SCIP *scip)
GScipSolverCallbackHandler(const GScipSolverCallbackHandler &)=delete
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
MPCallback * callback
Collection of objects used to extend the Constraint Solver library.
STL namespace.
#define SCIP_TO_STATUS(x)