33 #ifndef OR_TOOLS_UTIL_TUPLE_SET_H_
34 #define OR_TOOLS_UTIL_TUPLE_SET_H_
39 #include "absl/container/flat_hash_map.h"
40 #include "absl/container/flat_hash_set.h"
64 int Insert(
const std::vector<int>& tuple);
65 int Insert(
const std::vector<int64>& tuple);
71 void InsertAll(
const std::vector<std::vector<int64> >& tuples);
72 void InsertAll(
const std::vector<std::vector<int> >& tuples);
75 bool Contains(
const std::vector<int>& tuple)
const;
76 bool Contains(
const std::vector<int64>& tuple)
const;
83 int64 Value(
int tuple_index,
int pos_in_tuple)
const;
101 explicit Data(
int arity);
102 Data(
const Data& data);
104 void AddSharedOwner();
105 bool RemovedSharedOwner();
106 Data* CopyIfShared();
108 int Insert(
const std::vector<T>& tuple);
110 bool Contains(
const std::vector<T>& candidate)
const;
112 int64 Fingerprint(
const std::vector<T>& tuple)
const;
123 std::vector<int64> flat_tuples_;
127 absl::flat_hash_map<int64, std::vector<int> > tuple_fprint_to_index_;
133 IntTupleSet::Data* data;
134 IndexData(
int i, IntTupleSet::Data*
const d) :
index(i), data(d) {}
135 static bool Compare(
const IndexData&
a,
const IndexData&
b);
142 static bool Compare(
const IndexValue&
a,
const IndexValue&
b);
149 inline IntTupleSet::Data::Data(
int arity) :
arity_(arity), num_owners_(0) {}
151 inline IntTupleSet::Data::Data(
const Data& data)
154 flat_tuples_(data.flat_tuples_),
155 tuple_fprint_to_index_(data.tuple_fprint_to_index_) {}
157 inline IntTupleSet::Data::~Data() {}
159 inline void IntTupleSet::Data::AddSharedOwner() { num_owners_++; }
161 inline bool IntTupleSet::Data::RemovedSharedOwner() {
162 return (--num_owners_ == 0);
165 inline IntTupleSet::Data* IntTupleSet::Data::CopyIfShared() {
166 if (num_owners_ > 1) {
167 Data*
const new_data =
new Data(*
this);
168 RemovedSharedOwner();
169 new_data->AddSharedOwner();
176 int IntTupleSet::Data::Insert(
const std::vector<T>& tuple) {
180 if (!Contains(tuple)) {
181 const int index = NumTuples();
182 const int offset = flat_tuples_.size();
183 flat_tuples_.resize(offset +
arity_);
185 for (
int i = 0; i <
arity_; ++i) {
186 flat_tuples_[offset + i] = tuple[i];
188 const int64 fingerprint = Fingerprint(tuple);
189 tuple_fprint_to_index_[fingerprint].push_back(
index);
197 bool IntTupleSet::Data::Contains(
const std::vector<T>& candidate)
const {
198 if (candidate.size() !=
arity_) {
201 const int64 fingerprint = Fingerprint(candidate);
203 const std::vector<int>& indices =
205 for (
int i = 0; i < indices.size(); ++i) {
206 const int tuple_index = indices[i];
207 for (
int j = 0; j <
arity_; ++j) {
208 if (candidate[j] != flat_tuples_[tuple_index *
arity_ + j]) {
219 int64 IntTupleSet::Data::Fingerprint(
const std::vector<T>& tuple)
const {
235 for (
int i = 1; i < tuple.size(); ++i) {
245 inline int IntTupleSet::Data::NumTuples()
const {
246 return tuple_fprint_to_index_.size();
257 inline int IntTupleSet::Data::Arity()
const {
return arity_; }
259 inline const int64* IntTupleSet::Data::RawData()
const {
260 return flat_tuples_.data();
263 inline void IntTupleSet::Data::Clear() {
264 flat_tuples_.clear();
265 tuple_fprint_to_index_.clear();
270 data_->AddSharedOwner();
274 data_->AddSharedOwner();
278 CHECK(data_ !=
nullptr);
279 if (data_->RemovedSharedOwner()) {
285 data_ = data_->CopyIfShared();
290 data_ = data_->CopyIfShared();
291 return data_->Insert(tuple);
295 data_ = data_->CopyIfShared();
296 return data_->Insert(tuple);
300 std::vector<int64> tuple(2);
307 std::vector<int64> tuple(3);
315 std::vector<int64> tuple(4);
324 return data_->Contains(tuple);
328 return data_->Contains(tuple);
332 const std::vector<std::vector<int> >& tuples) {
333 data_ = data_->CopyIfShared();
334 for (
int i = 0; i < tuples.size(); ++i) {
340 const std::vector<std::vector<int64> >& tuples) {
341 data_ = data_->CopyIfShared();
342 for (
int i = 0; i < tuples.size(); ++i) {
350 return data_->Value(
index, pos);
358 if (col < 0 || col >= data_->Arity()) {
361 absl::flat_hash_set<int64> values;
362 for (
int i = 0; i < data_->NumTuples(); ++i) {
363 values.insert(data_->Value(i,
col));
365 return values.size();
368 inline bool IntTupleSet::IndexValue::Compare(
const IndexValue&
a,
369 const IndexValue&
b) {
370 return a.value <
b.value || (
a.value ==
b.value &&
a.index <
b.index);
374 std::vector<IndexValue> keys;
375 keys.reserve(data_->NumTuples());
379 std::sort(keys.begin(), keys.end(), IntTupleSet::IndexValue::Compare);
380 const int arity = data_->Arity();
382 for (
int i = 0; i < keys.size(); ++i) {
383 const int64* tuple_ptr = data_->RawData() + keys[i].index * arity;
384 sorted.
Insert(std::vector<int64>(tuple_ptr, tuple_ptr + arity));
389 inline bool IntTupleSet::IndexData::Compare(
const IndexData&
a,
390 const IndexData&
b) {
391 const IntTupleSet::Data*
const data =
a.data;
392 const int arity = data->Arity();
393 for (
int i = 0; i < arity; ++i) {
394 const int64 value1 = data->Value(
a.index, i);
395 const int64 value2 = data->Value(
b.index, i);
396 if (value1 < value2) {
399 if (value1 > value2) {
407 std::vector<IndexData> keys;
408 keys.reserve(data_->NumTuples());
410 keys.push_back(IndexData(
index, data_));
412 std::sort(keys.begin(), keys.end(), IntTupleSet::IndexData::Compare);
413 const int arity = data_->Arity();
415 for (
int i = 0; i < keys.size(); ++i) {
416 std::vector<int64> tuple(arity);
417 const int64* tuple_ptr = data_->RawData() + keys[i].index * arity;
418 sorted.
Insert(std::vector<int64>(tuple_ptr, tuple_ptr + arity));
424 #endif // OR_TOOLS_UTIL_TUPLE_SET_H_