35 template<
class Matrix,
class SymmGroup>
36 class MPO :
public std::vector<MPOTensor<Matrix, SymmGroup> >
47 std::size_t length()
const {
return this->size(); }
49 void compress(
double cutoff)
53 for (
int p = 0; p < this->size()-1; ++p) {
68 maquis::cout <<
"MPO bond truncation: " <<
bond_indices[p+1].sum_of_sizes() <<
" -> ";
70 maquis::cout <<
bond_indices[p+1].sum_of_sizes() << std::endl;
75 std::vector<std::map<std::size_t, typename SymmGroup::charge> > bond_index_charges;
80 size_t L = this->size();
81 bond_index_charges.clear();
82 bond_index_charges.resize(L+1);
84 bond_index_charges[0][0] = SymmGroup::IdentityCharge;
86 for (
size_t p = 1; p <= L; ++p)
88 for (
size_t c = 0; c < (*this)[p-1].col_dim(); ++c) {
89 std::set<typename SymmGroup::charge> charge_diffs;
90 for (
size_t r = 0; r < (*this)[p-1].row_dim(); ++r) {
91 assert( bond_index_charges[p-1].count(r) > 0 );
92 if (!(*
this)[p-1].has(r,c))
94 for (
size_t b = 0; b < (*this)[p-1].at(r, c).op.n_blocks(); ++b) {
97 -(*this)[p-1].at(r,c).op.right_basis()[b].first)));
108 assert( charge_diffs.size() <= 1 );
110 if (charge_diffs.size() == 1)
111 bond_index_charges[p][c] = *charge_diffs.begin();
113 bond_index_charges[p][c] = SymmGroup::IdentityCharge;
119 for (
size_t p = 0; p <= L; ++p)
122 for (
typename std::map<std::size_t, typename SymmGroup::charge>::iterator it
123 = bond_index_charges[p].begin();
124 it != bond_index_charges[p].end();
126 if (index.
has(it->second))
129 index.
insert(std::make_pair(it->second, 1));
135 typedef typename SymmGroup::charge charge;
138 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r)
139 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c)
141 if (!(*
this)[p].has(r,c))
143 for (
size_t cs = 0; cs < (*this)[p].at(r, c).op.left_basis().size(); ++cs) {
144 std::pair<charge, size_t> sector = (*this)[p].at(r, c).op.left_basis()[cs];
145 if (! phys_i.
has(sector.first))
157 std::map<charge, size_t> visited_c_basis;
158 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c) {
160 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r)
161 for (
size_t ls = 0; ls < phys_i.
size(); ++ls)
162 for (
size_t rs = 0; rs < phys_i.
size(); ++rs) {
166 charge rc = bond_index_charges[p+1][c];
173 if (! (*
this)[p].has(r,c))
175 if (! (*
this)[p].at(r,c).op.has_block(phys_i[ls].first, phys_i[rs].first) )
178 std::size_t cs = (*this)[p].at(r, c).op.left_basis().position(phys_i[ls].first);
184 assert(
num_rows((*
this)[p].at(r,c).op[cs]) == 1 );
185 assert(
num_cols((*
this)[p].at(r,c).op[cs]) == 1 );
187 ret(std::make_pair(lc, outr),
188 std::make_pair(rc, visited_c_basis[rc])) =
189 (*this)[p].at(r,c).op[cs](0,0);
196 visited_c_basis[bond_index_charges[p+1][c]]++;
207 typedef typename SymmGroup::charge charge;
210 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r)
211 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c)
213 if (!(*
this)[p].has(r,c))
215 for (
size_t cs = 0; cs < (*this)[p].at(r, c).op.left_basis().size(); ++cs) {
216 std::pair<charge, size_t> sector = (*this)[p].at(r, c).op.left_basis()[cs];
217 if (! phys_i.
has(sector.first))
229 std::map<charge, size_t> visited_r_basis;
230 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r) {
232 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c)
233 for (
size_t ls = 0; ls < phys_i.
size(); ++ls)
234 for (
size_t rs = 0; rs < phys_i.
size(); ++rs) {
235 charge lc = bond_index_charges[p][r];
245 if (! (*
this)[p].has(r,c))
247 if (! (*
this)[p].at(r, c).op.has_block(phys_i[ls].first, phys_i[rs].first) )
250 std::size_t cs = (*this)[p].at(r, c).op.left_basis().position(phys_i[ls].first);
256 assert(
num_rows((*
this)[p].at(r,c).op[cs]) == 1 );
257 assert(
num_cols((*
this)[p].at(r,c).op[cs]) == 1 );
259 ret(std::make_pair(lc, visited_r_basis[lc]),
260 std::make_pair(rc, outc)) =
261 (*this)[p].at(r,c).op[cs](0,0);
268 visited_r_basis[bond_index_charges[p][r]]++;
281 typedef typename SymmGroup::charge charge;
284 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r)
285 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c)
287 for (
size_t cs = 0; cs < (*this)[p].at(r, c).op.left_basis().size(); ++cs) {
288 std::pair<charge, size_t> sector = (*this)[p].at(r, c).op.left_basis()[cs];
289 if (! phys_i.
has(sector.first))
297 std::size_t count = 0;
298 bond_index_charges[p+1].clear();
301 bond_index_charges[p+1][count++] = (*it).first;
305 bond_indices[p+1].sum_of_sizes());
307 std::map<charge, size_t> visited_c_basis;
308 for (
size_t c = 0; c < (*this)[p].col_dim(); ++c) {
310 for (
size_t r = 0; r < (*this)[p].row_dim(); ++r)
311 for (
size_t ls = 0; ls < phys_i.
size(); ++ls)
312 for (
size_t rs = 0; rs < phys_i.
size(); ++rs)
317 charge rc = bond_index_charges[p+1][c];
324 typename Matrix::value_type val = left(std::make_pair(lc, outr),
325 std::make_pair(rc, visited_c_basis[rc]));
327 if (std::abs(val) > 1e-40) {
329 charge blc = phys_i[ls].first, brc = phys_i[rs].first;
330 if ( (*
this)[p].has(r,c) )
331 block = (*this)[p].at(r,c).op;
333 (*this)[p].set(r, c, block);
341 visited_c_basis[bond_index_charges[p+1][c]]++;
345 (*this)[p+1].col_dim());
347 std::map<charge, size_t> visited_r_basis;
348 for (
size_t r = 0; r < (*this)[p+1].row_dim(); ++r) {
350 for (
size_t c = 0; c < (*this)[p+1].col_dim(); ++c)
351 for (
size_t ls = 0; ls < phys_i.
size(); ++ls)
352 for (
size_t rs = 0; rs < phys_i.
size(); ++rs)
354 charge lc = bond_index_charges[p+1][r];
364 typename Matrix::value_type val = right(std::make_pair(lc, visited_r_basis[lc]),
365 std::make_pair(rc, outc));
367 if (std::abs(val) > 1e-40) {
369 charge blc = phys_i[ls].first, brc = phys_i[rs].first;
370 if ( (*
this)[p+1].has(r,c) )
371 block = (*this)[p+1].at(r,c).op;
373 (*this)[p+1].set(r, c, block);
381 visited_r_basis[bond_index_charges[p+1][r]]++;
block_matrix< Matrix, SymmGroup > make_right_matrix(std::size_t p)
size_type insert_block(Matrix const &, charge, charge)
std::size_t size_of_block(charge c) const
MPOTensor< Matrix, SymmGroup > elem_type
std::size_t num_rows(maquis::dmrg::one_matrix< T > const &m)
block_matrix< Matrix, SymmGroup > sqrt(block_matrix< Matrix, SymmGroup > m)
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)
std::size_t num_cols(maquis::dmrg::one_matrix< T > const &m)
declaration of MPOTensor object
Index< SymmGroup > const & right_basis() const
std::vector< Index< SymmGroup > > bond_indices
std::size_t position(charge c) const
block_matrix< Matrix, SymmGroup > make_left_matrix(std::size_t p)
std::size_t insert(std::pair< charge, std::size_t > const &x)
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
Index< SymmGroup > const & left_basis() const
Index< SymmGroup > common_subset(Index< SymmGroup > &a, Index< SymmGroup > &b)
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.
void replace_pair(block_matrix< Matrix, SymmGroup > &left, block_matrix< Matrix, SymmGroup > &right, std::size_t p)