14#ifndef OR_TOOLS_MATH_OPT_CORE_MODEL_SUMMARY_H_
15#define OR_TOOLS_MATH_OPT_CORE_MODEL_SUMMARY_H_
18#include <initializer_list>
26#include "absl/algorithm/container.h"
27#include "absl/container/flat_hash_map.h"
28#include "absl/log/check.h"
29#include "absl/status/status.h"
30#include "absl/status/statusor.h"
31#include "absl/strings/string_view.h"
32#include "absl/types/span.h"
35#include "ortools/math_opt/model.pb.h"
36#include "ortools/math_opt/model_update.pb.h"
55 : nonempty_name_to_id_(
56 check_names ?
std::make_optional<
57 absl::flat_hash_map<
absl::string_view, int64_t>>()
70 IdNameBiMap(std::initializer_list<std::pair<int64_t, absl::string_view>> ids);
81 inline absl::Status
Insert(int64_t
id, std::string
name);
84 inline absl::Status
Erase(int64_t
id);
86 inline bool HasId(int64_t
id)
const;
90 inline bool Empty()
const;
91 inline int Size()
const;
107 const std::optional<absl::flat_hash_map<absl::string_view, int64_t>>&
109 return nonempty_name_to_id_;
113 absl::Status
BulkUpdate(absl::Span<const int64_t> deleted_ids,
114 absl::Span<const int64_t> new_ids,
115 absl::Span<const std::string* const> names);
119 int64_t next_free_id_ = 0;
124 std::optional<absl::flat_hash_map<absl::string_view, int64_t>>
125 nonempty_name_to_id_;
130 static absl::StatusOr<ModelSummary>
Create(
const ModelProto&
model,
131 bool check_names =
true);
132 absl::Status
Update(
const ModelUpdateProto& model_update);
151 if (
id < next_free_id_) {
153 <<
"expected id=" <<
id
154 <<
" to be at least next_free_id_=" << next_free_id_
155 <<
" (ids should be nonnegative and inserted in strictly increasing "
158 if (
id == std::numeric_limits<int64_t>::max()) {
159 return absl::InvalidArgumentError(
"id of max(int64_t) is not allowed");
161 next_free_id_ =
id + 1;
163 const auto [it, success] = id_to_name_.
emplace(
id, std::move(
name));
166 const absl::string_view name_view(it->second);
167 if (nonempty_name_to_id_.has_value() && !name_view.empty()) {
168 const auto [it, success] = nonempty_name_to_id_->insert({name_view,
id});
171 <<
"duplicate name inserted: " << name_view;
174 return absl::OkStatus();
178 const auto it = id_to_name_.
find(
id);
179 if (it == id_to_name_.
end()) {
181 <<
"cannot delete missing id " << id;
183 const absl::string_view name_view(it->second);
184 if (nonempty_name_to_id_.has_value() && !name_view.empty()) {
187 CHECK_EQ(nonempty_name_to_id_->erase(name_view), 1)
188 <<
"name: " << name_view <<
" id: " << id;
190 id_to_name_.
erase(it);
191 return absl::OkStatus();
201 if (!nonempty_name_to_id_.has_value()) {
204 return nonempty_name_to_id_->contains(
name);
215 const int64_t largest_id = id_to_name_.
back().first;
216 if (new_next_free_id <= largest_id) {
218 <<
"new_next_free_id=" << new_next_free_id
219 <<
" must be greater than largest_id=" << largest_id;
222 if (new_next_free_id < 0) {
224 <<
"new_next_free_id=" << new_next_free_id
225 <<
" must be nonnegative";
228 next_free_id_ = new_next_free_id;
229 return absl::OkStatus();
242template <
typename DataProto>
244 const absl::Span<const int64_t> deleted_ids,
245 const google::protobuf::Map<int64_t, DataProto>& proto_map,
248 <<
"invalid deleted ids";
249 for (
const int64_t
id : deleted_ids) {
252 std::vector<int64_t> new_ids;
253 new_ids.reserve(proto_map.size());
254 for (
const auto& [
id,
value] : proto_map) {
255 new_ids.push_back(
id);
257 absl::c_sort(new_ids);
258 for (
const int64_t
id : new_ids) {
261 return absl::OkStatus();
#define RETURN_IF_ERROR(expr)
bool contains(const key_arg< K > &key) const
iterator find(const key_arg< K > &key)
size_type erase(const key_arg< K > &key)
size_type size() const
Derive size_ from set_, as list::size might be O(N).
std::pair< iterator, bool > emplace(Args &&... args)
absl::Status Erase(int64_t id)
Removes the given id, or returns an error if id is not present.
const std::optional< absl::flat_hash_map< absl::string_view, int64_t > > & nonempty_name_to_id() const
Is std::nullopt if check_names was false at construction.
absl::Status SetNextFreeId(int64_t new_next_free_id)
const gtl::linked_hash_map< int64_t, std::string > & id_to_name() const
Iteration order is in increasing id order.
IdNameBiMap(bool check_names=true)
IdNameBiMap & operator=(IdNameBiMap &&other)=default
bool HasName(absl::string_view name) const
Will always return false if name is empty or if check_names was false.
bool HasId(int64_t id) 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)
int64_t next_free_id() const
IdNameBiMap(IdNameBiMap &&other)=default
absl::Status Insert(int64_t id, std::string name)
const std::string name
A name for logging purposes.
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)
In SWIG mode, we don't want anything besides these top-level includes.
StatusBuilder InvalidArgumentErrorBuilder()
ModelSummary(bool check_names=true)
absl::Status Update(const ModelUpdateProto &model_update)
IdNameBiMap sos2_constraints
IdNameBiMap second_order_cone_constraints
IdNameBiMap linear_constraints
IdNameBiMap sos1_constraints
IdNameBiMap quadratic_constraints
IdNameBiMap auxiliary_objectives
IdNameBiMap indicator_constraints
static absl::StatusOr< ModelSummary > Create(const ModelProto &model, bool check_names=true)
std::string primary_objective_name