1#ifndef DMRG_HAMILTONIAN_TERMS
2#define DMRG_HAMILTONIAN_TERMS
3#define EIGEN_DONT_VECTORIZE
5#define DEBUG_VERBOSITY 0
8#ifndef MAX_SUMPROD_STRINGLENGTH
9#define MAX_SUMPROD_STRINGLENGTH 700
15#include "boost/multi_array.hpp"
18#include "numeric_limits.h"
25#ifdef USE_HDF5_STORAGE
26 #include <HDF5Interface.h>
34template<
typename Symmetry,
typename Scalar>
class MpoTerms
38 typedef typename Symmetry::qType
qType;
39 typedef Eigen::SparseMatrix<Scalar,Eigen::ColMajor,EIGEN_DEFAULT_SPARSE_INDEX_TYPE>
MatrixType;
47 std::vector<std::map<std::array<qType, 2>,std::vector<std::vector<std::map<qType,OperatorType>>>>>
O;
55 std::vector<std::map<qType, std::size_t>>
auxdim;
86 std::vector<std::vector<std::string>>
info;
184 void add (
const std::size_t loc,
const OperatorType &op,
const qType &qIn,
const qType &qOut,
const std::size_t IndexIn,
const std::size_t IndexOut);
225 std::map<qType, std::vector<std::map<qType,OperatorType>>>
delete_row (
const std::size_t loc,
const qType &qIn,
const std::size_t row_to_delete,
const bool SAMESITE);
235 std::map<qType, std::vector<std::map<qType,OperatorType>>>
delete_col (
const std::size_t loc,
const qType &qOut,
const std::size_t col_to_delete,
const bool SAMESITE);
245 void add_to_row (
const std::size_t loc,
const qType &qIn,
const std::size_t row,
const std::map<
qType,std::vector<std::map<qType,OperatorType>>> &ops,
const Scalar factor);
255 void add_to_col (
const std::size_t loc,
const qType &qOut,
const std::size_t col,
const std::map<
qType,std::vector<std::map<qType,OperatorType>>> &ops,
const Scalar factor);
302 inline std::tuple<std::size_t,std::size_t,std::size_t,std::size_t>
auxdim_infos ()
const;
312 static void prod_swap_IBC (std::vector<std::map<std::array<qType,2>,std::vector<std::vector<std::map<qType,OperatorType>>>>> &O_out, std::vector<std::size_t> &row_qVac, std::vector<std::size_t> &col_qVac, std::vector<std::size_t> &row_qTot, std::vector<std::size_t> &col_qTot);
344 std::vector<qType>
calc_qList (
const std::vector<OperatorType> &opList);
354 std::vector<std::vector<qType>>
qOp;
360 std::vector<Qbasis<Symmetry>>
qAux;
366 std::vector<std::vector<qType>>
qPhys;
372 std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>>
W;
390 std::vector<std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>>>
W_powers;
404 std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>>
W;
405 std::vector<Qbasis<Symmetry>>
qAux;
419 void reconstruct (
const std::vector<std::map<std::array<qType,2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> &O_in,
const std::vector<
Qbasis<Symmetry>> &qAux_in,
const std::vector<std::vector<qType>> &qPhys_in,
const bool FINALIZED_IN,
const BC boundary_condition_in,
const qType &qTot_in = Symmetry::qvacuum());
446 virtual void push (
const std::size_t loc,
const std::vector<OperatorType> &opList,
const std::vector<qType> &qList,
const Scalar lambda = 1.0);
455 void push (
const std::size_t loc,
const std::vector<OperatorType> &opList,
const Scalar lambda = 1.0) {
push(loc, opList,
calc_qList(opList), lambda);}
466 void save_label (
const std::size_t loc,
const std::string &info_label);
488 void scale (
const Scalar factor,
const Scalar offset=0.,
const std::size_t power=0ul,
const double tolerance=1.e-14);
510 void finalize (
const bool COMPRESS=
true,
const std::size_t power=1,
const double tolerance=::mynumeric_limits<double>::epsilon());
516 void calc (
const std::size_t power);
526 const std::vector<std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> &
get_O ()
const {
return O;}
531 const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>> &
get_W ()
const {assert(
GOT_W and
"W has not been calculated!");
return W;}
536 const std::vector<Qbasis<Symmetry>> &
get_qAux ()
const {assert(
GOT_QAUX and
"qAux has not been calculated!");
return qAux;}
541 const std::vector<std::vector<qType>> &
get_qOp ()
const {assert(
GOT_QOP and
"qOp has not been calculated!");
return qOp;}
552 const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>> &
get_W_power (std::size_t power)
const;
564 const std::vector<std::vector<qType>> &
get_qOp_power (std::size_t power)
const;
628 void transform_base (
const qType &qShift,
const bool PRINT=
false,
const int factor=-1,
const std::size_t powre=0ul);
638 std::vector<std::pair<qType,std::size_t>>
base_order_IBC (
const std::size_t power=1)
const;
645 double memory (MEMUNIT memunit=kB)
const;
653 double sparsity (
const std::size_t power=1,
const bool PER_MATRIX=
false)
const;
677 void set_Identity (
const typename Symmetry::qType &Q=Symmetry::qvacuum());
695 void save (std::string filename);
696 void load (std::string filename);
699 const std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>> &
W_at (
const std::size_t loc)
const {
return W[loc];}
700 const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, MatrixType>>>>> &
W_full ()
const {
return W;}
703 const std::vector<qType> &
locBasis (
const std::size_t loc)
const {
return qPhys[loc];}
710 const std::vector<std::vector<qType>> &
opBasis ()
const {
return qOp;}
711 const std::vector<qType> &
opBasis (
const std::size_t loc)
const {
return qOp[loc];}
715 void setLocBasis (
const std::vector<std::vector<qType>> &q) {
for(std::size_t loc=0; loc<q.size(); ++loc)
set_qPhys(loc, q[loc]);}
725 void setQtarget (
const qType &q) {assert(
false and
"setQtarget should not be called after the MPO has been initialized.");}
733: N_sites(L), boundary_condition(boundary_condition_in), qTot(qTot_in), VERB(VERB_in)
744 #if DEBUG_VERBOSITY > 0
747 lout <<
"Initializing an MPO with L=" << N_sites <<
", Boundary condition=" << boundary_condition <<
" and qTot={" << Sym::format<Symmetry>(qTot) <<
"}" << std::endl;
751 std::stringstream ss;
752 ss << before_verb_set <<
"Initializing an MPO with L=" << N_sites <<
", Boundary condition=" << boundary_condition <<
" and qTot={" << Sym::format<Symmetry>(qTot) <<
"}" << std::endl;
753 before_verb_set = ss.str();
756 assert(boundary_condition ==
BC::OPEN or qTot == qVac);
768 hilbert_dimension.clear();
769 hilbert_dimension.resize(N_sites, 0);
774 auxdim.resize(N_sites+1);
776 qPhys.resize(N_sites);
778 GOT_QPHYS.resize(N_sites,
false);
780 info.resize(N_sites);
784 increment_first_auxdim_OBC(qVac);
785 increment_first_auxdim_OBC(qTot);
786 increment_last_auxdim_OBC(qVac);
787 increment_last_auxdim_OBC(qTot);
791 increment_auxdim(0,qVac);
792 increment_auxdim(0,qTot);
794 for(std::size_t loc=1; loc<N_sites; ++loc)
796 increment_auxdim(loc,qVac);
797 increment_auxdim(loc,qTot);
802initialize (
const std::size_t L,
const BC boundary_condition_in,
const qType &qTot_in)
805 boundary_condition = boundary_condition_in;
811reconstruct (
const std::vector<std::map<std::array<qType,2>,std::vector<std::vector<std::map<qType,OperatorType>>>>> &O_in,
const std::vector<
Qbasis<Symmetry>> &qAux_in,
const std::vector<std::vector<qType>> &qPhys_in,
const bool FINALIZED_IN,
const BC boundary_condition_in,
const qType &qTot_in)
813 #if DEBUG_VERBOSITY > 0
816 lout <<
"Reconstructing an MPO with L=" << O_in.size() <<
", Boundary condition=" << boundary_condition_in <<
" and qTot={" << Sym::format<Symmetry>(qTot_in) <<
"}" << std::endl;
820 std::stringstream ss;
821 ss << before_verb_set <<
"Reconstructing an MPO with L=" << O_in.size() <<
", Boundary condition=" << boundary_condition_in <<
" and qTot={" << Sym::format<Symmetry>(qTot_in) <<
"}" << std::endl;
822 before_verb_set = ss.str();
825 N_sites = O_in.size();
826 boundary_condition = boundary_condition_in;
839 assert(boundary_condition ==
BC::OPEN or qTot == qVac);
851 hilbert_dimension.clear();
852 hilbert_dimension.resize(N_sites,0);
855 auxdim.resize(N_sites+1);
857 GOT_QPHYS.resize(N_sites,
false);
859 info.resize(N_sites);
860 for(std::size_t loc=0; loc<N_sites; ++loc)
862 hilbert_dimension[loc] = qPhys[loc].size();
863 GOT_QPHYS[loc] =
true;
865 for(std::size_t loc=0; loc<N_sites+1; ++loc)
867 std::vector<qType> qs = qAux_in[loc].qs();
869 for(
const auto &q : qs)
871 std::size_t deg = qAux_in[loc].inner_dim(q);
872 auxdim[loc].insert({q,deg});
883 #if DEBUG_VERBOSITY > 0
886 lout << before_verb_set;
893push (
const std::size_t loc,
const std::vector<OperatorType> &opList,
const std::vector<qType> &qList,
const Scalar lambda)
895 assert(loc < N_sites and
"Chosen lattice site out of bounds");
896 assert((loc+opList.size() <= N_sites or boundary_condition ==
BC::INFINITE) and
"For finite lattices operators must not exceed lattice size");
898 std::size_t range = opList.size();
899 assert(qList.size() == range+1 and
"Amount of quantum numbers does not match amount of operators!");
900 assert(qList[0] == qVac and qList[range] == qTot and
"Quantum number list does not match the total MPO quantum number!");
901 if(std::abs(lambda) < ::mynumeric_limits<double>::epsilon())
905 for(std::size_t i=0; i<range; ++i)
907 assert_hilbert((loc+i)%N_sites, opList[i].data.rows());
908 if(opList[i].data.norm() < ::mynumeric_limits<double>::epsilon())
915 #if DEBUG_VERBOSITY > 0
918 lout <<
"Local interaction at site " << loc;
920 lout <<
": " << lambda <<
" * " << opList[0].label;
925 assert(opList[0].Q == qTot and
"Local operator does not match the total MPO quantum number!");
926 add(loc, lambda*opList[0], qVac, qTot, pos_qVac, pos_qTot);
930 #if DEBUG_VERBOSITY > 0
933 lout << range-1 <<
".-neighbour interaction between the sites " << loc <<
" and " << (loc+range-1)%N_sites;
935 lout <<
": " << lambda <<
" * " << opList[0].label <<
" ";
936 for(std::size_t n=1; n<range; ++n)
938 lout <<
" * " << opList[n].label;
944 std::size_t row = pos_qVac;
945 std::size_t col = get_auxdim(loc+1, qList[1]);
946 increment_auxdim((loc+1)%N_sites, qList[1]);
947 add(loc, lambda*opList[0], qVac, qList[1], row, col);
948 for(
int i=1; i<range-1; ++i)
951 col = get_auxdim(loc+1+i, qList[i+1]);
952 increment_auxdim((loc+1+i)%N_sites, qList[i+1]);
953 add((loc+i)%N_sites, opList[i], qList[i], qList[i+1], row, col);
957 add((loc+range-1)%N_sites, opList[range-1], qList[range-1], qTot, row, col);
962calc_qList (
const std::vector<OperatorType> &opList)
967 std::vector<qType> history;
969 qBranch(
qType current_in, std::vector<qType> history_in)
970 : current{current_in}, history{history_in}{}
973 std::stringstream sout;
974 for(
int i=0; i<history.size(); ++i)
976 sout <<
"{" << Sym::format<Symmetry>(history[i]) <<
"} -> ";
978 sout <<
"{" << Sym::format<Symmetry>(current) <<
"}";
983 std::size_t range = opList.size();
984 std::vector<std::vector<qBranch>> Qtree(range);
985 qBranch temp{opList[0].Q, {}};
986 Qtree[0].push_back(temp);
987 for(std::size_t m=1; m<range; ++m)
989 for(
int i=0; i<Qtree[m-1].size(); ++i)
991 std::vector<qType> qs = Symmetry::reduceSilent(opList[m].Q, Qtree[m-1][i].current);
992 for(
int j=0; j<qs.size(); ++j)
994 qBranch temp{qs[j], Qtree[m-1][i].history};
995 temp.history.push_back(Qtree[m-1][i].current);
996 Qtree[m].push_back(temp);
1001 std::vector<qType> qList(range+1);
1004 for (
int i=0; i<Qtree[range-1].size(); ++i)
1006 if (Qtree[range-1][i].current == qTot)
1009 for (
int j=0; j<range-1; ++j)
1011 qList[j+1] = Qtree[range-1][i].history[j];
1013 qList[range] = qTot;
1014 #if DEBUG_VERBOSITY > 1
1017 lout <<
"This branch of quantum numbers leads to the total MPO quantum number: {" << Sym::format<Symmetry>(qList[0]) <<
"} -> ";
1018 for(
int j=0; j<range-1; ++j)
1020 lout <<
"{" << Sym::format<Symmetry>(qList[j+1]) <<
"} -> ";
1022 lout <<
"{" << Sym::format<Symmetry>(qList[range]) <<
"}" << std::endl;
1027 if (count > 1) {lout << termcolor::red << count <<
" quantum number branches lead to the total MPO quantum number" << termcolor::reset << endl;}
1028 else if (count == 0) {lout << termcolor::red <<
"No quantum number branch leads to the total MPO quantum number" << termcolor::reset << endl;}
1036 lout <<
"####################################################################################################" << std::endl;
1037 lout <<
"Name: " << label << std::endl;
1038 lout <<
"System with " << N_sites <<
" lattice sites and " << boundary_condition <<
" boundary condition, target quantum number {" << Sym::format<Symmetry>(qTot) <<
"}";
1042 lout <<
", alterable and not finalized yet." << std::endl;
1045 lout <<
", already finalized." << std::endl;
1048 lout <<
", ill-defined state!" << std::endl;
1051 lout <<
"Approximate memory usage: " << round(memory(kB),1) <<
" kB";
1052 if(GOT_W and GOT_QOP)
1054 lout <<
", sparsity: " << round(sparsity()*100,1) <<
"%";
1057 auto [total_auxdim, maximum_local_auxdim, total_full_auxdim, maximum_local_full_auxdim] = auxdim_infos();
1058 lout <<
"Calculated bases and data:\n";
1061 lout <<
"• MPO auxiliar bases (Average bond dimension: " << (total_auxdim*1.0)/N_sites <<
" (max. " << maximum_local_auxdim <<
")";
1062 if(Symmetry::NON_ABELIAN)
1064 lout <<
", average full bond dimension: " << (total_full_auxdim*1.0)/N_sites <<
" (max. " << maximum_local_full_auxdim <<
")";
1066 lout <<
")" << std::endl;
1068 if(check_qPhys()) lout <<
"• Physical bases of local Hilbert spaces" << std::endl;
1069 if(GOT_QOP) lout <<
"• Local operator bases" << std::endl;
1070 if(GOT_W) lout <<
"• W matrix" << std::endl;
1071 if(current_power > 1) lout <<
"• All of the previous up to " << current_power <<
". power of the MPO" << std::endl;
1072 if(reversed.
SET) lout <<
"• Reversed W matrix and auxiliar bases" << std::endl;
1073 #if DEBUG_VERBOSITY > 0
1074 for(std::size_t loc=0; loc<N_sites; ++loc)
1076 lout <<
"Lattice site: " << loc << std::endl;
1077 lout <<
"\tPhysical basis of local Hilbert space (" << hilbert_dimension[loc] <<
" dim):\t";
1080 for(std::size_t n=0; n<qPhys[loc].size(); ++n)
1082 lout <<
"\t{" << Sym::format<Symmetry>(qPhys[loc][n]) <<
"}";
1085 lout <<
"\n\tIncoming quantum numbers:\t";
1086 for(
const auto &[qIn, deg] : auxdim[loc])
1088 lout <<
"\t({" << Sym::format<Symmetry>(qIn) <<
"} [#=" << deg <<
"])";
1090 lout <<
"\n\tOutgoing quantum numbers:\t";
1091 for(
const auto &[qOut, deg] : auxdim[loc+1])
1093 lout <<
"\t({" << Sym::format<Symmetry>(qOut) <<
"} [#=" << deg <<
"])";
1096 #if DEBUG_VERBOSITY > 2
1097 lout <<
"\tOperators:" << std::endl;
1098 for(
const auto &[qs, ops] : O[loc])
1100 std::size_t rows = get_auxdim(loc, std::get<0>(qs));
1101 std::size_t cols = get_auxdim(loc+1, std::get<1>(qs));
1102 bool any_nonzero =
false;
1103 for(std::size_t row=0; row<rows; ++row)
1105 for(std::size_t col=0; col<cols; ++col)
1107 if(ops[row][col].size() > 0)
1112 lout <<
"\t\t{" << Sym::format<Symmetry>(std::get<0>(qs)) <<
"}->{" << Sym::format<Symmetry>(std::get<1>(qs)) <<
"}:" << std::endl;
1114 lout <<
"\t\t\tPosition [" << row <<
"|" << col <<
"]:";
1115 for(
const auto &[Q,op] : ops[row][col])
1118 lout <<
"\t" << op.label <<
" ({" << Sym::format<Symmetry>(Q) <<
"}) norm=" << op.data.norm();
1120 lout <<
"\t ({" << Sym::format<Symmetry>(Q) <<
"}) norm=" << op.data.norm();
1131 lout <<
"####################################################################################################" << std::endl;
1135calc (
const std::size_t power)
1150 qAux_powers.clear();
1152 W_powers.resize(power-1);
1153 qAux_powers.resize(power-1);
1154 qOp_powers.resize(power-1);
1156 for(std::size_t n=2; n<=power; ++n)
1158 std::vector<qType> qTots = Symmetry::reduceSilent(current.
get_qTot(),qTot);
1159 assert(qTots.size() == 1 and
"Target quantum number has to be unique for computing higher powers of the MPO.");
1161 W_powers[n-2] = current.
get_W();
1162 qAux_powers[n-2] = current.
get_qAux();
1163 qOp_powers[n-2] = current.
get_qOp();
1164 #if DEBUG_VERBOSITY > 0
1167 lout << n <<
". power of the MPO:" << std::endl;
1172 current_power = power;
1178 assert(GOT_QOP and
"qOp is needed for calculation of W matrix!");
1181 for(std::size_t loc=0; loc<N_sites; ++loc)
1183 std::size_t hdim = hilbert_dimension[loc];
1184 std::size_t odim = qOp[loc].size();
1185 W[loc].resize(hdim);
1186 for(std::size_t m=0; m<hdim; ++m)
1188 W[loc][m].resize(hdim);
1189 for(std::size_t n=0; n<hdim; ++n)
1191 W[loc][m][n].resize(odim);
1192 for(std::size_t t=0; t<odim; ++t)
1195 for(
const auto &[qIn, rows] : auxdim[loc])
1197 for(
const auto &[qOut, cols] : auxdim[loc+1])
1199 auto it = O[loc].find({qIn, qOut});
1200 assert(it != O[loc].end());
1201 bool found_match =
false;
1204 for(std::size_t row=0; row<rows; ++row)
1206 for(std::size_t col=0; col<cols; ++col)
1208 for(
const auto &[Q,op] : (it->second)[row][col])
1210 if(Q == qOp[loc][t])
1212 mat.coeffRef(row, col) = op.data.coeff(m,n);
1213 if(std::abs(mat.coeffRef(row, col)) > ::mynumeric_limits<double>::epsilon())
1221 if(found_match and mat.norm() > ::mynumeric_limits<double>::epsilon())
1227 W[loc][m][n][t] = bip;
1238 qOp.resize(N_sites);
1240 for(std::size_t loc=0; loc<N_sites; ++loc)
1242 std::set<typename Symmetry::qType> qOp_set;
1243 for(
const auto &[qs, ops] : O[loc])
1245 std::size_t rows = get_auxdim(loc, std::get<0>(qs));
1246 std::size_t cols = get_auxdim(loc+1, std::get<1>(qs));
1247 for(std::size_t row=0; row<rows; ++row)
1249 for(std::size_t col=0; col<cols; ++col)
1251 for(
const auto &[Q,op] : ops[row][col])
1258 qOp[loc].resize(qOp_set.size());
1259 copy(qOp_set.begin(), qOp_set.end(), qOp[loc].begin());
1267 qAux.resize(N_sites+1);
1268 for(std::size_t loc=0; loc<N_sites+1; ++loc)
1271 for(
const auto &[q,deg] : auxdim[loc])
1273 qAux[loc].push_back(q,deg);
1281finalize (
const bool COMPRESS,
const std::size_t power,
const double tolerance)
1285 for(std::size_t loc=0; loc<N_sites; ++loc)
1287 if(hilbert_dimension[loc] == 0) hilbert_dimension[loc] = 1;
1288 OperatorType Id(Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Identity(hilbert_dimension[loc], hilbert_dimension[loc]).sparseView(),qVac);
1292 add(loc, Id, qVac, qVac, pos_qVac, pos_qVac);
1293 add(loc, Id, qTot, qTot, pos_qTot, pos_qTot);
1297 delete_row(0, qTot, pos_qTot,
false);
1298 bool SAMESITE =
false;
1303 delete_col(N_sites-1, qVac, pos_qVac,SAMESITE);
1305 decrement_first_auxdim_OBC(qTot);
1306 decrement_last_auxdim_OBC(qVac);
1313 compress(tolerance);
1318#ifdef USE_OLD_COMPRESSION
1322 std::size_t lindep_checks=0;
1324 #if DEBUG_VERBOSITY > 0
1327 lout <<
"Starting compression of the MPO" << std::endl;
1331 auto [total_auxdim_initial, maximum_local_auxdim_initial, total_full_auxdim_initial, maximum_local_full_auxdim_initial] = auxdim_infos();
1332 std::vector<bool> updated_bond(N_sites,
true);
1333 std::size_t minimum_bond = 0;
1337 updated_bond[0] =
false;
1339 auto any_update = [minimum_bond](
const std::vector<bool> &bonds)->
bool
1341 for(std::size_t loc=minimum_bond; loc<bonds.size(); ++loc)
1350 std::size_t counter = 0;
1351 while(any_update(updated_bond))
1353 bool change =
false;
1354 for(std::size_t loc=minimum_bond; loc<N_sites; ++loc)
1356 if(updated_bond[(loc+N_sites-1)%N_sites] or updated_bond[loc])
1358 for(
auto &[q,deg] : auxdim[loc])
1361 if(eliminate_linearlyDependent_cols((loc+N_sites-1)%N_sites,q,tolerance))
1364 updated_bond[loc] =
true;
1366 #if DEBUG_VERBOSITY > 2
1369 lout <<
"Current MPO:" << std::endl;
1377 if(!change and (updated_bond[loc] or updated_bond[(loc+1)%N_sites]))
1379 for(
auto &[q,deg] : auxdim[loc])
1382 if(eliminate_linearlyDependent_rows(loc,q,tolerance))
1385 updated_bond[loc] =
true;
1387 #if DEBUG_VERBOSITY > 2
1390 lout <<
"Current MPO:" << std::endl;
1403 else if(updated_bond[loc])
1405 #if DEBUG_VERBOSITY > 1
1408 lout <<
"Bond connecting lattice sites " << (loc+N_sites-1)%N_sites <<
" and " << loc <<
": No linear dependence detected" << std::endl;
1411 updated_bond[loc] =
false;
1415 auto [total_auxdim_final, maximum_local_auxdim_final, total_full_auxdim_final, maximum_local_full_auxdim_final] = auxdim_infos();
1416 int compr_rate = (int)std::round(100.-(100.*total_auxdim_final)/(1.0*total_auxdim_initial));
1417 std::stringstream ss;
1418 auto curr_prec = std::cout.precision();
1419 ss << this->get_name() <<
" - Compression (Old alg.) | " << watch.info(
"Time") <<
" | Steps: " << counter <<
" | Rate: " << compr_rate <<
"% (" << std::setprecision(1)
1420 << std::fixed << (total_auxdim_initial*1.0)/N_sites <<
"(max=" << maximum_local_auxdim_initial <<
")" <<
" ⇒ " << (total_auxdim_final*1.0)/N_sites <<
"(max=" << maximum_local_auxdim_final <<
")"
1421 <<
") | Linear dependence checks: " << lindep_checks << std::defaultfloat << std::endl;
1422 std::cout.precision(curr_prec);
1426 #if DEBUG_VERBOSITY > 1
1427 lout <<
"Compressed MPO:" << std::endl;
1433 before_verb_set += ss.str();
1440 std::size_t lindep_checks = 0;
1442 #if DEBUG_VERBOSITY > 0
1445 lout <<
"Starting compression of the MPO" << std::endl;
1449 auto [total_auxdim_initial, maximum_local_auxdim_initial, total_full_auxdim_initial, maximum_local_full_auxdim_initial] = auxdim_infos();
1450 std::vector<std::size_t> bonds_to_check;
1451 for(std::size_t bond=1; bond<N_sites; bond+=2ul)
1453 bonds_to_check.push_back(bond);
1455 if(boundary_condition ==
BC::INFINITE and N_sites%2 == 1)
1457 bonds_to_check.push_back(N_sites);
1459 std::size_t counter = 0;
1460 std::size_t threads = 1;
1462 threads = omp_get_max_threads();
1464 while(!bonds_to_check.empty())
1467 std::vector<std::vector<std::size_t>> next_bonds_to_check(threads);
1468 std::size_t lindep_checks_temp = 0ul;
1469 #pragma omp parallel for shared(next_bonds_to_check) reduction(+ : lindep_checks_temp)
1470 for(std::size_t i=0; i<bonds_to_check.size(); ++i)
1472 std::size_t thread_id = 0;
1474 thread_id = omp_get_thread_num();
1476 std::size_t loc = bonds_to_check[i];
1477 std::vector<qType> qs;
1478 for(
const auto &[q,deg] : auxdim[loc])
1482 for(std::size_t j=0; j<qs.size(); ++j)
1485 lindep_checks_temp++;
1486 if(eliminate_linearlyDependent_cols(loc-1,q,tolerance))
1490 next_bonds_to_check[thread_id].push_back(loc-1);
1494 next_bonds_to_check[thread_id].push_back(loc+1);
1496 if(boundary_condition ==
BC::INFINITE and (loc <= 1ul or loc >= N_sites-1))
1498 next_bonds_to_check[thread_id].push_back(N_sites);
1500 lindep_checks_temp++;
1501 while(eliminate_linearlyDependent_cols(loc-1,q,tolerance)) {lindep_checks_temp++;}
1503 #if DEBUG_VERBOSITY > 1
1506 lout <<
"O[" << loc-1 <<
"](...->{" << Sym::format<Symmetry>(q) <<
"}): No linear dependent columns detected!" << std::endl;
1509 lindep_checks_temp++;
1510 if(eliminate_linearlyDependent_rows(loc%N_sites,q,tolerance))
1514 next_bonds_to_check[thread_id].push_back(loc-1);
1518 next_bonds_to_check[thread_id].push_back(loc+1);
1520 if(boundary_condition ==
BC::INFINITE and (loc <= 1ul or loc >= N_sites-1))
1522 next_bonds_to_check[thread_id].push_back(N_sites);
1524 lindep_checks_temp++;
1525 while(eliminate_linearlyDependent_rows(loc%N_sites,q,tolerance)) {lindep_checks_temp++;}
1527 #if DEBUG_VERBOSITY > 1
1530 lout <<
"O[" << loc%N_sites <<
"]({" << Sym::format<Symmetry>(q) <<
"}->...): No linear dependent rows detected!" << std::endl;
1535 lindep_checks += lindep_checks_temp;
1537 #if DEBUG_VERBOSITY > 2
1540 lout <<
"Current MPO:" << std::endl;
1545 std::set<std::size_t> unique_control;
1548 for(std::size_t bond=2; bond<N_sites; bond+=2ul)
1550 unique_control.insert(bond);
1552 if(boundary_condition ==
BC::INFINITE and N_sites%2 == 0)
1554 unique_control.insert(N_sites);
1557 for(std::size_t thread_id=0; thread_id<threads; ++thread_id)
1559 for(std::size_t i=0; i<next_bonds_to_check[thread_id].size(); ++i)
1561 unique_control.insert(next_bonds_to_check[thread_id][i] != 0 ? next_bonds_to_check[thread_id][i] : N_sites);
1564 bonds_to_check.resize(0);
1565 for(std::set<std::size_t>::iterator it = unique_control.begin(); it != unique_control.end(); ++it)
1567 bonds_to_check.push_back(*it);
1571 auto [total_auxdim_final, maximum_local_auxdim_final, total_full_auxdim_final, maximum_local_full_auxdim_final] = auxdim_infos();
1572 int compr_rate = (int)std::round(100.-(100.*total_auxdim_final)/(1.0*total_auxdim_initial));
1573 std::stringstream ss;
1574 auto curr_prec = std::cout.precision();
1575 ss << this->get_name() <<
" - Compression (New alg., threads: " << threads <<
") | " << watch.info(
"Time") <<
" | Steps: " << counter <<
" | Rate: " << compr_rate <<
"% (" << std::setprecision(1) << std::fixed << (total_auxdim_initial*1.0)/N_sites <<
" ⇒ " << (total_auxdim_final*1.0)/N_sites <<
") | Linear dependence checks: " << lindep_checks << std::defaultfloat << std::endl;
1576 std::cout.precision(curr_prec);
1580 #if DEBUG_VERBOSITY > 1
1581 lout <<
"Compressed MPO:" << std::endl;
1587 before_verb_set += ss.str();
1595 std::size_t rows = get_auxdim(loc, qIn);
1600 bool SAMESITE =
false;
1601 if(N_sites == 1 and boundary_condition ==
BC::INFINITE)
1605 assert(hilbert_dimension[loc] > 0);
1606 std::size_t cols_eff = 0;
1607 std::size_t hd = hilbert_dimension[loc];
1609 std::map<qType,std::vector<std::vector<qType>>> opQs;
1610 for(
const auto &[qs,ops] : O[loc])
1612 if(std::get<0>(qs) != qIn)
1616 std::vector<std::vector<qType>> opQs_fixed_qOut(ops[0].size());
1617 for(std::size_t col=0; col<ops[0].size(); ++col)
1619 std::unordered_set<qType> unique_control;
1620 for(std::size_t row=0; row<ops.size(); ++row)
1623 for(
const auto &[Q,op] : ops[row][col])
1625 unique_control.insert(Q);
1628 cols_eff += (unique_control.size() * hd * hd);
1629 opQs_fixed_qOut[col].resize(unique_control.size());
1630 std::copy(unique_control.begin(), unique_control.end(), opQs_fixed_qOut[col].begin());
1632 opQs.insert({std::get<1>(qs), opQs_fixed_qOut});
1634 std::size_t rows_eff = rows;
1635 std::size_t skipcount = 0;
1638 rows_eff = rows_eff-2;
1640 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> mat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(rows_eff, cols_eff);
1641 for(std::size_t row=0; row<rows; ++row)
1643 std::size_t count = 0;
1644 if((boundary_condition ==
BC::INFINITE and qIn == qVac and (row == pos_qVac or row == pos_qTot)))
1649 bool zero_row =
true;
1650 for(
const auto &[qOut, deg] : auxdim[loc+1])
1652 auto it_ops = O[loc].find({qIn,qOut});
1653 assert(it_ops != O[loc].end());
1654 auto it_qs = opQs.find(qOut);
1655 assert(it_qs != opQs.end());
1656 for(std::size_t col=0; col<deg; ++col)
1658 std::map<qType,OperatorType> &ops = (it_ops->second)[row][col];
1659 for(std::size_t n=0; n<(it_qs->second)[col].size(); ++n)
1661 qType &opQ = (it_qs->second)[col][n];
1662 auto it_op = ops.find(opQ);
1663 if(it_op != ops.end() and (it_op->second).data.norm() > tolerance)
1666 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> opmat((it_op->second).data);
1667 mat.block(row-skipcount, hd*hd*count, 1, hd*hd) = Eigen::Map<Eigen::Matrix<Scalar, 1, Eigen::Dynamic>>(opmat.data(), hd*hd);
1677 #if DEBUG_VERBOSITY > 1
1680 lout <<
"O[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->...): Row " << row <<
" is a zero row, but not the last row in these blocks. Thus it is deleted." << std::endl;
1683 delete_row(loc, qIn, row,
false);
1684 delete_col((loc+N_sites-1)%N_sites, qIn, row, SAMESITE);
1686 #if DEBUG_VERBOSITY > 1
1691 lout <<
"O[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->...): Row " << row <<
" is a zero row and the last row in this block. Thus the quantum number is removed from the auxiliar basis to delete the row and the corresponding column at the previous lattice site." << std::endl;
1695 decrement_auxdim(loc,qIn);
1699 if(rows > 3 or (rows > 1 and (boundary_condition ==
BC::OPEN or qIn != qVac)))
1701 std::size_t rowskipcount = 0;
1702 for(std::size_t row_to_delete=0; row_to_delete<rows; ++row_to_delete)
1704 if((boundary_condition ==
BC::INFINITE and qIn == qVac and (row_to_delete == pos_qVac or row_to_delete == pos_qTot)))
1709 std::size_t row_to_delete_eff = row_to_delete - rowskipcount;
1710 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> tempmat(cols_eff, rows_eff-1);
1711 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> tempvec(cols_eff);
1712 tempvec = mat.block(row_to_delete_eff, 0, 1, cols_eff).transpose();
1713 tempmat.block(0,0, cols_eff, row_to_delete_eff) = mat.block(0,0,row_to_delete_eff,cols_eff).transpose();
1714 tempmat.block(0,row_to_delete_eff, cols_eff, rows_eff-row_to_delete_eff-1) = mat.block(row_to_delete_eff+1,0,rows_eff-row_to_delete_eff-1,cols_eff).transpose();
1717 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> vec = tempmat.colPivHouseholderQr().solve(tempvec);
1719 if((tempmat*vec - tempvec).
norm() < tolerance)
1721 #if DEBUG_VERBOSITY > 1
1724 lout <<
"O[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->...): Row " << row_to_delete <<
" can be written as linear combination of other rows" << std::endl;
1727 delete_row(loc, qIn, row_to_delete,
false);
1728 std::map<qType, std::vector<std::map<qType,OperatorType>>> deleted_col = delete_col((loc+N_sites-1)%N_sites, qIn, row_to_delete, SAMESITE);
1729 decrement_auxdim(loc,qIn);
1730 std::size_t cols = get_auxdim(loc,qIn);
1731 std::size_t colskipcount = 0;
1732 for(std::size_t col=0; col<cols; ++col)
1734 if((boundary_condition ==
BC::INFINITE and qIn == qVac and (col == pos_qVac or col == pos_qTot)))
1739 if(std::abs(vec(col-colskipcount)) > tolerance)
1741 add_to_col((loc+N_sites-1)%N_sites, qIn, col, deleted_col, vec(col-colskipcount));
1754 std::size_t cols = get_auxdim(loc+1, qOut);
1759 bool SAMESITE =
false;
1760 if(N_sites == 1 and boundary_condition ==
BC::INFINITE)
1764 assert(hilbert_dimension[loc] > 0);
1765 std::size_t rows_eff = 0;
1766 std::size_t hd = hilbert_dimension[loc];
1768 std::map<qType,std::vector<std::vector<qType>>> opQs;
1769 for(
const auto &[qs,ops] : O[loc])
1771 if(std::get<1>(qs) != qOut)
1775 std::vector<std::vector<qType>> opQs_fixed_qIn(ops.size());
1776 for(std::size_t row=0; row<ops.size(); ++row)
1778 std::unordered_set<qType> unique_control;
1779 for(std::size_t col=0; col<ops[row].size(); ++col)
1781 for(
const auto &[Q,op] : ops[row][col])
1783 unique_control.insert(Q);
1786 rows_eff += (unique_control.size() * hd * hd);
1787 opQs_fixed_qIn[row].resize(unique_control.size());
1788 std::copy(unique_control.begin(), unique_control.end(), opQs_fixed_qIn[row].begin());
1790 opQs.insert({std::get<0>(qs), opQs_fixed_qIn});
1793 std::size_t cols_eff = cols;
1794 std::size_t skipcount = 0;
1795 if(boundary_condition ==
BC::INFINITE and qOut == qVac)
1797 cols_eff = cols_eff-2;
1799 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> mat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(rows_eff, cols_eff);
1800 for(std::size_t col=0; col<cols; ++col)
1802 std::size_t count = 0;
1803 if((boundary_condition ==
BC::INFINITE and qOut == qVac and (col == pos_qVac or col == pos_qTot)))
1808 bool zero_col =
true;
1809 for(
const auto &[qIn, deg] : auxdim[loc])
1811 auto it_ops = O[loc].find({qIn,qOut});
1812 assert(it_ops != O[loc].end());
1813 auto it_qs = opQs.find(qIn);
1814 assert(it_qs != opQs.end());
1815 for(std::size_t row=0; row<deg; ++row)
1817 std::map<qType,OperatorType> &ops = (it_ops->second)[row][col];
1818 for(std::size_t n=0; n<(it_qs->second)[row].size(); ++n)
1820 qType &opQ = (it_qs->second)[row][n];
1821 auto it_op = ops.find(opQ);
1822 if(it_op != ops.end() and (it_op->second).data.norm() > tolerance)
1825 Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> opmat((it_op->second).data);
1826 mat.block(hd*hd*count, col-skipcount, hd*hd, 1) = Eigen::Map<Eigen::Matrix<Scalar, Eigen::Dynamic,1>>(opmat.data(), hd*hd);
1836 #if DEBUG_VERBOSITY > 1
1839 lout <<
"O[" << loc <<
"](...->{" << Sym::format<Symmetry>(qOut) <<
"}): Column " << col <<
" is a zero column, but not the last column in these blocks. Thus it is deleted." << std::endl;
1842 delete_col(loc, qOut, col,
false);
1843 delete_row((loc+1)%N_sites, qOut, col, SAMESITE);
1845 #if DEBUG_VERBOSITY > 1
1850 lout <<
"O[" << loc <<
"](...->{" << Sym::format<Symmetry>(qOut) <<
"}): Column " << col <<
" is a zero column and the last column in this block. Thus the quantum number is removed from the auxiliar basis to delete the column and the corresponding row at the next lattice site." << std::endl;
1854 decrement_auxdim((loc+1)%N_sites,qOut);
1858 if(cols > 3 or ((boundary_condition ==
BC::OPEN or qOut != qVac) and cols>1))
1860 std::size_t colskipcount = 0;
1861 for(std::size_t col_to_delete=0; col_to_delete<cols; ++col_to_delete)
1863 if((boundary_condition ==
BC::INFINITE and qOut == qVac and (col_to_delete == pos_qVac or col_to_delete == pos_qTot)))
1869 std::size_t col_to_delete_eff = col_to_delete - colskipcount;
1870 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> tempmat(rows_eff, cols_eff-1);
1871 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> tempvec(rows_eff);
1872 tempvec = mat.block(0, col_to_delete_eff, rows_eff, 1);
1873 tempmat.block(0,0, rows_eff, col_to_delete_eff) = mat.block(0, 0, rows_eff, col_to_delete_eff);
1874 tempmat.block(0, col_to_delete_eff, rows_eff, cols_eff-col_to_delete_eff-1) = mat.block(0, col_to_delete_eff+1, rows_eff, cols_eff-col_to_delete_eff-1);
1876 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> vec = tempmat.colPivHouseholderQr().solve(tempvec);
1878 if((tempmat*vec - tempvec).
norm() < tolerance)
1880 #if DEBUG_VERBOSITY > 1
1883 lout <<
"O[" << loc <<
"](...->{" << Sym::format<Symmetry>(qOut) <<
"}): Column " << col_to_delete <<
" can be written as linear combination of other columns" << std::endl;
1886 delete_col(loc, qOut, col_to_delete,
false);
1887 std::map<qType, std::vector<std::map<qType,OperatorType>>> deleted_row = delete_row((loc+1)%N_sites, qOut, col_to_delete, SAMESITE);
1888 decrement_auxdim((loc+1)%N_sites,qOut);
1889 std::size_t rows = get_auxdim(loc+1,qOut);
1890 std::size_t rowskipcount = 0;
1891 for(std::size_t row=0; row<rows; ++row)
1893 if((boundary_condition ==
BC::INFINITE and qOut == qVac and (row == pos_qVac or row == pos_qTot)))
1899 if(std::abs(vec(row-rowskipcount)) > tolerance)
1901 add_to_row((loc+1)%N_sites, qOut, row, deleted_row, vec(row-rowskipcount));
1912add_to_row (
const std::size_t loc,
const qType &qIn,
const std::size_t row,
const std::map<
qType,std::vector<std::map<qType,OperatorType>>> &ops,
const Scalar factor)
1914 #if DEBUG_VERBOSITY > 2
1917 lout <<
"\tO[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->...): Add another row scaled by factor " << factor <<
" to row " << row << std::endl;
1920 std::size_t rows = get_auxdim(loc, qIn);
1921 assert(row < rows and
"Trying to add to a nonexisting row");
1923 for(
const auto &[qOut, deg] : auxdim[loc+1])
1925 auto it = O[loc].find({qIn, qOut});
1926 auto it2 = ops.find(qOut);
1927 assert(it != O[loc].end());
1928 assert(it2 != ops.end());
1929 assert((it2->second).size() == deg and
"Adding rows of different size");
1930 for(std::size_t col=0; col<deg; ++col)
1932 std::map<qType,OperatorType> &existing_ops = (it->second)[row][col];
1933 const std::map<qType,OperatorType> &ops_new = (it2->second)[col];
1934 for(
const auto &[Q_new,op_new] : ops_new)
1936 auto it3 = existing_ops.find(Q_new);
1937 if(it3 != existing_ops.end())
1939 (it3->second) += factor*op_new;
1943 existing_ops.insert({Q_new,factor*op_new});
1951add_to_col (
const std::size_t loc,
const qType &qOut,
const std::size_t col,
const std::map<
qType, std::vector<std::map<qType,OperatorType>>> &ops,
const Scalar factor)
1953 #if DEBUG_VERBOSITY > 2
1956 lout <<
"\tO[" << loc <<
"](...->{" << Sym::format<Symmetry>(qOut) <<
"}): Add another column scaled by factor " << factor <<
" to column " << col << std::endl;
1959 std::size_t cols = get_auxdim(loc+1, qOut);
1960 assert(col < cols and
"Trying to add to a nonexisting col");
1962 for(
const auto &[qIn, deg] : auxdim[loc])
1964 auto it = O[loc].find({qIn, qOut});
1965 auto it2 = ops.find(qIn);
1966 assert(it != O[loc].end());
1967 assert(it2 != ops.end());
1968 assert((it2->second).size() == deg and
"Adding columns of different size");
1969 for(std::size_t row=0; row<deg; ++row)
1971 std::map<qType,OperatorType> &existing_ops = (it->second)[row][col];
1972 const std::map<qType,OperatorType> &ops_new = (it2->second)[row];
1973 for(
const auto &[Q_new,op_new] : ops_new)
1975 auto it3 = existing_ops.find(Q_new);
1976 if(it3 != existing_ops.end())
1978 (it3->second) += factor*op_new;
1982 existing_ops.insert({Q_new,factor*op_new});
1989template<
typename Symmetry,
typename Scalar> std::map<typename Symmetry::qType,std::vector<std::map<typename Symmetry::qType,SiteOperator<Symmetry,Scalar>>>>
MpoTerms<Symmetry,Scalar>::
1990delete_row (
const std::size_t loc,
const qType &qIn,
const std::size_t row_to_delete,
const bool SAMESITE)
1992 #if DEBUG_VERBOSITY > 2
1995 lout <<
"\tO[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->...): Delete row " << row_to_delete << std::endl;
1998 lout <<
"\tPaying attention since a column has been deleted at the same site before" << std::endl;
2002 std::map<qType, std::vector<std::map<qType,OperatorType>>> deleted_row;
2003 std::size_t rows = get_auxdim(loc, qIn);
2004 assert(row_to_delete < rows and
"Trying to delete a nonexisting row");
2006 std::map<qType,OperatorType> empty_op_map;
2007 for(
const auto &[qOut, deg] : auxdim[loc+1])
2009 auto it = O[loc].find({qIn, qOut});
2010 std::vector<std::map<qType,OperatorType>> temp;
2011 assert(it != O[loc].end());
2012 std::size_t skip = 0;
2013 if(SAMESITE and qOut == qIn)
2017 for(std::size_t col=0; col<deg-skip; ++col)
2019 temp.push_back((it->second)[row_to_delete][col]);
2020 for(std::size_t row=row_to_delete; row<rows-1; ++row)
2022 (it->second)[row][col] = (it->second)[row+1][col];
2024 (it->second)[rows-1][col] = empty_op_map;
2026 deleted_row.insert({qOut, temp});
2031template<
typename Symmetry,
typename Scalar> std::map<typename Symmetry::qType,std::vector<std::map<typename Symmetry::qType,SiteOperator<Symmetry,Scalar>>>>
MpoTerms<Symmetry,Scalar>::
2032delete_col (
const std::size_t loc,
const qType &qOut,
const std::size_t col_to_delete,
const bool SAMESITE)
2034 #if DEBUG_VERBOSITY > 2
2037 lout <<
"\tO[" << loc <<
"](...->{" << Sym::format<Symmetry>(qOut) <<
"}): Delete column " << col_to_delete << std::endl;
2040 lout <<
"\tPaying attention since a row has been deleted at the same site before" << std::endl;
2044 std::map<qType, std::vector<std::map<qType,OperatorType>>> deleted_col;
2045 std::size_t cols = get_auxdim(loc+1, qOut);
2046 assert(col_to_delete < cols and
"Trying to delete a nonexisting column");
2048 std::map<qType,OperatorType> empty_op_map;
2049 for(
const auto &[qIn, deg] : auxdim[loc])
2051 auto it = O[loc].find({qIn, qOut});
2052 std::vector<std::map<qType,OperatorType>> temp;
2053 assert(it != O[loc].end());
2054 std::size_t skip = 0;
2055 if(SAMESITE and qIn == qOut)
2059 for(std::size_t row=0; row<deg-skip; ++row)
2061 temp.push_back((it->second)[row][col_to_delete]);
2062 for(std::size_t col=col_to_delete; col<cols-1; ++col)
2064 (it->second)[row][col] = (it->second)[row][col+1];
2066 (it->second)[row][cols-1] = empty_op_map;
2068 deleted_col.insert({qIn, temp});
2074add (
const std::size_t loc,
const OperatorType &op,
const qType &qIn,
const qType &qOut,
const std::size_t leftIndex,
const std::size_t rightIndex)
2076 #if DEBUG_VERBOSITY > 2
2080 lout <<
"O[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"})[" << leftIndex <<
"|" << rightIndex <<
"]: Add " << op.
label <<
" ({" << Sym::format<Symmetry>(op.
Q) <<
"})" << std::endl;
2082 lout <<
"O[" << loc <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"})[" << leftIndex <<
"|" << rightIndex <<
"]: Add Operator ({" << Sym::format<Symmetry>(op.
Q) <<
"})" << std::endl;
2086 std::size_t rows = get_auxdim(loc, qIn);
2087 std::size_t cols = get_auxdim(loc+1, qOut);
2088 auto it = O[loc].find({qIn, qOut});
2089 assert(leftIndex <= rows and
"Index out of bounds");
2090 assert(rightIndex <= cols and
"Index out of bounds");
2091 assert(it != O[loc].end() and
"Quantum numbers not available");
2093 std::map<qType,OperatorType> &existing_ops = (it->second)[leftIndex][rightIndex];
2094 auto it2 = existing_ops.find(op.
Q);
2095 if(it2 != existing_ops.end())
2097 (it2->second) += op;
2101 existing_ops.insert({op.
Q,op});
2108 #if DEBUG_VERBOSITY > 1
2111 lout <<
"\tqAux[" << (loc+N_sites-1)%N_sites <<
"->" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}): ";
2115 std::map<qType,OperatorType> empty_op_map;
2118 assert(loc < N_sites);
2119 auto it = auxdim[loc].find(q);
2120 if(it == auxdim[loc].end())
2122 #if DEBUG_VERBOSITY > 1
2125 lout <<
"New counter started" << std::endl;
2128 for(
const auto &[qPrev,dimPrev] : auxdim[loc-1])
2130 #if DEBUG_VERBOSITY > 2
2133 lout <<
"\t\tO[" << loc-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Block created with one column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2136 std::vector<std::map<qType,OperatorType>> temp_col(1,empty_op_map);
2137 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(dimPrev,temp_col);
2138 O[loc-1].insert({{qPrev,q},temp_ops});
2140 for(
const auto &[qNext,dimNext] : auxdim[loc+1])
2142 #if DEBUG_VERBOSITY > 2
2145 lout <<
"\t\tO[" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Block created with one row of operators (number of columns: " << dimNext <<
")" << std::endl;
2148 std::vector<std::map<qType,OperatorType>> temp_col(dimNext,empty_op_map);
2149 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(1,temp_col);
2150 O[loc].insert({{q,qNext},temp_ops});
2152 auxdim[loc].insert({q,1});
2156 #if DEBUG_VERBOSITY > 1
2159 lout <<
"Counter incremented to " << (it->second)+1 << std::endl;
2162 for(
const auto &[qPrev,dimPrev] : auxdim[loc-1])
2164 #if DEBUG_VERBOSITY > 2
2167 lout <<
"\t\tO[" << loc-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Create a new column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2170 auto it_prev = O[loc-1].find({qPrev,q});
2171 assert(it_prev != O[loc-1].end());
2172 for(std::size_t row=0; row<dimPrev; ++row)
2174 (it_prev->second)[row].push_back(empty_op_map);
2177 for(
const auto &[qNext,dimNext] : auxdim[loc+1])
2179 #if DEBUG_VERBOSITY > 1
2182 lout <<
"\t\tO[" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Create a new row of operators (number of columns: " << dimNext <<
")" << std::endl;
2185 auto it_next = O[loc].find({q,qNext});
2186 assert(it_next != O[loc].end());
2187 std::vector<std::map<qType,OperatorType>> temp_row(dimNext, empty_op_map);
2188 (it_next->second).push_back(temp_row);
2196 auto it = auxdim[0].find(q);
2197 if(it == auxdim[0].end())
2199 #if DEBUG_VERBOSITY > 1
2202 lout <<
"New counter started" << std::endl;
2205 for(
const auto &[qPrev,dimPrev] : auxdim[N_sites-1])
2207 #if DEBUG_VERBOSITY > 2
2210 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Block created with one column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2213 std::vector<std::map<qType,OperatorType>> temp_col(1,empty_op_map);
2214 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(dimPrev,temp_col);
2215 O[N_sites-1].insert({{qPrev,q},temp_ops});
2217 for(
const auto &[qNext,dimNext] : auxdim[1])
2219 #if DEBUG_VERBOSITY > 2
2222 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Block created with one row of operators (number of columns: " << dimNext <<
")" << std::endl;
2225 std::vector<std::map<qType,OperatorType>> temp_col(dimNext,empty_op_map);
2226 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(1,temp_col);
2227 O[0].insert({{q,qNext},temp_ops});
2229 auxdim[0].insert({q,1});
2230 auxdim[N_sites].insert({q,1});
2234 #if DEBUG_VERBOSITY > 1
2237 lout <<
"Counter incremented to " << (it->second)+1 << std::endl;
2240 for(
const auto &[qPrev,dimPrev] : auxdim[N_sites-1])
2242 #if DEBUG_VERBOSITY > 2
2245 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Create a new column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2248 auto it_prev = O[N_sites-1].find({qPrev,q});
2249 assert(it_prev != O[N_sites-1].end());
2250 for(std::size_t row=0; row<dimPrev; ++row)
2252 (it_prev->second)[row].push_back(empty_op_map);
2255 for(
const auto &[qNext,dimNext] : auxdim[1])
2257 #if DEBUG_VERBOSITY > 2
2260 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Create a new row of operators (number of columns: " << dimNext <<
")" << std::endl;
2263 auto it_next = O[0].find({q,qNext});
2264 assert(it_next != O[0].end());
2265 std::vector<std::map<qType,OperatorType>> temp_row(dimNext, empty_op_map);
2266 (it_next->second).push_back(temp_row);
2269 auto it_edge = auxdim[N_sites].find(q);
2270 assert(it_edge != auxdim[N_sites].end());
2271 (it_edge->second)++;
2275 auto it = O[0].find({q,q});
2276 if(it == O[0].end())
2278 #if DEBUG_VERBOSITY > 2
2281 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Create a new block of operators with 1 row and 1 column" << std::endl;
2284 std::vector<std::map<qType,OperatorType>> temp_col(1,empty_op_map);
2285 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(1,temp_col);
2286 O[0].insert({{q,q},temp_ops});
2290 #if DEBUG_VERBOSITY > 2
2293 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Add the corner operator" << std::endl;
2296 (it->second)[(it->second).size()-1].push_back(empty_op_map);
2305 assert(boundary_condition ==
BC::OPEN);
2306 #if DEBUG_VERBOSITY > 1
2309 lout <<
"\tqAux[left edge->0]({" << Sym::format<Symmetry>(qIn) <<
"}): ";
2313 std::map<qType,OperatorType> empty_op_map;
2314 auto it = auxdim[0].find(qIn);
2315 if(it == auxdim[0].end())
2317 #if DEBUG_VERBOSITY > 1
2320 lout <<
"New counter started" << std::endl;
2323 for(
const auto &[qOut,deg] : auxdim[1])
2325 #if DEBUG_VERBOSITY > 2
2328 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Block created with one row of operators (number of columns: " << deg <<
")" << std::endl;
2331 std::vector<std::map<qType,OperatorType>> temp_col(deg,empty_op_map);
2332 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(1,temp_col);
2333 O[0].insert({{qIn,qOut},temp_ops});
2335 auxdim[0].insert({qIn,1});
2339 #if DEBUG_VERBOSITY > 1
2342 lout <<
"Counter incremented to " << (it->second)+1 << std::endl;
2345 for(
const auto &[qOut,deg] : auxdim[1])
2347 #if DEBUG_VERBOSITY > 2
2350 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Create a new row of operators (number of columns: " << deg <<
")" << std::endl;
2353 auto it_ops = O[0].find({qIn,qOut});
2354 assert(it_ops != O[0].end());
2355 std::vector<std::map<qType,OperatorType>> temp_row(deg, empty_op_map);
2356 (it_ops->second).push_back(temp_row);
2365 assert(boundary_condition ==
BC::OPEN);
2366 #if DEBUG_VERBOSITY > 1
2369 lout <<
"\tqAux[" << N_sites-1 <<
"->right edge]({" << Sym::format<Symmetry>(qOut) <<
"}): ";
2373 std::map<qType,OperatorType> empty_op_map;
2374 auto it = auxdim[N_sites].find(qOut);
2375 if(it == auxdim[N_sites].end())
2377 #if DEBUG_VERBOSITY > 1
2380 lout <<
"New counter started" << std::endl;
2383 for(
const auto &[qIn,deg] : auxdim[N_sites-1])
2385 #if DEBUG_VERBOSITY > 2
2388 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Block created with one column of operators (number of rows: " << deg <<
")" << std::endl;
2391 std::vector<std::map<qType,OperatorType>> temp_col(1,empty_op_map);
2392 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(deg,temp_col);
2393 O[N_sites-1].insert({{qIn,qOut},temp_ops});
2395 auxdim[N_sites].insert({qOut,1});
2399 #if DEBUG_VERBOSITY > 1
2402 lout <<
"Counter incremented to " << (it->second)+1 << std::endl;
2405 for(
const auto &[qIn,deg] : auxdim[N_sites-1])
2407 #if DEBUG_VERBOSITY > 2
2410 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Create a new column of operators (number of rows: " << deg <<
")" << std::endl;
2413 auto it_ops = O[N_sites-1].find({qIn,qOut});
2414 assert(it_ops != O[N_sites-1].end());
2415 for(std::size_t row=0; row<deg; ++row)
2417 (it_ops->second)[row].push_back(empty_op_map);
2427 #if DEBUG_VERBOSITY > 1
2430 lout <<
"\tqAux[" << (loc+N_sites-1)%N_sites <<
"->" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}): ";
2434 auto it = auxdim[loc].find(q);
2435 assert(it != auxdim[loc].end());
2438 assert(loc < N_sites);
2441 #if DEBUG_VERBOSITY > 1
2444 lout <<
"Quantum number deleted" << std::endl;
2447 for(
const auto &[qPrev,dimPrev] : auxdim[loc-1])
2449 #if DEBUG_VERBOSITY > 2
2452 lout <<
"\t\tO[" << loc-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Block deleted" << std::endl;
2455 O[loc-1].erase({qPrev,q});
2457 for(
const auto &[qNext,dimNext] : auxdim[loc+1])
2459 #if DEBUG_VERBOSITY > 2
2462 lout <<
"\t\tO[" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Block deleted" << std::endl;
2465 O[loc].erase({q,qNext});
2467 auxdim[loc].erase(q);
2471 #if DEBUG_VERBOSITY > 1
2474 lout <<
"Counter decremented to " << (it->second)-1 << std::endl;
2477 for(
const auto &[qPrev,dimPrev] : auxdim[loc-1])
2479 #if DEBUG_VERBOSITY > 2
2482 lout <<
"\t\tO[" << loc-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Delete a column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2485 auto it_prev = O[loc-1].find({qPrev,q});
2486 assert(it_prev != O[loc-1].end());
2487 for(std::size_t row=0; row<dimPrev; ++row)
2489 (it_prev->second)[row].resize((it_prev->second)[row].size()-1);
2492 for(
const auto &[qNext,dimNext] : auxdim[loc+1])
2494 #if DEBUG_VERBOSITY > 2
2497 lout <<
"\t\tO[" << loc <<
"]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Delete a row of operators (number of columns: " << dimNext <<
")" << std::endl;
2500 auto it_next = O[loc].find({q,qNext});
2501 assert(it_next != O[loc].end());
2502 (it_next->second).resize((it_next->second).size()-1);
2512 #if DEBUG_VERBOSITY > 1
2515 lout <<
"Quantum number deleted" << std::endl;
2518 for(
const auto &[qPrev,dimPrev] : auxdim[N_sites-1])
2520 #if DEBUG_VERBOSITY > 2
2523 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Block deleted" << std::endl;
2526 O[N_sites-1].erase({qPrev,q});
2528 for(
const auto &[qNext,dimNext] : auxdim[1])
2530 #if DEBUG_VERBOSITY > 2
2533 lout <<
"\t\tOperators[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Block deleted" << std::endl;
2536 O[0].erase({q,qNext});
2539 auxdim[N_sites].erase(q);
2543 #if DEBUG_VERBOSITY > 1
2546 lout <<
"Counter decremented to " << (it->second)-1 << std::endl;
2549 for(
const auto &[qPrev,dimPrev] : auxdim[N_sites-1])
2551 #if DEBUG_VERBOSITY > 2
2554 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qPrev) <<
"}->{" << Sym::format<Symmetry>(q) <<
"}): Delete a column of operators (number of rows: " << dimPrev <<
")" << std::endl;
2557 auto it_prev = O[N_sites-1].find({qPrev,q});
2558 assert(it_prev != O[N_sites-1].end());
2559 for(std::size_t row=0; row<dimPrev; ++row)
2561 (it_prev->second)[row].resize((it_prev->second)[row].size()-1);
2564 for(
const auto &[qNext,dimNext] : auxdim[1])
2566 #if DEBUG_VERBOSITY > 2
2569 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(q) <<
"}->{" << Sym::format<Symmetry>(qNext) <<
"}): Delete a row of operators (number of columns: " << dimNext <<
")" << std::endl;
2572 auto it_next = O[0].find({q,qNext});
2573 assert(it_next != O[0].end());
2574 (it_next->second).resize((it_next->second).size()-1);
2577 auto it_edge = auxdim[N_sites].find(q);
2578 assert(it_edge != auxdim[N_sites].end());
2579 (it_edge->second)--;
2588 assert(boundary_condition ==
BC::OPEN);
2589 #if DEBUG_VERBOSITY > 1
2592 lout <<
"\tqAux[left edge->0]({" << Sym::format<Symmetry>(qIn) <<
"}): ";
2596 auto it = auxdim[0].find(qIn);
2597 assert(it != auxdim[0].end());
2600 #if DEBUG_VERBOSITY > 1
2603 lout <<
"Quantum number deleted" << std::endl;
2606 for(
const auto &[qOut,deg] : auxdim[1])
2608 #if DEBUG_VERBOSITY > 2
2611 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Block deleted" << std::endl;
2614 O[0].erase({qIn,qOut});
2616 auxdim[0].erase(qIn);
2620 #if DEBUG_VERBOSITY > 1
2623 lout <<
"Counter decremented to " << (it->second)-1 << std::endl;
2626 for(
const auto &[qOut,deg] : auxdim[1])
2628 #if DEBUG_VERBOSITY > 2
2631 lout <<
"\t\tO[0]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Delete a row of operators (number of columns: " << deg <<
")" << std::endl;
2634 auto it_ops = O[0].find({qIn,qOut});
2635 assert(it_ops != O[0].end());
2636 (it_ops->second).resize((it_ops->second).size()-1);
2645 assert(boundary_condition ==
BC::OPEN);
2646 #if DEBUG_VERBOSITY > 1
2649 lout <<
"\tqAux[" << N_sites-1 <<
"->right edge]({" << Sym::format<Symmetry>(qOut) <<
"}): ";
2653 auto it = auxdim[N_sites].find(qOut);
2654 assert(it != auxdim[N_sites].end());
2657 #if DEBUG_VERBOSITY > 1
2660 lout <<
"Quantum number deleted" << std::endl;
2663 for(
const auto &[qIn,deg] : auxdim[N_sites-1])
2665 #if DEBUG_VERBOSITY > 2
2668 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Block deleted" << std::endl;
2671 O[N_sites-1].erase({qIn,qOut});
2673 auxdim[N_sites].erase(qOut);
2677 #if DEBUG_VERBOSITY > 1
2680 lout <<
"Counter decremented to " << (it->second)-1 << std::endl;
2683 for(
const auto &[qIn,deg] : auxdim[N_sites-1])
2685 #if DEBUG_VERBOSITY > 2
2688 lout <<
"\t\tO[" << N_sites-1 <<
"]({" << Sym::format<Symmetry>(qIn) <<
"}->{" << Sym::format<Symmetry>(qOut) <<
"}): Delete a column of operators (number of rows: " << deg <<
")" << std::endl;
2691 auto it_ops = O[N_sites-1].find({qIn,qOut});
2692 assert(it_ops != O[N_sites-1].end());
2693 for(std::size_t row=0; row<deg; ++row)
2695 (it_ops->second)[row].resize((it_ops->second)[row].size()-1);
2707 std::size_t loc_eff;
2710 loc_eff = loc%N_sites;
2716 auto it = auxdim[loc_eff].find(q);
2717 if (it != auxdim[loc_eff].end())
2719 return (it->second);
2730 if(hilbert_dimension[loc] == 0)
2732 hilbert_dimension[loc] =
dim;
2736 if (hilbert_dimension[loc] !=
dim)
2738 lout << termcolor::red <<
"hilbert_dimension[loc]=" << hilbert_dimension[loc] <<
", dim=" <<
dim << termcolor::reset << endl;
2740 assert(hilbert_dimension[loc] ==
dim and
"Dimensions of operator and local Hilbert space do not match!");
2745save_label (
const std::size_t loc,
const std::string &info_label)
2747 assert(loc < N_sites and
"Chosen lattice site out of bounds");
2748 if(info_label !=
"")
2750 info[loc].push_back(info_label);
2757 std::vector<std::string> res(N_sites);
2758 for(std::size_t loc=0; loc<N_sites; ++loc)
2760 std::stringstream ss;
2761 if (info[loc].size()>0)
2763 std::copy(info[loc].begin(), info[loc].end()-1, std::ostream_iterator<std::string>(ss,
","));
2764 ss << info[loc].back();
2771 res[loc] = ss.str();
2773 while (res[loc].find(
"perp") != std::string::npos) res[loc].replace(res[loc].find(
"perp"), 4,
"⟂");
2774 while (res[loc].find(
"para") != std::string::npos) res[loc].replace(res[loc].find(
"para"), 4,
"∥");
2775 while (res[loc].find(
"prime") != std::string::npos) res[loc].replace(res[loc].find(
"prime"), 5,
"'");
2776 while (res[loc].find(
"Perp") != std::string::npos) res[loc].replace(res[loc].find(
"Perp"), 4,
"⟂");
2777 while (res[loc].find(
"Para") != std::string::npos) res[loc].replace(res[loc].find(
"Para"), 4,
"∥");
2778 while (res[loc].find(
"Prime") != std::string::npos) res[loc].replace(res[loc].find(
"Prime"), 5,
"'");
2779 while (res[loc].find(
"mu") != std::string::npos) res[loc].replace(res[loc].find(
"mu"), 2,
"µ");
2780 while (res[loc].find(
"Delta") != std::string::npos) res[loc].replace(res[loc].find(
"Delta"), 5,
"Δ");
2781 while (res[loc].find(
"next") != std::string::npos) res[loc].replace(res[loc].find(
"next"), 4,
"ₙₑₓₜ");
2782 while (res[loc].find(
"prev") != std::string::npos) res[loc].replace(res[loc].find(
"prev"), 4,
"ₚᵣₑᵥ");
2783 while (res[loc].find(
"3site") != std::string::npos) res[loc].replace(res[loc].find(
"3site"), 5,
"₃ₛᵢₜₑ");
2784 while (res[loc].find(
"sub") != std::string::npos) res[loc].replace(res[loc].find(
"sub"), 3,
"ˢᵘᵇ");
2785 while (res[loc].find(
"rung") != std::string::npos) res[loc].replace(res[loc].find(
"rung"), 4,
"ʳᵘⁿᵍ");
2786 while (res[loc].find(
"t0") != std::string::npos) res[loc].replace(res[loc].find(
"t0"), 2,
"t₀");
2796template<
typename Symmetry,
typename Scalar>
const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry, Eigen::SparseMatrix<Scalar,Eigen::ColMajor,EIGEN_DEFAULT_SPARSE_INDEX_TYPE>>>>>> &
MpoTerms<Symmetry,Scalar>::
2799 assert(power > 0 and
"Power has to be at least 1");
2800 assert(power <= current_power and
"This power of the MPO has not been calculated!");
2807 return W_powers[power-2];
2814 assert(power > 0 and
"Power has to be at least 1");
2815 assert(power <= current_power and
"This power of the MPO has not been calculated!");
2822 return qAux_powers[power-2];
2830 assert(power > 0 and
"Power has to be at least 1");
2831 assert(power <= current_power and
"This power of the MPO has not been calculated!");
2838 return qOp_powers[power-2];
2846 for(std::size_t loc=0; loc<N_sites; ++loc)
2857scale (
const Scalar factor,
const Scalar offset,
const std::size_t power,
const double tolerance)
2859 std::size_t calc_to_power = (power != 0 ? power : current_power);
2861 if (std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon() or std::abs(offset) > tolerance)
2866 if (std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon())
2871 bool sign_factor = (std::abs(std::arg(factor)) > 0. ? true :
false);
2873 double factor_per_site = std::pow(std::abs(factor), 1./(1.*N_sites));
2874 for(std::size_t loc=0; loc<N_sites; ++loc)
2876 for(
const auto &[qIn, rows] : auxdim[loc])
2878 for(
const auto &[qOut, cols] : auxdim[loc+1])
2880 auto it = O[loc].find({qIn,qOut});
2881 assert(it != O[loc].end());
2882 for(std::size_t row=0; row<rows; ++row)
2884 for(std::size_t col=0; col<cols; ++col)
2886 std::map<qType,OperatorType> &existing_ops = (it->second)[row][col];
2887 for(
auto &[q,op] : existing_ops)
2889 op = factor_per_site*op;
2900 for(std::size_t loc=0; loc<N_sites; ++loc)
2902 for(
const auto &[qOut, cols] : auxdim[loc+1])
2904 auto it = O[loc].find({qVac,qOut});
2905 assert(it != O[loc].end());
2906 for(std::size_t col=0; col<cols; ++col)
2912 std::map<qType,OperatorType> &existing_ops = (it->second)[pos_qVac][col];
2913 for(
auto &[q,op] : existing_ops)
2915 if constexpr(std::is_same<Scalar,complex<double>>::value)
2917 op = exp(1.i*std::arg(factor))*op;
2930 for(
const auto &[qIn,rows] : auxdim[0])
2932 for(
const auto &[qOut,cols] : auxdim[1])
2934 auto it = O[0].find({qIn,qOut});
2935 assert(it != O[0].end());
2936 for(std::size_t row=0; row<rows; ++row)
2938 for(std::size_t col=0; col<cols; ++col)
2940 std::map<qType,OperatorType> &existing_ops = (it->second)[row][col];
2941 for(
auto &[q,op] : existing_ops)
2943 if constexpr(std::is_same<Scalar,complex<double>>::value)
2945 op = exp(1.i*std::arg(factor))*op;
2959 if (std::abs(offset) > tolerance)
2963 double offset_per_site = std::abs(offset)/(1.*N_sites);
2967 assert(qTot == qVac and
"For adding an offset, the MPO needs to be a singlet.");
2968 assert(get_auxdim(0,qVac) == 1 and get_auxdim(N_sites,qVac) == 1 and
"Ill-formed auxiliar basis for open boundary condition");
2969 for(std::size_t loc=0; loc<N_sites-1; ++loc)
2971 increment_auxdim(loc+1, qVac);
2972 auto it = O[loc].find({qVac,qVac});
2973 assert(it != O[loc].end());
2974 std::map<qType,OperatorType> &existing_ops = (it->second)[get_auxdim(loc,qVac)-1][get_auxdim(loc+1,qVac)-1];
2976 Id.
data = Matrix<Scalar,Dynamic,Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView();
2977 if(loc == N_sites/2)
2979 if constexpr(std::is_same<Scalar,complex<double>>::value)
2981 Id.
data *= exp(1.i*std::arg(offset));
2985 Id.
data *= (offset<0.)? -1.:+1.;
2991 auto itQ = existing_ops.find(qVac);
2992 if(itQ == existing_ops.end())
2994 existing_ops.insert({qVac,offset_per_site*Id});
2998 (itQ->second) += offset_per_site*Id;
3001 auto it = O[N_sites-1].find({qVac,qVac});
3002 assert(it != O[N_sites-1].end());
3003 std::map<qType,OperatorType> &existing_ops = (it->second)[get_auxdim(N_sites-1,qVac)-1][get_auxdim(N_sites,qVac)-1];
3005 Id.
data = Matrix<Scalar,Dynamic,Dynamic>::Identity(hilbert_dimension[N_sites-1],hilbert_dimension[N_sites-1]).sparseView();
3009 auto itQ = existing_ops.find(qVac);
3010 if(itQ == existing_ops.end())
3012 existing_ops.insert({qVac,offset_per_site*Id});
3016 (itQ->second) += offset_per_site*Id;
3018 compress(tolerance);
3022 for(std::size_t loc=0; loc<N_sites; ++loc)
3024 auto it = O[loc].find({qVac,qVac});
3025 assert(it != O[loc].end());
3026 std::map<qType,OperatorType> &existing_ops = (it->second)[pos_qVac][pos_qTot];
3028 Id.
data = Matrix<Scalar,Dynamic,Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView();
3032 auto op_it = existing_ops.find(qVac);
3033 if(op_it == existing_ops.end())
3035 existing_ops.insert({qVac,offset_per_site*Id});
3039 (op_it->second) = (op_it->second) + offset_per_site*Id;
3045 if (std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon() or std::abs(offset) > tolerance)
3047 std::stringstream new_name;
3048 if(std::abs(offset) > ::mynumeric_limits<double>::epsilon())
3052 std::size_t curr_prec = std::cout.precision();
3053 if(std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon())
3055 new_name << setprecision(3) <<
"(" << factor <<
"*" << label <<
")" << setprecision(curr_prec);
3057 if(std::abs(offset) > ::mynumeric_limits<double>::epsilon())
3059 new_name <<
" + " << setprecision(3) << offset << setprecision(curr_prec) <<
"]";
3064 set_name(new_name.str());
3068 set_name(label+
"+[...]");
3071 calc(calc_to_power);
3080 for(std::size_t loc=0; loc<N_sites; ++loc)
3082 for(
const auto &[qIn, rows] : auxdim[loc])
3084 for(
const auto &[qOut, cols] : auxdim[loc+1])
3086 auto it = O[loc].find({qIn,qOut});
3087 assert(it != O[loc].end());
3088 for(std::size_t row=0; row<rows; ++row)
3090 for(std::size_t col=0; col<cols; ++col)
3092 std::map<qType,OperatorType> &existing_ops = (it->second)[row][col];
3093 for(
auto &[q,op] : existing_ops)
3095 op.template cast<OtherScalar>();
3102 for(std::size_t loc=0; loc<N_sites; ++loc)
3104 for(std::size_t i=0; i<info[loc].size(); ++i)
3113transform_base (
const qType &qShift,
const bool PRINT,
const int factor,
const std::size_t power)
3115 std::size_t calc_to_power = (power != 0ul ? power : current_power);
3116 int length = (factor==-1)?
static_cast<int>(qPhys.size()):factor;
3117 ::transform_base<Symmetry>(qPhys, qShift, PRINT,
false, length);
3119 std::vector<std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> O_new(N_sites);
3120 std::vector<std::map<qType, std::size_t>> auxdim_new(N_sites+1);
3122 if(qShift != Symmetry::qvacuum())
3124 std::vector<std::size_t> symmetries_to_transform;
3125 for(std::size_t n=0; n<Symmetry::Nq; ++n)
3127 if(Symmetry::kind()[n] != Sym::KIND::S and Symmetry::kind()[n] != Sym::KIND::T)
3129 symmetries_to_transform.push_back(n);
3133 for(std::size_t n=0; n<symmetries_to_transform.size(); ++n)
3135 qTot[symmetries_to_transform[n]] *= length;
3136 qVac[symmetries_to_transform[n]] *= length;
3139 for(std::size_t loc=0; loc<N_sites; ++loc)
3141 for(
const auto &[qs_key, ops] : O[loc])
3144 qType qIn = std::get<0>(qs_key);
3145 qType qOut = std::get<1>(qs_key);
3146 for(std::size_t n=0; n<symmetries_to_transform.size(); ++n)
3148 qIn[symmetries_to_transform[n]] *= length;
3149 qOut[symmetries_to_transform[n]] *= length;
3151 std::map<qType,OperatorType> empty_op_map;
3152 std::vector<std::map<qType,OperatorType>> temp_row(ops[0].size(), empty_op_map);
3153 std::vector<std::vector<std::map<qType,OperatorType>>> ops_new(ops.size(), temp_row);
3154 for(std::size_t row=0; row<ops.size(); ++row)
3156 for(std::size_t col=0; col<ops[row].size(); ++col)
3158 for(
const auto &[q,op] : ops[row][col])
3162 for(std::size_t n=0; n<symmetries_to_transform.size(); ++n)
3164 q_new[symmetries_to_transform[n]] *= length;
3165 op_new.
Q[symmetries_to_transform[n]] *= length ;
3167 ops_new[row][col].insert({q_new,op_new});
3171 O_new[loc].insert({{qIn,qOut},ops_new});
3175 for(std::size_t loc=0; loc<N_sites+1; ++loc)
3177 for(
const auto &[q_key, deg] : auxdim[loc])
3180 for(std::size_t n=0; n<symmetries_to_transform.size(); ++n)
3182 q[symmetries_to_transform[n]] *= length;
3184 auxdim_new[loc].insert({q,deg});
3189 auxdim = auxdim_new;
3191 calc(calc_to_power);
3198 std::vector<std::vector<TwoSiteData<Symmetry,Scalar>>> tsd(N_sites-1);
3200 for(std::size_t loc=0; loc<N_sites-1; ++loc)
3207 for(std::size_t n_lefttop=0; n_lefttop<qPhys[loc].size(); ++n_lefttop)
3209 for(std::size_t n_leftbottom=0; n_leftbottom<qPhys[loc].size(); ++n_leftbottom)
3211 for(std::size_t t_left=0; t_left<qOp[loc].size(); ++t_left)
3213 if(std::array<qType,3> qCheck = {qPhys[loc][n_leftbottom], qOp[loc][t_left], qPhys[loc][n_lefttop]}; !Symmetry::validate(qCheck))
3217 for(std::size_t n_righttop=0; n_righttop<qPhys[loc+1].size(); ++n_righttop)
3219 for(std::size_t n_rightbottom=0; n_rightbottom<qPhys[loc+1].size(); ++n_rightbottom)
3221 for(std::size_t t_right=0; t_right<qOp[loc+1].size(); ++t_right)
3223 if(std::array<qType,3> qCheck = {qPhys[loc+1][n_rightbottom], qOp[loc+1][t_right], qPhys[loc+1][n_righttop]}; !Symmetry::validate(qCheck))
3228 auto qOp_merges = Symmetry::reduceSilent(qOp[loc][t_left], qOp[loc+1][t_right]);
3230 for(
const auto &qOp_merge : qOp_merges)
3232 if(!qAux[loc+1].find(qOp_merge))
3237 auto qPhys_tops = Symmetry::reduceSilent(qPhys[loc][n_lefttop], qPhys[loc+1][n_righttop]);
3238 auto qPhys_bottoms = Symmetry::reduceSilent(qPhys[loc][n_leftbottom], qPhys[loc+1][n_rightbottom]);
3239 for(
const auto &qPhys_top : qPhys_tops)
3241 for(
const auto &qPhys_bottom : qPhys_bottoms)
3247 size_t n_top = tensor_basis.
outer_num(qPhys_top) + tensor_basis.
leftOffset(qPhys_top,{qPhys[loc][n_lefttop],qPhys[loc+1][n_righttop]},
3253 size_t n_bottom = tensor_basis.
outer_num(qPhys_bottom) + tensor_basis.
leftOffset(qPhys_bottom,{qPhys[loc][n_leftbottom],qPhys[loc+1][n_rightbottom]},
3255 Scalar factor_cgc = 1.;
3256 if(Symmetry::NON_ABELIAN)
3258 factor_cgc = Symmetry::coeff_tensorProd(qPhys[loc][n_leftbottom], qPhys[loc+1][n_rightbottom], qPhys_bottom, qOp[loc][t_left], qOp[loc+1][t_right], qOp_merge, qPhys[loc][n_lefttop], qPhys[loc+1][n_righttop], qPhys_top);
3260 if(std::abs(factor_cgc) < mynumeric_limits<double>::epsilon())
3264 TwoSiteData<Symmetry,Scalar> entry({{n_lefttop,n_leftbottom,n_righttop,n_rightbottom,n_top,n_bottom}}, {{qPhys_top,qPhys_bottom}}, {{t_left,t_right}}, qOp_merge, factor_cgc);
3265 tsd[loc].push_back(entry);
3291 typedef typename Symmetry::qType
qType;
3293 typedef Eigen::SparseMatrix<Scalar,Eigen::ColMajor,EIGEN_DEFAULT_SPARSE_INDEX_TYPE>
MatrixType;
3298 lout <<
"MPO multiplication of " << top.
get_name() <<
"*" << bottom.
get_name() <<
" to quantum number {" << Sym::format<Symmetry>(qTot) <<
"}" << std::endl;
3301 assert(bottom.
size() == top.
size() and
"Error: Multiplying two MPOs of different size");
3305 std::vector<qType> qTots = Symmetry::reduceSilent(bottom.
get_qTot(), top.
get_qTot());
3306 auto it = std::find(qTots.begin(), qTots.end(), qTot);
3307 if (it==qTots.end())
3309 lout <<
"qTot=" << qTot << endl;
3310 for (
const auto& qTotVal:qTots)
3312 lout <<
"val=" << qTotVal << endl;
3314 assert(it != qTots.end() and
"Cannot multiply these two operators to an operator with target quantum number");
3317 std::vector<std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> O_bottom, O_top, O;
3318 std::vector<Qbasis<Symmetry>> qAux_bottom, qAux_top, qAux;
3319 std::vector<std::vector<qType>> qPhys, qPhys_check;
3320 std::vector<std::vector<qType>> qOp_bottom, qOp_top;
3322 std::map<qType,OperatorType> empty_op_map;
3327 O_bottom = bottom.
get_O();
3328 O_top = top.
get_O();
3333 qOp_bottom = bottom.
get_qOp();
3336 std::size_t N_sites = bottom.
size();
3338 qAux.resize(N_sites+1);
3340 std::size_t pos_qTot_out = 0;
3341 if(qTot == Symmetry::qvacuum())
3346 std::vector<std::size_t> row_qVac(N_sites);
3347 std::vector<std::size_t> col_qVac(N_sites);
3348 std::vector<std::size_t> row_qTot(N_sites);
3349 std::vector<std::size_t> col_qTot(N_sites);
3352 qAux[0] = qAux_bottom[0].combine(qAux_top[0]);
3355 for(std::size_t loc=0; loc<N_sites; ++loc)
3357 std::size_t hilbert_dimension = qPhys[loc].size();
3359 assert(hilbert_dimension != 0 and
"Not all Hilbert space dimensions have been set!");
3360 assert(hilbert_dimension == qPhys_check[loc].size() and
"Local Hilbert space dimensions do not match!");
3362 qAux[loc+1] = qAux_bottom[loc+1].combine(qAux_top[loc+1]);
3363 for(
const auto &entry_left : qAux[loc])
3365 for(
const auto &entry_right : qAux[loc+1])
3367 std::size_t rows = std::get<2>(entry_left).size();
3368 std::size_t cols = std::get<2>(entry_right).size();
3369 qType Qin = std::get<0>(entry_left);
3370 qType Qout = std::get<0>(entry_right);
3371 std::vector<std::map<qType,OperatorType>> temp_row(cols, empty_op_map);
3372 std::vector<std::vector<std::map<qType,OperatorType>>> temp(rows, temp_row);
3373 O[loc].insert({{Qin,Qout},temp});
3376 #if DEBUG_VERBOSITY > 1
3379 lout <<
"Lattice site " << loc <<
":" << std::endl;
3382 std::vector<qType> Qins = qAux[loc].qs();
3383 for(
const auto &Qin : Qins)
3385 std::size_t total_rows = qAux[loc].inner_dim(Qin);
3386 auto qins = Sym::split<Symmetry>(Qin,qAux_top[loc].qs(), qAux_bottom[loc].qs());
3387 for(
const auto &[qin_top, qin_bottom] : qins)
3389 std::size_t rows_bottom = qAux_bottom[loc].inner_dim(qin_bottom);
3390 std::size_t rows_top = qAux_top[loc].inner_dim(qin_top);
3391 #if DEBUG_VERBOSITY > 1
3394 lout <<
"\tQin = {" << Sym::format<Symmetry>(Qin) <<
"} can be reached by {" << Sym::format<Symmetry>(qin_bottom) <<
"} + {" << Sym::format<Symmetry>(qin_top) <<
"}" << std::endl;
3397 std::vector<qType> Qouts = qAux[loc+1].qs();
3398 for(
const auto &Qout : Qouts)
3400 if(boundary_condition ==
BC::OPEN and (loc+1 == N_sites) and (Qout != qTot))
3404 std::size_t total_cols = qAux[loc+1].inner_dim(Qout);
3405 auto qouts = Sym::split<Symmetry>(Qout,qAux_top[loc+1].qs(), qAux_bottom[loc+1].qs());
3406 for(
const auto &[qout_top, qout_bottom] : qouts)
3408 std::size_t cols_bottom = qAux_bottom[loc+1].inner_dim(qout_bottom);
3409 std::size_t cols_top = qAux_top[loc+1].inner_dim(qout_top);
3410 #if DEBUG_VERBOSITY > 1
3413 lout <<
"\t\tQout = {" << Sym::format<Symmetry>(Qout) <<
"} can be reached by {" << Sym::format<Symmetry>(qout_bottom) <<
"} + {" << Sym::format<Symmetry>(qout_top) <<
"}" << std::endl;
3416 auto it = O[loc].find({Qin, Qout});
3417 auto it_bottom = O_bottom[loc].find({qin_bottom, qout_bottom});
3418 auto it_top = O_top[loc].find({qin_top, qout_top});
3419 std::size_t in_pos = qAux[loc].leftAmount(Qin, {qin_bottom, qin_top});
3420 std::size_t out_pos = qAux[loc+1].leftAmount(Qout, {qout_bottom, qout_top});
3421 for(std::size_t row_bottom=0; row_bottom<rows_bottom; ++row_bottom)
3423 for(std::size_t row_top=0; row_top<rows_top; ++row_top)
3425 std::size_t total_row = in_pos + row_bottom*rows_top + row_top;
3426 if((qin_bottom == bottom.
qVac and row_bottom == bottom.
pos_qVac) and (qin_top == top.
qVac and row_top == top.
pos_qVac) and total_row != row_qVac[loc])
3428 row_qVac[loc] = total_row;
3430 if((qin_bottom == bottom.
qTot and row_bottom == bottom.
pos_qTot) and (qin_top == top.
qTot and row_top == top.
pos_qTot) and total_row != row_qTot[loc])
3432 row_qTot[loc] = total_row;
3434 for(std::size_t col_bottom=0; col_bottom<cols_bottom; ++col_bottom)
3436 for(std::size_t col_top=0; col_top<cols_top; ++col_top)
3438 for(
const auto &[qOp_bottom,op_bottom] : (it_bottom->second)[row_bottom][col_bottom])
3440 for(
const auto &[qOp_top,op_top] : (it_top->second)[row_top][col_top])
3442 std::size_t total_col = out_pos + col_bottom*cols_top + col_top;
3443 if((qout_bottom == bottom.
qVac and col_bottom == bottom.
pos_qVac) and (qout_top == top.
qVac and col_top == top.
pos_qVac) and total_col != col_qVac[loc])
3445 col_qVac[loc] = total_col;
3447 if((qout_bottom == bottom.
qTot and col_bottom == bottom.
pos_qTot) and (qout_top == top.
qTot and col_top == top.
pos_qTot) and total_col != col_qTot[loc])
3449 col_qTot[loc] = total_col;
3451 std::map<qType,OperatorType> &ops = (it->second)[total_row][total_col];
3452 std::vector<qType> Qops = Symmetry::reduceSilent(qOp_bottom, qOp_top);
3453 for(
const auto &Qop : Qops)
3455 if(std::array<qType,3> qCheck = {Qin,Qop,Qout}; !Symmetry::validate(qCheck))
3460 OperatorType op(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Zero(hilbert_dimension, hilbert_dimension).sparseView(), Qop, op_top.label+
"*"+op_bottom.label);
3461 #if DEBUG_VERBOSITY > 1
3464 lout <<
"\t\t\tBlock {" << Sym::format<Symmetry>(Qin) <<
"}->{" << Sym::format<Symmetry>(Qout) <<
"},\tPosition [" << total_row <<
"|" << total_col <<
"], " << op.
label <<
" {" << Sym::format<Symmetry>(Qop) <<
"}" << std::endl;
3468 OperatorType op(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Zero(hilbert_dimension,hilbert_dimension).sparseView(), Qop);
3469 #if DEBUG_VERBOSITY > 1
3472 lout <<
"\t\t\tBlock {" << Sym::format<Symmetry>(Qin) <<
"}->{" << Sym::format<Symmetry>(Qout) <<
"},\tPosition [" << total_row <<
"|" << total_col <<
"], Operator {" << Sym::format<Symmetry>(Qop) <<
"}" << std::endl;
3476 Scalar factor_9j = Symmetry::coeff_tensorProd(qin_bottom, qin_top, Qin, qOp_bottom, qOp_top, Qop, qout_bottom, qout_top, Qout);
3477 if(std::abs(factor_9j) < ::mynumeric_limits<double>::epsilon())
3481 for(std::size_t n_bottom=0; n_bottom<hilbert_dimension; ++n_bottom)
3483 for(std::size_t n_top=0; n_top<hilbert_dimension; ++n_top)
3485 if(std::array<qType,3> qCheck = {qPhys[loc][n_bottom], Qop, qPhys[loc][n_top]}; !Symmetry::validate(qCheck))
3489 #if DEBUG_VERBOSITY > 2
3492 lout <<
"\t\t\t\tmat(" << n_top <<
"," << n_bottom <<
") = 0";
3497 for(std::size_t n_middle=0; n_middle<hilbert_dimension; ++n_middle)
3499 if(std::array<qType,3> qCheck = {qPhys[loc][n_bottom], qOp_bottom, qPhys[loc][n_middle]}; !Symmetry::validate(qCheck))
3503 if(std::array<qType,3> qCheck = {qPhys[loc][n_middle], qOp_top, qPhys[loc][n_top]}; !Symmetry::validate(qCheck))
3507 if(std::abs(op_top.data.coeff(n_top, n_middle)) < ::mynumeric_limits<double>::epsilon() or std::abs(op_bottom.data.coeff(n_middle, n_bottom)) < ::mynumeric_limits<double>::epsilon())
3511 Scalar factor_6j = Symmetry::coeff_Apair(qPhys[loc][n_top], qOp_top, qPhys[loc][n_middle], qOp_bottom, qPhys[loc][n_bottom], Qop);
3512 if(std::abs(factor_6j) < ::mynumeric_limits<double>::epsilon())
3516 val += op_top.data.coeff(n_top, n_middle) * op_bottom.data.coeff(n_middle, n_bottom) * factor_9j * factor_6j;
3517 #if DEBUG_VERBOSITY > 2
3520 lout <<
" + " << op_top.data.coeff(n_top, n_middle) <<
"*" << op_bottom.data.coeff(n_middle, n_bottom) <<
"*" << factor_9j*factor_6j;
3524 if(std::abs(val) < ::mynumeric_limits<double>::epsilon())
3526 #if DEBUG_VERBOSITY > 2
3529 lout <<
" = 0" << std::endl;
3534 op.
data.coeffRef(n_top, n_bottom) = val;
3535 #if DEBUG_VERBOSITY > 2
3538 lout <<
" = " << val << std::endl;
3543 if(op.
data.norm() > ::mynumeric_limits<double>::epsilon())
3545 auto it_op = ops.find(Qop);
3546 if(it_op != ops.end())
3548 (it_op->second) = (it_op->second) + op;
3552 ops.insert({Qop,op});
3569 #if DEBUG_VERBOSITY > 1
3572 lout <<
"Infinite system: Swap rows and columns to ensure identity operators to be at [0|0] and [1|1]" << std::endl;
3575 prod_swap_IBC(O, row_qVac, col_qVac, row_qTot, col_qTot);
3579 #if DEBUG_VERBOSITY > 1
3582 lout <<
"Open system: Delete columns at last lattice site which do not match target quantum number" << std::endl;
3585 prod_delZeroCols_OBC(O[N_sites-1], qAux[N_sites], qAux[N_sites-1], qTot, col_qTot[N_sites-1]);
3588 out.
reconstruct(O, qAux, qPhys,
true, boundary_condition, qTot);
3589 auto [name_top, power_top] = detect_and_remove_power(top.
get_name());
3590 auto [name_bot, power_bot] = detect_and_remove_power(bottom.
get_name());
3594 if(name_top == name_bot)
3596 out.
set_name(name_top + power_to_string(power_top+power_bot));
3619 std::vector<std::string> str_powers(10);
3620 str_powers[0] =
"⁰";
3621 str_powers[1] =
"¹";
3622 str_powers[2] =
"²";
3623 str_powers[3] =
"³";
3624 str_powers[4] =
"⁴";
3625 str_powers[5] =
"⁵";
3626 str_powers[6] =
"⁶";
3627 str_powers[7] =
"⁷";
3628 str_powers[8] =
"⁸";
3629 str_powers[9] =
"⁹";
3631 std::string name_wo_power = name_w_power;
3632 std::size_t power = 1ul;
3633 for(std::size_t ip=0; ip<str_powers.size(); ip++)
3635 auto pos = name_wo_power.find(str_powers[ip]);
3636 if(pos == std::string::npos)
3640 name_wo_power.erase(pos,pos+str_powers[ip].size());
3644 return std::make_pair(name_wo_power,power);
3650 assert(power<10 and
"power_to_string has only strings for power < 10.");
3651 std::vector<std::string> str_powers(10);
3652 str_powers[0] =
"⁰";
3653 str_powers[1] =
"¹";
3654 str_powers[2] =
"²";
3655 str_powers[3] =
"³";
3656 str_powers[4] =
"⁴";
3657 str_powers[5] =
"⁵";
3658 str_powers[6] =
"⁶";
3659 str_powers[7] =
"⁷";
3660 str_powers[8] =
"⁸";
3661 str_powers[9] =
"⁹";
3662 return str_powers[power];
3668 typedef typename Symmetry::qType
qType;
3675 lout <<
"MPO addition of " << bottom.
get_name() <<
"+" << top.
get_name() << std::endl;
3679 assert(bottom.
size() == top.
size() and
"Error: Adding two MPOs of different size");
3684 std::vector<std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> O_bottom, O_top, O_out;
3685 std::vector<Qbasis<Symmetry>> qAux_bottom, qAux_top, qAux_out;
3686 std::vector<std::vector<qType>> qPhys, qPhys_check;
3687 std::vector<std::vector<qType>> qOp_bottom, qOp_top;
3688 std::map<qType,OperatorType> empty_op_map;
3690 assert(bottom.
get_qTot() == top.
get_qTot() and
"Addition only possible for MPOs with the same total quantum number.");
3696 O_bottom = bottom.
get_O();
3697 O_top = top.
get_O();
3702 qOp_bottom = bottom.
get_qOp();
3705 std::size_t N_sites = bottom.
size();
3706 O_out.resize(N_sites);
3707 qAux_out.resize(N_sites+1);
3709 std::vector<std::map<qType,std::size_t>> auxdim(N_sites+1);
3710 std::vector<std::size_t> auxdim_bottom_starts(N_sites+1);
3712 for(std::size_t loc=0; loc<=N_sites; ++loc)
3714 for(
const auto &entry : qAux_top[loc])
3716 qType q = std::get<0>(entry);
3717 std::size_t deg = std::get<2>(entry).size();
3718 auxdim[loc].insert({q,deg});
3719 if(q == Symmetry::qvacuum())
3721 auxdim_bottom_starts[loc] = deg;
3724 for(
const auto &entry : qAux_bottom[loc])
3726 qType q = std::get<0>(entry);
3727 std::size_t deg = std::get<2>(entry).size();
3728 auto it = auxdim[loc].find(q);
3729 if(it != auxdim[loc].end())
3731 (it->second) += deg;
3735 auxdim[loc].insert({q,deg});
3738 for(
const auto &[q,deg] : auxdim[loc])
3740 qAux_out[loc].push_back(q,deg);
3744 for(std::size_t loc=0; loc<N_sites; ++loc)
3746 #if DEBUG_VERBOSITY > 1
3749 lout <<
"Lattice site " << loc << std::endl;
3752 std::size_t hilbert_dimension = qPhys[loc].size();
3753 assert(hilbert_dimension == qPhys_check[loc].size() and
"Local Hilbert space dimensions do not match!");
3755 for(
const auto &[qIn,rows] : auxdim[loc])
3757 std::size_t row_start = 0;
3758 if(qAux_top[loc].find(qIn))
3760 row_start = qAux_top[loc].inner_dim(qIn);
3764 for(
const auto &[qOut,cols] : auxdim[loc+1])
3766 std::size_t col_start = 0;
3767 if(qAux_top[loc+1].find(qOut))
3769 col_start = qAux_top[loc+1].inner_dim(qOut);
3771 #if DEBUG_VERBOSITY > 1
3774 lout <<
"\tqIn = {" << Sym::format<Symmetry>(qIn) <<
"} and qOut = {" << Sym::format<Symmetry>(qOut) <<
"} is a " << rows <<
"x" << cols <<
"-matrix:" << std::endl;
3777 std::vector<std::map<qType,OperatorType>> temp_row(cols, empty_op_map);
3778 std::vector<std::vector<std::map<qType,OperatorType>>> O_temp(rows, temp_row);
3779 auto it_top = O_top[loc].find({qIn,qOut});
3780 auto it_bottom = O_bottom[loc].find({qIn,qOut});
3781 if(it_top != O_top[loc].end())
3783 const std::vector<std::vector<std::map<qType,OperatorType>>> &O_top_temp = it_top->second;
3784 std::size_t top_rows = O_top_temp.size();
3785 std::size_t top_cols = O_top_temp[0].size();
3786 #if DEBUG_VERBOSITY > 1
3789 lout <<
"\t\t Block exists in top MPO and is written from [0|0] to [" << top_rows-1 <<
"|" << top_cols-1 <<
"]";
3792 for(std::size_t row=0; row<top_rows; ++row)
3794 for(std::size_t col=0; col<top_cols; ++col)
3796 O_temp[row][col] = O_top_temp[row][col];
3800 #if DEBUG_VERBOSITY > 1
3805 lout <<
"\t\t Block does not exist in top MPO";
3809 if(it_bottom != O_bottom[loc].end())
3811 const std::vector<std::vector<std::map<qType,OperatorType>>> &O_bottom_temp = it_bottom->second;
3812 std::size_t bottom_rows = O_bottom_temp.size();
3813 std::size_t bottom_cols = O_bottom_temp[0].size();
3814 #if DEBUG_VERBOSITY > 1
3817 lout <<
"\t|\t Block exists in bottom MPO and is written from [" << row_start <<
"|" << col_start <<
"] to [" << row_start+bottom_rows-1 <<
"|" << col_start+bottom_cols-1 <<
"]" << std::endl;
3820 for(std::size_t row=0; row<bottom_rows; ++row)
3822 for(std::size_t col=0; col<bottom_cols; ++col)
3824 O_temp[row_start+row][col_start+col] = O_bottom_temp[row][col];
3828 #if DEBUG_VERBOSITY > 1
3833 lout <<
"\t|\t Block does not exist in bottom MPO" << std::endl;
3837 O_out[loc].insert({{qIn,qOut},O_temp});
3843 out.
reconstruct(O_out, qAux_out, qPhys,
true, boundary_condition_out,qTot);
3844 if(boundary_condition_out ==
BC::OPEN)
3846 #if DEBUG_VERBOSITY > 1
3849 lout <<
"Open System: Add both rows at first lattice site and both columns at last lattice site" << std::endl;
3859 #if DEBUG_VERBOSITY > 1
3862 lout <<
"Infinite System: Add both incoming operator columns and both outgoing operator rows at each lattice site" << std::endl;
3865 for(std::size_t loc=0; loc<N_sites; ++loc)
3867 out.
delete_col(loc, Symmetry::qvacuum(), auxdim_bottom_starts[loc+1],
false);
3870 out.
add_to_row(loc, Symmetry::qvacuum(), 0, out.
delete_row(loc, Symmetry::qvacuum(), auxdim_bottom_starts[loc],
false),1.);
3872 for(std::size_t loc=0; loc<N_sites; ++loc)
3898 std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>> O_new;
3901 for(
const auto &entry : qAux_prev)
3903 qType qIn = std::get<0>(entry);
3904 std::size_t rows = std::get<2>(entry).size();
3905 std::map<qType,OperatorType> empty_op_map;
3906 std::vector<std::map<qType,OperatorType>> temp_row(1,empty_op_map);
3907 std::vector<std::vector<std::map<qType,OperatorType>>> temp(rows,temp_row);
3908 auto it = O_last.find({qIn,qTot});
3909 assert(it != O_last.end());
3910 for(std::size_t row=0; row<rows; ++row)
3912 temp[row][0] = (it->second)[row][col_qTot];
3914 O_new.insert({{qIn,qTot},temp});
3917 qAux_last = qAux_new;
3922prod_swap_IBC (std::vector<std::map<std::array<qType, 2>, std::vector<std::vector<std::map<qType,OperatorType>>>>> &O_out, std::vector<std::size_t> &row_qVac, std::vector<std::size_t> &col_qVac, std::vector<std::size_t> &row_qTot, std::vector<std::size_t> &col_qTot)
3924 std::size_t N_sites = O_out.size();
3925 qType qVac = Symmetry::qvacuum();
3927 for(std::size_t loc=0; loc<N_sites; ++loc)
3929 if(row_qVac[loc] != 0)
3931 for(
auto &[qs, ops] : O_out[loc])
3933 if(std::get<0>(qs) != qVac)
3937 std::vector<std::map<qType,OperatorType>> temp = ops[0];
3938 ops[0] = ops[row_qVac[loc]];
3939 ops[row_qVac[loc]] = temp;
3941 if(row_qTot[loc] == 0)
3943 row_qTot[loc] = row_qVac[0];
3946 if(col_qVac[loc] != 0)
3948 for(
auto &[qs, ops] : O_out[loc])
3950 if(std::get<1>(qs) != qVac)
3954 std::size_t rows = ops.size();
3955 for(std::size_t row=0; row<rows; ++row)
3957 std::map<qType,OperatorType> temp = ops[row][0];
3958 ops[row][0] = ops[row][col_qVac[loc]];
3959 ops[row][col_qVac[loc]] = temp;
3962 if(col_qTot[loc] == 0)
3964 col_qTot[loc] = col_qVac[0];
3967 if(row_qTot[loc] != 1)
3969 for(
auto &[qs, ops] : O_out[loc])
3971 if(std::get<0>(qs) != qVac)
3975 std::vector<std::map<qType,OperatorType>> temp = ops[1];
3976 ops[1] = ops[row_qTot[loc]];
3977 ops[row_qTot[loc]] = temp;
3980 if(col_qTot[loc] != 1)
3982 for(
auto &[qs, ops] : O_out[loc])
3984 if(std::get<1>(qs) != qVac)
3988 std::size_t rows = ops.size();
3989 for(std::size_t row=0; row<rows; ++row)
3991 std::map<qType,OperatorType> temp = ops[row][1];
3992 ops[row][1] = ops[row][col_qTot[loc]];
3993 ops[row][col_qTot[loc]] = temp;
4006 auxdim.resize(N_sites+1);
4008 for(std::size_t loc=0; loc<N_sites; ++loc)
4010 auxdim[loc].insert({Q,1});
4011 std::map<qType,OperatorType> op_map;
4012 OperatorType op =
OperatorType(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Identity(qPhys[loc].size(),qPhys[loc].size()).sparseView(),Symmetry::qvacuum());
4016 op_map.insert({Symmetry::qvacuum(),op});
4017 std::vector<std::map<qType,OperatorType>> temp(1,op_map);
4018 std::vector<std::vector<std::map<qType,OperatorType>>> Oloc(1,temp);
4019 O[loc].insert({{Q,Q},Oloc});
4021 auxdim[N_sites].insert({Q,1});
4033 auxdim.resize(N_sites+1);
4035 for(std::size_t loc=0; loc<N_sites; ++loc)
4037 auxdim[loc].insert({qVac,1});
4038 std::map<qType,OperatorType> op_map;
4039 OperatorType op =
OperatorType(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Zero(qPhys[loc].size(),qPhys[loc].size()).sparseView(),qVac);
4043 op_map.insert({qVac,op});
4044 std::vector<std::map<qType,OperatorType>> temp(1,op_map);
4045 std::vector<std::vector<std::map<qType,OperatorType>>> Oloc(1,temp);
4046 O[loc].insert({{qVac,qVac},Oloc});
4048 auxdim[N_sites].insert({qVac,1});
4057 assert(power > 0 and power <= current_power);
4058 const std::vector<Qbasis<Symmetry>> &qAux_ = (power == 1) ? qAux : qAux_powers[power-2];
4059 const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry,MatrixType>>>>> &W_ = (power == 1) ? W : W_powers[power-2];
4060 std::vector<std::pair<qType, std::size_t>> vout(0);
4061 std::vector<std::pair<qType, std::size_t>> vout_temp(0);
4062 std::size_t hd = hilbert_dimension[0];
4063 vout.push_back({qVac, pos_qTot});
4064 for(std::size_t i=0; i<qAux_[0].data_.size(); ++i)
4066 qType qIn = std::get<0>(qAux_[0].data_[i]);
4067 std::size_t
dim = std::get<2>(qAux_[0].data_[i]).size();
4068 for(std::size_t row=0; row<
dim; row++)
4070 if(qIn == qVac and row == pos_qVac)
4074 if(qIn == qTot and row == pos_qTot)
4078 bool isZeroOp =
true;
4079 for(std::size_t m=0; m<hd; ++m)
4081 for(std::size_t n=0; n<hd; ++n)
4083 for(std::size_t t=0; t<W_[0][m][n].size(); ++t)
4085 auto it = W_[0][m][n][t].dict.find({qIn,qVac});
4086 if(it != W_[0][m][n][t].dict.end() and
4087 std::abs(W_[0][m][n][t].block[it->second].coeff(row,pos_qTot)) > ::mynumeric_limits<double>::epsilon())
4093 if(!isZeroOp)
break;
4095 if(!isZeroOp)
break;
4099 vout.push_back({qIn,row});
4103 vout_temp.push_back({qIn,row});
4107 vout.insert(vout.end(), vout_temp.begin(), vout_temp.end());
4108 vout.push_back({qVac, pos_qVac});
4109 #if DERBUG_VERBOSITY > 0
4110 lout <<
"Base order for VUMPS:" << std::endl;
4111 for(std::size_t i=0; i<vout.size(); ++i)
4113 lout <<
"\t#" << i <<
": {" << Sym::format<Symmetry>(std::get<0>(vout[i])) <<
"}[" << std::get<1>(vout[i]) <<
"]" << std::endl;
4123 std::vector<double>
norm(N_sites, 0.);
4124 for(std::size_t loc=0; loc<N_sites; ++loc)
4126 for(
const auto &[qs,ops] : O[loc])
4128 for(std::size_t row=0; row<ops.size(); ++row)
4130 for(std::size_t col=0; col<ops[row].size(); ++col)
4132 for(
const auto &[Q,op] : ops[row][col])
4134 norm[loc] += op.data.norm();
4140 double overall_norm = 1;
4141 for(std::size_t loc=0; loc<N_sites; ++loc)
4143 overall_norm *=
norm[loc];
4145 overall_norm = std::pow(overall_norm, 1.0/N_sites);
4146 for(std::size_t loc=0; loc<N_sites; ++loc)
4148 for(
auto &[qs,ops] : O[loc])
4150 for(std::size_t row=0; row<ops.size(); ++row)
4152 for(std::size_t col=0; col<ops[row].size(); ++col)
4154 for(
auto &[Q,op] : ops[row][col])
4156 double factor = overall_norm/
norm[loc];
4157 op.data = factor * op.data;
4168 for(std::size_t loc=0; loc<N_sites; ++loc)
4170 for(
auto &[qs,ops] : O[loc])
4172 for(std::size_t row=0; row<ops.size(); ++row)
4174 for(std::size_t col=0; col<ops[row].size(); ++col)
4176 for(
auto &[Q,op] : ops[row][col])
4189 std::size_t total_auxdim = 0;
4190 std::size_t maximum_local_auxdim = 0;
4191 std::size_t total_full_auxdim = 0;
4192 std::size_t maximum_local_full_auxdim = 0;
4193 for(std::size_t bond=0; bond<N_sites; ++bond)
4195 std::size_t local_auxdim = 0;
4196 std::size_t local_full_auxdim = 0;
4197 for(
const auto &[q,deg] : auxdim[bond])
4199 local_auxdim += deg;
4200 local_full_auxdim += deg * Symmetry::degeneracy(q);
4202 total_auxdim += local_auxdim;
4203 total_full_auxdim += local_full_auxdim;
4204 if(local_auxdim > maximum_local_auxdim)
4206 maximum_local_auxdim = local_auxdim;
4208 if(local_full_auxdim > maximum_local_full_auxdim)
4210 maximum_local_full_auxdim = local_full_auxdim;
4213 return std::make_tuple(total_auxdim,maximum_local_auxdim,total_full_auxdim,maximum_local_full_auxdim);
4217memory (MEMUNIT memunit)
const
4220 for(std::size_t loc=0; loc<O.size(); ++loc)
4222 mem_O += calc_memory<std::size_t>(2 * Symmetry::Nq * O[loc].size(),memunit);
4223 for(
const auto &[qs,ops] : O[loc])
4225 for(std::size_t row=0; row<ops.size(); ++row)
4227 for(std::size_t col=0; col<ops[row].size(); ++col)
4229 mem_O += calc_memory<std::size_t>(Symmetry::Nq * ops[row][col].size(),memunit);
4230 for(
const auto &[Q,op] : ops[row][col])
4232 mem_O += calc_memory(op.data,memunit) + calc_memory(op.label,memunit);
4239 double mem_auxdim = 0.;
4240 for(std::size_t loc=0; loc<=N_sites; ++loc)
4242 mem_auxdim += calc_memory<std::size_t>((Symmetry::Nq + 1) * auxdim[loc].size(),memunit);
4245 double mem_qAux = 0.;
4248 for(std::size_t loc=0; loc<qAux.size(); ++loc)
4250 for(std::size_t i=0; i<qAux[loc].data_.size(); ++i)
4252 mem_qAux += calc_memory<std::size_t>(Symmetry::Nq + 1,memunit);
4253 mem_qAux += std::get<2>(qAux[loc].data_[i]).size() * (calc_memory(
"",memunit)+calc_memory<std::size_t>(1ul,memunit));
4255 mem_qAux += calc_memory<std::size_t>(Symmetry::Nq * qAux[loc].history.size(),memunit);
4256 for(
const auto &[q,vec] : qAux[loc].history)
4258 mem_qAux += calc_memory<std::size_t>((2*Symmetry::Nq + 1) * vec.size(), memunit);
4263 double mem_qOp = 0.;
4266 for(std::size_t loc=0; loc<qOp.size(); ++loc)
4268 mem_qOp += Symmetry::Nq * calc_memory<std::size_t>(qOp[loc].size(), memunit);
4272 double mem_qPhys = 0.;
4273 for(std::size_t loc=0; loc<qPhys.size(); ++loc)
4277 mem_qOp += Symmetry::Nq * calc_memory<std::size_t>(qPhys[loc].size(), memunit);
4284 for(std::size_t loc=0; loc<W.size(); ++loc)
4286 for(std::size_t m=0; m<W[loc].size(); ++m)
4288 for(std::size_t n=0; n<W[loc][m].size(); ++n)
4290 for(std::size_t t=0; t<W[loc][m][n].size(); ++t)
4292 mem_W += W[loc][m][n][t].memory(memunit) + W[loc][m][n][t].overhead(memunit);
4299 double mem_info = 0.;
4300 mem_info += calc_memory(label,memunit);
4301 for(std::size_t loc=0; loc<info.size(); ++loc)
4303 for(std::size_t i=0; i<info[loc].size(); ++i)
4305 mem_info += calc_memory(info[loc][i],memunit);
4309 double mem_powers = 0.;
4310 for(std::size_t power=2; power<=current_power; ++power)
4312 for(std::size_t loc=0; loc<W_powers[power-2].size(); ++loc)
4314 for(std::size_t m=0; m<W_powers[power-2][loc].size(); ++m)
4316 for(std::size_t n=0; n<W_powers[power-2][loc][m].size(); ++n)
4318 for(std::size_t t=0; t<W_powers[power-2][loc][m][n].size(); ++t)
4320 mem_powers += W_powers[power-2][loc][m][n][t].memory(memunit) + W_powers[power-2][loc][m][n][t].overhead(memunit);
4324 mem_powers += Symmetry::Nq * calc_memory<std::size_t>(qOp_powers[power-2][loc].size(), memunit);
4325 for(std::size_t i=0; i<qAux_powers[power-2][loc].data_.size(); ++i)
4327 mem_powers += calc_memory<std::size_t>(Symmetry::Nq + 1,memunit);
4328 mem_powers += std::get<2>(qAux_powers[power-2][loc].data_[i]).size() * (calc_memory(
"",memunit)+calc_memory<std::size_t>(1ul,memunit));
4330 mem_powers += calc_memory<std::size_t>(Symmetry::Nq * qAux_powers[power-2][loc].history.size(),memunit);
4331 for(
const auto &[q,vec] : qAux_powers[power-2][loc].history)
4333 mem_powers += calc_memory<std::size_t>((2*Symmetry::Nq + 1) * vec.size(), memunit);
4338 return mem_O + mem_auxdim + mem_qAux + mem_qOp + mem_qPhys + mem_W + mem_info + mem_powers;
4342sparsity (
const std::size_t power,
const bool PER_MATRIX)
const
4344 assert(power > 0 and power <= current_power);
4347 assert(!PER_MATRIX and
"? TODO");
4348 std::size_t nonzero_elements = 0;
4349 std::size_t overall_elements = 0;
4350 const std::vector<Qbasis<Symmetry>> &qAux_ = (power == 1) ? qAux : qAux_powers[power-2];
4351 const std::vector<std::vector<std::vector<std::vector<Biped<Symmetry,MatrixType>>>>> &W_ = (power == 1) ? W : W_powers[power-2];
4352 std::vector<std::size_t> dims(N_sites+1);
4353 for(std::size_t i=0; i<qAux_[0].data_.size(); ++i)
4355 dims[0] += std::get<2>(qAux_[0].data_[i]).size();
4357 for(std::size_t loc=0; loc<N_sites; ++loc)
4359 for(std::size_t i=0; i<qAux_[loc+1].data_.size(); ++i)
4361 dims[loc+1] += std::get<2>(qAux_[loc+1].data_[i]).size();
4363 std::size_t hd = hilbert_dimension[loc];
4364 overall_elements += hd * hd * dims[loc] * dims[loc+1];
4365 for(std::size_t m=0; m<hd; ++m)
4367 for(std::size_t n=0; n<hd; ++n)
4369 const auto &left = qAux_[loc].data_;
4370 const auto &right = qAux_[loc+1].data_;
4371 for(std::size_t i=0; i<left.size(); ++i)
4373 for(std::size_t j=0; j<right.size(); ++j)
4375 Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic> entries = Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>::Zero(std::get<2>(left[i]).size(),std::get<2>(right[j]).size());
4376 for(std::size_t t=0; t<W_[loc][m][n].size(); ++t)
4378 auto it = W_[loc][m][n][t].dict.find({std::get<0>(left[i]),std::get<0>(right[j])});
4379 if(it != W_[loc][m][n][t].dict.end())
4381 const MatrixType &mat = W_[loc][m][n][t].block[it->second];
4382 assert(mat.rows() == std::get<2>(left[i]).size());
4383 assert(mat.cols() == std::get<2>(right[j]).size());
4384 for(std::size_t row=0; row<mat.rows(); ++row)
4386 for(std::size_t col=0; col<mat.cols(); ++col)
4388 if(entries(row,col) == 0 and std::abs(mat.coeff(row,col)) > ::mynumeric_limits<double>::epsilon())
4391 entries(row,col) = 1;
4402 return (nonzero_elements+0.)/(overall_elements+0.);
4405#ifdef USE_HDF5_STORAGE
4407save (std::string filename)
4409 assert(GOT_W and
"W has to be calculated before saving.");
4410 assert(GOT_QAUX and
"qAux has to be calculated before saving.");
4411 assert(GOT_QOP and
"qOp has to be calculated before saving.");
4413 lout << termcolor::green <<
"Saving MPO to path " << filename << termcolor::reset << std::endl;
4414 HDF5Interface target(filename, WRITE);
4416 target.save_scalar(N_sites,
"L");
4417 target.save_scalar(N_phys,
"vol");
4418 target.save_scalar(
static_cast<int>(boundary_condition),
"boundary_condition");
4419 target.save_scalar(
static_cast<int>(status),
"status");
4420 std::string labelstring =
"Label";
4421 target.save_char(label,labelstring.c_str());
4422 target.save_scalar(current_power,
"maxPower");
4424 target.create_group(
"qTot");
4425 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4427 std::stringstream ss;
4429 target.save_scalar(qTot[nq],ss.str(),
"qTot");
4432 target.create_group(
"qPhys");
4433 for(std::size_t loc=0; loc<N_sites; ++loc)
4435 std::stringstream ss_hd;
4436 ss_hd <<
"loc=" << loc <<
",hd";
4437 target.save_scalar(hilbert_dimension[loc],ss_hd.str(),
"qPhys");
4438 for(std::size_t n=0; n<hilbert_dimension[loc]; ++n)
4440 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4442 std::stringstream ss;
4443 ss <<
"loc=" << loc <<
",n=" << n <<
",nq=" << nq;
4444 target.save_scalar((qPhys[loc][n])[nq],ss.str(),
"qPhys");
4449 for(std::size_t power = 1; power<=current_power; ++power)
4451 std::stringstream ss;
4453 std::string powerstring = (power == 1 ?
"" : ss.str());
4455 std::vector<Qbasis<Symmetry>> &qAux_ = (power == 1 ? qAux : qAux_powers[power-2]);
4456 std::vector<std::vector<qType>> &qOp_ = (power == 1 ? qOp : qOp_powers[power-2]);
4457 std::vector<std::vector<std::vector<std::vector<Biped<Symmetry,MatrixType>>>>> &W_ = (power == 1 ? W : W_powers[power-2]);
4459 std::vector<std::vector<qType>> qAuxVec_(N_sites+1);
4460 std::vector<std::vector<std::size_t>> qAuxVec_deg_(N_sites+1);
4461 for(std::size_t loc=0; loc<=N_sites; ++loc)
4463 for(std::size_t k=0; k<qAux_[loc].data_.size(); ++k)
4465 qAuxVec_[loc].push_back(std::get<0>(qAux_[loc].data_[k]));
4466 qAuxVec_deg_[loc].push_back(std::get<2>(qAux_[loc].data_[k]).size());
4471 target.create_group(
"qAux"+powerstring);
4472 for(std::size_t loc=0; loc<=N_sites; ++loc)
4474 std::stringstream ss_size;
4475 ss_size <<
"loc=" << loc <<
",size";
4476 target.save_scalar(qAuxVec_[loc].size(),ss_size.str(),
"qAux"+powerstring);
4477 for(std::size_t k=0; k<qAuxVec_[loc].size(); ++k)
4479 std::stringstream ss_deg;
4480 ss_deg <<
"loc=" << loc <<
",k=" << k <<
",deg";
4481 target.save_scalar(qAuxVec_deg_[loc][k], ss_deg.str(),
"qAux"+powerstring);
4482 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4484 std::stringstream ss_quantum;
4485 ss_quantum <<
"loc=" << loc <<
",k=" << k <<
",nq=" << nq;
4486 target.save_scalar((qAuxVec_[loc][k])[nq], ss_quantum.str(),
"qAux"+powerstring);
4491 target.create_group(
"qOp"+powerstring);
4492 for(std::size_t loc=0; loc<N_sites; ++loc)
4494 std::stringstream ss_size;
4495 ss_size <<
"loc=" << loc <<
",size";
4496 target.save_scalar(qOp_[loc].size(),ss_size.str(),
"qOp"+powerstring);
4497 for(std::size_t t=0; t<qOp_[loc].size(); ++t)
4499 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4501 std::stringstream ss;
4502 ss <<
"loc=" << loc <<
",t=" << t <<
",nq=" << nq;
4503 target.save_scalar((qOp_[loc][t])[nq],ss.str(),
"qOp"+powerstring);
4508 target.create_group(
"W"+powerstring);
4509 for(std::size_t loc=0; loc<N_sites; ++loc)
4511 for(std::size_t m=0; m<hilbert_dimension[loc]; ++m)
4513 for(std::size_t n=0; n<hilbert_dimension[loc]; ++n)
4515 for(std::size_t t=0; t<qOp_[loc].size(); ++t)
4518 std::vector<std::size_t> ins, outs;
4519 for(std::size_t entry=0; entry<bip.
dim; ++entry)
4521 auto it_in = find(qAuxVec_[loc].begin(), qAuxVec_[loc].end(), bip.
in[entry]);
4522 auto it_out = find(qAuxVec_[loc+1].begin(), qAuxVec_[loc+1].end(), bip.
out[entry]);
4523 assert(it_in != qAuxVec_[loc].end() and it_out != qAuxVec_[loc+1].end());
4524 std::size_t qAux_in_pos = std::distance(qAuxVec_[loc].begin(),it_in);
4525 std::size_t qAux_out_pos = std::distance(qAuxVec_[loc+1].begin(),it_out);
4526 ins.push_back(qAux_in_pos);
4527 outs.push_back(qAux_out_pos);
4528 std::stringstream ss;
4529 ss <<
"loc=" << loc <<
",m=" << m <<
",n=" << n <<
",t=" << t <<
",k'=" << qAux_in_pos <<
",k=" << qAux_out_pos;
4530 if constexpr(std::is_same<Scalar,std::complex<double>>::value)
4532 target.save_matrix(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(bip.
block[entry].real()), ss.str()+
",Re",
"W"+powerstring);
4533 target.save_matrix(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(bip.
block[entry].imag()), ss.str()+
",Im",
"W"+powerstring);
4537 target.save_matrix(Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(bip.
block[entry]),ss.str(),
"W"+powerstring);
4540 Eigen::Matrix<std::size_t,Eigen::Dynamic,Eigen::Dynamic> entries(ins.size(),2);
4541 for(std::size_t i=0; i<ins.size(); ++i)
4543 entries(i,0) = ins[i];
4544 entries(i,1) = outs[i];
4546 std::stringstream ss_entries;
4547 ss_entries <<
"loc=" << loc <<
",m=" << m <<
",n=" << n <<
",t=" << t <<
",entries";
4548 target.save_matrix(entries,ss_entries.str(),
"W"+powerstring);
4558load (std::string filename)
4561 lout << termcolor::green <<
"Loading MPO from path " << filename << termcolor::reset << std::endl;
4562 HDF5Interface source(filename, READ);
4564 source.load_scalar(N_sites,
"L");
4565 source.load_scalar(N_phys,
"vol");
4566 source.load_scalar(current_power,
"maxPower");
4568 source.load_scalar(boundary,
"boundary_condition");
4569 boundary_condition =
static_cast<BC>(boundary);
4571 source.load_scalar(stat,
"status");
4574 source.load_char(label,
"Label");
4578 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4580 std::stringstream ss;
4582 source.load_scalar(qTot[nq],ss.str(),
"qTot");
4585 hilbert_dimension.clear();
4586 hilbert_dimension.resize(N_sites,0);
4588 GOT_QPHYS.resize(N_sites,
true);
4590 qPhys.resize(N_sites);
4591 for(std::size_t loc=0; loc<N_sites; ++loc)
4593 std::stringstream ss_hd;
4594 ss_hd <<
"loc=" << loc <<
",hd";
4595 source.load_scalar(hilbert_dimension[loc],ss_hd.str(),
"qPhys");
4596 qPhys[loc].resize(hilbert_dimension[loc]);
4597 for(std::size_t n=0; n<hilbert_dimension[loc]; ++n)
4599 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4601 std::stringstream ss;
4602 ss <<
"loc=" << loc <<
",n=" << n <<
",nq=" << nq;
4603 source.load_scalar((qPhys[loc][n])[nq],ss.str(),
"qPhys");
4608 qAux_powers.clear();
4611 if(current_power > 1)
4613 qAux_powers.resize(current_power-1);
4614 W_powers.resize(current_power-1);
4615 qOp_powers.resize(current_power-1);
4618 for(std::size_t power = 1; power<=current_power; ++power)
4620 std::stringstream ss;
4622 std::string powerstring = (power == 1 ?
"" : ss.str());
4623 std::vector<Qbasis<Symmetry>> &qAux_ = (power == 1 ? qAux : qAux_powers[power-2]);
4624 std::vector<std::vector<qType>> &qOp_ = (power == 1 ? qOp : qOp_powers[power-2]);
4625 std::vector<std::vector<std::vector<std::vector<Biped<Symmetry,MatrixType>>>>> &W_ = (power == 1 ? W : W_powers[power-2]);
4628 qAux_.resize(N_sites+1);
4630 qOp_.resize(N_sites);
4634 std::vector<std::vector<qType>> qAuxVec_(N_sites+1);
4635 std::vector<std::vector<std::size_t>> qAuxVec_deg_(N_sites+1);
4636 for(std::size_t loc=0; loc<=N_sites; ++loc)
4638 std::stringstream ss_size;
4639 ss_size <<
"loc=" << loc <<
",size";
4641 source.load_scalar(size,ss_size.str(),
"qAux"+powerstring);
4642 qAuxVec_[loc].resize(size);
4643 qAuxVec_deg_[loc].resize(size);
4644 for(std::size_t k=0; k<qAuxVec_[loc].size(); ++k)
4646 std::stringstream ss_deg;
4647 ss_deg <<
"loc=" << loc <<
",k=" << k <<
",deg";
4648 source.load_scalar(qAuxVec_deg_[loc][k], ss_deg.str(),
"qAux"+powerstring);
4649 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4651 std::stringstream ss_quantum;
4652 ss_quantum <<
"loc=" << loc <<
",k=" << k <<
",nq=" << nq;
4653 source.load_scalar((qAuxVec_[loc][k])[nq], ss_quantum.str(),
"qAux"+powerstring);
4657 qAux_.resize(N_sites+1);
4658 for(std::size_t loc=0; loc<=N_sites; ++loc)
4661 for(std::size_t k=0; k<qAuxVec_[loc].size(); ++k)
4663 qAux_[loc].push_back(qAuxVec_[loc][k],qAuxVec_deg_[loc][k]);
4668 for(std::size_t loc=0; loc<N_sites; ++loc)
4670 std::stringstream ss_size;
4671 ss_size <<
"loc=" << loc <<
",size";
4673 source.load_scalar(size,ss_size.str(),
"qOp"+powerstring);
4674 qOp_[loc].resize(size);
4675 for(std::size_t t=0; t<qOp_[loc].size(); ++t)
4677 for(std::size_t nq=0; nq<Symmetry::Nq; ++nq)
4679 std::stringstream ss;
4680 ss <<
"loc=" << loc <<
",t=" << t <<
",nq=" << nq;
4681 source.load_scalar((qOp_[loc][t])[nq],ss.str(),
"qOp"+powerstring);
4686 for(std::size_t loc=0; loc<N_sites; ++loc)
4688 W_[loc].resize(hilbert_dimension[loc]);
4689 for(std::size_t m=0; m<hilbert_dimension[loc]; ++m)
4691 W_[loc][m].resize(hilbert_dimension[loc]);
4692 for(std::size_t n=0; n<hilbert_dimension[loc]; ++n)
4694 W_[loc][m][n].resize(qOp_[loc].size());
4695 for(std::size_t t=0; t<qOp_[loc].size(); ++t)
4698 Eigen::Matrix<std::size_t, Eigen::Dynamic, Eigen::Dynamic> entries;
4699 std::stringstream ss_entries;
4700 ss_entries <<
"loc=" << loc <<
",m=" << m <<
",n=" << n <<
",t=" << t <<
",entries";
4701 source.load_matrix(entries,ss_entries.str(),
"W"+powerstring);
4702 for(std::size_t i=0; i<entries.rows(); ++i)
4704 std::stringstream ss_mat;
4705 ss_mat <<
"loc=" << loc <<
",m=" << m <<
",n=" << n <<
",t=" << t <<
",k'=" << entries(i,0) <<
",k=" << entries(i,1);
4706 if constexpr(std::is_same<Scalar,std::complex<double>>::value)
4708 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> Real;
4709 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> Imag;
4710 source.load_matrix(Real,ss_mat.str()+
",Re",
"W"+powerstring);
4711 source.load_matrix(Imag,ss_mat.str()+
",Im",
"W"+powerstring);
4712 bip.
push_back(qAuxVec_[loc][entries(i,0)],qAuxVec_[loc+1][entries(i,1)],(Real+1.i*Imag).sparseView());
4716 Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> mat;
4717 source.load_matrix(mat,ss_mat.str(),
"W"+powerstring);
4718 bip.
push_back(qAuxVec_[loc][entries(i,0)],qAuxVec_[loc+1][entries(i,1)],mat.sparseView());
4738 auxdim.resize(N_sites+1);
4740 std::map<qType,OperatorType> empty_op_map;
4741 for(std::size_t k=0; k<qAux[0].data_.size(); ++k)
4743 auxdim[0].insert({std::get<0>(qAux[0].data_[k]),std::get<2>(qAux[0].data_[k]).size()});
4745 for(std::size_t loc=0; loc<N_sites; ++loc)
4747 std::size_t hd = hilbert_dimension[loc];
4748 std::size_t od = qOp[loc].size();
4749 for(std::size_t k=0; k<qAux[loc+1].data_.size(); ++k)
4751 auxdim[loc+1].insert({std::get<0>(qAux[loc+1].data_[k]),std::get<2>(qAux[loc+1].data_[k]).size()});
4753 for(
const auto &[qIn,rows] : auxdim[loc])
4755 std::map<std::array<qType, 2>,std::vector<std::vector<std::map<qType,OperatorType>>>> O_loc;
4756 for(
const auto &[qOut,cols] : auxdim[loc+1])
4758 std::vector<std::map<qType,OperatorType>> temp_col(cols,empty_op_map);
4759 std::vector<std::vector<std::map<qType,OperatorType>>> temp_ops(rows,temp_col);
4761 std::vector<Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>> operator_entries_Qs(od, Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Zero(hd,hd));
4762 std::vector<std::vector<Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>>> operator_entries_col(cols,operator_entries_Qs);
4763 std::vector<std::vector<std::vector<Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>>>> operator_entries(rows,operator_entries_col);
4765 for(std::size_t m=0; m<hd; ++m)
4767 for(std::size_t n=0; n<hd; ++n)
4769 for(std::size_t t=0; t<od; ++t)
4771 auto it = W[loc][m][n][t].dict.find({qIn,qOut});
4772 if(it != W[loc][m][n][t].dict.end())
4774 Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> mat = W[loc][m][n][t].block[it->second];
4775 for(std::size_t row=0; row<rows; ++row)
4777 for(std::size_t col=0; col<cols; ++col)
4779 (operator_entries[row][col][t]).coeffRef(m,n) = mat(row,col);
4787 for(std::size_t row=0; row<rows; ++row)
4789 for(std::size_t col=0; col<cols; ++col)
4791 for(std::size_t t=0; t<od; ++t)
4793 if(operator_entries[row][col][t].
norm() > ::mynumeric_limits<double>::epsilon())
4796 op.
data = operator_entries[row][col][t].sparseView();
4798 temp_ops[row][col].insert({qOp[loc][t], op});
4803 O[loc].insert({{qIn,qOut},temp_ops});
double norm(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
#define MAX_SUMPROD_STRINGLENGTH
static MpoTerms< Symmetry, Scalar > prod(const MpoTerms< Symmetry, Scalar > &top, const MpoTerms< Symmetry, Scalar > &bottom, const qType &qTot, const double tolerance=::mynumeric_limits< double >::epsilon())
void decrement_auxdim(const std::size_t loc, const qType &q)
MpoTerms(const std::size_t L=0, const BC boundary_condition_in=BC::OPEN, const qType &qTot_in=Symmetry::qvacuum(), const DMRG::VERBOSITY::OPTION &VERB_in=DMRG::VERBOSITY::OPTION::SILENT)
const std::vector< Qbasis< Symmetry > > & get_qAux_power(std::size_t power) const
std::vector< int > hilbert_dimension
const std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > & Wsq_at(const std::size_t loc) const
std::vector< bool > GOT_QPHYS
const Qbasis< Symmetry > & outBasis(const std::size_t loc) const
std::vector< std::vector< std::string > > info
static void prod_swap_IBC(std::vector< std::map< std::array< qType, 2 >, std::vector< std::vector< std::map< qType, OperatorType > > > > > &O_out, std::vector< std::size_t > &row_qVac, std::vector< std::size_t > &col_qVac, std::vector< std::size_t > &row_qTot, std::vector< std::size_t > &col_qTot)
void finalize(const bool COMPRESS=true, const std::size_t power=1, const double tolerance=::mynumeric_limits< double >::epsilon())
const Qbasis< Symmetry > & auxBasis(const std::size_t loc) const
void set_verbosity(const DMRG::VERBOSITY::OPTION VERB_in)
const std::size_t get_pos_qTot() const
const std::vector< qType > & opBasisSq(const std::size_t loc) const
const std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > & W_at(const std::size_t loc) const
const qType & get_qVac() const
std::vector< std::string > get_info() const
double sparsity(bool USE_SQUARE, bool PER_MATRIX) const
void scale(const Scalar factor, const Scalar offset=0., const std::size_t power=0ul, const double tolerance=1.e-14)
const bool check_SQUARE() const
void setLocBasis(const std::vector< std::vector< qType > > &q)
std::vector< std::map< std::array< qType, 2 >, std::vector< std::vector< std::map< qType, OperatorType > > > > > O
std::vector< std::vector< qType > > qPhys
void reconstruct(const std::vector< std::map< std::array< qType, 2 >, std::vector< std::vector< std::map< qType, OperatorType > > > > > &O_in, const std::vector< Qbasis< Symmetry > > &qAux_in, const std::vector< std::vector< qType > > &qPhys_in, const bool FINALIZED_IN, const BC boundary_condition_in, const qType &qTot_in=Symmetry::qvacuum())
const std::vector< std::map< std::array< qType, 2 >, std::vector< std::vector< std::map< qType, OperatorType > > > > > & get_O() const
void save(std::string filename)
const std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > & W_full() const
void assert_hilbert(const std::size_t loc, const std::size_t dim)
DMRG::VERBOSITY::OPTION VERB
static MpoTerms< Symmetry, Scalar > sum(const MpoTerms< Symmetry, Scalar > &top, const MpoTerms< Symmetry, Scalar > &bottom, const double tolerance=::mynumeric_limits< double >::epsilon())
const std::vector< std::vector< qType > > & get_qOp() const
virtual void push(const std::size_t loc, const std::vector< OperatorType > &opList, const std::vector< qType > &qList, const Scalar lambda=1.0)
void add_to_row(const std::size_t loc, const qType &qIn, const std::size_t row, const std::map< qType, std::vector< std::map< qType, OperatorType > > > &ops, const Scalar factor)
std::vector< Qbasis< Symmetry > > qAux
double memory(MEMUNIT memunit=kB) const
bool eliminate_linearlyDependent_rows(const std::size_t loc, const qType &qIn, const double tolerance)
void decrement_first_auxdim_OBC(const qType &qIn)
DMRG::VERBOSITY::OPTION get_verbosity() const
MPO_STATUS::OPTION status
const std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > & get_W() const
std::vector< std::vector< qType > > qOp
bool eliminate_linearlyDependent_cols(const std::size_t loc, const qType &qOut, const double tolerance)
void compress(const double tolerance)
void setQtarget(const qType &q)
MpoTerms< Symmetry, OtherScalar > cast()
void push(const std::size_t loc, const std::vector< OperatorType > &opList, const Scalar lambda=1.0)
std::vector< std::vector< std::vector< qType > > > qOp_powers
const std::vector< qType > & opBasis(const std::size_t loc) const
std::vector< std::vector< TwoSiteData< Symmetry, Scalar > > > calc_TwoSiteData() const
const std::vector< std::vector< qType > > & locBasis() const
std::vector< std::map< qType, std::size_t > > auxdim
const std::vector< qType > & locBasis(const std::size_t loc) const
void calc(const std::size_t power)
std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > W
void set_qPhys(const std::size_t loc, const std::vector< qType > &qPhys_in)
const Qbasis< Symmetry > & inBasis(const std::size_t loc) const
std::size_t current_power
void decrement_last_auxdim_OBC(const qType &qOut)
const std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > & get_W_power(std::size_t power) const
static std::pair< std::string, std::size_t > detect_and_remove_power(const std::string &name_w_power)
const std::string get_name() const
static std::string power_to_string(std::size_t power)
void initialize(const std::size_t L, const BC boundary_condition_in, const qType &qTot_in)
const std::vector< std::vector< qType > > & get_qOp_power(std::size_t power) const
std::vector< std::vector< Qbasis< Symmetry > > > qAux_powers
void transform_base(const qType &qShift, const bool PRINT=false, const int factor=-1, const std::size_t powre=0ul)
BC get_boundary_condition() const
std::size_t get_auxdim(const std::size_t loc, const qType &q) const
void load(std::string filename)
std::map< qType, std::vector< std::map< qType, OperatorType > > > delete_row(const std::size_t loc, const qType &qIn, const std::size_t row_to_delete, const bool SAMESITE)
const qType & get_qTot() const
bool is_finalized() const
void set_name(const std::string &label_in)
bool check_power(std::size_t power) const
std::string before_verb_set
const std::vector< std::vector< qType > > & get_qPhys() const
Eigen::SparseMatrix< Scalar, Eigen::ColMajor, EIGEN_DEFAULT_SPARSE_INDEX_TYPE > MatrixType
std::size_t maxPower() const
void set_Identity(const typename Symmetry::qType &Q=Symmetry::qvacuum())
static void prod_delZeroCols_OBC(std::map< std::array< qType, 2 >, std::vector< std::vector< std::map< qType, OperatorType > > > > &O_last, Qbasis< Symmetry > &qAux_last, Qbasis< Symmetry > &qAux_prev, const qType &qTot, const std::size_t col_qTot)
const std::vector< Qbasis< Symmetry > > & get_qAux() const
void increment_last_auxdim_OBC(const qType &qOut)
std::vector< std::pair< qType, std::size_t > > base_order_IBC(const std::size_t power=1) const
SiteOperator< Symmetry, Scalar > OperatorType
std::tuple< std::size_t, std::size_t, std::size_t, std::size_t > auxdim_infos() const
std::vector< qType > calc_qList(const std::vector< OperatorType > &opList)
void increment_auxdim(const std::size_t loc, const qType &q)
const std::vector< std::vector< qType > > & opBasisSq() const
void increment_first_auxdim_OBC(const qType &qIn)
void add(const std::size_t loc, const OperatorType &op, const qType &qIn, const qType &qOut, const std::size_t IndexIn, const std::size_t IndexOut)
void save_label(const std::size_t loc, const std::string &info_label)
std::vector< std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > > W_powers
void setLocBasis(const std::vector< qType > &q, std::size_t loc)
const std::vector< std::vector< qType > > & opBasis() const
std::map< qType, std::vector< std::map< qType, OperatorType > > > delete_col(const std::size_t loc, const qType &qOut, const std::size_t col_to_delete, const bool SAMESITE)
const qType & Qtarget() const
void add_to_col(const std::size_t loc, const qType &qOut, const std::size_t col, const std::map< qType, std::vector< std::map< qType, OperatorType > > > &ops, const Scalar factor)
std::size_t get_hilbert_dimension(const std::size_t loc) const
const std::vector< Qbasis< Symmetry > > & auxBasis() const
double sparsity(const std::size_t power=1, const bool PER_MATRIX=false) const
void push_back(const std::tuple< qType, Eigen::Index, std::vector< std::string > > &state)
Eigen::Index inner_num(const Eigen::Index &outer_num) const
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
Eigen::Index leftOffset(const qType &qnew, const std::array< qType, 2 > &qold, const std::array< Eigen::Index, 2 > &plain_old) const
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
Eigen::Index outer_num(const qType &q) const
std::vector< MatrixType_ > block
void push_back(qType qin, qType qout, const MatrixType_ &M)
std::vector< Qbasis< Symmetry > > qAux
std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > W
Eigen::SparseMatrix< Scalar_ > data