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"
63 int Insert(
const std::vector<int>& tuple);
64 int Insert(
const std::vector<int64_t>& tuple);
66 int Insert2(int64_t v0, int64_t v1);
67 int Insert3(int64_t v0, int64_t v1, int64_t v2);
68 int Insert4(int64_t v0, int64_t v1, int64_t v2, int64_t v3);
70 void InsertAll(
const std::vector<std::vector<int64_t> >& tuples);
71 void InsertAll(
const std::vector<std::vector<int> >& tuples);
74 bool Contains(
const std::vector<int>& tuple)
const;
75 bool Contains(
const std::vector<int64_t>& tuple)
const;
82 int64_t
Value(
int tuple_index,
int pos_in_tuple)
const;
100 explicit Data(
int arity);
101 Data(
const Data& data);
103 void AddSharedOwner();
104 bool RemovedSharedOwner();
105 Data* CopyIfShared();
107 int Insert(
const std::vector<T>& tuple);
109 bool Contains(
const std::vector<T>& candidate)
const;
111 int64_t Fingerprint(
const std::vector<T>& tuple)
const;
115 const int64_t*
RawData()
const;
122 std::vector<int64_t> flat_tuples_;
126 absl::flat_hash_map<int64_t, std::vector<int> > tuple_fprint_to_index_;
132 IntTupleSet::Data* data;
133 IndexData(
int i, IntTupleSet::Data*
const d) :
index(i), data(d) {}
134 static bool Compare(
const IndexData&
a,
const IndexData&
b);
140 IndexValue(
int i, int64_t v) :
index(i),
value(v) {}
141 static bool Compare(
const IndexValue&
a,
const IndexValue&
b);
148 inline IntTupleSet::Data::Data(
int arity) :
arity_(arity), num_owners_(0) {}
150 inline IntTupleSet::Data::Data(
const Data& data)
153 flat_tuples_(data.flat_tuples_),
154 tuple_fprint_to_index_(data.tuple_fprint_to_index_) {}
156 inline IntTupleSet::Data::~Data() {}
158 inline void IntTupleSet::Data::AddSharedOwner() { num_owners_++; }
160 inline bool IntTupleSet::Data::RemovedSharedOwner() {
161 return (--num_owners_ == 0);
164 inline IntTupleSet::Data* IntTupleSet::Data::CopyIfShared() {
165 if (num_owners_ > 1) {
166 Data*
const new_data =
new Data(*
this);
167 RemovedSharedOwner();
168 new_data->AddSharedOwner();
175 int IntTupleSet::Data::Insert(
const std::vector<T>& tuple) {
176 DCHECK(
arity_ == 0 || flat_tuples_.size() %
arity_ == 0);
177 CHECK_EQ(
arity_, tuple.size());
178 DCHECK_EQ(1, num_owners_);
179 if (!Contains(tuple)) {
180 const int index = NumTuples();
181 const int offset = flat_tuples_.size();
182 flat_tuples_.resize(offset +
arity_);
184 for (
int i = 0; i <
arity_; ++i) {
185 flat_tuples_[offset + i] = tuple[i];
187 const int64_t fingerprint = Fingerprint(tuple);
188 tuple_fprint_to_index_[fingerprint].push_back(
index);
196 bool IntTupleSet::Data::Contains(
const std::vector<T>& candidate)
const {
197 if (candidate.size() !=
arity_) {
200 const int64_t fingerprint = Fingerprint(candidate);
201 if (tuple_fprint_to_index_.contains(fingerprint)) {
202 const std::vector<int>& indices = tuple_fprint_to_index_.at(fingerprint);
203 for (
int i = 0; i < indices.size(); ++i) {
204 const int tuple_index = indices[i];
205 for (
int j = 0; j <
arity_; ++j) {
206 if (candidate[j] != flat_tuples_[tuple_index *
arity_ + j]) {
217 int64_t IntTupleSet::Data::Fingerprint(
const std::vector<T>& tuple)
const {
224 uint64_t x = tuple[0];
225 uint64_t y = uint64_t{0xe08c1d668b756f82};
226 uint64_t z = tuple[1];
231 uint64_t x = tuple[0];
232 uint64_t y = uint64_t{0xe08c1d668b756f82};
233 for (
int i = 1; i < tuple.size(); ++i) {
234 uint64_t z = tuple[i];
243 inline int IntTupleSet::Data::NumTuples()
const {
244 return tuple_fprint_to_index_.size();
255 inline int IntTupleSet::Data::Arity()
const {
return arity_; }
257 inline const int64_t* IntTupleSet::Data::RawData()
const {
258 return flat_tuples_.data();
261 inline void IntTupleSet::Data::Clear() {
262 flat_tuples_.clear();
263 tuple_fprint_to_index_.clear();
268 data_->AddSharedOwner();
272 data_->AddSharedOwner();
276 CHECK(data_ !=
nullptr);
277 if (data_->RemovedSharedOwner()) {
283 data_ = data_->CopyIfShared();
288 data_ = data_->CopyIfShared();
289 return data_->Insert(tuple);
293 data_ = data_->CopyIfShared();
294 return data_->Insert(tuple);
298 std::vector<int64_t> tuple(2);
305 std::vector<int64_t> tuple(3);
314 std::vector<int64_t> tuple(4);
323 return data_->Contains(tuple);
327 return data_->Contains(tuple);
331 const std::vector<std::vector<int> >& tuples) {
332 data_ = data_->CopyIfShared();
333 for (
int i = 0; i < tuples.size(); ++i) {
339 const std::vector<std::vector<int64_t> >& tuples) {
340 data_ = data_->CopyIfShared();
341 for (
int i = 0; i < tuples.size(); ++i) {
349 return data_->Value(
index, pos);
357 if (col < 0 || col >= data_->Arity()) {
360 absl::flat_hash_set<int64_t> values;
361 for (
int i = 0; i < data_->NumTuples(); ++i) {
362 values.insert(data_->Value(i,
col));
364 return values.size();
367 inline bool IntTupleSet::IndexValue::Compare(
const IndexValue&
a,
368 const IndexValue&
b) {
369 return a.value <
b.value || (
a.value ==
b.value &&
a.index <
b.index);
373 std::vector<IndexValue> keys;
374 keys.reserve(data_->NumTuples());
378 std::sort(keys.begin(), keys.end(), IntTupleSet::IndexValue::Compare);
379 const int arity = data_->Arity();
381 for (
int i = 0; i < keys.size(); ++i) {
382 const int64_t* tuple_ptr = data_->RawData() + keys[i].index * arity;
383 sorted.
Insert(std::vector<int64_t>(tuple_ptr, tuple_ptr + arity));
388 inline bool IntTupleSet::IndexData::Compare(
const IndexData&
a,
389 const IndexData&
b) {
390 const IntTupleSet::Data*
const data =
a.data;
391 const int arity = data->Arity();
392 for (
int i = 0; i < arity; ++i) {
393 const int64_t value1 = data->Value(
a.index, i);
394 const int64_t value2 = data->Value(
b.index, i);
395 if (value1 < value2) {
398 if (value1 > value2) {
406 std::vector<IndexData> keys;
407 keys.reserve(data_->NumTuples());
409 keys.push_back(IndexData(
index, data_));
411 std::sort(keys.begin(), keys.end(), IntTupleSet::IndexData::Compare);
412 const int arity = data_->Arity();
414 for (
int i = 0; i < keys.size(); ++i) {
415 std::vector<int64_t> tuple(arity);
416 const int64_t* tuple_ptr = data_->RawData() + keys[i].index * arity;
417 sorted.
Insert(std::vector<int64_t>(tuple_ptr, tuple_ptr + arity));
int Insert4(int64_t v0, int64_t v1, int64_t v2, int64_t v3)
IntTupleSet SortedLexicographically() const
int Insert2(int64_t v0, int64_t v1)
IntTupleSet SortedByColumn(int col) const
void InsertAll(const std::vector< std::vector< int64_t > > &tuples)
int64_t Value(int tuple_index, int pos_in_tuple) const
bool Contains(const std::vector< int > &tuple) const
int Insert(const std::vector< int > &tuple)
int NumDifferentValuesInColumn(int col) const
const int64_t * RawData() const
int Insert3(int64_t v0, int64_t v1, int64_t v2)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Collection of objects used to extend the Constraint Solver library.
static void mix(uint64_t &a, uint64_t &b, uint64_t &c)