ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
corr_maker.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 #ifndef GENERATE_MPO_CORR_MAKER_H
28 #define GENERATE_MPO_CORR_MAKER_H
29 
31 
35 
36 #include "dmrg/mp_tensors/mpo.h"
37 
38 #include "dmrg/models/lattice.h"
39 #include "dmrg/models/op_handler.h"
40 
41 #include <string>
42 #include <sstream>
43 
44 namespace generate_mpo
45 {
46  template<class Matrix, class SymmGroup>
47  class CorrMakerBase {
48  public:
49  virtual ~CorrMakerBase() {}
51  virtual std::string description () const=0;
52  virtual vector<vector<size_t> > const& numeric_labels()=0;
53  };
54 
55  template<class Matrix, class SymmGroup>
56  class CorrMaker : public CorrMakerBase<Matrix, SymmGroup>
57  {
58  typedef tag_detail::tag_type tag_type;
60  typedef boost::tuple<size_t, size_t, tag_type, typename Matrix::value_type> block;
61  typedef boost::tuple<size_t, size_t, string> tag;
62 
63  public:
64  CorrMaker(Lattice const& lat_,
65  const std::vector<op_t> & ident_,
66  const std::vector<op_t> & fill_,
67  std::vector<std::pair<std::vector<op_t>, bool> > const & ops,
68  int ref = -1)
69  : lat(lat_)
70  , prempo(lat.size())
71  , tags(lat.size())
72  , used(lat.size())
73  , with_sign(lat.size()+2)
74  , identities(ident_.size())
75  , fillings(fill_.size())
76  , op_tags(ops.size())
77  {
78  /// register operators
79  for (int type=0; type<ident_.size(); ++type)
80  identities[type] = tag_handler.register_op(ident_[type], tag_detail::bosonic);
81  for (int type=0; type<fill_.size(); ++type)
82  fillings[type] = tag_handler.register_op(fill_[type], tag_detail::bosonic);
83 
84  for (size_t n=0; n<ops.size(); ++n) {
85  op_tags[n].first.resize(ops[n].first.size());
86  op_tags[n].second = ops[n].second;
87  std::vector<tag_type> & tops = op_tags[n].first;
88  for (int type=0; type<tops.size(); ++type)
89  tops[type] = tag_handler.register_op(ops[n].first[type], ops[n].second ? tag_detail::fermionic : tag_detail::bosonic);
90  }
91 
92  with_sign[0][0] = false;
93  recurse(0, 0, 0, std::vector<size_t>(), ref);
94  }
95 
97  {
98  MPO<Matrix, SymmGroup> r(prempo.size());
99  for (size_t p = 1; p < prempo.size()-1; ++p)
100  r[p] = as_bulk(prempo[p]);
101  r[0] = as_left(prempo[0]);
102  r[prempo.size()-1] = as_right(*prempo.rbegin());
103 
104  return r;
105  }
106 
107  std::string description () const
108  {
109  std::ostringstream ss;
110  for (size_t p = 0; p < prempo.size(); ++p)
111  {
112  ss << "Site: " << p << std::endl;
113  for (typename vector<tag>::const_iterator it = tags[p].begin(); it != tags[p].end(); ++it)
114  ss << " " << get<0>(*it) << " " << get<1>(*it) << " " << get<2>(*it) << std::endl;
115  }
116  return ss.str();
117  }
118 
119  vector<vector<size_t> > const& numeric_labels() { return labels; }
120 
121  private:
122  Lattice const& lat;
123  TagHandler<Matrix, SymmGroup> tag_handler;
124 
125  vector<vector<block> > prempo;
126  vector<vector<tag> > tags;
127  vector<vector<size_t> > labels;
128 
129  vector<set<size_t> > used;
130  vector<map<size_t, bool> > with_sign;
131  std::vector<tag_type> identities, fillings;
132  // TODO: use just vector<tag_type>, as there is the is_fermionic() function in TagHandler
133  vector<std::pair<std::vector<tag_type>, bool> > op_tags;
134 
135  size_t term(size_t p, size_t u1, std::pair<std::vector<tag_type>, bool> const & op_p, bool trivial)
136  {
137  std::string lab;
138  tag_type op;
139  typename Matrix::value_type scale;
140  if (trivial) {
141  op = (with_sign[p][u1]) ? fillings[lat.get_prop<int>("type", p)] : identities[lat.get_prop<int>("type", p)];
142  scale = 1.;
143  lab = (with_sign[p][u1]) ? "filling" : "ident";
144  } else {
145  lab = "nontriv";
146  if (!with_sign[p][u1] && op_p.second) {
147  //gemm(fill, op_p.first, op);
148  boost::tie(op, scale) = tag_handler.get_product_tag(fillings[lat.get_prop<int>("type", p)], op_p.first[lat.get_prop<int>("type", p)]);
149  lab += "*fill";
150  } else if (with_sign[p][u1] && !op_p.second) {
151  //gemm(fill, op_p.first, op);
152  boost::tie(op, scale) = tag_handler.get_product_tag(fillings[lat.get_prop<int>("type", p)], op_p.first[lat.get_prop<int>("type", p)]);
153  lab += "*fill";
154  } else {
155  op = op_p.first[lat.get_prop<int>("type", p)];
156  scale = 1.;
157  }
158  }
159 
160  size_t u2 = 0;
161  while (used[p].count(u2) > 0) ++u2;
162  prempo[p].push_back( boost::make_tuple(u1, u2, op, scale) );
163  used[p].insert(u2);
164  with_sign[p+1][u2] = (op_p.second) ? !with_sign[p][u1] : with_sign[p][u1];
165  // maquis::cout << "Adding a " << lab << " term at " << p << ", " << u1 << " -> " << u2 << std::endl;
166  // maquis::cout << op;
167  if (trivial)
168  tags[p].push_back( boost::make_tuple(u1, u2, lab) );
169  else
170  tags[p].push_back( boost::make_tuple(u1, u2, lab) );
171  return u2;
172  }
173 
174  void recurse(size_t p0, size_t which, size_t use, vector<size_t> label, int ref)
175  {
176  if (p0 + op_tags.size() - which < prempo.size()) {
177  size_t use_next = term(p0, use, std::make_pair(identities, false), true);
178  recurse(p0+1, which, use_next, label, ref);
179  }
180 
181  {
182  if (ref >= 0 && which == 0 && p0 != ref)
183  return;
184 
185  if (tag_handler.get_op(op_tags[which].first[lat.get_prop<int>("type", p0)]).n_blocks() == 0)
186  return;
187 
188  size_t use_next = term(p0, use, op_tags[which], false);
189 
190  vector<size_t> label_(label);
191  label_.push_back(p0);
192 
193  if (which == op_tags.size()-1) {
194  size_t t1 = use_next, t2 = use_next;
195  for (size_t p2 = p0+1; p2 < prempo.size(); ++p2) {
196  t2 = term(p2, t1, std::make_pair(identities, false), true);
197  t1 = t2;
198  }
199  labels.resize(std::max(t2+1, labels.size()));
200  labels[t2] = label_;
201  } else {
202  recurse(p0+1, which+1, use_next, label_, ref);
203  }
204  }
205  }
206 
207  MPOTensor<Matrix, SymmGroup> as_bulk(vector<block> const & ops)
208  {
209  pair<size_t, size_t> rcd = rcdim(ops);
210  MPOTensor<Matrix, SymmGroup> r(rcd.first, rcd.second, ops, tag_handler.get_operator_table());
211  return r;
212  }
213 
214  MPOTensor<Matrix, SymmGroup> as_left(vector<block> const & ops)
215  {
216  pair<size_t, size_t> rcd = rcdim(ops);
217  MPOTensor<Matrix, SymmGroup> r(1, rcd.second, ops, tag_handler.get_operator_table());
218  return r;
219  }
220 
221  MPOTensor<Matrix, SymmGroup> as_right(vector<block> const & ops)
222  {
223  pair<size_t, size_t> rcd = rcdim(ops);
224  MPOTensor<Matrix, SymmGroup> r(rcd.first, rcd.second, ops, tag_handler.get_operator_table());
225  return r;
226  }
227  };
228 
229  // same as CorrMaker, but operators in ops have to be even,
230  // and are avaluated as ops[0](i)*ops[1](i+1)*ops[2](j)*ops[3](j+1)
231  template<class Matrix, class SymmGroup>
232  class CorrMakerNN : public CorrMakerBase<Matrix, SymmGroup>
233  {
234  typedef tag_detail::tag_type tag_type;
236  typedef boost::tuple<size_t, size_t, tag_type, typename Matrix::value_type> block;
237  typedef boost::tuple<size_t, size_t, string> tag;
238 
239  public:
240  CorrMakerNN(Lattice const& lat_,
241  const std::vector<op_t> & ident_,
242  const std::vector<op_t> & fill_,
243  std::vector<std::pair<std::vector<op_t>, bool> > const & ops,
244  int ref = -1)
245  : lat(lat_)
246  , prempo(lat.size())
247  , tags(lat.size())
248  , used(lat.size())
249  , with_sign(lat.size()+2)
250  , identities(ident_.size())
251  , fillings(fill_.size())
252  , op_tags(ops.size())
253  {
254  assert(ops.size() % 2 == 0);
255 
256  /// register operators
257  for (int type=0; type<ident_.size(); ++type)
258  identities[type] = tag_handler.register_op(ident_[type], tag_detail::bosonic);
259  for (int type=0; type<fill_.size(); ++type)
260  fillings[type] = tag_handler.register_op(fill_[type], tag_detail::bosonic);
261 
262  for (size_t n=0; n<ops.size(); ++n) {
263  op_tags[n].first.resize(ops[n].first.size());
264  op_tags[n].second = ops[n].second;
265  std::vector<tag_type> & tops = op_tags[n].first;
266  for (int type=0; type<tops.size(); ++type)
267  tops[type] = tag_handler.register_op(ops[n].first[type], ops[n].second ? tag_detail::fermionic : tag_detail::bosonic);
268  }
269 
270  with_sign[0][0] = false;
271  recurse(0, 0, 0, vector<size_t>(), ref);
272  }
273 
275  {
276  MPO<Matrix, SymmGroup> r(prempo.size());
277  for (size_t p = 1; p < prempo.size()-1; ++p)
278  r[p] = as_bulk(prempo[p]);
279  r[0] = as_left(prempo[0]);
280  r[prempo.size()-1] = as_right(*prempo.rbegin());
281 
282  return r;
283  }
284 
285  vector<vector<size_t> > const& numeric_labels() { return labels; }
286 
287  std::string description () const
288  {
289  std::ostringstream ss;
290  for (size_t p = 0; p < prempo.size(); ++p)
291  {
292  ss << "Site: " << p << std::endl;
293  for (typename vector<tag>::const_iterator it = tags[p].begin(); it != tags[p].end(); ++it)
294  ss << " " << get<0>(*it) << " " << get<1>(*it) << " " << get<2>(*it) << std::endl;
295  }
296  return ss.str();
297  }
298 
299  private:
300  Lattice const& lat;
301  TagHandler<Matrix, SymmGroup> tag_handler;
302 
303  vector<vector<block> > prempo;
304  vector<vector<tag> > tags;
305  vector<vector<size_t> > labels;
306 
307  vector<set<size_t> > used;
308  vector<map<size_t, bool> > with_sign;
309 
310  std::vector<tag_type> identities, fillings;
311  // TODO: use just vector<tag_type>, as there is the is_fermionic() function in TagHandler
312  vector<std::pair<std::vector<tag_type>, bool> > op_tags;
313 
314  size_t term(size_t p, size_t u1, std::pair<std::vector<tag_type>, bool> const & op_p, bool trivial)
315  {
316  std::string lab;
317  tag_type op;
318  typename Matrix::value_type scale;
319  if (trivial) {
320  op = (with_sign[p][u1]) ? fillings[lat.get_prop<int>("type", p)] : identities[lat.get_prop<int>("type", p)];
321  lab = (with_sign[p][u1]) ? "filling" : "ident";
322  } else {
323  lab = "nontriv";
324  if (!with_sign[p][u1] && op_p.second) {
325  //gemm(fill, op_p.first, op);
326  boost::tie(op, scale) = tag_handler.get_product_tag(fillings[lat.get_prop<int>("type", p)], op_p.first[lat.get_prop<int>("type", p)]);
327  lab += "*fill";
328  } else if (with_sign[p][u1] && !op_p.second) {
329  //gemm(fill, op_p.first, op);
330  boost::tie(op, scale) = tag_handler.get_product_tag(fillings[lat.get_prop<int>("type", p)], op_p.first[lat.get_prop<int>("type", p)]);
331  lab += "*fill";
332  } else {
333  op = op_p.first[lat.get_prop<int>("type", p)];
334  }
335  }
336 
337  size_t u2 = 0;
338  while (used[p].count(u2) > 0) ++u2;
339  prempo[p].push_back( boost::make_tuple(u1, u2, op, 1.0) );
340  used[p].insert(u2);
341  with_sign[p+1][u2] = (op_p.second) ? !with_sign[p][u1] : with_sign[p][u1];
342  // maquis::cout << "Adding a " << lab << " term at " << p << ", " << u1 << " -> " << u2 << std::endl;
343  // maquis::cout << op;
344  if (trivial)
345  tags[p].push_back( boost::make_tuple(u1, u2, lab) );
346  else
347  tags[p].push_back( boost::make_tuple(u1, u2, lab) );
348  return u2;
349  }
350 
351  void recurse(size_t p0, size_t which, size_t use, vector<size_t> label, int ref)
352  {
353  if (p0 + op_tags.size() - which < prempo.size()) {
354  size_t use_next = term(p0, use, std::make_pair(identities, false), true);
355  recurse(p0+1, which, use_next, label, ref);
356  }
357 
358  {
359  if (ref >= 0 && which == 0 && p0 != ref)
360  return;
361 
362  if (tag_handler.get_op(op_tags[which].first[lat.get_prop<int>("type", p0)]).n_blocks() == 0)
363  return;
364  size_t use_next = term(p0++, use, op_tags[which++], false);
365 
366  if (tag_handler.get_op(op_tags[which].first[lat.get_prop<int>("type", p0)]).n_blocks() == 0)
367  return;
368  use_next = term(p0, use_next, op_tags[which], false);
369 
370  vector<size_t> label_(label);
371  label_.push_back(p0-1);
372  label_.push_back(p0);
373 
374  if (which == op_tags.size()-1) {
375  size_t t1 = use_next, t2 = use_next;
376  for (size_t p2 = p0+1; p2 < prempo.size(); ++p2) {
377  t2 = term(p2, t1, std::make_pair(identities, false), true);
378  t1 = t2;
379  }
380  labels.resize(std::max(t2+1, labels.size()));
381  labels[t2] = label_;
382  } else {
383  recurse(p0+1, which+1, use_next, label_, ref);
384  }
385  }
386  }
387 
388  MPOTensor<Matrix, SymmGroup> as_bulk(vector<block> const & ops)
389  {
390  pair<size_t, size_t> rcd = rcdim(ops);
391  MPOTensor<Matrix, SymmGroup> r(rcd.first, rcd.second, ops, tag_handler.get_operator_table());
392  return r;
393  }
394 
395  MPOTensor<Matrix, SymmGroup> as_left(vector<block> const & ops)
396  {
397  pair<size_t, size_t> rcd = rcdim(ops);
398  MPOTensor<Matrix, SymmGroup> r(1, rcd.second, ops, tag_handler.get_operator_table());
399  return r;
400  }
401 
402  MPOTensor<Matrix, SymmGroup> as_right(vector<block> const & ops)
403  {
404  pair<size_t, size_t> rcd = rcdim(ops);
405  MPOTensor<Matrix, SymmGroup> r(rcd.first, rcd.second, ops, tag_handler.get_operator_table());
406  return r;
407  }
408  };
409 
410 }
411 
412 
413 #endif
definition of Lattice base class
CorrMakerNN(Lattice const &lat_, const std::vector< op_t > &ident_, const std::vector< op_t > &fill_, std::vector< std::pair< std::vector< op_t >, bool > > const &ops, int ref=-1)
Definition: corr_maker.hpp:240
MPO< Matrix, SymmGroup > create_mpo()
Definition: corr_maker.hpp:96
include all symmetry definitions
virtual MPO< Matrix, SymmGroup > create_mpo()=0
vector< vector< size_t > > const & numeric_labels()
Definition: corr_maker.hpp:285
declaration of block_matrix class
virtual std::string description() const =0
Definition: mpo.h:36
MPO< Matrix, SymmGroup > create_mpo()
Definition: corr_maker.hpp:274
vector< vector< size_t > > const & numeric_labels()
Definition: corr_maker.hpp:119
std::string description() const
Definition: corr_maker.hpp:107
definition of MPO class (vector of MPOTensor)
T get_prop(std::string property, pos_t site) const
Definition: lattice.h:103
std::pair< size_t, size_t > rcdim(Vector const &pm)
Definition: utils.hpp:212
algorithms for block_matrix (gemm, svd, etc.)
CorrMaker(Lattice const &lat_, const std::vector< op_t > &ident_, const std::vector< op_t > &fill_, std::vector< std::pair< std::vector< op_t >, bool > > const &ops, int ref=-1)
Definition: corr_maker.hpp:64
virtual vector< vector< size_t > > const & numeric_labels()=0
std::string description() const
Definition: corr_maker.hpp:287
unsigned tag_type
Definition: tag_detail.h:36
pimpl resolved Lattice
Definition: lattice.h:84
declaration of OPTable, TagHandler and KronHandler