23#include "absl/base/thread_annotations.h"
24#include "absl/memory/memory.h"
25#include "absl/status/status.h"
26#include "absl/status/statusor.h"
27#include "absl/strings/str_cat.h"
28#include "absl/synchronization/mutex.h"
29#include "absl/types/span.h"
33#include "ortools/math_opt/callback.pb.h"
38#include "ortools/math_opt/model.pb.h"
39#include "ortools/math_opt/model_update.pb.h"
40#include "ortools/math_opt/parameters.pb.h"
41#include "ortools/math_opt/result.pb.h"
54template <
typename IdNameContainer>
55void UpdateIdNameMap(
const absl::Span<const int64_t> deleted_ids,
56 const IdNameContainer& container, IdNameBiMap& bimap) {
57 for (
const int64_t deleted_id : deleted_ids) {
58 bimap.Erase(deleted_id);
60 for (
int i = 0; i < container.ids_size(); ++i) {
62 if (!container.names().empty()) {
63 name = container.names(i);
65 bimap.Insert(container.ids(i), std::move(
name));
69ModelSummary MakeSummary(
const ModelProto&
model) {
71 UpdateIdNameMap<VariablesProto>({},
model.variables(), summary.variables);
72 UpdateIdNameMap<LinearConstraintsProto>({},
model.linear_constraints(),
73 summary.linear_constraints);
77void UpdateSummaryFromModelUpdate(
const ModelUpdateProto& model_update,
78 ModelSummary& summary) {
79 UpdateIdNameMap<VariablesProto>(model_update.deleted_variable_ids(),
80 model_update.new_variables(),
82 UpdateIdNameMap<LinearConstraintsProto>(
83 model_update.deleted_linear_constraint_ids(),
84 model_update.new_linear_constraints(), summary.linear_constraints);
89absl::Status ToInternalError(
const absl::Status original) {
94 return absl::InternalError(original.message());
121class ConcurrentCallsGuard {
125 static absl::StatusOr<ConcurrentCallsGuard> TryAcquire(absl::Mutex& mutex)
126 ABSL_NO_THREAD_SAFETY_ANALYSIS {
130 if (!mutex.TryLock()) {
131 return absl::InvalidArgumentError(
"concurrent calls are forbidden");
133 return ConcurrentCallsGuard(mutex);
136 ConcurrentCallsGuard(
const ConcurrentCallsGuard&) =
delete;
137 ConcurrentCallsGuard& operator=(
const ConcurrentCallsGuard&) =
delete;
138 ConcurrentCallsGuard& operator=(ConcurrentCallsGuard&&) =
delete;
140 ConcurrentCallsGuard(ConcurrentCallsGuard&& other)
141 : mutex_(
std::exchange(other.mutex_, nullptr)) {}
144 ~ConcurrentCallsGuard() {
145 if (mutex_ !=
nullptr) {
151 explicit ConcurrentCallsGuard(absl::Mutex& mutex) : mutex_(&mutex) {
152 mutex_->AssertHeld();
162 const ModelProto&
model,
const SolverTypeProto solver_type,
166 return solver->Solve(solve_args);
171 : underlying_solver_(
std::move(underlying_solver)),
172 model_summary_(
std::move(model_summary)) {
173 CHECK(underlying_solver_ !=
nullptr);
180 const SolverTypeProto solver_type,
const ModelProto&
model,
185 auto underlying_solver,
187 auto result = absl::WrapUnique(
188 new Solver(std::move(underlying_solver), MakeSummary(
model)));
193 ASSIGN_OR_RETURN(
const auto guard, ConcurrentCallsGuard::TryAcquire(mutex_));
200 <<
"invalid parameters";
203 <<
"invalid model_parameters";
206 if (arguments.
user_cb !=
nullptr) {
209 cb = [&](
const CallbackDataProto& callback_data)
210 -> absl::StatusOr<CallbackResultProto> {
213 auto callback_result = arguments.
user_cb(callback_data);
215 callback_result, callback_data.event(),
217 return callback_result;
222 underlying_solver_->Solve(arguments.
parameters,
238 ASSIGN_OR_RETURN(
const auto guard, ConcurrentCallsGuard::TryAcquire(mutex_));
241 if (!underlying_solver_->CanUpdate(model_update)) {
244 UpdateSummaryFromModelUpdate(model_update, model_summary_);
252 const SolverTypeProto solver_type) {
253 if (solver_type == SOLVER_TYPE_UNSPECIFIED) {
254 return absl::InvalidArgumentError(
255 "can't use SOLVER_TYPE_UNSPECIFIED as solver_type parameter");
260 return absl::InvalidArgumentError(
261 absl::StrCat(
"input non_streamable init arguments are for ",
266 return absl::OkStatus();
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static AllSolversRegistry * Instance()
static absl::StatusOr< SolveResultProto > NonIncrementalSolve(const ModelProto &model, SolverTypeProto solver_type, const InitArgs &init_args, const SolveArgs &solve_args)
absl::StatusOr< SolveResultProto > Solve(const SolveArgs &arguments)
Solver(const Solver &)=delete
static absl::StatusOr< std::unique_ptr< Solver > > New(SolverTypeProto solver_type, const ModelProto &model, const InitArgs &arguments)
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update)
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
std::atomic< int64_t > debug_num_solver
absl::Status ValidateInitArgs(const Solver::InitArgs &init_args, const SolverTypeProto solver_type)
absl::Status ValidateResult(const SolveResultProto &result, const ModelSolveParametersProto ¶meters, const ModelSummary &model_summary)
absl::Status ValidateModelUpdateAndSummary(const ModelUpdateProto &model_update, const ModelSummary &model_summary, const bool check_names)
absl::Status ValidateSolveParameters(const SolveParametersProto ¶meters)
absl::Status ValidateCallbackResultProto(const CallbackResultProto &callback_result, const CallbackEventProto callback_event, const CallbackRegistrationProto &callback_registration, const ModelSummary &model_summary)
absl::Status ValidateCallbackDataProto(const CallbackDataProto &cb_data, const CallbackRegistrationProto &callback_registration, const ModelSummary &model_summary)
absl::Status ValidateCallbackRegistration(const CallbackRegistrationProto &callback_registration, const ModelSummary &model_summary)
absl::Status ValidateModelSolveParameters(const ModelSolveParametersProto ¶meters, const ModelSummary &model_summary)
absl::Status ValidateModel(const ModelProto &model, const bool check_names)
Collection of objects used to extend the Constraint Solver library.
std::string ProtoEnumToString(ProtoEnumType enum_value)
virtual SolverTypeProto solver_type() const =0
CallbackRegistrationProto callback_registration
ModelSolveParametersProto model_parameters
MessageCallback message_callback
SolveInterrupter * interrupter
SolveParametersProto parameters
const NonStreamableSolverInitArguments * non_streamable