OR-Tools  9.3
solve.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 <functional>
17#include <memory>
18#include <optional>
19#include <utility>
20
21#include "absl/container/flat_hash_set.h"
22#include "absl/memory/memory.h"
23#include "absl/status/statusor.h"
26#include "ortools/math_opt/callback.pb.h"
30
31namespace operations_research {
32namespace math_opt {
33
34namespace {
35
36Solver::InitArgs ToSolverInitArgs(const SolverInitArguments& arguments) {
37 Solver::InitArgs solver_init_args;
38 solver_init_args.streamable = arguments.streamable.Proto();
39 if (arguments.non_streamable != nullptr) {
40 solver_init_args.non_streamable = arguments.non_streamable.get();
41 }
42
43 return solver_init_args;
44}
45
46// Asserts (with CHECK) that the input pointer is either nullptr or that it
47// points to the same model storage as storage_.
48void CheckModelStorage(const ModelStorage* const storage,
49 const ModelStorage* const expected_storage) {
50 if (storage != nullptr) {
51 CHECK_EQ(storage, expected_storage)
53 }
54}
55
56absl::StatusOr<SolveResult> CallSolve(
57 Solver& solver, const ModelStorage* const expected_storage,
58 const SolveArguments& arguments) {
59 CheckModelStorage(/*storage=*/arguments.model_parameters.storage(),
60 /*expected_storage=*/expected_storage);
61 CheckModelStorage(/*storage=*/arguments.callback_registration.storage(),
62 /*expected_storage=*/expected_storage);
63
64 if (arguments.callback == nullptr) {
65 CHECK(arguments.callback_registration.events.empty())
66 << "No callback was provided to run, but callback events were "
67 "registered.";
68 }
69
70 Solver::Callback cb = nullptr;
71 if (arguments.callback != nullptr) {
72 cb = [&](const CallbackDataProto& callback_data_proto) {
73 const CallbackData data(expected_storage, callback_data_proto);
74 const CallbackResult result = arguments.callback(data);
75 CheckModelStorage(/*storage=*/result.storage(),
76 /*expected_storage=*/expected_storage);
77 return result.Proto();
78 };
79 }
81 SolveResultProto solve_result,
82 solver.Solve(
83 {.parameters = arguments.parameters.Proto(),
84 .model_parameters = arguments.model_parameters.Proto(),
85 .message_callback = arguments.message_callback,
86 .callback_registration = arguments.callback_registration.Proto(),
87 .user_cb = std::move(cb),
88 .interrupter = arguments.interrupter}));
89 return SolveResult::FromProto(expected_storage, solve_result);
90}
91
92} // namespace
93
94absl::StatusOr<SolveResult> Solve(const Model& model,
95 const SolverType solver_type,
96 const SolveArguments& solve_args,
97 const SolverInitArguments& init_args) {
98 ASSIGN_OR_RETURN(const std::unique_ptr<Solver> solver,
99 Solver::New(EnumToProto(solver_type), model.ExportModel(),
100 ToSolverInitArgs(init_args)));
101 return CallSolve(*solver, model.storage(), solve_args);
102}
103
104absl::StatusOr<std::unique_ptr<IncrementalSolver>> IncrementalSolver::New(
105 Model* const model, const SolverType solver_type,
106 SolverInitArguments arguments) {
107 if (model == nullptr) {
108 return absl::InvalidArgumentError("input model can't be null");
109 }
110 std::unique_ptr<UpdateTracker> update_tracker = model->NewUpdateTracker();
111 ASSIGN_OR_RETURN(const ModelProto model_proto, update_tracker->ExportModel());
112 ASSIGN_OR_RETURN(std::unique_ptr<Solver> solver,
113 Solver::New(EnumToProto(solver_type), model_proto,
114 ToSolverInitArgs(arguments)));
115 return absl::WrapUnique<IncrementalSolver>(
116 new IncrementalSolver(solver_type, std::move(arguments), model->storage(),
117 std::move(update_tracker), std::move(solver)));
118}
119
120IncrementalSolver::IncrementalSolver(
121 SolverType solver_type, SolverInitArguments init_args,
122 const ModelStorage* const expected_storage,
123 std::unique_ptr<UpdateTracker> update_tracker,
124 std::unique_ptr<Solver> solver)
125 : solver_type_(solver_type),
126 init_args_(std::move(init_args)),
127 expected_storage_(expected_storage),
128 update_tracker_(std::move(update_tracker)),
129 solver_(std::move(solver)) {}
130
131absl::StatusOr<SolveResult> IncrementalSolver::Solve(
132 const SolveArguments& arguments) {
134 return SolveWithoutUpdate(arguments);
135}
136
137absl::StatusOr<IncrementalSolver::UpdateResult> IncrementalSolver::Update() {
138 ASSIGN_OR_RETURN(std::optional<ModelUpdateProto> model_update,
139 update_tracker_->ExportModelUpdate());
140 if (!model_update) {
141 return UpdateResult(true, std::move(model_update));
142 }
143
144 ASSIGN_OR_RETURN(const bool did_update, solver_->Update(*model_update));
145 RETURN_IF_ERROR(update_tracker_->Checkpoint());
146
147 if (did_update) {
148 return UpdateResult(true, std::move(model_update));
149 }
150
151 ASSIGN_OR_RETURN(const ModelProto model_proto,
152 update_tracker_->ExportModel());
153 ASSIGN_OR_RETURN(solver_, Solver::New(EnumToProto(solver_type_), model_proto,
154 ToSolverInitArgs(init_args_)));
155
156 return UpdateResult(false, std::move(model_update));
157}
158
159absl::StatusOr<SolveResult> IncrementalSolver::SolveWithoutUpdate(
160 const SolveArguments& arguments) const {
161 return CallSolve(*solver_, expected_storage_, arguments);
162}
163
164} // namespace math_opt
165} // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:495
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
absl::StatusOr< SolveResult > Solve(const SolveArguments &arguments={})
Definition: solve.cc:131
absl::StatusOr< UpdateResult > Update()
Definition: solve.cc:137
absl::StatusOr< SolveResult > SolveWithoutUpdate(const SolveArguments &arguments={}) const
Definition: solve.cc:159
static absl::StatusOr< std::unique_ptr< IncrementalSolver > > New(Model *model, SolverType solver_type, SolverInitArguments arguments={})
Definition: solve.cc:104
SolverInterface::InitArgs InitArgs
Definition: solver.h:69
std::function< CallbackResultProto(const CallbackDataProto &)> Callback
Definition: solver.h:82
static absl::StatusOr< std::unique_ptr< Solver > > New(SolverTypeProto solver_type, const ModelProto &model, const InitArgs &arguments)
Definition: solver.cc:179
CpModelProto const * model_proto
absl::Status status
Definition: g_gurobi.cc:35
GRBmodel * model
constexpr absl::string_view kObjectsFromOtherModelStorage
Definition: key_types.h:56
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
Definition: solve.cc:94
Enum< E >::Proto EnumToProto(const std::optional< E > value)
Definition: enums.h:264
Collection of objects used to extend the Constraint Solver library.
STL namespace.
static SolveResult FromProto(const ModelStorage *model, const SolveResultProto &solve_result_proto)