00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef OR_TOOLS_UTIL_TUPLE_SET_H_
00034 #define OR_TOOLS_UTIL_TUPLE_SET_H_
00035
00036 #include "base/hash.h"
00037 #include <vector>
00038
00039 #include "base/integral_types.h"
00040 #include "base/logging.h"
00041 #include "base/macros.h"
00042 #include "base/map-util.h"
00043 #include "base/hash.h"
00044
00045 namespace operations_research {
00046
00047 class IntTupleSet {
00048 public:
00049
00050 explicit IntTupleSet(int arity);
00051
00052 IntTupleSet(const IntTupleSet& set);
00053 ~IntTupleSet();
00054
00055
00056 void Clear();
00057
00058
00059
00060
00061 void Insert(const std::vector<int>& tuple);
00062 void Insert(const std::vector<int64>& tuple);
00063
00064 void Insert2(int64 v0, int64 v1);
00065 void Insert3(int64 v0, int64 v1, int64 v2);
00066 void Insert4(int64 v0, int64 v1, int64 v2, int64 v3);
00067
00068 void InsertAll(const std::vector<std::vector<int64> >& tuples);
00069 void InsertAll(const std::vector<std::vector<int> >& tuples);
00070
00071
00072 bool Contains(const std::vector<int>& tuple);
00073 bool Contains(const std::vector<int64>& tuple);
00074
00075
00076 int NumTuples() const;
00077
00078 int64 Value(int tuple_index, int pos_in_tuple) const;
00079
00080 int Arity() const;
00081
00082 const int64* RawData() const;
00083
00084 private:
00085
00086
00087 class Data {
00088 public:
00089 explicit Data(int arity);
00090 Data(const Data& data);
00091 ~Data();
00092 void AddSharedOwner();
00093 bool RemovedSharedOwner();
00094 Data* CopyIfShared();
00095 template <class T> void Insert(const std::vector<T>& tuple);
00096 template <class T> bool Contains(const std::vector<T>& candidate);
00097 template <class T> int64 Fingerprint(const std::vector<T>& tuple);
00098 int NumTuples() const;
00099 int64 Value(int index, int pos) const;
00100 int Arity() const;
00101 const int64* RawData() const;
00102 void Clear();
00103
00104 private:
00105 const int arity_;
00106 int num_owners_;
00107
00108 std::vector<int64> flat_tuples_;
00109
00110
00111
00112 hash_map<int64, std::vector<int> > tuple_fprint_to_index_;
00113 };
00114
00115 mutable Data* data_;
00116 };
00117
00118
00119 inline IntTupleSet::Data::Data(int arity) : arity_(arity), num_owners_(0) {}
00120
00121 inline IntTupleSet::Data::Data(const Data& data)
00122 : arity_(data.arity_),
00123 num_owners_(0),
00124 flat_tuples_(data.flat_tuples_),
00125 tuple_fprint_to_index_(data.tuple_fprint_to_index_) {}
00126
00127 inline IntTupleSet::Data::~Data() {}
00128
00129 inline void IntTupleSet::Data::AddSharedOwner() {
00130 num_owners_++;
00131 }
00132
00133 inline bool IntTupleSet::Data::RemovedSharedOwner() {
00134 return (--num_owners_ == 0);
00135 }
00136
00137 inline IntTupleSet::Data* IntTupleSet::Data::CopyIfShared() {
00138 if (num_owners_ > 1) {
00139 Data* const new_data = new Data(*this);
00140 RemovedSharedOwner();
00141 new_data->AddSharedOwner();
00142 return new_data;
00143 }
00144 return this;
00145 }
00146
00147 template <class T> void IntTupleSet::Data::Insert(const std::vector<T>& tuple) {
00148 DCHECK(arity_ == 0 || flat_tuples_.size() % arity_ == 0);
00149 CHECK_EQ(arity_, tuple.size());
00150 DCHECK_EQ(1, num_owners_);
00151 if (!Contains(tuple)) {
00152 const int index = NumTuples();
00153 flat_tuples_.reserve(flat_tuples_.size() + arity_);
00154 for (int i = 0; i < arity_; ++i) {
00155 flat_tuples_.push_back(tuple[i]);
00156 }
00157 const int64 fingerprint = Fingerprint(tuple);
00158 tuple_fprint_to_index_[fingerprint].push_back(index);
00159 }
00160 }
00161
00162 template <class T> bool IntTupleSet::Data::Contains(
00163 const std::vector<T>& candidate) {
00164 if (candidate.size() != arity_) {
00165 return false;
00166 }
00167 const int64 fingerprint = Fingerprint(candidate);
00168 if (ContainsKey(tuple_fprint_to_index_, fingerprint)) {
00169 const std::vector<int>& indices = tuple_fprint_to_index_[fingerprint];
00170 for (int i = 0; i < indices.size(); ++i) {
00171 const int tuple_index = indices[i];
00172 for (int j = 0; j < arity_; ++j) {
00173 if (candidate[j] != flat_tuples_[tuple_index * arity_ + j]) {
00174 return false;
00175 }
00176 }
00177 return true;
00178 }
00179 }
00180 return false;
00181 }
00182
00183 template <class T> int64 IntTupleSet::Data::Fingerprint(
00184 const std::vector<T>& tuple) {
00185 switch (arity_) {
00186 case 0:
00187 return 0;
00188 case 1:
00189 return tuple[0];
00190 case 2: {
00191 uint64 x = tuple[0];
00192 uint64 y = GG_ULONGLONG(0xe08c1d668b756f82);
00193 uint64 z = tuple[1];
00194 mix(x, y, z);
00195 return z;
00196 }
00197 default: {
00198 uint64 x = tuple[0];
00199 uint64 y = GG_ULONGLONG(0xe08c1d668b756f82);
00200 for (int i = 1; i < tuple.size(); ++i) {
00201 uint64 z = tuple[i];
00202 mix(x, y, z);
00203 x = z;
00204 }
00205 return x;
00206 }
00207 }
00208 }
00209
00210 inline int IntTupleSet::Data::NumTuples() const {
00211 return tuple_fprint_to_index_.size();
00212 }
00213
00214 inline int64 IntTupleSet::Data::Value(int index, int pos) const {
00215 DCHECK_GE(index, 0);
00216 DCHECK_LT(index, flat_tuples_.size() / arity_);
00217 DCHECK_GE(pos, 0);
00218 DCHECK_LT(pos, arity_);
00219 return flat_tuples_[index * arity_ + pos];
00220 }
00221
00222 inline int IntTupleSet::Data::Arity() const { return arity_; }
00223
00224 inline const int64* IntTupleSet::Data::RawData() const {
00225 return flat_tuples_.data();
00226 }
00227
00228 inline void IntTupleSet::Data::Clear() {
00229 flat_tuples_.clear();
00230 tuple_fprint_to_index_.clear();
00231 }
00232
00233 inline IntTupleSet::IntTupleSet(int arity) : data_(new Data(arity)) {
00234 CHECK_GE(arity, 0);
00235 data_->AddSharedOwner();
00236 }
00237
00238 inline IntTupleSet::IntTupleSet(const IntTupleSet& set) : data_(set.data_) {
00239 data_->AddSharedOwner();
00240 }
00241
00242 inline IntTupleSet::~IntTupleSet() {
00243 CHECK_NOTNULL(data_);
00244 if (data_->RemovedSharedOwner()) {
00245 delete data_;
00246 }
00247 }
00248
00249 inline void IntTupleSet::Clear() {
00250 data_ = data_->CopyIfShared();
00251 data_->Clear();
00252 }
00253
00254 inline void IntTupleSet::Insert(const std::vector<int>& tuple) {
00255 data_ = data_->CopyIfShared();
00256 data_->Insert(tuple);
00257 }
00258
00259 inline void IntTupleSet::Insert2(int64 v0, int64 v1) {
00260 std::vector<int64> tuple(2);
00261 tuple[0] = v0;
00262 tuple[1] = v1;
00263 Insert(tuple);
00264 }
00265
00266 inline void IntTupleSet::Insert3(int64 v0, int64 v1, int64 v2) {
00267 std::vector<int64> tuple(3);
00268 tuple[0] = v0;
00269 tuple[1] = v1;
00270 tuple[2] = v2;
00271 Insert(tuple);
00272 }
00273
00274 inline void IntTupleSet::Insert4(int64 v0, int64 v1, int64 v2, int64 v3) {
00275 std::vector<int64> tuple(4);
00276 tuple[0] = v0;
00277 tuple[1] = v1;
00278 tuple[2] = v2;
00279 tuple[3] = v3;
00280 Insert(tuple);
00281 }
00282
00283 inline bool IntTupleSet::Contains(const std::vector<int>& tuple) {
00284 return data_->Contains(tuple);
00285 }
00286
00287 inline void IntTupleSet::Insert(const std::vector<int64>& tuple) {
00288 data_ = data_->CopyIfShared();
00289 data_->Insert(tuple);
00290 }
00291
00292 inline void IntTupleSet::InsertAll(const std::vector<std::vector<int64> >& tuples) {
00293 data_ = data_->CopyIfShared();
00294 for (int i = 0; i < tuples.size(); ++i) {
00295 Insert(tuples[i]);
00296 }
00297 }
00298
00299 inline void IntTupleSet::InsertAll(const std::vector<std::vector<int> >& tuples) {
00300 data_ = data_->CopyIfShared();
00301 for (int i = 0; i < tuples.size(); ++i) {
00302 Insert(tuples[i]);
00303 }
00304 }
00305
00306 inline bool IntTupleSet::Contains(const std::vector<int64>& tuple) {
00307 return data_->Contains(tuple);
00308 }
00309
00310 inline int IntTupleSet::NumTuples() const {
00311 return data_->NumTuples();
00312 }
00313
00314 inline int64 IntTupleSet::Value(int index, int pos) const {
00315 return data_->Value(index, pos);
00316 }
00317
00318 inline int IntTupleSet::Arity() const {
00319 return data_->Arity();
00320 }
00321
00322 inline const int64* IntTupleSet::RawData() const {
00323 return data_->RawData();
00324 }
00325 }
00326
00327 #endif // OR_TOOLS_UTIL_TUPLE_SET_H_