OR-Tools  9.2
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 
22 #include "ortools/base/logging.h"
23 #include "absl/container/flat_hash_set.h"
24 #include "absl/status/statusor.h"
25 #include "absl/strings/string_view.h"
26 #include "ortools/base/int_type.h"
27 #include "ortools/math_opt/callback.pb.h"
31 #include "ortools/math_opt/model_update.pb.h"
33 
34 namespace operations_research {
35 namespace math_opt {
36 
37 absl::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 
112 std::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 
121 std::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 
130 std::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 
139 std::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 
148 std::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 
157 ModelProto MathOpt::ExportModel() const { return model_->ExportModel(); }
158 
159 void 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:495
constexpr absl::string_view kObjectsFromOtherIndexedModel
Definition: key_types.h:56
std::vector< LinearConstraint > ColumnNonzeros(Variable variable)
Definition: math_opt.cc:130
std::vector< Variable > SortedVariables()
Definition: math_opt.cc:121
LinearConstraint AddLinearConstraint(absl::string_view name="")
Definition: math_opt.h:348
const absl::flat_hash_map< VariableId, double > & raw_terms() const
const std::string name
MPCallback * callback
GRBmodel * model
int64_t coef
Definition: expr_array.cc:1875
absl::flat_hash_set< CallbackEventProto > events
Definition: callback.h:138
std::function< CallbackResult(CallbackData)> Callback
Definition: math_opt.h:139
static absl::StatusOr< std::unique_ptr< Solver > > New(SolverType solver_type, const ModelProto &model, const SolverInitializerProto &initializer)
Definition: solver.cc:101
std::vector< Variable > Variables()
Definition: math_opt.cc:112
CallbackRegistrationProto Proto() const
Definition: callback.cc:98
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:702
std::function< CallbackResultProto(const CallbackDataProto &)> Callback
Definition: solver.h:61
std::vector< LinearConstraint > SortedLinearConstraints()
Definition: math_opt.cc:148
Collection of objects used to extend the Constraint Solver library.
absl::StatusOr< Result > Solve(const SolveParametersProto &solver_parameters, const ModelSolveParameters &model_parameters={}, const CallbackRegistration &callback_registration={}, Callback callback=nullptr)
Definition: math_opt.cc:37
const std::string & name() const
Definition: math_opt.h:305
std::vector< LinearConstraint > LinearConstraints()
Definition: math_opt.cc:139
#define ASSIGN_OR_RETURN(lhs, rexpr)
Definition: status_macros.h:55