27 #ifndef BLOCK_MATRIX_ALGORITHMS_H
28 #define BLOCK_MATRIX_ALGORITHMS_H
40 #include <boost/lambda/lambda.hpp>
41 #include <boost/function.hpp>
61 template<
class Matrix1,
class Matrix2,
class Matrix3,
class SymmGroup>
68 typedef typename SymmGroup::charge charge;
69 for (std::size_t k = 0; k < A.
n_blocks(); ++k) {
77 gemm(A[k], B[matched_block], C[new_block]);
81 template<
class Matrix1,
class Matrix2,
class Matrix3,
class SymmGroup>
88 typedef typename SymmGroup::charge charge;
89 for (std::size_t k = 0; k < A.
n_blocks(); ++k) {
102 gemm(A[k], B[matched_block], C[new_block]);
106 template<
class Matrix1,
class Matrix2,
class Matrix3,
class SymmGroup>
113 typedef typename SymmGroup::charge charge;
114 for (std::size_t k = 0; k < B.
n_blocks(); ++k) {
127 gemm(A[matched_block], B[k], C[new_block]);
131 template<
class Matrix,
class DiagMatrix,
class SymmGroup>
138 for (std::size_t i = 0; i < M.
n_blocks(); ++i)
139 m[i].second = std::min(r[i].second, c[i].second);
144 std::size_t loop_max = M.
n_blocks();
147 svd(M[k], U[k], V[k], S[k]);
150 template<
class Matrix,
class DiagMatrix,
class SymmGroup>
158 std::size_t loop_max = M.
n_blocks();
161 heev(M[k], evecs[k], evals[k]);
172 template<
class DiagMatrix,
class SymmGroup>
174 size_t Mmax,
double cutoff,
size_t* keeps,
175 double & truncated_fraction,
double & truncated_weight,
double & smallest_ev)
177 typedef typename DiagMatrix::value_type value_type;
180 for(std::size_t k = 0; k < evals.
n_blocks(); ++k){
184 typedef std::vector<typename maquis::traits::real_type<value_type>::type > real_vector_t;
185 real_vector_t allevals(length);
187 std::size_t position = 0;
188 for(std::size_t k = 0; k < evals.
n_blocks(); ++k){
189 std::transform(evals[k].diagonal().first, evals[k].diagonal().second, allevals.begin()+position, gather_real_pred<value_type>);
193 assert( allevals.size() > 0 );
194 std::sort(allevals.begin(), allevals.end());
195 std::reverse(allevals.begin(), allevals.end());
197 double evalscut = cutoff * allevals[0];
199 if (allevals.size() > Mmax)
200 evalscut = std::max(evalscut, allevals[Mmax]);
201 smallest_ev = evalscut / allevals[0];
203 truncated_fraction = 0.0; truncated_weight = 0.0;
204 for (
typename real_vector_t::const_iterator it = std::find_if(allevals.begin(), allevals.end(), boost::lambda::_1 < evalscut);
205 it != allevals.end(); ++it) {
206 truncated_fraction += *it;
207 truncated_weight += (*it)*(*it);
209 truncated_fraction /=
std::accumulate(allevals.begin(), allevals.end(), 0.0);
210 truncated_weight /=
std::accumulate(allevals.begin(), allevals.end(), 0.0, boost::lambda::_1 + boost::lambda::_2 *boost::lambda::_2);
212 for(std::size_t k = 0; k < evals.
n_blocks(); ++k){
213 real_vector_t evals_k(
num_rows(evals[k]));
214 std::transform(evals[k].diagonal().first, evals[k].diagonal().second, evals_k.begin(), gather_real_pred<value_type>);
215 keeps[k] = std::find_if(evals_k.begin(), evals_k.end(), boost::lambda::_1 < evalscut)-evals_k.begin();
220 template<
class Matrix,
class DiagMatrix,
class SymmGroup>
225 double rel_tol, std::size_t Mmax,
232 size_t* keeps =
new size_t[S.
n_blocks()];
233 double truncated_fraction, truncated_weight, smallest_ev;
238 estimate_truncation(S, Mmax, rel_tol, keeps, truncated_fraction, truncated_weight, smallest_ev);
240 for (
int k = S.
n_blocks() - 1; k >= 0; --k)
242 size_t keep = keeps[k];
253 if (keep >=
num_rows(S[k]))
continue;
271 std::size_t bond_dimension = S.
left_basis().sum_of_sizes();
273 maquis::cout <<
"Sum: " << old_basis.
sum_of_sizes() <<
" -> " << bond_dimension << std::endl;
278 return truncation_results(bond_dimension, truncated_weight, truncated_fraction, smallest_ev);
282 template<
class Matrix,
class DiagMatrix,
class SymmGroup>
287 double rel_tol, std::size_t Mmax,
307 maquis::cout <<
"S.n_blocks: " << D.
n_blocks() << std::endl;
308 maquis::cout <<
"S.trace: " <<
trace(D) << std::endl;
309 maquis::cout <<
"R.n_blocks: " << R.
n_blocks() << std::endl;
310 maquis::cout <<
"R.trace: " <<
trace(R) << std::endl;
317 for (
int i=0; i<
num_rows(D[n]); ++i)
318 if ( abs(D[n](i,i) - R[n](i,i)*R[n](i,i)) > 1e-6 )
319 maquis::cout <<
"n=" << n <<
", i=" << i <<
" broken. D=" << D[n](i,i) <<
", td=" << R[n](i,i)*R[n](i,i) << std::endl;
333 template<
class Matrix,
class DiagMatrix,
class SymmGroup>
337 double cutoff, std::size_t Mmax,
341 heev(M, evecs, evals);
343 size_t* keeps =
new size_t[evals.
n_blocks()];
344 double truncated_fraction, truncated_weight, smallest_ev;
346 estimate_truncation(evals, Mmax, cutoff, keeps, truncated_fraction, truncated_weight, smallest_ev);
348 for (
int k = evals.
n_blocks() - 1; k >= 0; --k)
350 size_t keep = keeps[k];
360 if(keep >=
num_rows(evals[k]))
continue;
373 std::size_t bond_dimension = evals.
left_basis().sum_of_sizes();
375 maquis::cout <<
"Sum: " << old_basis.
sum_of_sizes() <<
" -> " << bond_dimension << std::endl;
379 return truncation_results(bond_dimension, truncated_fraction, truncated_fraction, smallest_ev);
382 template<
class Matrix,
class SymmGroup>
389 for (
size_t i=0; i<k.size(); ++i)
390 k[i].second = std::min(m[i].second,n[i].second);
394 std::size_t loop_max = M.
n_blocks();
397 qr(M[k], Q[k], R[k]);
404 template<
class Matrix,
class SymmGroup>
411 for (
size_t i=0; i<k.size(); ++i)
412 k[i].second = std::min(m[i].second,n[i].second);
416 std::size_t loop_max = M.
n_blocks();
419 lq(M[k], L[k], Q[k]);
426 template<
class Matrix,
class SymmGroup>
430 for(
size_t k=0; k<m.
n_blocks(); ++k)
435 template<
class Matrix,
class SymmGroup>
442 template<
class Matrix,
class SymmGroup>
449 template<
class Matrix,
class SymmGroup>
455 template<
class Matrix,
class SymmGroup>
459 for (std::size_t k = 0; k < m.
n_blocks(); ++k)
466 template<
class Matrix,
class SymmGroup,
class Generator>
472 template<
class Matrix,
class SymmGroup>
476 for (std::size_t k = 0; k < ret.
n_blocks(); ++k)
481 template<
class Matrix,
class SymmGroup>
485 for (
size_t k=0; ret && k < m.
n_blocks(); ++k) {
498 template<
class Matrix,
class SymmGroup>
501 for (std::size_t k = 0; k < m.
n_blocks(); ++k)
523 template <
class Matrix,
class SymmGroup,
class A>
526 A
const & alpha = 1.)
529 if (M.
has_block(it_c->first, it_c->first))
530 M(it_c->first, it_c->first) = exp_hermitian(M(it_c->first, it_c->first), alpha);
533 it_c->first, it_c->first);
539 template <
class Matrix>
540 typename boost::enable_if<boost::is_complex<typename Matrix::value_type>, Matrix>::type
543 return exp(m, alpha);
546 template <
class Matrix>
547 typename boost::disable_if<boost::is_complex<typename Matrix::value_type>, Matrix>::type
550 throw std::runtime_error(
"Exponential of non-hermitian real matrices not implemented!");
555 template <
class Matrix,
class SymmGroup,
class A>
558 A
const & alpha = 1.)
561 if (M.
has_block(it_c->first, it_c->first))
565 it_c->first, it_c->first);
569 template<
class Matrix1,
class Matrix2,
class SymmGroup>
581 for (
int i = 0; i < A.
n_blocks(); ++i) {
582 for (
int j = 0; j < B.
n_blocks(); ++j) {
602 template<
class Matrix,
class SymmGroup>
611 assert( midx.
size() == 2*(dist+1) );
620 it != midx.
end(); ++it)
622 bool has_block = A.
has_block((*it)[0].first, (*it)[1].first);
623 has_block = has_block && B.
has_block((*it)[2*dist].first, (*it)[2*dist+1].first);
624 for (
size_t i=1; has_block && i<dist; ++i)
625 has_block = F.
has_block((*it)[2*i].first, (*it)[2*i+1].first);
630 typename Matrix::value_type val = A((*it)[0], (*it)[1]) * B((*it)[2*dist], (*it)[2*dist+1]);
631 for (
size_t i=1; i<dist; ++i)
632 val *= F((*it)[2*i], (*it)[2*i+1]);
636 boost::tie(coord_l, coord_r) = midx.
get_coords(s, *it);
638 C.
reserve(coord_l.first, coord_r.first,
641 C(coord_l, coord_r) += val;
void run(std::string const &chkp1, std::string const &chkp2)
double truncated_fraction
base_t::const_iterator const_iterator
bool is_hermitian(block_matrix< Matrix, SymmGroup > const &m)
void heev(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &evecs, block_matrix< DiagMatrix, SymmGroup > &evals)
std::pair< coord_t, coord_t > get_coords(set_id s, key_t const &key) const
size_type n_blocks() const
std::pair< charge, elem_id > coord_t
void gemm_trim_left(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
void match_and_add_block(Matrix const &, charge, charge)
declaration of block_matrix class
block_matrix< Matrix, SymmGroup > op_exp(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > M, A const &alpha=1.)
size_t size(charge pc) const
maquis::traits::real_type< T >::type gather_real_pred(T const &val)
block_matrix< Matrix, SymmGroup > identity_matrix(Index< SymmGroup > const &size)
size_type insert_block(Matrix const &, charge, charge)
std::size_t size_of_block(charge c) const
const_iterator end() const
void op_kron(Index< SymmGroup > const &phys_A, Index< SymmGroup > const &phys_B, block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix1, SymmGroup > const &B, block_matrix< Matrix2, SymmGroup > &C)
std::size_t num_rows(maquis::dmrg::one_matrix< T > const &m)
block_matrix< Matrix, SymmGroup > adjoint(block_matrix< Matrix, SymmGroup > m)
scalar_type trace() const
size_t right_size(set_id s, charge const &c) const
truncation_results(std::size_t m, double tw, double tf, double se)
block_matrix< Matrix, SymmGroup > sqrt(block_matrix< Matrix, SymmGroup > m)
void resize_block(charge r, charge c, size_type new_r, size_type new_c, bool pretend=false)
void op_kron_long(MultiIndex< SymmGroup > const &midx, typename MultiIndex< SymmGroup >::set_id s, block_matrix< Matrix, SymmGroup > const &A, block_matrix< Matrix, SymmGroup > const &B, block_matrix< Matrix, SymmGroup > const &F, std::size_t dist, block_matrix< Matrix, SymmGroup > &C)
block_matrix< Matrix, SymmGroup >::scalar_type trace(block_matrix< Matrix, SymmGroup > const &m)
maquis::traits::scalar_type< Matrix >::type scalar_type
include one of the Index class definitions
truncation_results svd_truncate(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &U, block_matrix< Matrix, SymmGroup > &V, block_matrix< DiagMatrix, SymmGroup > &S, double rel_tol, std::size_t Mmax, bool verbose=true)
block_matrix< Matrix, SymmGroup > adjoin(block_matrix< Matrix, SymmGroup > const &m)
void estimate_truncation(block_matrix< DiagMatrix, SymmGroup > const &evals, size_t Mmax, double cutoff, size_t *keeps, double &truncated_fraction, double &truncated_weight, double &smallest_ev)
truncation_results heev_truncate(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &evecs, block_matrix< DiagMatrix, SymmGroup > &evals, double cutoff, std::size_t Mmax, bool verbose=true)
#define parallel_for(constraint,...)
real_type< typename T::value_type >::type type
bool has_block(charge r, charge c) const
block_matrix< Matrix, SymmGroup > conjugate(block_matrix< Matrix, SymmGroup > m)
size_t left_size(set_id s, charge const &c) const
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)
void op_kron(Matrix2 &out, const Matrix1 &in, const Matrix1 &alfa, size_t out_y_offset, size_t out_x_offset, size_t ldim1, size_t ldim2, size_t rdim1, size_t rdim2)
const_iterator begin() const
Index< SymmGroup > const & right_basis() const
void generate(Generator g)
void remove_block(charge r, charge c)
void reserve(charge, charge, std::size_t, std::size_t)
void lq(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &L, block_matrix< Matrix, SymmGroup > &Q)
truncation_results alt_svd_truncate(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &U, block_matrix< Matrix, SymmGroup > &V, block_matrix< DiagMatrix, SymmGroup > &S, double rel_tol, std::size_t Mmax, bool verbose=true)
void generate(block_matrix< Matrix, SymmGroup > &m, Generator &g)
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
block_matrix< typename maquis::traits::transpose_view< Matrix >::type, SymmGroup > transpose(block_matrix< Matrix, SymmGroup > const &m)
void gemm_trim_right(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
block_matrix< Matrix, SymmGroup > op_exp_hermitian(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > M, A const &alpha=1.)
Index< SymmGroup > const & left_basis() const
boost::enable_if< boost::is_complex< typename Matrix::value_type >, Matrix >::type exp_dispatcher(Matrix const &m, typename Matrix::value_type const &alpha)
alps::numeric::real_type< T >::type real(T f)
void qr(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &Q, block_matrix< Matrix, SymmGroup > &R)
std::size_t bond_dimension
std::size_t sum_of_sizes() const
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.