ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mps.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 
27 #include "dmrg/mp_tensors/mps.h"
28 #include "contractions.h"
29 
30 #include "dmrg/utils/archive.h"
31 
32 #include <limits>
33 
34 template<class Matrix, class SymmGroup>
36 {
37  std::ostringstream oss;
38  for (int i = 0; i < length(); ++i)
39  {
40  oss << "MPS site " << i << std::endl;
41  oss << (*this)[i].row_dim() << std::endl;
42  oss << "Sum: " << (*this)[i].row_dim().sum_of_sizes() << std::endl;
43  oss << (*this)[i].col_dim() << std::endl;
44  oss << "Sum: " << (*this)[i].col_dim().sum_of_sizes() << std::endl;
45  }
46  return oss.str();
47 }
48 
49 template<class Matrix, class SymmGroup>
51 : canonized_i(std::numeric_limits<size_t>::max())
52 { }
53 
54 template<class Matrix, class SymmGroup>
56 : data_(L)
57 , canonized_i(std::numeric_limits<size_t>::max())
58 { }
59 
60 template<class Matrix, class SymmGroup>
62 : data_(L)
63 , canonized_i(std::numeric_limits<size_t>::max())
64 {
65  init(*this);
66 
67  // MD: this is actually important
68  // it turned out, this is also quite dangerous: if a block is 1x2,
69  // normalize_left will resize it to 1x1
70  // init() should take care of it, in case needed. Otherwise some
71  // adhoc states will be broken (e.g. identity MPS)
72  // for (int i = 0; i < L; ++i)
73  // (*this)[i].normalize_left(DefaultSolver());
74 
75  this->normalize_left();
76 }
77 
78 template<class Matrix, class SymmGroup>
80 { return data_[i]; }
81 
82 template<class Matrix, class SymmGroup>
84 {
85  if (i != canonized_i)
86  canonized_i=std::numeric_limits<size_t>::max();
87  return data_[i];
88 }
89 
90 template<class Matrix, class SymmGroup>
92 {
93  // if canonized_i < L and L < current L, we could conserve canonized_i
94  canonized_i=std::numeric_limits<size_t>::max();
95  data_.resize(L);
96 }
97 
98 template<class Matrix, class SymmGroup>
99 size_t MPS<Matrix, SymmGroup>::canonization(bool search) const
100 {
101  if (!search)
102  return canonized_i;
103 
104  size_t center = ((*this)[0].isleftnormalized()) ? 1 : 0;
105  for (size_t i=1; i<length(); ++i) {
106  if (!(*this)[i].isnormalized() && center != i) {
107  canonized_i = std::numeric_limits<size_t>::max();
108  return canonized_i;
109  } else if ((*this)[i].isleftnormalized() && center == i)
110  center = i+1;
111  else if ((*this)[i].isleftnormalized()) {
112  canonized_i = std::numeric_limits<size_t>::max();
113  return canonized_i;
114  }
115  }
116  if (center == length())
117  center = length()-1;
118 
119  canonized_i = center;
120  return canonized_i;
121 }
122 
123 template<class Matrix, class SymmGroup>
125 {
126  canonize(length()-1);
127  // now state is: A A A A A A M
128  block_matrix<Matrix, SymmGroup> t = (*this)[length()-1].normalize_left(DefaultSolver());
129  // now state is: A A A A A A A
130  canonized_i = length()-1;
131 }
132 
133 template<class Matrix, class SymmGroup>
135 {
136  canonize(0);
137  // now state is: M B B B B B B
138  block_matrix<Matrix, SymmGroup> t = (*this)[0].normalize_right(DefaultSolver());
139  // now state is: B B B B B B B
140  canonized_i = 0;
141 }
142 
143 // input: M M M M M M M
144 // (idx) c
145 // output: A A M B B B B
146 template<class Matrix, class SymmGroup>
147 void MPS<Matrix, SymmGroup>::canonize(std::size_t center, DecompMethod method)
148 {
149  if (canonized_i == center)
150  return;
151 
152  if (canonized_i < center)
153  move_normalization_l2r(canonized_i, center, method);
154  else if (canonized_i < length())
155  move_normalization_r2l(canonized_i, center, method);
156  else {
157  move_normalization_l2r(0, center, method);
158  move_normalization_r2l(length()-1, center, method);
159  }
160  canonized_i = center;
161 }
162 
163 // input: M M M M M M M
164 // (idx) p1 p2
165 // output: M A A A M M M
166 template<class Matrix, class SymmGroup>
168 {
169  size_t tmp_i = canonized_i;
170  for (int i = p1; i < std::min(p2, length()); ++i)
171  {
172  if ((*this)[i].isleftnormalized())
173  continue;
174  block_matrix<Matrix, SymmGroup> t = (*this)[i].normalize_left(method);
175  if (i < length()-1) {
176  (*this)[i+1].multiply_from_left(t);
177  (*this)[i+1].divide_by_scalar((*this)[i+1].scalar_norm());
178  }
179  }
180  if (tmp_i == p1)
181  canonized_i = p2;
182  else
183  canonized_i = std::numeric_limits<size_t>::max();
184 }
185 
186 // input: M M M M M M M
187 // (idx) p2 p1
188 // output: M M B B B M M
189 template<class Matrix, class SymmGroup>
191 {
192  size_t tmp_i = canonized_i;
193  for (int i = p1; i > static_cast<int>(std::max(p2, size_t(0))); --i)
194  {
195  if ((*this)[i].isrightnormalized())
196  continue;
197  block_matrix<Matrix, SymmGroup> t = (*this)[i].normalize_right(method);
198  if (i > 0) {
199  (*this)[i-1].multiply_from_right(t);
200  (*this)[i-1].divide_by_scalar((*this)[i-1].scalar_norm());
201  }
202  }
203  if (tmp_i == p1)
204  canonized_i = p2;
205  else
206  canonized_i = std::numeric_limits<size_t>::max();
207 }
208 
209 template<class Matrix, class SymmGroup>
210 template<class OtherMatrix>
214  Boundary<OtherMatrix, SymmGroup> const & right,
215  std::size_t l, double alpha,
216  double cutoff, std::size_t Mmax)
217 { // canonized_i invalided through (*this)[]
219  truncation_results trunc;
220 
221  boost::tie(new_mps, trunc) =
222  contraction::predict_new_state_l2r_sweep((*this)[l], mpo, left, right, alpha, cutoff, Mmax);
223 
224  (*this)[l+1] = contraction::predict_lanczos_l2r_sweep((*this)[l+1],
225  (*this)[l], new_mps);
226  (*this)[l] = new_mps;
227  return trunc;
228 }
229 
230 template<class Matrix, class SymmGroup>
231 template<class OtherMatrix>
235  Boundary<OtherMatrix, SymmGroup> const & right,
236  std::size_t l, double alpha,
237  double cutoff, std::size_t Mmax)
238 { // canonized_i invalided through (*this)[]
240  truncation_results trunc;
241 
242  boost::tie(new_mps, trunc) =
243  contraction::predict_new_state_r2l_sweep((*this)[l], mpo, left, right, alpha, cutoff, Mmax);
244 
245  (*this)[l-1] = contraction::predict_lanczos_r2l_sweep((*this)[l-1],
246  (*this)[l], new_mps);
247  (*this)[l] = new_mps;
248  return trunc;
249 }
250 
251 template<class Matrix, class SymmGroup>
254 {
255  Index<SymmGroup> i = (*this)[0].row_dim();
256  Boundary<Matrix, SymmGroup> ret(i, i, 1);
257 
258  for(std::size_t k(0); k < ret[0].n_blocks(); ++k)
260 
261  return ret;
262 }
263 
264 template<class Matrix, class SymmGroup>
267 {
268  Index<SymmGroup> i = (*this)[length()-1].col_dim();
269  Boundary<Matrix, SymmGroup> ret(i, i, 1);
270 
271 // Original
272 // for(typename Index<SymmGroup>::basis_iterator it = i.basis_begin(); !it.end(); ++it)
273 // ret(0,*it,*it) = 1;
274 
275  for(std::size_t k(0); k < ret[0].n_blocks(); ++k)
277 
278  return ret;
279 }
280 
281 template<class Matrix, class SymmGroup>
283 {
284  typedef typename SymmGroup::charge charge;
285  using std::size_t;
286 
287  /// Compute (and check) charge difference
288  charge diff = SymmGroup::IdentityCharge;
289  if (op.n_blocks() > 0)
290  diff = SymmGroup::fuse(op.right_basis()[0].first, -op.left_basis()[0].first);
291  for (size_t n=0; n< op.n_blocks(); ++n) {
292  if ( SymmGroup::fuse(op.right_basis()[n].first, -op.left_basis()[n].first) != diff )
293  throw std::runtime_error("Operator not allowed. All non-zero blocks have to provide same `diff`.");
294  }
295 
296  /// Apply operator
297  (*this)[p] = contraction::multiply_with_op((*this)[p], op);
298 
299  /// Propagate charge difference
300  for (size_t i=p+1; i<length(); ++i) {
301  (*this)[i].shift_aux_charges(diff);
302  }
303 }
304 
305 template<class Matrix, class SymmGroup>
307 {
308  for (size_t i=0; i<p; ++i) {
309  (*this)[i] = contraction::multiply_with_op((*this)[i], fill);
310  }
311  apply(op, p);
312 }
313 
314 template<class Matrix, class SymmGroup>
315 void load(std::string const& dirname, MPS<Matrix, SymmGroup> & mps)
316 {
317  /// get size of MPS
318  std::size_t L = 0;
319  while (boost::filesystem::exists( dirname + "/mps" + boost::lexical_cast<std::string>(++L) + ".h5" ));
320 
321  /// load tensors
322  MPS<Matrix, SymmGroup> tmp(L);
323  size_t loop_max = tmp.length();
324  semi_parallel_for(/*removed...*/, std::size_t k = 0; k < loop_max; ++k){
325  std::string fname = dirname+"/mps"+boost::lexical_cast<std::string>((size_t)k)+".h5";
326  storage::archive ar(fname);
327  ar["/tensor"] >> tmp[k];
328  }
329  swap(mps, tmp);
330 }
331 
332 template<class Matrix, class SymmGroup>
333 void save(std::string const& dirname, MPS<Matrix, SymmGroup> const& mps)
334 {
335  size_t loop_max = mps.length();
336  parallel_for(/*removed...*/, std::size_t k = 0; k < loop_max; ++k){
337  const std::string fname = dirname+"/mps"+boost::lexical_cast<std::string>((size_t)k)+".h5.new";
338  storage::archive ar(fname, "w");
339  ar["/tensor"] << mps[k];
340  }
341  parallel_for(/*removed...*/, std::size_t k = 0; k < loop_max; ++k){
342  const std::string fname = dirname+"/mps"+boost::lexical_cast<std::string>((size_t)k)+".h5";
343  boost::filesystem::rename(fname+".new", fname);
344  }
345 }
346 
347 template <class Matrix, class SymmGroup>
349 {
350  // Length
351  if (mps1.length() != mps2.length())
352  throw std::runtime_error("Length doesn't match.");
353 
354  for (int i=0; i<mps1.length(); ++i)
355  try {
356  mps1[i].check_equal(mps2[i]);
357  } catch (std::exception & e) {
358  maquis::cerr << "Problem on site " << i << ":" << e.what() << std::endl;
359  exit(1);
360  }
361 }
362 
363 
void move_normalization_l2r(size_t p1, size_t p2, DecompMethod method=DefaultSolver())
Definition: mps.hpp:167
std::size_t size_t
Definition: mps.h:44
static MPSTensor< Matrix, SymmGroup > predict_lanczos_l2r_sweep(MPSTensor< Matrix, SymmGroup > B, MPSTensor< Matrix, SymmGroup > const &psi, MPSTensor< Matrix, SymmGroup > const &A)
Definition: contractions.h:548
void normalize_left()
Definition: mps.hpp:124
void move_normalization_r2l(size_t p1, size_t p2, DecompMethod method=DefaultSolver())
Definition: mps.hpp:190
truncation_results grow_r2l_sweep(MPOTensor< Matrix, SymmGroup > const &mpo, Boundary< OtherMatrix, SymmGroup > const &left, Boundary< OtherMatrix, SymmGroup > const &right, std::size_t l, double alpha, double cutoff, std::size_t Mmax)
Definition: mps.hpp:233
size_type n_blocks() const
declaration of the MPS class (vector of MPSTensor)
void check_equal_mps(MPS< Matrix, SymmGroup > const &mps1, MPS< Matrix, SymmGroup > const &mps2)
Definition: mps.hpp:348
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
void save(std::string const &dirname, MPS< Matrix, SymmGroup > const &mps)
Definition: mps.hpp:333
Boundary< Matrix, SymmGroup > left_boundary() const
Definition: mps.hpp:253
size_t canonization(bool=false) const
Definition: mps.hpp:99
data_t::size_type size_type
Definition: mps.h:47
Boundary< Matrix, SymmGroup > right_boundary() const
Definition: mps.hpp:266
#define semi_parallel_for(constraint,...)
DecompMethod
Definition: mpstensor.h:41
static std::pair< MPSTensor< Matrix, SymmGroup >, truncation_results > predict_new_state_l2r_sweep(MPSTensor< Matrix, SymmGroup > const &mps, MPOTensor< Matrix, SymmGroup > const &mpo, Boundary< OtherMatrix, SymmGroup > const &left, Boundary< OtherMatrix, SymmGroup > const &right, double alpha, double cutoff, std::size_t Mmax)
Definition: contractions.h:507
data_t::value_type value_type
Definition: mps.h:48
MPS()
Definition: mps.hpp:50
Definition: mps.h:40
#define parallel_for(constraint,...)
void apply(block_matrix< Matrix, SymmGroup > const &, size_type)
void left_right_boundary_init(alps::numeric::matrix< T, A > &M)
static MPSTensor< Matrix, SymmGroup > multiply_with_op(MPSTensor< Matrix, SymmGroup > const &mps, block_matrix< Matrix, SymmGroup > const &op)
Definition: contractions.h:690
void normalize_right()
Definition: mps.hpp:134
static std::pair< MPSTensor< Matrix, SymmGroup >, truncation_results > predict_new_state_r2l_sweep(MPSTensor< Matrix, SymmGroup > const &mps, MPOTensor< Matrix, SymmGroup > const &mpo, Boundary< OtherMatrix, SymmGroup > const &left, Boundary< OtherMatrix, SymmGroup > const &right, double alpha, double cutoff, std::size_t Mmax)
Definition: contractions.h:564
Index< SymmGroup > const & right_basis() const
size_t length() const
Definition: mps.h:58
std::string description() const
Definition: mps.hpp:35
void canonize(size_t center, DecompMethod method=DefaultSolver())
Definition: mps.hpp:147
void load(std::string const &dirname, MPS< Matrix, SymmGroup > &mps)
Definition: mps.hpp:315
void resize(size_t L)
Definition: mps.hpp:91
value_type const & operator[](size_t i) const
Definition: mps.hpp:79
static MPSTensor< Matrix, SymmGroup > predict_lanczos_r2l_sweep(MPSTensor< Matrix, SymmGroup > B, MPSTensor< Matrix, SymmGroup > const &psi, MPSTensor< Matrix, SymmGroup > const &A)
Definition: contractions.h:605
Index< SymmGroup > const & left_basis() const
truncation_results grow_l2r_sweep(MPOTensor< Matrix, SymmGroup > const &mpo, Boundary< OtherMatrix, SymmGroup > const &left, Boundary< OtherMatrix, SymmGroup > const &right, std::size_t l, double alpha, double cutoff, std::size_t Mmax)
Definition: mps.hpp:212
functions to contract tensor network states
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.