ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
block_matrix.hpp
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  * 2011-2011 by Bela Bauer <bauerb@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 
28 
29 #include "utils/function_objects.h"
30 #include "utils/bindings.hpp"
31 
32 #include <alps/type_traits/is_complex.hpp>
33 
34 #include <boost/serialization/serialization.hpp>
35 #include <boost/ptr_container/serialize_ptr_vector.hpp>
36 
37 template<class Matrix, class SymmGroup>
39 {
40 }
41 
42 template<class Matrix, class SymmGroup>
44  Index<SymmGroup> cols)
45 : rows_(rows)
46 , cols_(cols)
47 {
48  assert(rows_.size() == cols_.size());
49  for (size_type k = 0; k < rows_.size(); ++k)
50  data_.push_back(new Matrix(rows_[k].second, cols_[k].second));
51 }
52 
53 template<class Matrix, class SymmGroup>
55 : rows_(rhs.left_basis())
56 , cols_(rhs.right_basis())
57 , data_(rhs.data_)
58 { }
59 
60 template<class Matrix, class SymmGroup>
61 template <class OtherMatrix>
63 : rows_(rhs.left_basis())
64 , cols_(rhs.right_basis())
65 {
66  data_.reserve(rhs.n_blocks());
67  for (size_type k = 0; k < rhs.n_blocks(); ++k)
68  data_.push_back(new Matrix(rhs[k]));
69 }
70 
71 template<class Matrix, class SymmGroup>
73 {
74  swap(*this, rhs);
75  return *this;
76 }
77 
78 template<class Matrix, class SymmGroup>
79 template<class OtherMatrix>
81 {
82  rows_ = rhs.rows_;
83  cols_ = rhs.cols_;
84  data_.resize(rhs.data_.size());
85  for(int k = 0; k < data_.size(); k++){
86  data_[k].resize(num_rows(rhs.data_[k]), num_cols(rhs.data_[k]));
87  data_[k] = rhs.data_[k];
88  }
89  return *this;
90 }
91 
92 // Remove by Tim 06/08/2012, presently not used in any DMRG/TE code
93 //template<class Matrix, class SymmGroup>
94 //block_matrix<Matrix, SymmGroup>::block_matrix(charge rc, charge cc, Matrix& m)
95 //{
96 // rows_.push_back(std::make_pair(rc, num_rows(m)));
97 // cols_.push_back(std::make_pair(cc, num_cols(m)));
98 // data_.push_back(&m);
99 //}
100 
101 template<class Matrix, class SymmGroup>
103 {
104  for (size_type k = 0; k < rhs.n_blocks(); ++k)
105  {
106  charge rhs_rc = rhs.rows_[k].first;
107  charge rhs_cc = rhs.cols_[k].first;
108  if (this->has_block(rhs_rc, rhs_cc))
109  (*this)(rhs_rc, rhs_cc) += rhs.data_[k];
110  else
111  this->insert_block(rhs.data_[k], rhs_rc, rhs_cc);
112  }
113  return *this;
114 }
115 
116 template<class Matrix, class SymmGroup>
118 {
119  for (size_type k = 0; k < rhs.n_blocks(); ++k)
120  {
121  charge rhs_rc = rhs.rows_[k].first;
122  charge rhs_cc = rhs.cols_[k].first;
123  if (this->has_block(rhs_rc, rhs_cc))
124  (*this)(rhs_rc, rhs_cc) -= rhs.data_[k];
125  else
126  this->insert_block(-1*rhs.data_[k], rhs_rc, rhs_cc);
127  }
128  return *this;
129 }
130 
131 template<class Matrix, class SymmGroup>
133 {
134  assert( !has_block(c1, c2) );
135 
136  std::pair<charge, size_type>
137  p1 = std::make_pair(c1, num_rows(mtx)),
138  p2 = std::make_pair(c2, num_cols(mtx));
139 
140  size_type i1 = rows_.insert(p1);
141  cols_.insert(i1, p2);
142  Matrix* block = new Matrix(mtx);
143  data_.insert(data_.begin() + i1, block);
144 
145  return i1;
146  //rows_.push_back(p1);
147  //cols_.push_back(p2);
148  //data_.push_back(mtx);
149 }
150 
151 template<class Matrix, class SymmGroup>
153 {
154  assert( !has_block(c1, c2) );
155 
156  std::pair<charge, size_type>
157  p1 = std::make_pair(c1, num_rows(*mtx)),
158  p2 = std::make_pair(c2, num_cols(*mtx));
159 
160  size_type i1 = rows_.insert(p1);
161  cols_.insert(i1, p2);
162  data_.insert(data_.begin() + i1, mtx);
163 
164  return i1;
165 }
166 
167 template<class Matrix, class SymmGroup>
169 
170 template<class Matrix, class SymmGroup>
172 
173 template<class Matrix, class SymmGroup>
174 typename Matrix::size_type block_matrix<Matrix, SymmGroup>::n_blocks() const { return data_.size(); }
175 
176 template<class Matrix, class SymmGroup>
178 {
179  std::ostringstream oss;
180  oss << rows_ << cols_;
181  return oss.str();
182 }
183 
184 template<class Matrix, class SymmGroup>
185 void block_matrix<Matrix, SymmGroup>::shift_basis(typename block_matrix<Matrix, SymmGroup>::charge diff)
186 {
187  rows_.shift(diff);
188  cols_.shift(diff);
189 }
190 
191 template<class Matrix, class SymmGroup>
193 
194 template<class Matrix, class SymmGroup>
195 Matrix const & block_matrix<Matrix, SymmGroup>::operator[](size_type c) const { return data_[c]; }
196 
197 template<class Matrix, class SymmGroup>
199 {
200  std::size_t p1 = rows_.position(r);
201  std::size_t p2 = cols_.position(c);
202 
203  if (p1 == p2 && p1 != rows_.size()) return p1;
204  else return n_blocks();
205 }
206 
207 template<class Matrix, class SymmGroup>
208 bool block_matrix<Matrix, SymmGroup>::has_block(charge r, charge c) const
209 {
210  std::size_t p1 = rows_.position(r);
211  if (p1 == rows_.size()) return false;
212  std::size_t p2 = cols_.position(c);
213  if (p2 == cols_.size()) return false;
214  return (p1 == p2);
215 }
216 
217 template<class Matrix, class SymmGroup>
218 bool block_matrix<Matrix, SymmGroup>::has_block(std::pair<charge, size_type> const & r,
219  std::pair<charge, size_type> const & c) const
220 {
221  return has_block(r.first, c.first);
222 }
223 
224 template<class Matrix, class SymmGroup>
225 typename Matrix::value_type & block_matrix<Matrix, SymmGroup>::operator()(std::pair<charge, size_type> const & r,
226  std::pair<charge, size_type> const & c)
227 {
228  assert( rows_.position(r.first) == cols_.position(c.first) );
229  return data_[rows_.position(r.first)](r.second, c.second);
230 }
231 
232 template<class Matrix, class SymmGroup>
233 typename Matrix::value_type const & block_matrix<Matrix, SymmGroup>::operator()(std::pair<charge, size_type> const & r,
234  std::pair<charge, size_type> const & c) const
235 {
236  assert( rows_.position(r.first) == cols_.position(c.first) );
237  return data_[rows_.position(r.first)](r.second, c.second);
238 }
239 // Remove by Tim 06/08/2012, presently not used in any DMRG/TE code
240 //template<class Matrix, class SymmGroup>
241 //void block_matrix<Matrix, SymmGroup>::remove_rows_from_block(size_type block, size_type r, size_type k)
242 //{ // we should add an assert block < data_.size()
243 // remove_rows(data_[block], r, k);
244 // rows_[block].second -= k;
245 //}
246 
247 // Remove by Tim 06/08/2012, presently not used in any DMRG/TE code
248 //template<class Matrix, class SymmGroup>
249 //void block_matrix<Matrix, SymmGroup>::remove_cols_from_block(size_type block, size_type r, size_type k)
250 //{ // we should add an assert block < data_.size()
251 // remove_cols(data_[block], r, k);
252 // cols_[block].second -= k;
253 //}
254 
255 template<class Matrix, class SymmGroup>
257 {
258  // todo: check if "omp for" used in nested regions
259  semi_parallel_for(/*locale::compact(n_blocks())*/, std::size_t k = 0; k < n_blocks(); ++k) data_[k] *= v;
260  return *this;
261 }
262 
263 template<class Matrix, class SymmGroup>
265 {
266  // todo: check if "omp for" used in nested regions
267  semi_parallel_for(/*locale::compact(n_blocks())*/, std::size_t k = 0; k < n_blocks(); ++k) data_[k] /= v;
268  return *this;
269 }
270 
271 
272 template<class Matrix, class SymmGroup>
274 {
275  std::vector<scalar_type> vt; vt.reserve(data_.size());
276  std::transform(data_.begin(), data_.end(), back_inserter(vt), utils::functor_trace());
277  return maquis::accumulate(vt.begin(), vt.end(), scalar_type(0.));
278 }
279 
280 template<class Matrix, class SymmGroup>
282 {
283  std::vector<real_type> vt; vt.reserve(data_.size());
284  semi_parallel_for(/*locale::compact(n_blocks())*/, std::size_t k = 0; k < n_blocks(); ++k) vt.push_back(norm_square(data_[k]));
285  return maquis::sqrt(maquis::accumulate(vt.begin(), vt.end(), real_type(0.)));
286 }
287 
288 template<class Matrix, class SymmGroup>
290 {
291  std::for_each(data_.begin(), data_.end(), utils::functor_transpose_inplace());
292  std::swap(rows_, cols_);
293 }
294 
295 template<class Matrix, class SymmGroup>
297 {
298  std::for_each(data_.begin(), data_.end(), utils::functor_conj_inplace());
299 }
300 
301 template<class Matrix, class SymmGroup>
303 {
304  std::for_each(data_.begin(), data_.end(), utils::functor_adjoint_inplace());
305  std::swap(rows_, cols_);
306 }
307 
308 namespace detail {
309  // md: this is needed because block_matrix::generate is hiding the correct one
310  template<class Matrix, class Generator>
311  void generate_impl(Matrix & m, Generator g)
312  { generate(m, g); }
313 }
314 
315 template<class Matrix, class SymmGroup>
316 template<class Generator>
318 {
319  for(std::size_t k = 0; k < n_blocks(); ++k) ::detail::generate_impl(data_[k], g);
320 }
321 
322 template<class Matrix, class SymmGroup>
324 {
325  data_.clear();
326  rows_ = Index<SymmGroup>();
327  cols_ = Index<SymmGroup>();
328 }
329 
330 template<class Matrix, class SymmGroup>
331 std::ostream& operator<<(std::ostream& os, block_matrix<Matrix, SymmGroup> const & m)
332 {
333  os << "Left HS: " << m.left_basis() << std::endl;
334  os << "Right HS: " << m.right_basis() << std::endl;
335  for (std::size_t k = 0; k < m.n_blocks(); ++k)
336  os << "Block (" << m.left_basis()[k].first << "," << m.right_basis()[k].first << "):\n" << m[k] << std::endl;
337  os << std::endl;
338  return os;
339 }
340 
341 template<class Matrix, class SymmGroup>
342 void block_matrix<Matrix, SymmGroup>::match_and_add_block(Matrix const & mtx, charge c1, charge c2)
343 {
344 
345  if (this->has_block(c1, c2))
346  {
347  if (num_rows(mtx) == num_rows((*this)(c1, c2)) &&
348  num_cols(mtx) == num_cols((*this)(c1, c2)))
349  (*this)(c1, c2) += mtx;
350  else if (num_rows(mtx) > num_rows((*this)(c1, c2)) &&
351  num_cols(mtx) > num_cols((*this)(c1, c2)))
352  {
353  resize_block(c1, c2, num_rows(mtx), num_cols(mtx));
354  (*this)(c1, c2) += mtx;
355  } else {
356  std::size_t maxrows = std::max(num_rows(mtx),
357  num_rows((*this)(c1, c2)));
358  std::size_t maxcols = std::max(num_cols(mtx),
359  num_cols((*this)(c1, c2)));
360 
361  Matrix cpy(mtx); // only in this case do we need to copy the argument matrix
362 
363  resize_block(c1, c2, maxrows, maxcols); // I think useless
364  resize(cpy, maxrows, maxcols);
365 
366  (*this)(c1, c2) += cpy;
367  }
368  } else
369  insert_block(mtx, c1, c2);
370 }
371 
372 template<class Matrix, class SymmGroup>
374  size_type new_r, size_type new_c,
375  bool pretend)
376 {
377  if (!pretend)
378  resize((*this)(r,c), new_r, new_c);
379  rows_[rows_.position(r)].second = new_r;
380  cols_[cols_.position(c)].second = new_c;
381 }
382 
383 template<class Matrix, class SymmGroup>
385 {
386  assert( has_block(r, c) );
387  assert( rows_.position(r) == cols_.position(c) );
388 
389  std::size_t which = rows_.position(r);
390 
391  rows_.erase(rows_.begin() + which);
392  cols_.erase(cols_.begin() + which);
393  data_.erase(data_.begin() + which);
394 }
395 template<class Matrix, class SymmGroup>
397 {
398  assert( which < data_.size() );
399 
400  rows_.erase(rows_.begin() + which);
401  cols_.erase(cols_.begin() + which);
402  data_.erase(data_.begin() + which);
403 }
404 
405 template<class Matrix, class SymmGroup>
406 template<class Archive>
408 {
409  ar["rows_"] >> rows_;
410  ar["cols_"] >> cols_;
411 
412  data_.clear();
413  if (alps::is_complex<typename Matrix::value_type>() && !ar.is_complex("data_"))
414  {
416  std::vector<LoadMatrix> tmp;
417  ar["data_"] >> tmp;
418  for(typename std::vector<LoadMatrix>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
419  data_.push_back(new Matrix(maquis::bindings::matrix_cast<Matrix>(*it)));
420  } else {
421  std::vector<Matrix> tmp;
422  ar["data_"] >> tmp;
423  // TODO: is swap here possible?
424  for(typename std::vector<Matrix>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
425  data_.push_back(new Matrix(*it));
426  }
427 }
428 
429 template<class Matrix, class SymmGroup>
430 template<class Archive>
432 {
433  ar["rows_"] << rows_;
434  ar["cols_"] << cols_;
435 
436  std::vector<Matrix> tmp(data_.begin(), data_.end());
437  ar["data_"] << tmp;
438 }
439 
440 template<class Matrix, class SymmGroup>
441 template <class Archive>
442 void block_matrix<Matrix, SymmGroup>::serialize(Archive & ar, const unsigned int version)
443 {
444  ar & rows_ & cols_ & data_;
445 }
446 
447 template<class Matrix, class SymmGroup>
449  std::size_t r, std::size_t c)
450 {
451  if (this->has_block(c1, c2))
452  {
453  std::size_t maxrows = std::max(rows_[rows_.position(c1)].second, r);
454  std::size_t maxcols = std::max(cols_[cols_.position(c2)].second, c);
455 
456  rows_[rows_.position(c1)].second = maxrows;
457  cols_[cols_.position(c2)].second = maxcols;
458  } else {
459  std::pair<charge, size_type>
460  p1 = std::make_pair(c1, r),
461  p2 = std::make_pair(c2, c);
462 
463  assert(rows_.size() == cols_.size());
464  assert(rows_.size() == data_.size());
465 
466  size_type i1 = rows_.insert(p1);
467  cols_.insert(i1, p2);
468  Matrix* block = new Matrix(1,1);
469  data_.insert(data_.begin() + i1, block);
470  }
471  assert( this->has_block(c1,c2) );
472 }
473 
474 template<class Matrix, class SymmGroup>
475 inline void block_matrix<Matrix, SymmGroup>::reserve_pos(charge c1, charge c2,
476  std::size_t ri, std::size_t ci)
477 { reserve(c1, c2, ri+1, ci+1); }
478 
479 
480 template<class Matrix, class SymmGroup>
482 {
483  for (std::size_t k = 0; k < n_blocks(); ++k)
484  resize(data_[k], rows_[k].second, cols_[k].second);
485 }
486 
487 template<class Matrix, class SymmGroup>
489 {
490  for (size_t k=0; k<n_blocks(); ++k)
491  if (num_rows((*this)[k]) != rows_[k].second || num_cols((*this)[k]) != cols_[k].second)
492  return false;
493  return true;
494 }
495 
496 template<class Matrix, class SymmGroup>
498 {
499  size_t ret = 0;
500  for (size_t k = 0; k < n_blocks(); ++k)
501  ret += num_rows(data_[k])*num_cols(data_[k]);
502  return ret;
503 }
void conjugate_inplace()
void transpose_inplace()
void generate_impl(Matrix &m, Generator g)
void load(Archive &ar)
size_type n_blocks() const
std::size_t num_elements() const
void match_and_add_block(Matrix const &, charge, charge)
value_type & operator()(std::pair< charge, size_type > const &r, std::pair< charge, size_type > const &c)
void serialize(Archive &ar, const unsigned int version)
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
declaration of block_matrix class
size_type insert_block(Matrix const &, charge, charge)
std::string description() const
void shift_basis(charge diff)
std::size_t num_rows(maquis::dmrg::one_matrix< T > const &m)
Definition: one_matrix.hpp:99
scalar_type trace() const
#define semi_parallel_for(constraint,...)
Matrix & operator[](size_type c)
void resize_block(charge r, charge c, size_type new_r, size_type new_c, bool pretend=false)
maquis::traits::scalar_type< Matrix >::type scalar_type
Definition: block_matrix.h:52
bool reasonable() const
bool has_block(charge r, charge c) const
std::size_t num_cols(maquis::dmrg::one_matrix< T > const &m)
Definition: one_matrix.hpp:102
block_matrix const & operator/=(const scalar_type &v)
Index< SymmGroup > const & right_basis() const
void generate(Generator g)
void remove_block(charge r, charge c)
void adjoint_inplace()
block_matrix & operator+=(block_matrix const &rhs)
void reserve(charge, charge, std::size_t, std::size_t)
maquis::traits::real_type< Matrix >::type real_type
Definition: block_matrix.h:53
void generate(block_matrix< Matrix, SymmGroup > &m, Generator &g)
T sqrt(T arg)
Definition: bindings.hpp:49
real_type norm() const
void save(Archive &ar) const
size_type find_block(charge r, charge c) const
block_matrix & operator-=(block_matrix const &rhs)
void reserve_pos(charge, charge, std::size_t, std::size_t)
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
Definition: bindings.hpp:44
void allocate_blocks()
Index< SymmGroup > const & left_basis() const
block_matrix const & operator*=(const scalar_type &v)
block_matrix & operator=(block_matrix rhs)
Matrix::size_type size_type
Definition: block_matrix.h:50