24 #include "absl/container/flat_hash_set.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/string_view.h"
28 #include "absl/types/span.h"
35 constexpr
double kInf = std::numeric_limits<double>::infinity();
38 absl::Status CheckSortedIdsSubsetWithIndexOffset(
39 const absl::Span<const int64_t> ids,
40 const absl::Span<const int64_t> universe,
const int64_t offset) {
42 int universe_index = 0;
45 while (id_index < ids.size() && universe_index < universe.size()) {
46 if (universe[universe_index] < ids[id_index]) {
48 }
else if (universe[universe_index] == ids[id_index]) {
54 if (id_index < ids.size()) {
55 return absl::InvalidArgumentError(
56 absl::StrCat(
"Bad id: ", ids[id_index],
57 " (at index: ", id_index + offset,
") found"));
59 return absl::OkStatus();
70 explicit FastIdCheck(
const absl::Span<const int64_t> ids) {
72 interval_mode_ =
true;
73 }
else if (ids.size() == ids.back() + 1 - ids.front()) {
74 interval_mode_ =
true;
75 interval_lb_ = ids.front();
76 interval_ub_ = ids.back() + 1;
78 ids_ = absl::flat_hash_set<int64_t>(ids.begin(), ids.end());
81 bool contains(int64_t
id)
const {
83 return id >= interval_lb_ &&
id < interval_ub_;
85 return ids_.contains(
id);
90 bool interval_mode_ =
false;
91 int64_t interval_lb_ = 0;
92 int64_t interval_ub_ = 0;
93 absl::flat_hash_set<int64_t> ids_;
99 absl::Status CheckSortedIdsNotBad(
const absl::Span<const int64_t> ids,
100 const absl::Span<const int64_t> bad_list) {
103 while (id_index < ids.size() && bad_index < bad_list.size()) {
104 if (bad_list[bad_index] < ids[id_index]) {
106 }
else if (bad_list[bad_index] > ids[id_index]) {
109 return absl::InvalidArgumentError(absl::StrCat(
110 "Bad id: ", ids[id_index],
" (at index: ", id_index,
") found."));
113 return absl::OkStatus();
118 absl::Span<const int64_t> ids) {
119 int64_t previous{-1};
120 for (
int i = 0; i < ids.size(); ++i) {
121 if (ids[i] <= previous) {
122 std::string error_base = absl::StrCat(
123 "Expected ids to be nonnegative and strictly increasing, but at "
125 i,
", found id: ", ids[i]);
127 return absl::InvalidArgumentError(
128 absl::StrCat(error_base,
" (a negative id)"));
130 return absl::InvalidArgumentError(absl::StrCat(
131 error_base,
" and at index ", i - 1,
" found id: ", ids[i - 1]));
136 return absl::OkStatus();
140 const absl::Span<const int64_t> universe) {
141 RETURN_IF_ERROR(CheckSortedIdsSubsetWithIndexOffset(ids, universe, 0));
142 return absl::OkStatus();
146 const absl::Span<const int64_t> universe) {
148 return absl::OkStatus();
150 const FastIdCheck id_check(universe);
151 for (
int i = 0; i < ids.size(); ++i) {
152 if (!id_check.contains(ids[i])) {
153 return absl::InvalidArgumentError(
154 absl::StrCat(
"Bad id: ", ids[i],
" (at index: ", i,
") not found."));
157 return absl::OkStatus();
161 for (
int i = 0; i < deleted_ids_.size(); ++i) {
162 const int64_t deleted_id = deleted_ids_[i];
163 if (!old_ids_.
HasId(deleted_id)) {
164 return absl::InvalidArgumentError(
165 absl::StrCat(
"Tried to delete id: ", deleted_id,
" (at index: ", i,
166 ") but it was not present."));
169 if (old_ids_.
Empty() || new_ids_.empty()) {
170 return absl::OkStatus();
172 if (old_ids_.
LargestId() >= new_ids_.front()) {
173 return absl::InvalidArgumentError(absl::StrCat(
174 "All old ids should be less than all new ids, but final old id was: ",
175 old_ids_.
LargestId(),
" and first new id was: ", new_ids_.front()));
177 return absl::OkStatus();
181 const absl::Span<const int64_t> ids)
const {
182 RETURN_IF_ERROR(CheckSortedIdsNotBad(ids, deleted_ids_)) <<
" was deleted";
183 for (
int i = 0; i < ids.size(); ++i) {
184 if (!old_ids_.
HasId(ids[i])) {
185 return absl::InvalidArgumentError(
186 absl::StrCat(
"Bad id: ", ids[i],
" (at index: ", i,
") not found."));
189 return absl::OkStatus();
193 const absl::Span<const int64_t> ids)
const {
198 size_t split_point = ids.size();
199 if (!new_ids_.empty()) {
205 RETURN_IF_ERROR(CheckSortedIdsSubsetWithIndexOffset(ids.subspan(split_point),
206 new_ids_, split_point));
207 return absl::OkStatus();
214 const absl::Span<const int64_t> ids)
const {
216 return absl::OkStatus();
218 const FastIdCheck deleted_fast(deleted_ids_);
219 const FastIdCheck new_fast(new_ids_);
220 for (
int i = 0; i < ids.size(); ++i) {
221 const int64_t
id = ids[i];
223 if (!old_ids_.
HasId(
id)) {
224 return absl::InvalidArgumentError(
225 absl::StrCat(
"Bad id: ",
id,
" (at index: ", i,
") not found."));
226 }
else if (deleted_fast.contains(
id)) {
227 return absl::InvalidArgumentError(
228 absl::StrCat(
"Bad id: ",
id,
" (at index: ", i,
") was deleted."));
230 }
else if (!new_fast.contains(
id)) {
231 return absl::InvalidArgumentError(
232 absl::StrCat(
"Bad id: ",
id,
" (at index: ", i,
") not found."));
235 return absl::OkStatus();
240 absl::string_view ids_description,
241 absl::string_view universe_description) {
242 for (
int i = 0; i < ids.size(); ++i) {
243 const int64_t
id = ids[i];
244 if (!universe.
HasId(
id)) {
245 return absl::InvalidArgumentError(
246 absl::StrCat(
"Id: ",
id,
" (at index: ", i,
") in ", ids_description,
247 " is missing from ", universe_description,
"."));
250 return absl::OkStatus();
255 absl::string_view first_description,
256 absl::string_view second_description) {
257 if (first_ids.size() != second_ids.
Size()) {
258 return absl::InvalidArgumentError(absl::StrCat(
259 first_description,
" has size ", first_ids.size(),
", but ",
260 second_description,
" has size ", second_ids.
Size(),
"."));
263 second_description));
264 return absl::OkStatus();
bool HasId(int64_t id) const
int64_t LargestId() const
absl::Status CheckSortedIdsSubsetOfFinal(const absl::Span< const int64_t > ids) const
absl::Status CheckIdsSubsetOfFinal(const absl::Span< const int64_t > ids) const
absl::Status CheckSortedIdsSubsetOfNotDeleted(const absl::Span< const int64_t > ids) const
absl::Status IsValid() const
absl::Status CheckUnsortedIdsSubset(const absl::Span< const int64_t > ids, const absl::Span< const int64_t > universe)
absl::Status CheckIdsNonnegativeAndStrictlyIncreasing(absl::Span< const int64_t > ids)
absl::Status CheckSortedIdsSubset(const absl::Span< const int64_t > ids, const absl::Span< const int64_t > universe)
absl::Status CheckIdsSubset(absl::Span< const int64_t > ids, const IdNameBiMap &universe, absl::string_view ids_description, absl::string_view universe_description)
absl::Status CheckIdsIdentical(absl::Span< const int64_t > first_ids, const IdNameBiMap &second_ids, absl::string_view first_description, absl::string_view second_description)
Collection of objects used to extend the Constraint Solver library.
#define RETURN_IF_ERROR(expr)