ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ss_optimize.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 SS_OPTIMIZE_H
28 #define SS_OPTIMIZE_H
29 
31 #include "dmrg/optimize/optimize.h"
32 
33 
34 template<class Matrix, class SymmGroup, class Storage>
35 class ss_optimize : public optimizer_base<Matrix, SymmGroup, Storage>
36 {
37 public:
38 
40  using base::mpo;
41  using base::mps;
42  using base::left_;
43  using base::right_;
44  using base::parms;
46  using base::stop_callback;
47 
49  MPO<Matrix, SymmGroup> const & mpo_,
50  BaseParameters & parms_,
51  boost::function<bool ()> stop_callback_,
52  int initial_site_ = 0)
53  : base(mps_, mpo_, parms_, stop_callback_, to_site(mps_.length(), initial_site_))
54  , initial_site((initial_site_ < 0) ? 0 : initial_site_)
55  { }
56 
57  inline int to_site(const int L, const int i) const
58  {
59  if (i < 0) return 0;
60  /// i, or (L-1) - (i - L)
61  return (i < L) ? i : 2*L - 1 - i;
62  }
63 
65  {
66  boost::chrono::high_resolution_clock::time_point sweep_now = boost::chrono::high_resolution_clock::now();
67 
69 
70  std::size_t L = mps.length();
71 
72  int _site = 0, site = 0;
73  if (initial_site != -1) {
74  _site = initial_site;
75  site = to_site(L, _site);
76  }
77 
78 // if (parms["beta_mode"] && sweep == 0 && resume_at < L) {
79 // int site = (resume_at == -1) ? 0 : resume_at;
80 // mpo = zero_after(mpo_orig, site+2);
81 // mps.canonize(site);
82 // this->init_left_right(mpo, site);
83 // }
84 
85  Storage::prefetch(left_[site]);
86  Storage::prefetch(right_[site+1]);
87 
88 #ifndef NDEBUG
89  maquis::cout << mps.description() << std::endl;
90 #endif
91  for (; _site < 2*L; ++_site) {
92 
93  int lr = (_site < L) ? +1 : -1;
94  site = to_site(L, _site);
95 
96  if (lr == -1 && site == L-1) {
97  maquis::cout << "Syncing storage" << std::endl;
98  Storage::sync();
99  }
100 
101  maquis::cout << "Sweep " << sweep << ", optimizing site " << site << std::endl;
102 
103 // mps[site].make_left_paired();
104 
105  // MD: some changes needed to re-enable it.
106 // if (parms.["beta_mode"]) {
107 // if (sweep == 0 && lr == 1) {
108 // mpo = zero_after(mpo_orig, 0);
109 // if (site == 0)
110 // this->init_left_right(mpo, 0);
111 // } else if (sweep == 0 && lr == -1 && site == L-1) {
112 // mpo = mpo_orig;
113 // //this->init_left_right(mpo, site);
114 // }
115 // }
116 
117 
118  Storage::fetch(left_[site]);
119  Storage::fetch(right_[site+1]);
120 
121  if (lr == +1) Storage::prefetch(left_[site+1]);
122  else Storage::prefetch(right_[site]);
123 
124  assert( left_[site].reasonable() ); // in case something went wrong
125  assert( right_[site+1].reasonable() ); // in case something went wrong
126 
127 
128 // maquis::cout << "My size: " << std::endl;
129 // maquis::cout << " left_: " << utils::size_of(left_.begin(), left_.end())/1024.0/1024 << std::endl;
130 // maquis::cout << " right_: " << utils::size_of(right_.begin(), right_.end())/1024.0/1024 << std::endl;
131 // maquis::cout << " MPS: " << utils::size_of(mps.begin(), mps.end())/1024.0/1024 << std::endl;
132 // maquis::cout << " MPS[i]: " << utils::size_of(mps[site])/1024.0/1024 << std::endl;
133 
134  //SiteProblem<Matrix, SymmGroup> sp(mps[site], left_[site], right_[site+1], mpo[site]);
135 
136  boost::chrono::high_resolution_clock::time_point now, then;
137 
138  std::pair<double, MPSTensor<Matrix, SymmGroup> > res;
139  SiteProblem<Matrix, SymmGroup> sp(left_[site], right_[site+1], mpo[site]);
140 
141  /// Compute orthogonal vectors
142  std::vector<MPSTensor<Matrix, SymmGroup> > ortho_vecs(base::northo);
143  for (int n = 0; n < base::northo; ++n) {
144  ortho_vecs[n] = contraction::site_ortho_boundaries(mps[site], base::ortho_mps[n][site],
145  base::ortho_left_[n][site], base::ortho_right_[n][site+1]);
146  }
147 
148  if (d == Both ||
149  (d == LeftOnly && lr == -1) ||
150  (d == RightOnly && lr == +1))
151  {
152  if (parms["eigensolver"] == std::string("IETL")) {
153  BEGIN_TIMING("IETL")
154  res = solve_ietl_lanczos(sp, mps[site], parms);
155  END_TIMING("IETL")
156  } else if (parms["eigensolver"] == std::string("IETL_JCD")) {
157  BEGIN_TIMING("JCD")
158  res = solve_ietl_jcd(sp, mps[site], parms, ortho_vecs);
159  END_TIMING("JCD")
160  } else {
161  throw std::runtime_error("I don't know this eigensolver.");
162  }
163 
164  mps[site] = res.second;
165  }
166 
167 #ifndef NDEBUG
168  // Caution: this is an O(L) operation, so it really should be done only in debug mode
169  for (int n = 0; n < base::northo; ++n)
170  maquis::cout << "MPS overlap: " << overlap(mps, base::ortho_mps[n]) << std::endl;
171 #endif
172 
173  maquis::cout << "Energy " << lr << " " << res.first << std::endl;
174 // maquis::cout << "Energy check " << maquis::real(expval(mps, mpo)) << std::endl;
175 
176  iteration_results_["Energy"] << res.first;
177 
178  double alpha;
179  int ngs = parms.template get<int>("ngrowsweeps"), nms = parms.template get<int>("nmainsweeps");
180  if (sweep < ngs)
181  alpha = parms.template get<double>("alpha_initial");
182  else if (sweep < ngs + nms)
183  alpha = parms.template get<double>("alpha_main");
184  else
185  alpha = parms.template get<double>("alpha_final");
186 
187  double cutoff = this->get_cutoff(sweep);
188  std::size_t Mmax = this->get_Mmax(sweep);
189  truncation_results trunc;
190 
191  if (lr == +1) {
192  if (site < L-1) {
193  maquis::cout << "Growing, alpha = " << alpha << std::endl;
194  trunc = mps.grow_l2r_sweep(mpo[site], left_[site], right_[site+1],
195  site, alpha, cutoff, Mmax);
196  } else {
197  block_matrix<Matrix, SymmGroup> t = mps[site].normalize_left(DefaultSolver());
198  if (site < L-1)
199  mps[site+1].multiply_from_left(t);
200  }
201 
202 
203  Storage::drop(left_[site+1]); // left_[site+1] is outdated
204  this->boundary_left_step(mpo, site); // creating left_[site+1]
205  } else if (lr == -1) {
206  if (site > 0) {
207  maquis::cout << "Growing, alpha = " << alpha << std::endl;
208  // Invalid read occurs after this!\n
209  trunc = mps.grow_r2l_sweep(mpo[site], left_[site], right_[site+1],
210  site, alpha, cutoff, Mmax);
211  } else {
212  block_matrix<Matrix, SymmGroup> t = mps[site].normalize_right(DefaultSolver());
213  if (site > 0)
214  mps[site-1].multiply_from_right(t);
215  }
216 
217 
218  Storage::drop(right_[site]); // right_[site] is outdated
219  this->boundary_right_step(mpo, site); // creating right_[site]
220  }
221 
222  Storage::evict(left_[site]); // move to out of core currently used boundary
223  Storage::evict(right_[site+1]); // move to out of core currently used boundary
224 
225  iteration_results_["BondDimension"] << trunc.bond_dimension;
226  iteration_results_["TruncatedWeight"] << trunc.truncated_weight;
227  iteration_results_["SmallestEV"] << trunc.smallest_ev;
228 
229  boost::chrono::high_resolution_clock::time_point sweep_then = boost::chrono::high_resolution_clock::now();
230  double elapsed = boost::chrono::duration<double>(sweep_then - sweep_now).count();
231  maquis::cout << "Sweep has been running for " << elapsed << " seconds." << std::endl;
232 
233  if (stop_callback())
234  throw dmrg::time_limit(sweep, _site+1);
235  }
236  initial_site = -1;
237  }
238 
239 private:
240  int initial_site;
241 };
242 
243 #endif
244 
std::size_t get_Mmax(int sweep) const
Definition: optimize.h:212
BaseParameters & parms
Definition: optimize.h:232
std::pair< double, MPSTensor< Matrix, SymmGroup > > solve_ietl_lanczos(SiteProblem< Matrix, SymmGroup > &sp, MPSTensor< Matrix, SymmGroup > const &initial, BaseParameters &params)
std::vector< Boundary< typename storage::constrained< Matrix >::type, SymmGroup > > left_
Definition: optimize.h:235
Definition: optimize.h:84
ss_optimize(MPS< Matrix, SymmGroup > &mps_, MPO< Matrix, SymmGroup > const &mpo_, BaseParameters &parms_, boost::function< bool()> stop_callback_, int initial_site_=0)
Definition: ss_optimize.hpp:48
static MPSTensor< Matrix, SymmGroup > site_ortho_boundaries(MPSTensor< Matrix, SymmGroup > const &mps, MPSTensor< Matrix, SymmGroup > const &ortho_mps, block_matrix< OtherMatrix, SymmGroup > const &ortho_left, block_matrix< OtherMatrix, SymmGroup > const &ortho_right)
Definition: contractions.h:479
std::vector< std::vector< block_matrix< typename storage::constrained< Matrix >::type, SymmGroup > > > ortho_left_
Definition: optimize.h:239
Definition: mpo.h:36
utility functions for the MPO
results_collector iteration_results_
Definition: optimize.h:227
optimization base class
MPS< Matrix, SymmGroup >::scalar_type overlap(MPS< Matrix, SymmGroup > const &mps1, MPS< Matrix, SymmGroup > const &mps2)
Definition: mps_mpo_ops.h:136
void sweep(int sweep, OptimizeDirection d=Both)
Definition: ss_optimize.hpp:64
std::vector< std::vector< block_matrix< typename storage::constrained< Matrix >::type, SymmGroup > > > ortho_right_
Definition: optimize.h:239
Definition: mps.h:40
OptimizeDirection
Definition: optimize.h:84
std::pair< double, MPSTensor< Matrix, SymmGroup > > solve_ietl_jcd(SiteProblem< Matrix, SymmGroup > &sp, MPSTensor< Matrix, SymmGroup > const &initial, BaseParameters &params, std::vector< MPSTensor< Matrix, SymmGroup > > ortho_vecs=std::vector< MPSTensor< Matrix, SymmGroup > >())
boost::function< bool()> stop_callback
Definition: optimize.h:233
MPO< Matrix, SymmGroup > const & mpo
Definition: optimize.h:230
MPS< Matrix, SymmGroup > & mps
Definition: optimize.h:229
optimizer_base< Matrix, SymmGroup, Storage > base
Definition: ss_optimize.hpp:39
double get_cutoff(int sweep) const
Definition: optimize.h:202
unsigned int northo
Definition: optimize.h:238
int to_site(const int L, const int i) const
Definition: ss_optimize.hpp:57
#define BEGIN_TIMING(name)
#define END_TIMING(name)
std::vector< Boundary< typename storage::constrained< Matrix >::type, SymmGroup > > right_
Definition: optimize.h:235
void boundary_right_step(MPO< Matrix, SymmGroup > const &mpo, int site)
Definition: optimize.h:144
std::vector< MPS< Matrix, SymmGroup > > ortho_mps
Definition: optimize.h:240
void boundary_left_step(MPO< Matrix, SymmGroup > const &mpo, int site)
Definition: optimize.h:135