ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ts_reshape.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  * 2011-2011 by Sebastian Keller <sebkelle@phys.ethz.ch>
7  * Michele Dolfi <dolfim@phys.ethz.ch>
8  *
9  * This software is part of the ALPS Applications, published under the ALPS
10  * Application License; you can use, redistribute it and/or modify it under
11  * the terms of the license, either version 1 or (at your option) any later
12  * version.
13  *
14  * You should have received a copy of the ALPS Application License along with
15  * the ALPS Applications; see the file LICENSE.txt. If not, the license is also
16  * available from http://alps.comp-phys.org/.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
21  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
22  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  *****************************************************************************/
27 
28 #include "twositetensor.h"
30 
33 
34 #include "dmrg/utils/random.hpp"
35 #include <alps/numeric/real.hpp>
36 
37 #include <vector>
38 #include <utility>
39 
40 namespace ts_reshape {
41 
42  template<class Matrix, class SymmGroup>
43  void reshape_both_to_left(Index<SymmGroup> const & physical_i_left,
44  Index<SymmGroup> const & physical_i_right,
45  Index<SymmGroup> const & left_i,
46  Index<SymmGroup> const & right_i,
49  {
50 
52 
53  typedef std::size_t size_t;
54  typedef typename SymmGroup::charge charge;
55 
56  Index<SymmGroup> phys2_i = physical_i_left*physical_i_right;
57  ProductBasis<SymmGroup> phys_pb(physical_i_left, physical_i_right);
58  ProductBasis<SymmGroup> in_left(physical_i_left, left_i);
59  ProductBasis<SymmGroup> in_right(physical_i_right, right_i,
60  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
61  -boost::lambda::_1, boost::lambda::_2));
62  ProductBasis<SymmGroup> out_left(phys2_i, left_i);
63 
64 
65  for (size_t block = 0; block < m1.n_blocks(); ++block)
66  {
67  for (size_t s1 = 0; s1 < physical_i_left.size(); ++s1)
68  for (size_t s2 = 0; s2 < physical_i_right.size(); ++s2)
69  {
70  size_t l = left_i.position(SymmGroup::fuse(m1.left_basis()[block].first,
71  -physical_i_left[s1].first));
72  if(l == left_i.size()) continue;
73  size_t r = right_i.position(SymmGroup::fuse(m1.right_basis()[block].first,
74  physical_i_right[s2].first));
75  if(r == right_i.size()) continue;
76 
77  {
78  charge s_charge = SymmGroup::fuse(physical_i_left[s1].first, physical_i_right[s2].first);
79  //size_t s_out = phys2_i.position(s_charge);
80 
81  //charge in_l_charge = SymmGroup::fuse(physical_i_left[s1].first, left_i[l].first);
82  //charge in_r_charge = SymmGroup::fuse(-physical_i_right[s2].first, right_i[r].first);
83  charge out_l_charge = SymmGroup::fuse(s_charge, left_i[l].first);
84  charge out_r_charge = right_i[r].first;
85 
86  //if (! m1.has_block(in_l_charge, in_r_charge) ) continue;
87 
88  // Why is this supposed to work?
89  if (! m2.has_block(out_l_charge, out_r_charge) )
90  m2.insert_block(new Matrix(out_left.size(s_charge, left_i[l].first), right_i[r].second, 0),
91  out_l_charge, out_r_charge);
92 
93  //maquis::dmrg::detail::reshape_b2l( m2(out_l_charge, out_r_charge), m1(in_l_charge, in_r_charge),
94  maquis::dmrg::detail::reshape_b2l( m2(out_l_charge, out_r_charge), m1[block],
95  in_left(physical_i_left[s1].first, left_i[l].first), in_right(physical_i_right[s2].first, right_i[r].first),
96  out_left(s_charge, left_i[l].first), phys_pb(physical_i_left[s1].first, physical_i_right[s2].first),
97  physical_i_left[s1].second, physical_i_right[s2].second, left_i[l].second, right_i[r].second );
98  }
99  }
100  }
101 
102  }
103 
104  /*
105  template<class Matrix, class SymmGroup>
106  void reshape_right_to_left(Index<SymmGroup> physical_i,
107  Index<SymmGroup> left_i,
108  Index<SymmGroup> right_i,
109  block_matrix<Matrix, SymmGroup> const & m1,
110  block_matrix<Matrix, SymmGroup> & m2)
111  { }
112  */
113 
114  template<class Matrix, class SymmGroup>
115  void reshape_left_to_both(Index<SymmGroup> const & physical_i_left,
116  Index<SymmGroup> const & physical_i_right,
117  Index<SymmGroup> const & left_i,
118  Index<SymmGroup> const & right_i,
121  {
122 
124 
125  typedef std::size_t size_t;
126  typedef typename SymmGroup::charge charge;
127 
128  Index<SymmGroup> phys2_i = physical_i_left*physical_i_right;
129  ProductBasis<SymmGroup> phys_pb(physical_i_left, physical_i_right);
130  ProductBasis<SymmGroup> in_left(phys2_i, left_i);
131 
132  ProductBasis<SymmGroup> out_right(physical_i_right, right_i,
133  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
134  -boost::lambda::_1, boost::lambda::_2));
135  ProductBasis<SymmGroup> out_left(physical_i_left, left_i);
136 
137  for (size_t block = 0; block < m1.n_blocks(); ++block)
138  {
139  size_t r = right_i.position(m1.right_basis()[block].first);
140  if(r == right_i.size()) continue;
141 
142  for (size_t s1 = 0; s1 < physical_i_left.size(); ++s1)
143  for (size_t s2 = 0; s2 < physical_i_right.size(); ++s2)
144  {
145  charge s_charge = SymmGroup::fuse(physical_i_left[s1].first, physical_i_right[s2].first);
146  //size_t s_out = phys2_i.position(s_charge);
147 
148  size_t l = left_i.position(SymmGroup::fuse(m1.left_basis()[block].first, -s_charge));
149  if(l == left_i.size()) continue;
150 
151  {
152  charge out_l_charge = SymmGroup::fuse(physical_i_left[s1].first, left_i[l].first);
153  charge out_r_charge = SymmGroup::fuse(-physical_i_right[s2].first, right_i[r].first);
154  //charge in_l_charge = SymmGroup::fuse(s_charge, left_i[l].first);
155  //charge in_r_charge = right_i[r].first;
156 
157  //if (! m1.has_block(in_l_charge, in_r_charge) ) continue;
158 
159  if (! m2.has_block(out_l_charge, out_r_charge) )
160  m2.insert_block(new Matrix(out_left.size(physical_i_left[s1].first, left_i[l].first),
161  out_right.size(-physical_i_right[s2].first, right_i[r].first), 0),
162  out_l_charge, out_r_charge);
163 
164  //maquis::dmrg::detail::reshape_l2b( m2(out_l_charge, out_r_charge), m1(in_l_charge, in_r_charge),
165  maquis::dmrg::detail::reshape_l2b( m2(out_l_charge, out_r_charge), m1[block],
166  in_left(s_charge, left_i[l].first), phys_pb(physical_i_left[s1].first, physical_i_right[s2].first),
167  out_left(physical_i_left[s1].first, left_i[l].first), out_right(physical_i_right[s2].first, right_i[r].first),
168  physical_i_left[s1].second, physical_i_right[s2].second, left_i[l].second, right_i[r].second );
169  }
170  }
171  }
172 
173  }
174 
175  template<class Matrix, class SymmGroup>
176  void reshape_right_to_both(Index<SymmGroup> const & physical_i_left,
177  Index<SymmGroup> const & physical_i_right,
178  Index<SymmGroup> const & left_i,
179  Index<SymmGroup> const & right_i,
182  {
183 
185 
186  typedef std::size_t size_t;
187  typedef typename SymmGroup::charge charge;
188 
189  Index<SymmGroup> phys2_i = physical_i_left*physical_i_right;
190  ProductBasis<SymmGroup> phys_pb(physical_i_left, physical_i_right);
191  ProductBasis<SymmGroup> in_right(phys2_i, right_i,
192  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
193  -boost::lambda::_1, boost::lambda::_2));
194 
195  ProductBasis<SymmGroup> out_right(physical_i_right, right_i,
196  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
197  -boost::lambda::_1, boost::lambda::_2));
198  ProductBasis<SymmGroup> out_left(physical_i_left, left_i);
199 
200  for (size_t block = 0; block < m1.n_blocks(); ++block)
201  {
202  size_t l = left_i.position(m1.left_basis()[block].first);
203  if(l == left_i.size()) continue;
204 
205  for (size_t s1 = 0; s1 < physical_i_left.size(); ++s1)
206  for (size_t s2 = 0; s2 < physical_i_right.size(); ++s2)
207  {
208  charge s_charge = SymmGroup::fuse(physical_i_left[s1].first, physical_i_right[s2].first);
209  //size_t s_out = phys2_i.position(s_charge);
210  size_t r = right_i.position(SymmGroup::fuse(m1.right_basis()[block].first, s_charge));
211  if(r == right_i.size()) continue;
212 
213  {
214  charge out_l_charge = SymmGroup::fuse(physical_i_left[s1].first, left_i[l].first);
215  charge out_r_charge = SymmGroup::fuse(-physical_i_right[s2].first, right_i[r].first);
216  //charge in_l_charge = left_i[l].first;
217  //charge in_r_charge = SymmGroup::fuse(-s_charge, right_i[r].first);
218 
219  //if (! m1.has_block(in_l_charge, in_r_charge) ) continue;
220 
221  if (! m2.has_block(out_l_charge, out_r_charge) )
222  m2.insert_block(new Matrix(out_left.size(physical_i_left[s1].first, left_i[l].first),
223  out_right.size(-physical_i_right[s2].first, right_i[r].first), 0),
224  out_l_charge, out_r_charge);
225 
226  size_t in_right_offset = in_right (s_charge , right_i[r].first);
227  size_t out_right_offset = out_right (physical_i_right[s2].first, right_i[r].first);
228  size_t out_left_offset = out_left (physical_i_left[s1].first, left_i[l].first);
229  size_t in_phys_offset = phys_pb (physical_i_left[s1].first, physical_i_right[s2].first);
230 
231  //Matrix const & in_block = m1(in_l_charge, in_r_charge);
232  Matrix const & in_block = m1[block];
233  Matrix & out_block = m2(out_l_charge, out_r_charge);
234 
235  for (size_t ss1 = 0; ss1 < physical_i_left[s1].second; ++ss1)
236  for (size_t ss2 = 0; ss2 < physical_i_right[s2].second; ++ss2)
237  {
238  size_t ss_out = in_phys_offset + ss1*physical_i_right[s2].second + ss2;
239  for (size_t rr = 0; rr < right_i[r].second; ++rr)
240  for (size_t ll = 0; ll < left_i[l].second; ++ll)
241  out_block(out_left_offset + ss1*left_i[l].second + ll, out_right_offset + ss2*right_i[r].second + rr) = in_block(ll, in_right_offset + ss_out*right_i[r].second + rr);
242  }
243 
244  }
245  }
246  }
247  }
248 
249  /*
250  template<class Matrix, class SymmGroup>
251  void reshape_left_to_right(Index<SymmGroup> physical_i,
252  Index<SymmGroup> left_i,
253  Index<SymmGroup> right_i,
254  block_matrix<Matrix, SymmGroup> const & m1,
255  block_matrix<Matrix, SymmGroup> & m2)
256  { }
257  */
258 
259  template<class Matrix, class SymmGroup>
260  void reshape_both_to_right(Index<SymmGroup> const & physical_i_left,
261  Index<SymmGroup> const & physical_i_right,
262  Index<SymmGroup> const & left_i,
263  Index<SymmGroup> const & right_i,
266  {
267 
269 
270  typedef std::size_t size_t;
271  typedef typename SymmGroup::charge charge;
272 
273  Index<SymmGroup> phys2_i = physical_i_left*physical_i_right;
274  ProductBasis<SymmGroup> phys_pb(physical_i_left, physical_i_right);
275  ProductBasis<SymmGroup> in_left(physical_i_left, left_i);
276  ProductBasis<SymmGroup> in_right(physical_i_right, right_i,
277  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
278  -boost::lambda::_1, boost::lambda::_2));
279  ProductBasis<SymmGroup> out_right(phys2_i, right_i,
280  boost::lambda::bind(static_cast<charge(*)(charge, charge)>(SymmGroup::fuse),
281  -boost::lambda::_1, boost::lambda::_2));
282 
283  for (size_t block = 0; block < m1.n_blocks(); ++block)
284  {
285  for (size_t s1 = 0; s1 < physical_i_left.size(); ++s1)
286  {
287  size_t l = left_i.position(SymmGroup::fuse(m1.left_basis()[block].first,
288  -physical_i_left[s1].first));
289  if(l == left_i.size()) continue;
290 
291  for (size_t s2 = 0; s2 < physical_i_right.size(); ++s2)
292  {
293  size_t r = right_i.position(SymmGroup::fuse(m1.right_basis()[block].first,
294  physical_i_right[s2].first));
295  if(r == right_i.size()) continue;
296 
297  {
298  charge s_charge = SymmGroup::fuse(physical_i_left[s1].first, physical_i_right[s2].first);
299  //size_t s_out = phys2_i.position(s_charge);
300 
301  //charge in_l_charge = SymmGroup::fuse(physical_i_left[s1].first, left_i[l].first);
302  //charge in_r_charge = SymmGroup::fuse(-physical_i_right[s2].first, right_i[r].first);
303  charge out_l_charge = left_i[l].first;
304  charge out_r_charge = SymmGroup::fuse(-s_charge, right_i[r].first);
305 
306  //if (! m1.has_block(in_l_charge, in_r_charge) ) continue;
307 
308  if (! m2.has_block(out_l_charge, out_r_charge) )
309  m2.insert_block(new Matrix(left_i[l].second, out_right.size(-s_charge, right_i[r].first), 0),
310  out_l_charge, out_r_charge);
311 
312  size_t in_left_offset = in_left(physical_i_left[s1].first, left_i[l].first);
313  size_t in_right_offset = in_right(physical_i_right[s2].first, right_i[r].first);
314  size_t out_right_offset = out_right(s_charge, right_i[r].first);
315  size_t out_phys_offset = phys_pb(physical_i_left[s1].first, physical_i_right[s2].first);
316 
317  //Matrix const & in_block = m1(in_l_charge, in_r_charge);
318  Matrix const & in_block = m1[block];
319  Matrix & out_block = m2(out_l_charge, out_r_charge);
320 
321  for (size_t ss1 = 0; ss1 < physical_i_left[s1].second; ++ss1)
322  for (size_t ss2 = 0; ss2 < physical_i_right[s2].second; ++ss2)
323  {
324  size_t ss_out = out_phys_offset + ss1*physical_i_right[s2].second + ss2;
325  for (size_t rr = 0; rr < right_i[r].second; ++rr)
326  for (size_t ll = 0; ll < left_i[l].second; ++ll)
327  out_block(ll, out_right_offset + ss_out*right_i[r].second + rr) = in_block(in_left_offset + ss1*left_i[l].second+ll, in_right_offset + ss2*right_i[r].second+rr);
328  }
329  }
330  }
331  }
332  }
333 
334  }
335 
336 } // namespace ts_reshape
size_type n_blocks() const
void reshape_l2b(alps::numeric::matrix< T, A > &out, const alps::numeric::matrix< T, A > &in, size_t in_left_offset, size_t in_phys_offset, size_t out_left_offset, size_t out_right_offset, size_t sdim1, size_t sdim2, size_t ldim, size_t rdim)
Definition: alps_detail.hpp:79
size_t size(charge pc) const
size_type insert_block(Matrix const &, charge, charge)
void reshape_both_to_right(Index< SymmGroup > const &physical_i_left, Index< SymmGroup > const &physical_i_right, Index< SymmGroup > const &left_i, Index< SymmGroup > const &right_i, block_matrix< Matrix, SymmGroup > const &m1, block_matrix< Matrix, SymmGroup > &m2)
Definition: ts_reshape.h:260
declaration of the TwoSiteTensor class
declaration of the MPSTensor class
bool has_block(charge r, charge c) const
Index< SymmGroup > const & right_basis() const
void reshape_b2l(alps::numeric::matrix< T, A > &out, const alps::numeric::matrix< T, A > &in, size_t in_left_offset, size_t in_right_offset, size_t out_left_offset, size_t out_phys_offset, size_t sdim1, size_t sdim2, size_t ldim, size_t rdim)
Definition: alps_detail.hpp:96
std::size_t position(charge c) const
void reshape_both_to_left(Index< SymmGroup > const &physical_i_left, Index< SymmGroup > const &physical_i_right, Index< SymmGroup > const &left_i, Index< SymmGroup > const &right_i, block_matrix< Matrix, SymmGroup > const &m1, block_matrix< Matrix, SymmGroup > &m2)
Definition: ts_reshape.h:43
algorithms for block_matrix (gemm, svd, etc.)
void reshape_right_to_both(Index< SymmGroup > const &physical_i_left, Index< SymmGroup > const &physical_i_right, Index< SymmGroup > const &left_i, Index< SymmGroup > const &right_i, block_matrix< Matrix, SymmGroup > const &m1, block_matrix< Matrix, SymmGroup > &m2)
Definition: ts_reshape.h:176
functions to reshape the representation of data in MPSTensor
Index< SymmGroup > const & left_basis() const
std::size_t size() const
void reshape_left_to_both(Index< SymmGroup > const &physical_i_left, Index< SymmGroup > const &physical_i_right, Index< SymmGroup > const &left_i, Index< SymmGroup > const &right_i, block_matrix< Matrix, SymmGroup > const &m1, block_matrix< Matrix, SymmGroup > &m2)
Definition: ts_reshape.h:115
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.