OR-Tools  9.6
model_summary.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <cstdint>
17 #include <initializer_list>
18 #include <limits>
19 #include <optional>
20 #include <string>
21 #include <utility>
22 
23 #include "absl/container/flat_hash_map.h"
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/string_view.h"
27 #include "absl/types/span.h"
28 #include "absl/log/check.h"
32 #include "ortools/math_opt/model.pb.h"
33 #include "ortools/math_opt/model_update.pb.h"
35 
36 namespace operations_research {
37 namespace math_opt {
38 
39 namespace internal {
40 
42  absl::Span<const int64_t> ids) {
43  int64_t previous{-1};
44  for (int i = 0; i < ids.size(); previous = ids[i], ++i) {
45  if (ids[i] < 0 || ids[i] == std::numeric_limits<int64_t>::max()) {
47  << "Expected ids to be nonnegative and not max(int64_t) but at "
48  "index "
49  << i << " found id: " << ids[i];
50  }
51  if (ids[i] <= previous) {
53  << "Expected ids to be strictly increasing, but at index " << i
54  << " found id: " << ids[i] << " and at previous index " << i - 1
55  << " found id: " << ids[i - 1];
56  }
57  }
58  return absl::OkStatus();
59 }
60 
61 } // namespace internal
62 
64  std::initializer_list<std::pair<int64_t, absl::string_view>> ids)
65  : IdNameBiMap(/*check_names=*/true) {
66  for (const auto& pair : ids) {
67  CHECK_OK(Insert(pair.first, std::string(pair.second)));
68  }
69 }
70 
71 IdNameBiMap::IdNameBiMap(const IdNameBiMap& other) { *this = other; }
72 
74  if (&other == this) {
75  return *this;
76  }
77  next_free_id_ = other.next_free_id_;
78  id_to_name_ = other.id_to_name_;
79  if (!other.nonempty_name_to_id_.has_value()) {
80  nonempty_name_to_id_ = std::nullopt;
81  } else {
82  nonempty_name_to_id_.emplace();
83  for (const auto& [id, name] : id_to_name_) {
84  if (!name.empty()) {
85  const auto [it, success] =
86  nonempty_name_to_id_->insert({absl::string_view(name), id});
87  CHECK(success); // CHECK is OK, other cannot have duplicate names and
88  // non nullopt nonempty_name_to_id_.
89  }
90  }
91  }
92 
93  return *this;
94 }
95 
97  absl::Span<const int64_t> deleted_ids, absl::Span<const int64_t> new_ids,
98  const absl::Span<const std::string* const> names) {
100  << "invalid deleted ids";
102  << "invalid new ids";
103  if (!names.empty() && names.size() != new_ids.size()) {
105  << "names had size " << names.size()
106  << " but should either be empty of have size matching new_ids which "
107  "has size "
108  << new_ids.size();
109  }
110  for (const int64_t id : deleted_ids) {
111  RETURN_IF_ERROR(Erase(id));
112  }
113  for (int i = 0; i < new_ids.size(); ++i) {
115  Insert(new_ids[i], names.empty() ? std::string{} : *names[i]));
116  }
117  return absl::OkStatus();
118 }
119 
120 ModelSummary::ModelSummary(const bool check_names)
121  : variables(check_names),
122  auxiliary_objectives(check_names),
123  linear_constraints(check_names),
124  quadratic_constraints(check_names),
125  sos1_constraints(check_names),
126  sos2_constraints(check_names),
127  indicator_constraints(check_names) {}
128 
129 absl::StatusOr<ModelSummary> ModelSummary::Create(const ModelProto& model,
130  const bool check_names) {
131  ModelSummary summary(check_names);
132  RETURN_IF_ERROR(summary.variables.BulkUpdate({}, model.variables().ids(),
133  model.variables().names()))
134  << "ModelProto.variables are invalid";
136  {}, model.auxiliary_objectives(), summary.auxiliary_objectives))
137  << "ModelProto.auxiliary_objectives are invalid";
138  {
139  const std::string& objective_name = model.objective().name();
140  if (summary.auxiliary_objectives.HasName(objective_name)) {
142  << "duplicate objective name: " << objective_name;
143  }
144  summary.primary_objective_name = objective_name;
145  }
147  {}, model.linear_constraints().ids(), model.linear_constraints().names()))
148  << "ModelProto.linear_constraints are invalid";
150  {}, model.quadratic_constraints(), summary.quadratic_constraints))
151  << "ModelProto.quadratic_constraints are invalid";
153  {}, model.sos1_constraints(), summary.sos1_constraints))
154  << "ModelProto.sos1_constraints are invalid";
156  {}, model.sos2_constraints(), summary.sos2_constraints))
157  << "ModelProto.sos2_constraints are invalid";
159  {}, model.indicator_constraints(), summary.indicator_constraints))
160  << "ModelProto.indicator_constraints are invalid";
161  return summary;
162 }
163 
164 absl::Status ModelSummary::Update(const ModelUpdateProto& model_update) {
165  RETURN_IF_ERROR(variables.BulkUpdate(model_update.deleted_variable_ids(),
166  model_update.new_variables().ids(),
167  model_update.new_variables().names()))
168  << "invalid variables";
170  model_update.auxiliary_objectives_updates().deleted_objective_ids(),
171  model_update.auxiliary_objectives_updates().new_objectives(),
173  << "invalid auxiliary objectives";
176  << "duplicate objective name: " << primary_objective_name;
177  }
179  model_update.deleted_linear_constraint_ids(),
180  model_update.new_linear_constraints().ids(),
181  model_update.new_linear_constraints().names()))
182  << "invalid linear constraints";
184  model_update.quadratic_constraint_updates().deleted_constraint_ids(),
185  model_update.quadratic_constraint_updates().new_constraints(),
187  << "invalid quadratic constraints";
189  model_update.sos1_constraint_updates().deleted_constraint_ids(),
190  model_update.sos1_constraint_updates().new_constraints(),
192  << "invalid sos1 constraints";
194  model_update.sos2_constraint_updates().deleted_constraint_ids(),
195  model_update.sos2_constraint_updates().new_constraints(),
197  << "invalid sos2 constraints";
199  model_update.indicator_constraint_updates().deleted_constraint_ids(),
200  model_update.indicator_constraint_updates().new_constraints(),
202  << "invalid indicator constraints";
203  return absl::OkStatus();
204 }
205 
206 } // namespace math_opt
207 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
#define RETURN_IF_ERROR(expr)
bool HasName(absl::string_view name) const
IdNameBiMap & operator=(const IdNameBiMap &other)
absl::Status BulkUpdate(absl::Span< const int64_t > deleted_ids, absl::Span< const int64_t > new_ids, absl::Span< const std::string *const > names)
absl::Status Insert(int64_t id, std::string name)
const std::string name
GRBmodel * model
absl::Status UpdateBiMapFromMappedData(const absl::Span< const int64_t > deleted_ids, const google::protobuf::Map< int64_t, DataProto > &proto_map, IdNameBiMap &bimap)
absl::Status CheckIdsRangeAndStrictlyIncreasing2(absl::Span< const int64_t > ids)
Collection of objects used to extend the Constraint Solver library.
StatusBuilder InvalidArgumentErrorBuilder()
absl::Status Update(const ModelUpdateProto &model_update)
static absl::StatusOr< ModelSummary > Create(const ModelProto &model, bool check_names=true)