ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mpstensor.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 
31 
32 #include "dmrg/utils/random.hpp"
33 #include <alps/numeric/isnan.hpp>
34 #include <alps/numeric/isinf.hpp>
35 
36 #include "utils/traits.hpp"
37 
38 
39 // implementation of join functions
41 
42 template<class Matrix, class SymmGroup>
44  Index<SymmGroup> const & ld,
45  Index<SymmGroup> const & rd,
46  bool fillrand,
47  typename Matrix::value_type val)
48 : phys_i(sd)
49 , left_i(ld)
50 , right_i(rd)
51 , cur_storage(LeftPaired)
52 , cur_normalization(Unorm)
53 {
54  Index<SymmGroup> lb = sd*ld, rb = rd;
55  common_subset(lb, rb);
56 
57  // remove blocks from the right index that may not be allowed by the left index
58  right_i = rb;
59  // remove blocks from the left index that may not be allowed by the right index
60  Index<SymmGroup> possible_rp = adjoin(phys_i)*right_i, ltemp = ld;
61  common_subset(ltemp, possible_rp);
62  left_i = ltemp;
63 
64  // this is safe, since sd \otimes ld = rd forces the block_matrix to be diagonal
65  lb.sort();
66  rb.sort();
67  left_i.sort();
68  right_i.sort();
69 
71 
72  if (fillrand)
73  data().generate(static_cast<dmrg_random::value_type(*)()>(&dmrg_random::uniform));
74  else
76 }
77 
78 template<class Matrix, class SymmGroup>
80  Index<SymmGroup> const& ld,
81  Index<SymmGroup> const& rd,
83  MPSStorageLayout layout)
84 : phys_i(sd)
85 , left_i(ld)
86 , right_i(rd)
87 , data_(block)
88 , cur_storage(layout)
89 , cur_normalization(Unorm)
90 {
91  if (cur_storage == LeftPaired) {
92  Index<SymmGroup> new_right_i = data_.right_basis();
93  Index<SymmGroup> possible_left_i = adjoin(phys_i)*new_right_i;
94  Index<SymmGroup> old_left_i = left_i;
95 
96  common_subset(old_left_i, possible_left_i);
97 
98  swap(right_i, new_right_i);
99  swap(left_i, old_left_i);
100  } else {
101  Index<SymmGroup> new_left_i = data_.left_basis();
102  Index<SymmGroup> possible_right_i = phys_i*new_left_i;
103  Index<SymmGroup> old_right_i = right_i;
104 
105  common_subset(old_right_i, possible_right_i);
106 
107  swap(left_i, new_left_i);
108  swap(right_i, old_right_i);
109  }
110 }
111 
112 template<class Matrix, class SymmGroup>
114 {
115  make_left_paired();
116 
117  Index<SymmGroup> new_right_i = rhs.right_basis();
118  Index<SymmGroup> possible_left_i = adjoin(phys_i)*new_right_i;
119  Index<SymmGroup> old_left_i = left_i;
120 
121  common_subset(old_left_i, possible_left_i);
122 
123  swap(right_i, new_right_i);
124  swap(left_i, old_left_i);
125 
126  data() = rhs;
127  cur_normalization = normalization;
128 }
129 
130 template<class Matrix, class SymmGroup>
132 {
133  make_right_paired();
134 
135  Index<SymmGroup> new_left_i = rhs.left_basis();
136  Index<SymmGroup> possible_right_i = phys_i*new_left_i;
137  Index<SymmGroup> old_right_i = right_i;
138 
139  common_subset(old_right_i, possible_right_i);
140 
141  swap(left_i, new_left_i);
142  swap(right_i, old_right_i);
143 
144  data() = rhs;
145  cur_normalization = normalization;
146 }
147 
148 template<class Matrix, class SymmGroup>
150 {
151  return phys_i;
152 }
153 
154 template<class Matrix, class SymmGroup>
156 {
157  return left_i;
158 }
159 
160 template<class Matrix, class SymmGroup>
162 {
163  return right_i;
164 }
165 
166 template<class Matrix, class SymmGroup>
168 {
169  return false;
170 }
171 
172 template<class Matrix, class SymmGroup>
174 {
175  if (cur_storage == LeftPaired)
176  return;
177 
179  reshape_right_to_left_new<Matrix>(phys_i, left_i, right_i,
180  data(), tmp);
181  cur_storage = LeftPaired;
182  swap(data_, tmp);
183 
184  assert( weak_equal(right_i, data().right_basis()) );
185 }
186 
187 template<class Matrix, class SymmGroup>
189 {
190  if (cur_storage == RightPaired)
191  return;
192 
194  reshape_left_to_right_new<Matrix>(phys_i, left_i, right_i,
195  data(), tmp);
196  cur_storage = RightPaired;
197  swap(data_, tmp);
198 
199  assert( weak_equal(left_i, data().left_basis()) );
200 }
201 
202 template<class Matrix, class SymmGroup>
205  bool multiplied,
206  double truncation,
207  Index<SymmGroup> bond_dim)
208 {
209  if (cur_normalization == Unorm || cur_normalization == Rnorm) {
210  if (method == QR) {
211  make_left_paired();
212 
214  qr(data(), Q, R);
215 
216  swap(data(), Q);
217  right_i = data().right_basis();
218  assert(right_i == R.left_basis());
219 
220  cur_normalization = Lnorm;
221  return R;
222  } else {
223  make_left_paired();
224 
227 
228  svd(data(), U, V, S);
229 
230  right_i = U.right_basis();
231  assert(data().left_basis() == U.left_basis());
232 
233  swap(data(), U);
234  gemm(S, V, U);
235 
236  cur_normalization = Lnorm;
237  return U;
238  }
239  }
240  return identity_matrix<Matrix>(data().right_basis());
241 }
242 
243 template<class Matrix, class SymmGroup>
246  bool multiplied,
247  double truncation,
248  Index<SymmGroup> bond_dim)
249 {
250  if (cur_normalization == Unorm || cur_normalization == Lnorm) {
251  if (method == QR) { //enum QR but LQ decomposition
252  make_right_paired();
253 
255  lq(data(), L, Q);
256 
257  swap(data(), Q);
258  left_i = data().left_basis();
259  assert(left_i == L.right_basis());
260 
261  cur_normalization = Rnorm;
262  return L;
263  } else {
264  make_right_paired();
265 
268 
269  svd(data(), U, V, S);
270 
271  left_i = V.left_basis();
272  assert(data().right_basis() == V.right_basis());
273  swap(data(), V);
274 
275  gemm(U, S, V);
276 
277  cur_normalization = Rnorm;
278  return V;
279  }
280  }
281  return identity_matrix<Matrix>(data().left_basis());
282 }
283 
284 template<class Matrix, class SymmGroup>
285 void MPSTensor<Matrix, SymmGroup>::shift_aux_charges(typename SymmGroup::charge diff)
286 {
287  left_i.shift(diff);
288  right_i.shift(diff);
289  data().shift_basis(diff);
290 }
291 
292 template<class Matrix, class SymmGroup>
293 void
295 {
296  cur_normalization = Unorm;
298  make_left_paired();
299  gemm(data(), N, tmp);
300  replace_left_paired(tmp);
301 }
302 
303 template<class Matrix, class SymmGroup>
304 void
306 {
307  cur_normalization = Unorm;
309  make_right_paired();
310  gemm(N, data(), tmp);
311  replace_right_paired(tmp);
312 }
313 
314 template<class Matrix, class SymmGroup>
315 void
317 {
318  cur_normalization = Unorm;
319  *this *= s;
320 }
321 
322 template<class Matrix, class SymmGroup>
323 void
325 {
326  cur_normalization = Unorm;
327  *this /= s;
328 }
329 
330 template<class Matrix, class SymmGroup>
331 void
333 {
334  data() = data().inplace_conjugate();
335 }
336 
337 template<class Matrix, class SymmGroup>
340 {
341  return data().norm();
342 }
343 
344 template<class T>
345 void verbose_assert(T const & a, T const & b)
346 {
347  if (!( a == b) ) {
348  maquis::cout << "a: " << a << std::endl;
349  maquis::cout << "b: " << b << std::endl;
350  assert( a == b );
351  }
352 }
353 
354 template<class Matrix, class SymmGroup>
357 {
358  make_left_paired();
359  rhs.make_left_paired();
360 
361  // verbose_assert(left_i, rhs.left_i);
362  // verbose_assert(right_i, rhs.right_i);
363  // verbose_assert(phys_i, rhs.phys_i);
364  // verbose_assert(rhs.data_.left_basis(), data_.left_basis());
365  // verbose_assert(rhs.data_.right_basis(), data_.right_basis());
366  // verbose_assert(rhs.data_.n_blocks(), data_.n_blocks());
367 
368  // Bela says: this is a workaround for the very rare condition that site_hamil2 removes blocks
369  // This shouldn't be necessary, but as of Rev. 1702, is necessary in some cases
370  // If I haven't fixed this by the end of Feb 2012, remind me
371  Index<SymmGroup> i1 = data().left_basis(), i2 = rhs.data().left_basis();
372  common_subset(i1, i2);
373  std::vector<scalar_type> vt; vt.reserve(i1.size());
374 
375  semi_parallel_for (/*locale::compact(i1.size())*/, std::size_t b = 0; b < i1.size(); ++b) {
376  typename SymmGroup::charge c = i1[b].first;
377  assert( data().has_block(c,c) && rhs.data().has_block(c,c) );
378  vt.push_back(overlap(data()(c,c), rhs.data()(c,c)));
379  } // should be reformulated in terms of reduction (todo: Matthias, 30.04.12 / scalar-value types)
380 
381  return maquis::accumulate(vt.begin(), vt.end(), scalar_type(0.));
382 }
383 
384 template<class Matrix, class SymmGroup>
385 std::ostream& operator<<(std::ostream& os, MPSTensor<Matrix, SymmGroup> const & mps)
386 {
387  os << "Physical space: " << mps.phys_i << std::endl;
388  os << "Left space: " << mps.left_i << std::endl;
389  os << "Right space: " << mps.right_i << std::endl;
390  os << mps.data();
391  return os;
392 }
393 
394 template<class Matrix, class SymmGroup>
396 {
397  if (test)
398  throw std::runtime_error("Not implemented!");
399  else
400  return cur_normalization == Lnorm;
401 }
402 
403 template<class Matrix, class SymmGroup>
405 {
406  if (test)
407  throw std::runtime_error("Not implemented!");
408  else
409  return cur_normalization == Rnorm;
410 }
411 
412 template<class Matrix, class SymmGroup>
414 {
415  if (isleftnormalized(test) || isrightnormalized(test))
416  return true;
417  else
418  return false;
419 }
420 
421 template<class Matrix, class SymmGroup>
424 {
425  cur_normalization = Unorm;
426  return data_;
427 }
428 
429 template<class Matrix, class SymmGroup>
432 {
433  return const_data();
434 }
435 
436 template<class Matrix, class SymmGroup>
439 {
440  return data_;
441 }
442 
443 
444 template<class Matrix, class SymmGroup>
447 {
448  data() *= t;
449  return *this;
450 }
451 
452 template<class Matrix, class SymmGroup>
455 {
456  data() /= t;
457  return *this;
458 }
459 
460 template<class Matrix, class SymmGroup>
463 {
464  assert( weak_equal(left_i, rhs.left_i) );
465  assert( weak_equal(right_i, rhs.right_i) );
466  assert( phys_i == rhs.phys_i );
467 
468  // what if both are right_paired?
469  make_left_paired();
470  rhs.make_left_paired();
471 
472  cur_normalization = Unorm;
473 
474  for (std::size_t i = 0; i < data().n_blocks(); ++i)
475  {
476  typename SymmGroup::charge lc = data().left_basis()[i].first, rc = data().right_basis()[i].first;
477  std::size_t matched_block = rhs.data().find_block(lc,rc);
478  if (matched_block < rhs.data().n_blocks()) {
479  data()[i] += rhs.data()[matched_block];
480  }
481  }
482 
483  return *this;
484 }
485 
486 template<class Matrix, class SymmGroup>
489 {
490  assert( weak_equal(left_i, rhs.left_i) );
491  assert( weak_equal(right_i, rhs.right_i) );
492  assert( phys_i == rhs.phys_i );
493 
494  make_left_paired();
495  rhs.make_left_paired();
496 
497  cur_normalization = Unorm;
498 
499  for (std::size_t i = 0; i < data().n_blocks(); ++i)
500  {
501  typename SymmGroup::charge lc = data().left_basis()[i].first, rc = data().right_basis()[i].first;
502  if (rhs.data().has_block(lc,rc)) {
503  data()[i] -= rhs.data()(lc,rc);
504  }
505  }
506 
507  return *this;
508 }
509 
510 template<class Matrix, class SymmGroup>
512 {
513  using std::swap;
514  swap(this->phys_i, b.phys_i);
515  swap(this->left_i, b.left_i);
516  swap(this->right_i, b.right_i);
517  swap(this->data_, b.data_);
518  swap(this->cur_storage, b.cur_storage);
519  swap(this->cur_normalization, b.cur_normalization);
520 }
521 
522 template<class Matrix, class SymmGroup>
523 template<class Archive>
525 {
526  data_.clear();
527  make_left_paired();
528  ar["phys_i"] >> phys_i;
529  ar["left_i"] >> left_i;
530  ar["right_i"] >> right_i;
531  ar["data_"] >> data();
532  cur_normalization = Unorm;
533 }
534 
535 template<class Matrix, class SymmGroup>
536 template<class Archive>
537 void MPSTensor<Matrix, SymmGroup>::save(Archive & ar) const
538 {
539  make_left_paired();
540  ar["phys_i"] << phys_i;
541  ar["left_i"] << left_i;
542  ar["right_i"] << right_i;
543  ar["data_"] << data();
544 }
545 
546 template<class Matrix, class SymmGroup>
548 {
549  {
550  make_left_paired();
551  if ( !weak_equal(right_i, data().right_basis()) )
552  throw std::runtime_error("right basis is wrong");
553 
554 // maquis::cout << "** reasonable left_paired **" << std::endl;
555 // maquis::cout << "reasonable::left_i: " << left_i << std::endl;
556 // maquis::cout << "reasonable::right_i: " << right_i << std::endl;
557 // maquis::cout << "reasonable::data_:" << std::endl << data() << std::endl;
558  make_right_paired();
559  if ( !weak_equal(left_i, data().left_basis()) )
560  throw std::runtime_error("left basis is wrong");
561 
562 // maquis::cout << "** reasonable right_paired **" << std::endl;
563 // maquis::cout << "reasonable::left_i: " << left_i << std::endl;
564 // maquis::cout << "reasonable::right_i: " << right_i << std::endl;
565 // maquis::cout << "reasonable::data_:" << std::endl << data() << std::endl;
566  }
567 
568  {
569  for (std::size_t i = 0; i < data().n_blocks(); ++i)
570  {
571  if (data().left_basis()[i].first != data().right_basis()[i].first)
572  throw std::runtime_error("particle number is wrong");
573  }
574  }
575  return true;
576 }
577 
578 template<class Matrix, class SymmGroup>
580 {
581  for (std::size_t k = 0; k < data().n_blocks(); ++k)
582  {
583  for (size_t i = 0; i<num_rows(data()[k]); ++i)
584  for (size_t j = 0; j<num_cols(data()[k]); ++j)
585  {
586  if ( alps::numeric::isnan(data()[k](i,j)) )
587  throw std::runtime_error("NaN found!");
588  if ( alps::numeric::isinf(data()[k](i,j)) )
589  throw std::runtime_error("INF found!");
590  }
591  }
592  return true;
593 }
594 
595 template <class Matrix, class SymmGroup>
597 {
598  std::string error;
599  // Indexes
600 
601  try {
602  reasonable();
603  } catch (std::exception & e) {
604  error += "I'm unreasonable. " + std::string(e.what());
605  }
606  try {
607  rhs.reasonable();
608  } catch (std::exception & e) {
609  error += "He's unreasonable. " + std::string(e.what());
610  }
611 
612  // Storage
613 // if (cur_storage != rhs.cur_storage)
614 // error += "Storage doesn't match. ";
615 
616  make_left_paired();
617  rhs.make_left_paired();
618 
619  // Data
620  if (data().n_blocks() != rhs.data().n_blocks())
621  error += "n_blocks doesn't match. ";
622  else {
623  for (int b=0; b < data().n_blocks(); ++b) {
624  if (data()[b].num_cols() != rhs.data()[b].num_cols() || data()[b].num_rows() != rhs.data()[b].num_rows())
625  error += "Size of block doesn't match. ";
626  for (int i=0; i < data()[b].num_rows() && error.empty(); ++i)
627  for (int j=0; j < data()[b].num_cols() && error.empty(); ++j)
628  if (data()[b](i,j) != rhs.data()[b](i,j))
629  error += "Data doesn't match. ";
630  }
631  }
632  // Finalize
633  if (!error.empty())
634  throw std::runtime_error(error);
635 
636 }
637 
638 template<class Matrix, class SymmGroup>
640 {
641  return data().num_elements();
642 }
643 
block_matrix< Matrix, SymmGroup > normalize_right(DecompMethod method=DefaultSolver(), bool multiplied=true, double truncation=0, Index< SymmGroup > bond_dim=Index< SymmGroup >())
Definition: mpstensor.hpp:245
void multiply_by_scalar(const scalar_type &)
Definition: mpstensor.hpp:316
real_type scalar_norm() const
Definition: mpstensor.hpp:339
void sort()
void make_left_paired() const
Definition: mpstensor.hpp:173
bool isrightnormalized(bool test=false) const
Definition: mpstensor.hpp:404
Index< SymmGroup > const & col_dim() const
Definition: mpstensor.hpp:161
bool isobccompatible(Indicator) const
Definition: mpstensor.hpp:167
MPSTensor const & operator/=(const scalar_type &)
Definition: mpstensor.hpp:454
void load(Archive &ar)
Definition: mpstensor.hpp:524
maquis::traits::scalar_type< Matrix >::type scalar_type
Definition: mpstensor.h:52
void make_right_paired() const
Definition: mpstensor.hpp:188
void check_equal(MPSTensor< Matrix, SymmGroup > const &) const
Definition: mpstensor.hpp:596
scalar_type scalar_overlap(MPSTensor const &) const
Definition: mpstensor.hpp:356
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
void verbose_assert(T const &a, T const &b)
Definition: mpstensor.hpp:345
double value_type
Definition: random.hpp:33
data_type data
Index< SymmGroup > const & row_dim() const
Definition: mpstensor.hpp:155
void save(Archive &ar) const
Definition: mpstensor.hpp:537
std::size_t num_rows(maquis::dmrg::one_matrix< T > const &m)
Definition: one_matrix.hpp:99
#define semi_parallel_for(constraint,...)
void multiply_from_left(block_matrix< Matrix, SymmGroup > const &)
Definition: mpstensor.hpp:305
void conjugate_inplace()
Definition: mpstensor.hpp:332
functions for joining two MPS : |psi1> + |psi2>
block_matrix< Matrix, SymmGroup > normalize_left(DecompMethod method=DefaultSolver(), bool multiplied=true, double truncation=0, Index< SymmGroup > bond_dim=Index< SymmGroup >())
Definition: mpstensor.hpp:204
block_matrix< Matrix, SymmGroup > adjoin(block_matrix< Matrix, SymmGroup > const &m)
DecompMethod
Definition: mpstensor.h:41
static value_type uniform()
Definition: random.hpp:47
bool isnormalized(bool test=false) const
Definition: mpstensor.hpp:413
Index< SymmGroup > phys_i
Definition: mpstensor.h:141
MPS< Matrix, SymmGroup >::scalar_type overlap(MPS< Matrix, SymmGroup > const &mps1, MPS< Matrix, SymmGroup > const &mps2)
Definition: mps_mpo_ops.h:136
void replace_left_paired(block_matrix< Matrix, SymmGroup > const &, Indicator=Unorm)
Definition: mpstensor.hpp:113
bool weak_equal(Index< SymmGroup > const &a, Index< SymmGroup > const &b)
declaration of the MPSTensor class
MPSTensor(Index< SymmGroup > const &sd=Index< SymmGroup >(), Index< SymmGroup > const &ld=Index< SymmGroup >(), Index< SymmGroup > const &rd=Index< SymmGroup >(), bool fillrand=true, value_type val=0)
Definition: mpstensor.hpp:43
void svd(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &U, block_matrix< Matrix, SymmGroup > &V, block_matrix< DiagMatrix, SymmGroup > &S)
std::size_t num_cols(maquis::dmrg::one_matrix< T > const &m)
Definition: one_matrix.hpp:102
void shift_aux_charges(typename SymmGroup::charge)
Definition: mpstensor.hpp:285
block_matrix< Matrix, SymmGroup > const & const_data() const
Definition: mpstensor.hpp:438
Index< SymmGroup > const & right_basis() const
bool isleftnormalized(bool test=false) const
Definition: mpstensor.hpp:395
bool num_check() const
Definition: mpstensor.hpp:579
void multiply_from_right(block_matrix< Matrix, SymmGroup > const &)
Definition: mpstensor.hpp:294
algorithms for block_matrix (gemm, svd, etc.)
std::size_t num_elements() const
Definition: mpstensor.hpp:639
Index< SymmGroup > const & site_dim() const
Definition: mpstensor.hpp:149
void lq(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &L, block_matrix< Matrix, SymmGroup > &Q)
Index< SymmGroup > left_i
Definition: mpstensor.h:141
friend void swap(MPSTensor &a, MPSTensor &b)
Definition: mpstensor.h:128
MPSStorageLayout
Definition: mpstensor.h:38
MPSTensor const & operator+=(MPSTensor const &)
Definition: mpstensor.hpp:462
void swap_with(MPSTensor &b)
Definition: mpstensor.hpp:511
functions to reshape the representation of data in MPSTensor
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
Index< SymmGroup > right_i
Definition: mpstensor.h:141
Indicator
Definition: mpstensor.h:40
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
Definition: bindings.hpp:44
Index< SymmGroup > const & left_basis() const
block_matrix< Matrix, SymmGroup > & data()
Definition: mpstensor.hpp:423
std::size_t size() const
void replace_right_paired(block_matrix< Matrix, SymmGroup > const &, Indicator=Unorm)
Definition: mpstensor.hpp:131
void qr(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &Q, block_matrix< Matrix, SymmGroup > &R)
Index< SymmGroup > common_subset(Index< SymmGroup > &a, Index< SymmGroup > &b)
Definition: mpstensor.h:41
MPSTensor const & operator*=(const scalar_type &)
Definition: mpstensor.hpp:446
bool reasonable() const
Definition: mpstensor.hpp:547
maquis::traits::real_type< Matrix >::type real_type
Definition: mpstensor.h:53
void divide_by_scalar(const scalar_type &)
Definition: mpstensor.hpp:324
MPSTensor const & operator-=(MPSTensor const &)
Definition: mpstensor.hpp:488