OR-Tools  9.1
math_opt.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 <algorithm>
17#include <functional>
18#include <memory>
19#include <utility>
20#include <vector>
21
23#include "absl/container/flat_hash_set.h"
24#include "absl/status/statusor.h"
25#include "absl/strings/string_view.h"
27#include "ortools/math_opt/callback.pb.h"
31#include "ortools/math_opt/model_update.pb.h"
33
34namespace operations_research {
35namespace math_opt {
36
37absl::StatusOr<Result> MathOpt::Solve(
38 const SolveParametersProto& solver_parameters,
39 const ModelSolveParameters& model_parameters,
40 const CallbackRegistration& callback_registration, Callback callback) {
41 CheckModel(model_parameters.model());
42 CheckModel(callback_registration.model());
43 if (callback == nullptr) {
44 CHECK(callback_registration.events.empty())
45 << "No callback was provided to run, but callback events were "
46 "registered.";
47 }
48
49 bool attempted_incremental_solve = false;
50 if (solver_ != nullptr) {
51 const absl::optional<ModelUpdateProto> model_update =
52 update_tracker_->ExportModelUpdate();
53 bool did_update = false;
54 if (model_update == absl::nullopt) {
55 did_update = true;
56 } else {
57 ASSIGN_OR_RETURN(did_update, solver_->Update(*model_update));
58 update_tracker_->Checkpoint();
59 }
60 if (did_update) {
61 attempted_incremental_solve = true;
62 } else {
63 solver_ = nullptr;
64 // Note that we could keep the same tracker but it is simpler to have both
65 // solver_ and update_tracker_ synchronized. This removes the need for an
66 // extra branch below where we would have solver_ == nullptr but
67 // update_tracker_ != nullptr.
68 //
69 // This code will be removed when b/185769575 is addressed since we won't
70 // have a use-case where solver_ == nullptr anymore (the class that will
71 // represent an incremental solve will always have a solver by
72 // construction).
73 update_tracker_ = nullptr;
74 }
75 }
76 if (solver_ == nullptr) {
77 update_tracker_ = model_->NewUpdateTracker();
78 ASSIGN_OR_RETURN(solver_, Solver::New(solver_type_, model_->ExportModel(),
79 solver_initializer_));
80 }
81
82 Solver::Callback cb = nullptr;
83 if (callback != nullptr) {
84 cb = [&](const CallbackDataProto& callback_data_proto) {
85 const CallbackData data(model_.get(), callback_data_proto);
86 const CallbackResult result = callback(data);
87 CheckModel(result.model());
88 return result.Proto();
89 };
90 }
91 ASSIGN_OR_RETURN(const SolveResultProto solve_result,
92 solver_->Solve(solver_parameters, model_parameters.Proto(),
93 callback_registration.Proto(), cb));
94 Result result(model_.get(), solve_result);
95 result.attempted_incremental_solve = attempted_incremental_solve;
96 return result;
97}
98
100 const BoundedLinearExpression& bounded_expr, absl::string_view name) {
101 CheckModel(bounded_expr.expression.model());
102
103 const LinearConstraintId constraint = model_->AddLinearConstraint(
104 bounded_expr.lower_bound_minus_offset(),
105 bounded_expr.upper_bound_minus_offset(), name);
106 for (auto [variable, coef] : bounded_expr.expression.raw_terms()) {
107 model_->set_linear_constraint_coefficient(constraint, variable, coef);
108 }
109 return LinearConstraint(model_.get(), constraint);
110}
111
112std::vector<Variable> MathOpt::Variables() {
113 std::vector<Variable> result;
114 result.reserve(model_->num_variables());
115 for (const VariableId var_id : model_->variables()) {
116 result.push_back(Variable(model_.get(), var_id));
117 }
118 return result;
119}
120
121std::vector<Variable> MathOpt::SortedVariables() {
122 std::vector<Variable> result = Variables();
123 std::sort(result.begin(), result.end(),
124 [](const Variable& l, const Variable& r) {
125 return l.typed_id() < r.typed_id();
126 });
127 return result;
128}
129
130std::vector<LinearConstraint> MathOpt::ColumnNonzeros(const Variable variable) {
131 std::vector<LinearConstraint> result;
132 for (const LinearConstraintId constraint :
133 model_->linear_constraints_with_variable(variable.typed_id())) {
134 result.push_back(LinearConstraint(model_.get(), constraint));
135 }
136 return result;
137}
138
139std::vector<LinearConstraint> MathOpt::LinearConstraints() {
140 std::vector<LinearConstraint> result;
141 result.reserve(model_->num_linear_constraints());
142 for (const LinearConstraintId lin_con_id : model_->linear_constraints()) {
143 result.push_back(LinearConstraint(model_.get(), lin_con_id));
144 }
145 return result;
146}
147
148std::vector<LinearConstraint> MathOpt::SortedLinearConstraints() {
149 std::vector<LinearConstraint> result = LinearConstraints();
150 std::sort(result.begin(), result.end(),
151 [](const LinearConstraint& l, const LinearConstraint& r) {
152 return l.typed_id() < r.typed_id();
153 });
154 return result;
155}
156
157ModelProto MathOpt::ExportModel() const { return model_->ExportModel(); }
158
159void MathOpt::CheckModel(IndexedModel* model) {
160 if (model != nullptr) {
162 }
163}
164
165} // namespace math_opt
166} // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:491
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
const absl::flat_hash_map< VariableId, double > & raw_terms() const
std::function< CallbackResult(CallbackData)> Callback
Definition: math_opt.h:139
const std::string & name() const
Definition: math_opt.h:305
LinearConstraint AddLinearConstraint(absl::string_view name="")
Definition: math_opt.h:348
std::vector< Variable > Variables()
Definition: math_opt.cc:112
std::vector< LinearConstraint > ColumnNonzeros(Variable variable)
Definition: math_opt.cc:130
absl::StatusOr< Result > Solve(const SolveParametersProto &solver_parameters, const ModelSolveParameters &model_parameters={}, const CallbackRegistration &callback_registration={}, Callback callback=nullptr)
Definition: math_opt.cc:37
std::vector< LinearConstraint > LinearConstraints()
Definition: math_opt.cc:139
std::vector< LinearConstraint > SortedLinearConstraints()
Definition: math_opt.cc:148
std::vector< Variable > SortedVariables()
Definition: math_opt.cc:121
std::function< CallbackResultProto(const CallbackDataProto &)> Callback
Definition: solver.h:61
static absl::StatusOr< std::unique_ptr< Solver > > New(SolverType solver_type, const ModelProto &model, const SolverInitializerProto &initializer)
Definition: solver.cc:101
const std::string name
int64_t coef
Definition: expr_array.cc:1875
GRBmodel * model
MPCallback * callback
constexpr absl::string_view kObjectsFromOtherIndexedModel
Definition: key_types.h:56
Collection of objects used to extend the Constraint Solver library.
#define ASSIGN_OR_RETURN(lhs, rexpr)
Definition: status_macros.h:55
CallbackRegistrationProto Proto() const
Definition: callback.cc:98
absl::flat_hash_set< CallbackEventProto > events
Definition: callback.h:138
CallbackResultProto Proto() const
Definition: callback.cc:120