MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
string.hpp
1#ifndef MPQC_CI_STRING_HPP
2#define MPQC_CI_STRING_HPP
3
4#include "mpqc/range.hpp"
5
6#include <bitset>
7#include <iostream>
8#include <boost/iterator/zip_iterator.hpp>
9#include <boost/tuple/tuple.hpp>
10
11#ifdef HAVE_CMPH
12#include <cmph.h>
13#endif
14
15namespace mpqc {
16namespace ci {
17
18 inline int index(int i, int j) {
19 if (i > j)
20 std::swap(i, j);
21 return (i + (j * j + j) / 2);
22 }
23
24 struct String {
25 template<class > class List;
26 class Index;
27 class CMPH;
28 typedef std::bitset<64> bitset;
29
30 struct orbitals {
31 typedef const int* const_iterator;
32 const_iterator begin() const {
33 return data_;
34 }
35 const_iterator end() const {
36 return data_ + count_;
37 }
38 private:
39 friend class String;
40 explicit orbitals(int count) :
41 count_(count) {
42 }
43 int data_[64];
44 int count_;
45 };
46
51 String(size_t size, size_t count) {
52 MPQC_ASSERT(0 < size && size < 64);
53 MPQC_ASSERT(0 < count && count < size);
54 this->size_ = size;
55 this->count_ = count;
56 this->value_ = bitset((1 << count) - 1);
57 }
58
62 explicit String(std::string value) {
63 //std::cout << "from str " << value << std::endl;
64 MPQC_ASSERT(value.size() <= 64);
65 std::reverse(value.begin(), value.end());
66 this->size_ = value.size();
67 this->value_ = bitset(value);
68 this->count_ = bitset(value).count();
69 }
70
71 String(const String &s) {
72 this->size_ = s.size_;
73 this->count_ = s.count_;
74 this->value_ = s.value_;
75 }
76
77 const void* data() const {
78 return (const char*) &this->value_;
79 }
80
81 bool operator[](size_t i) const {
82 return this->value_[i];
83 }
84
85 size_t size() const {
86 return this->size_;
87 }
88
89 size_t count() const {
90 return this->count_;
91 }
92
93 orbitals occ() const {
94 orbitals o(this->count());
95 for (size_t i = 0, j = 0; i < this->count(); ++i) {
96 while (!this->operator[](j))
97 ++j;
98 o.data_[i] = j++;
99 }
100 return o;
101 }
102 String swap(size_t i, size_t j) const {
103 String s = *this;
104 //MPQC_ASSERT(s[i] != s[j]);
105 s.flip(i);
106 s.flip(j);
107 //std::swap(s.value_[i], s.value_[j]);
108 return s;
109 }
111 operator std::string() const {
112 std::string s(this->size_, '*');
113 for (size_t i = 0; i < this->size_; ++i) {
114 s[i] = ("01"[this->operator[](i)]);
115 }
116 return s;
117 //return this->value_.to_string<char, std::char_traits<char>, std::allocator<char>>();
118 }
119 size_t to_ulong() const {
120 return this->value_.to_ulong();
121 }
122 // size_t operator<(const String &b) const {
123 // return (this->to_ulong() > b.to_ulong());
124 // }
125 size_t operator^(const String &b) const {
126 return (b.to_ulong() ^ this->to_ulong());
127 }
128 size_t operator&(size_t b) const {
129 return (b & this->to_ulong());
130 }
131 static size_t difference(const String &a, const String &b) {
132 MPQC_ASSERT(a.size() == b.size());
133 MPQC_ASSERT(a.count() == b.count());
134 size_t n = String::count(a ^ b);
135 //std::cout << std::string(a) << " ^ " << std::string(b) << std::endl;
136 MPQC_ASSERT(!(n % 2));
137 return n / 2;
138 }
139 static size_t count(size_t b) {
140 return bitset(b).count();
141 }
142 private:
143 bitset value_;
144 size_t size_, count_;
145 void flip(size_t i) {
146 this->value_.flip(i);
147 }
148 };
149
150 inline std::ostream& operator<<(std::ostream& os, const String &s) {
151 os << std::string(s);
152 return os;
153 }
154
155
157 inline int sgn(size_t ij) {
158 return (ij % 2) ? -1 : 1;
159 }
160
161
165 inline int sgn(const String &I, int i, int j) {
166 uint64_t b = I.to_ulong();
167 int n = std::abs(i - j);
168 if (j < i) std::swap(i, j);
169 b = b & ((uint64_t(1) << j) - 1); // clear high bits
170 b = b >> i; b = b >> 1; // clear low bits by shifting
171 size_t p = String::bitset(b).count();
172 //size_t p = _mm_popcnt_u64(b);
173#if 0
174 MPQC_ASSERT(p < I.count());
175 size_t q = 0;
176 for (int k = std::min(i,j)+1; k < std::max(i,j); ++k) {
177 q += I[k];
178 }
179 if (p != q)
180 sc::ExEnv::err0() << sc::scprintf("string %s(%lu) [%i,%i] b=%lu, p=%lu, q=%lu\n",
181 std::string(I).c_str(), I.to_ulong(), i,j, b, p, q);
182 MPQC_ASSERT(p == q);
183#endif
184 return sgn(p);
185 }
186
187
194 template<class IndexType>
196 typedef typename std::vector<String>::iterator iterator;
197 typedef typename std::vector<String>::const_iterator const_iterator;
198 List(const std::vector<String> &v) {
199 data_ = v;
200 index_.initialize(data_);
201 for (int i = 0; i < v.size(); ++i) {
202 perm_.push_back(i);
203 }
204 }
205 size_t size() const {
206 return data_.size();
207 }
208 const_iterator begin() const {
209 return data_.begin();
210 }
211 const_iterator end() const {
212 return data_.end();
213 }
214 iterator begin() {
215 return data_.begin();
216 }
217 iterator end() {
218 return data_.end();
219 }
220 size_t operator[](const String &s) const {
221 return perm_[this->index_[s]];
222 }
223 const String& operator[](size_t i) const {
224 return data_[i];
225 }
226 const String& at(size_t i) const {
227 return data_.at(i);
228 }
229 operator mpqc::range() const {
230 return mpqc::range(0, this->size());
231 }
232 template<class F>
233 void sort(F f) {
234 std::stable_sort(data_.begin(), data_.end(), f);
235 // update permutation for string-to-index look up
236 for (int i = 0; i < data_.size(); ++i) {
237 perm_[this->index_[data_[i]]] = i;
238 }
239 }
240 const std::vector<String>& data() const { return data_; }
241 private:
242 std::vector<String> data_;
243 std::vector<int> perm_;
244 IndexType index_;
245 template<class F>
246 struct ZipSort {
247 F f;
248 explicit ZipSort(F f) : f(f) {}
249 template <typename Tuple>
250 bool operator()(const Tuple &a, const Tuple &b) const {
251 return f(boost::get<0>(a), boost::get<0>(b));
252 }
253 };
254 };
255
256#ifdef HAVE_CMPH
260 struct String::SparseIndex {
261 void intitialize(const std::vector<String> &v) {
262 cmph_io_adapter_t *source =
263 cmph_io_struct_vector_adapter((void*)&v[0], sizeof(v[0]),
264 0, v[0].bytes(), v.size());
265 cmph_config_t *config = cmph_config_new(source);
266 cmph_config_set_algo(config, CMPH_BDZ);
267 cmph_t *hash = cmph_new(config);
268 std::cout << cmph_packed_size(hash) << std::endl;
269 this->data_.resize(cmph_packed_size(hash));
270 cmph_pack(hash, &this->data_[0]);
271 cmph_destroy(hash);
272 }
273 size_t operator[](const String &s) const {
274 return cmph_search_packed((void*)&this->data_[0],
275 s.data(), s.bytes());
276 }
277 private:
278 std::vector<char> data_;
279 };
280#endif
281
286 static const size_t K = 2;
287 // initialize hash
288 void initialize(const std::vector<String> &v) {
289 String s = v.front();
290 size_t size[] = { s.count(), s.size() };
291 for (size_t k = 0, i = 0; k < K; ++k) {
292 shift_[k] = i;
293 mask_[k] = 0;
294 while (i < size[k]) {
295 mask_[k] = mask_[k] | (1UL << i);
296 ++i;
297 }
298 }
299 // // (h0,h1,..) - h0 *bits* change slowest
300 std::reverse(shift_, shift_ + K);
301 std::reverse(mask_, mask_ + K);
302 // populate hash buckets
303 size_t index[K] = { size_t(-1), size_t(-1) };
304 for (size_t i = 0; i < v.size(); ++i) {
305 const String &s = v[i];
306 for (int k = 0; k < K; ++k) {
307 if ((s & mask_[k]) != index[k]) {
308 index[k] = s & mask_[k];
309 *hash(k, s) = i;
310 for (int j = 0; j < k; ++j) {
311 *hash(k, s) -= *hash(j, s);
312 }
313 }
314 }
315 }
316 // verify hash
317 for (size_t i = 0; i < v.size(); ++i) {
318 const String &s = v.at(i);
319 //std::cout << "CI string " << i << " " << s << std::endl;
320 if (this->operator[](s) == i)
321 continue;
322 std::cout << i << " != " << this->operator[](s) << std::endl;
323 MPQC_ASSERT(0);
324 }
325 }
326 size_t operator[](const String &s) const {
327 size_t index = 0;
328 for (int k = 0; k < K; ++k) {
329 index += *hash(k, s);
330 }
331 return index;
332 }
333 private:
334 std::vector<String> data_;
335 typedef size_t bucket[1 << 16];
336 size_t shift_[K], mask_[K];
337
338 struct Bucket {
339 static const size_t N = 1 << 16;
340 Bucket() {
341 data_.resize(N * K, 0);
342 }
343 size_t* operator[](int k) {
344 return &data_[k * N];
345 }
346 const size_t* operator[](int k) const {
347 return &data_[k * N];
348 }
349 private:
350 std::vector<size_t> data_;
351 };
352
353 Bucket bucket_;
354
355 size_t* hash(size_t k, const String &s) const {
356 size_t b = s & mask_[k];
357 return (size_t*) bucket_[k] + (b >> shift_[k]);
358 }
359 };
360
361 inline String::List<String::Index> strings(size_t no, size_t ne, size_t N = 0) {
362 MPQC_ASSERT(no > ne);
363 MPQC_ASSERT(ne > 0);
364 std::vector<String> v;
365 std::string r = String(no, ne);
366 std::string s = r;
367 do {
368 if (N && (String::difference(String(r), String(s))) > N)
369 continue;
370 v.push_back(String(s));
371 //std::cout << s << std::endl;
372 }
373 // N.B. string representation is reversed
374 while (std::next_permutation(s.rbegin(), s.rend()));
375
376 //std::reverse(v.begin(), v.end()); // un-reverse order
378 }
379
380}
381}
382
383#endif // MPQC_CI_STRING_HPP
String::List represents a set of String objects.
Definition string.hpp:195
static std::ostream & err0()
Return an ostream for error messages that writes from node 0.
Definition exenv.h:87
This class allows printf-like output to be sent to an ostream.
Definition formio.h:97
std::vector< unsigned int > operator<<(const GaussianBasisSet &B, const GaussianBasisSet &A)
computes a map from basis functions in A to the equivalent basis functions in B.
Contains new MPQC code since version 3.
Definition integralenginepool.hpp:37
implements a dense String->index map, appropriate for a full CI string sets
Definition string.hpp:285
Definition string.hpp:30
Definition string.hpp:24
String(size_t size, size_t count)
Construct string with 'count' electrons, eg String(4,2) will generate a string '0011'.
Definition string.hpp:51
String(std::string value)
Construct String from a char string.
Definition string.hpp:62
Definition range.hpp:25

Generated at Wed Sep 25 2024 02:45:30 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.