MPQC  3.0.0-alpha
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 
15 namespace mpqc {
16 namespace 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>
195  struct String::List {
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
257 
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 
285  struct String::Index {
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
377  return String::List<String::Index>(v);
378  }
379 
380 }
381 }
382 
383 #endif // MPQC_CI_STRING_HPP
mpqc
Contains new MPQC code since version 3.
Definition: integralenginepool.hpp:37
mpqc::range
Definition: range.hpp:23
mpqc::ci::String::orbitals
Definition: string.hpp:30
mpqc::ci::String::List
String::List represents a set of String objects.
Definition: string.hpp:25
sc::ExEnv::err0
static std::ostream & err0()
Return an ostream for error messages that writes from node 0.
Definition: exenv.h:87
mpqc::operator&
range operator&(const range &a, const range &b)
Range intersection.
Definition: range.hpp:70
mpqc::ci::String::String
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
mpqc::ci::String::Index
implements a dense String->index map, appropriate for a full CI string sets
Definition: string.hpp:285
mpqc::operator<<
void operator<<(Array< T > A, const V &v)
Write to Array from a generic vector V.
Definition: array.hpp:191
sc::scprintf
This class allows printf-like output to be sent to an ostream.
Definition: formio.h:97
mpqc::ci::String::String
String(std::string value)
Construct String from a char string.
Definition: string.hpp:62
mpqc::ci::String
Definition: string.hpp:24

Generated at Sun Jan 26 2020 23:24:01 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.8.16.