ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
multi_index.h
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * ALPS MPS DMRG Project
4  *
5  * Copyright (C) 2013 Institute for Theoretical Physics, ETH Zurich
6  * 2013 by Michele Dolfi <dolfim@phys.ethz.ch>
7  *
8  * This software is part of the ALPS Applications, published under the ALPS
9  * Application License; you can use, redistribute it and/or modify it under
10  * the terms of the license, either version 1 or (at your option) any later
11  * version.
12  *
13  * You should have received a copy of the ALPS Application License along with
14  * the ALPS Applications; see the file LICENSE.txt. If not, the license is also
15  * available from http://alps.comp-phys.org/.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  *****************************************************************************/
26 
27 #ifndef MULTI_INDEX_H
28 #define MULTI_INDEX_H
29 
30 //#include "dmrg/block_matrix/indexing.h"
31 
32 #include <vector>
33 #include <algorithm>
34 #include <iostream>
35 
36 #include <boost/operators.hpp>
37 
38 
39 template <class SymmGroup>
41 : public boost::forward_iterator_helper<
42  index_product_iterator<SymmGroup>
43  , std::vector<std::pair<typename Index<SymmGroup>::charge, std::size_t> >
44  , std::ptrdiff_t
45  , std::vector<std::pair<typename Index<SymmGroup>::charge, std::size_t> > *
46  , std::vector<std::pair<typename Index<SymmGroup>::charge, std::size_t> > &
47 >
48 {
49 public:
50  typedef std::size_t index_id;
52  typedef typename index_t::charge charge; // element of Index
53  typedef std::size_t elem_id; // element of charge
54 
55  typedef std::pair<charge, elem_id> coord_t; // index inside block_matrix
56  typedef std::vector<coord_t> value_type;
57 
58  typedef std::vector<typename index_t::const_iterator> vec_iterator;
59 
60  index_product_iterator() : valid(false) { }
61 
62  index_product_iterator(std::vector<index_t> const & idx)
63  : size(idx.size())
64  , begin(size)
65  , state(size)
66  , end(size)
67  , cur_i(size, 0)
68  , max_i(size)
69  , valid(true)
70  {
71  for (int i=0; i<size; ++i) {
72  begin[i] = idx[i].begin();
73  state[i] = idx[i].begin();
74  max_i[i] = state[i]->second;
75  end[i] = idx[i].end();
76  }
77  }
78 
80  {
81  value_type ret(size);
82  for (int i=0; i<size; ++i)
83  ret[i] = std::make_pair(state[i]->first, cur_i[i]);
84  return ret;
85  }
86 
87  void operator++()
88  {
89  for (int i=size-1; i>=0; --i) {
90  cur_i[i]++;
91  if (cur_i[i] != max_i[i])
92  break;
93 
94  state[i]++;
95  if (state[i] != end[i]) {
96  cur_i[i] = 0;
97  max_i[i] = state[i]->second;
98  break;
99  }
100 
101  if (i == 0) {
102  state[i] = end[i];
103  valid = false;
104  break;
105  }
106 
107  state[i] = begin[i];
108  cur_i[i] = 0;
109  max_i[i] = state[i]->second;
110  }
111  }
112 
114  {
115  if (valid != rhs.valid)
116  return false;
117  if (!valid)
118  return true;
119 
120  return (size == rhs.size) && std::equal(state.begin(), state.end(), rhs.state.begin());
121  }
122 
123 
124 private:
125 
126  bool valid;
127  std::size_t size;
128 
129  vec_iterator begin;
130  vec_iterator end;
131  vec_iterator state;
132 
133  std::vector<elem_id> cur_i;
134  std::vector<std::size_t> max_i;
135 };
136 
137 
138 
139 template <class SymmGroup>
140 class MultiIndex {
141 public:
142  typedef std::size_t size_t;
143  typedef std::size_t index_id;
145  typedef typename index_t::charge charge; // element of Index
146  typedef std::size_t elem_id; // element of charge
147 
148  typedef std::pair<charge, elem_id> coord_t; // index inside block_matrix
149 
150  typedef std::size_t set_id;
151  typedef std::vector<coord_t> key_t;
152 
154 
155  MultiIndex () { }
156 
158  {
159  idx_.push_back(idx);
160  return idx_.size()-1;
161  }
162 
163  index_t const& index(index_id i) const
164  { return idx_[i]; }
165 
166  size_t size() const
167  { return idx_.size(); }
168 
169  set_id create_set(std::vector<std::pair<index_id, bool> > const & vec_left,
170  std::vector<std::pair<index_id, bool> > const & vec_right);
171 
173  {
174  left_keys.erase(left_keys.begin() + s);
175  left_vals.erase(left_vals.begin() + s);
176  set_left.erase(set_left.begin() + s);
177  right_keys.erase(right_keys.begin() + s);
178  right_vals.erase(right_vals.begin() + s);
179  set_right.erase(set_right.begin() + s);
180  }
181 
182  void clear_sets()
183  {
184  left_keys.clear();
185  left_vals.clear();
186  left_sizes.clear();
187  set_left.clear();
188  right_keys.clear();
189  right_vals.clear();
190  right_sizes.clear();
191  set_right.clear();
192  }
193 
194  void clear()
195  {
196  clear_sets();
197  idx_.clear();
198  }
199 
200 
201  size_t left_size(set_id s, charge const & c) const
202  {
203  assert( left_sizes[s].count(c) > 0 );
204  return left_sizes[s].find(c)->second;
205  }
206  size_t right_size(set_id s, charge const & c) const
207  {
208  assert( right_sizes[s].count(c) > 0 );
209  return right_sizes[s].find(c)->second;
210  }
211 
212  // TODO: cache the last search key to avoid find()
213 
214  // key --> coord
215  inline coord_t const& get_left_coord(set_id s, key_t const& key) const
216  {
217  return key_to_val(key, left_keys[s], left_vals[s]);
218  }
219  inline coord_t const& get_right_coord(set_id s, key_t const& key) const
220  {
221  return key_to_val(key, right_keys[s], right_vals[s]);
222  }
223  std::pair<coord_t, coord_t> get_coords(set_id s, key_t const& key) const
224  {
225  key_t left_k, right_k;
226  for (int i=0; i<set_left[s].size(); ++i)
227  left_k.push_back(key[ set_left[s][i].first ]);
228  for (int i=0; i<set_right[s].size(); ++i)
229  right_k.push_back(key[ set_right[s][i].first ]);
230 
231  return std::make_pair( get_left_coord(s, left_k), get_right_coord(s, right_k) );
232  }
233 
234  // coord --> key
235  inline key_t const& get_left_key(set_id s, coord_t const& ci) const
236  {
237  return val_to_key(ci, left_keys[s], left_vals[s]);
238  }
239  inline key_t const& get_right_key(set_id s, coord_t const& ci) const
240  {
241  return val_to_key(ci, right_keys[s], right_vals[s]);
242  }
243 
244  // coord --> coord
245  std::pair<coord_t, coord_t> convert_coords(set_id set1,
246  coord_t const & coord1_left,
247  coord_t const & coord1_right,
248  set_id set2) const
249  {
250  key_t key1_left = get_left_key(set1, coord1_left);
251 // maquis::cout << "got left key" << std::endl;
252  key_t key1_right = get_right_key(set1, coord1_right);
253 // maquis::cout << "got right key" << std::endl;
254 
255  assert( key1_left.size() == set_left[set1].size() );
256  assert( key1_right.size() == set_right[set1].size() );
257 
258  key_t key(idx_.size());
259  for (int i=0; i<set_left[set1].size(); ++i) {
260 // maquis::cout << "key index = " << set_left[set1][i].first << std::endl;
261  key[ set_left[set1][i].first ] = key1_left[i];
262  }
263 // maquis::cout << "left key --> key" << std::endl;
264  for (int i=0; i<set_right[set1].size(); ++i)
265  key[ set_right[set1][i].first ] = key1_right[i];
266 // maquis::cout << "right key --> key" << std::endl;
267 
268  return get_coords(set2, key);
269 
270  }
271  inline std::pair<coord_t, coord_t> convert_coords(set_id set1, std::pair<coord_t, coord_t> const & coords1,
272  set_id set2) const
273  { return convert_coords(set1, coords1.first, coords1.second, set2); }
274 
275 
277  { return const_iterator(idx_); }
278 
280  { return const_iterator(); }
281 
282 
283 private:
284  coord_t const& key_to_val(key_t const& key, std::vector<key_t> const& keys,
285  std::vector<coord_t> const& vals) const
286  {
287  assert( std::count(keys.begin(), keys.end(), key) > 0 );
288  size_t pos = std::find(keys.begin(), keys.end(), key)-keys.begin();
289  return vals[pos];
290  }
291 
292  key_t const& val_to_key(coord_t const& ci, std::vector<key_t> const& keys,
293  std::vector<coord_t> const& vals) const
294  {
295  assert( std::count(vals.begin(), vals.end(), ci) > 0 );
296  size_t pos = std::find(vals.begin(), vals.end(), ci)-vals.begin();
297  return keys[pos];
298  }
299 
300 
301 
302  std::vector<index_t> idx_;
303 
304  std::vector<std::vector<std::pair<index_id, bool> > > set_left, set_right;
305  std::vector<std::vector<key_t> > left_keys, right_keys;
306  std::vector<std::vector<coord_t> > left_vals, right_vals;
307  std::vector<std::map<charge, size_t> > left_sizes, right_sizes;
308 
309 };
310 
311 
312 template <class SymmGroup>
314 MultiIndex<SymmGroup>::create_set(std::vector<std::pair<index_id, bool> > const & vec_left,
315  std::vector<std::pair<index_id, bool> > const & vec_right)
316 {
317  {
318  std::vector<index_t> b;
319  for(int i=0; i<vec_left.size(); ++i)
320  b.push_back( idx_[vec_left[i].first] );
321 
322  std::map<charge, size_t> block_begins;
323  std::vector<key_t> keys_;
324  std::vector<coord_t> vals_;
325 
326  for (const_iterator it = const_iterator(b);
327  it != const_iterator();
328  it++)
329  {
330  charge c = SymmGroup::IdentityCharge;
331  for (int i=0; i<b.size(); ++i)
332  c = (vec_left[i].second) ? SymmGroup::fuse(c, (*it)[i].first) : SymmGroup::fuse(c, -(*it)[i].first);
333  keys_.push_back(*it);
334  vals_.push_back(std::make_pair(c, block_begins[c]));
335  block_begins[c]++;
336  }
337 
338  left_keys.push_back(keys_);
339  left_vals.push_back(vals_);
340  left_sizes.push_back(block_begins);
341  }
342 
343  {
344  std::vector<index_t> b;
345  for(int i=0; i<vec_right.size(); ++i)
346  b.push_back( idx_[vec_right[i].first] );
347 
348  std::map<charge, size_t> block_begins;
349  std::vector<key_t> keys_;
350  std::vector<coord_t> vals_;
351 
352  for (const_iterator it = const_iterator(b);
353  it != const_iterator();
354  it++)
355  {
356  charge c = SymmGroup::IdentityCharge;
357  for (int i=0; i<b.size(); ++i)
358  c = (vec_right[i].second) ? SymmGroup::fuse(c, (*it)[i].first) : SymmGroup::fuse(c, -(*it)[i].first);
359  keys_.push_back(*it);
360  vals_.push_back(std::make_pair(c, block_begins[c]));
361  block_begins[c]++;
362  }
363 
364  right_keys.push_back(keys_);
365  right_vals.push_back(vals_);
366  right_sizes.push_back(block_begins);
367  }
368 
369  set_left.push_back(vec_left);
370  set_right.push_back(vec_right);
371  return left_keys.size() - 1;
372 }
373 
374 // ostreams
375 //template <class SymmGroup>
376 //std::ostream& operator<< (std::ostream& os, std::pair<typename SymmGroup::charge, std::size_t> const& p)
377 //{
378 // os << "(" << p.first << " : " << p.second << ")";
379 // return os;
380 //}
381 //
382 //template <class SymmGroup>
383 //std::ostream& operator<< (std::ostream& os, typename index_product_iterator<SymmGroup>::value_type const& v)
384 //{
385 // //std::copy(v.begin(), v.end(), std::ostream_iterator<std::pair<symm::charge, std::size_t> >(os, " "));
386 // for (int i=0; i<v.size(); ++i)
387 // os << v[i] << " ";
388 // return os;
389 //}
390 //
391 //template <class SymmGroup>
392 //std::ostream& operator<< (std::ostream& os, std::pair<typename MultiIndex<SymmGroup>::coord_t, typename MultiIndex<SymmGroup>::coord_t> const& p)
393 //{
394 // os << p.first << ", " << p.second;
395 // return os;
396 //}
397 
398 
399 
400 #endif
SymmGroup::charge charge
std::pair< coord_t, coord_t > convert_coords(set_id set1, coord_t const &coord1_left, coord_t const &coord1_right, set_id set2) const
Definition: multi_index.h:245
key_t const & get_right_key(set_id s, coord_t const &ci) const
Definition: multi_index.h:239
std::size_t set_id
Definition: multi_index.h:150
std::pair< coord_t, coord_t > get_coords(set_id s, key_t const &key) const
Definition: multi_index.h:223
Index< SymmGroup > index_t
Definition: multi_index.h:144
std::vector< coord_t > value_type
Definition: multi_index.h:56
std::pair< charge, elem_id > coord_t
Definition: multi_index.h:148
std::pair< charge, elem_id > coord_t
Definition: multi_index.h:55
index_product_iterator< SymmGroup > const_iterator
Definition: multi_index.h:153
std::vector< typename index_t::const_iterator > vec_iterator
Definition: multi_index.h:58
std::pair< coord_t, coord_t > convert_coords(set_id set1, std::pair< coord_t, coord_t > const &coords1, set_id set2) const
Definition: multi_index.h:271
const_iterator end() const
Definition: multi_index.h:279
index_product_iterator(std::vector< index_t > const &idx)
Definition: multi_index.h:62
size_t right_size(set_id s, charge const &c) const
Definition: multi_index.h:206
index_id insert_index(index_t const &idx)
Definition: multi_index.h:157
set_id create_set(std::vector< std::pair< index_id, bool > > const &vec_left, std::vector< std::pair< index_id, bool > > const &vec_right)
Definition: multi_index.h:314
index_t::charge charge
Definition: multi_index.h:145
std::size_t elem_id
Definition: multi_index.h:146
coord_t const & get_right_coord(set_id s, key_t const &key) const
Definition: multi_index.h:219
value_type operator*() const
Definition: multi_index.h:79
size_t left_size(set_id s, charge const &c) const
Definition: multi_index.h:201
const_iterator begin() const
Definition: multi_index.h:276
index_t const & index(index_id i) const
Definition: multi_index.h:163
std::size_t index_id
Definition: multi_index.h:50
bool operator==(index_product_iterator< SymmGroup > const &rhs) const
Definition: multi_index.h:113
std::pair< bool, typename Matrix::value_type > equal(block_matrix< Matrix, SymmGroup > const &reference, block_matrix< Matrix, SymmGroup > const &sample)
Definition: tag_detail.h:120
index_t::charge charge
Definition: multi_index.h:52
std::size_t index_id
Definition: multi_index.h:143
void clear()
Definition: multi_index.h:194
void remove_set(set_id s)
Definition: multi_index.h:172
std::size_t size_t
Definition: multi_index.h:142
size_t size() const
Definition: multi_index.h:166
void clear_sets()
Definition: multi_index.h:182
std::vector< coord_t > key_t
Definition: multi_index.h:151
key_t const & get_left_key(set_id s, coord_t const &ci) const
Definition: multi_index.h:235
Index< SymmGroup > index_t
Definition: multi_index.h:51
coord_t const & get_left_coord(set_id s, key_t const &key) const
Definition: multi_index.h:215
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.