1#ifndef STRAWBERRY_MPS_WITH_Q
2#define STRAWBERRY_MPS_WITH_Q
14#ifdef USE_HDF5_STORAGE
15 #include <HDF5Interface.h>
16 static double dump_Mps;
25template<
typename Symmetry,
typename Scalar>
class Mpo;
26template<
typename Symmetry,
typename Scalar>
class TwoSiteGate;
37template<
typename Symmetry,
typename Scalar=
double>
41 static constexpr size_t Nq = Symmetry::Nq;
42 typedef typename Symmetry::qType
qType;
45 template<
typename Symmetry_,
typename MpHamiltonian,
typename Scalar_>
friend class DmrgSolver;
46 template<
typename Symmetry_,
typename S1,
typename S2>
friend class MpsCompressor;
47 template<
typename H,
typename Symmetry_,
typename S1,
typename S2,
typename V>
friend class TDVPPropagator;
48 template<
typename Symmetry_,
typename S1,
typename S2>
friend
50 template<
typename Symmetry_,
typename S1,
typename S2>
friend
52 template<
typename Symmetry_,
typename S1,
typename S2>
friend
53 void OxV_exact (
const Mpo<Symmetry_,S1> &H,
const Mps<Symmetry_,S2> &Vin,
Mps<Symmetry_,S2> &Vout,
double tol_compr,
DMRG::VERBOSITY::OPTION VERBOSITY,
int max_halfsweeps,
int min_halfsweeps,
int Minit);
55 template<
typename Symmetry_,
typename S_>
friend class Mps;
72 Mps (
size_t L_input, vector<vector<
qarray<Nq> > > qloc_input,
qarray<Nq> Qtot_input,
size_t N_phys_input,
int Nqmax_input,
bool TRIVIAL_BOUNDARIES=
true);
81 template<
typename Hamiltonian>
Mps (
const Hamiltonian &H,
size_t Mmax,
qarray<Nq> Qtot_input,
int Nqmax_input);
94 #ifdef USE_HDF5_STORAGE
100 Mps (
string filename) {load(filename);}
125 #ifdef USE_HDF5_STORAGE
134 void save (
string filename,
string info=
"none",
double energy=std::nan(
"1"));
141 void load (
string filename,
double &energy=dump_Mps);
281 double memory (MEMUNIT memunit=GB)
const;
444 inline vector<qarray<Nq> >
locBasis (
size_t loc)
const {
return qloc[loc];}
456 const vector<Biped<Symmetry,MatrixType> > &
A_at (
size_t loc)
const {
return A[loc];};
459 vector<Biped<Symmetry,MatrixType> > &
A_at (
size_t loc) {
return A[loc];};
495 else if (usePower == 1ul)
508 if (Nleft>0 or Nright>0)
511 size_t Lleft = Nleft * Lcell;
512 size_t Lright = Nright * Lcell;
513 size_t Lnew = this->
N_sites + Lleft + Lright;
515 vector<vector<Biped<Symmetry,MatrixType> > > Anew(Lnew);
516 vector<vector<qarray<Nq> > > qloc_new(Lnew);
520 for (
int l=0; l<Lleft; ++l)
526 for (
int l=0; l<this->
N_sites; ++l)
529 Anew [Lleft+l] =
A[l];
530 qloc_new[Lleft+l] =
qloc[l];
532 for (
int l=0; l<Lright; ++l)
535 Anew [Lleft+this->N_sites+l] =
Boundaries.A[1][l%Lcell];
536 qloc_new[Lleft+this->N_sites+l] =
Boundaries.qloc[l%Lcell];
542 this->N_sites = Lnew;
556 size_t Lleft = (Nshift<0)? 0:Nshift*Lcell;
557 size_t Lright = (Nshift<0)? abs(Nshift)*Lcell:0;
559 vector<vector<Biped<Symmetry,MatrixType>>> Anew(this->
N_sites);
560 vector<vector<qarray<Nq>>> qloc_new(this->
N_sites);
563 for (
size_t l=0; l<Lleft; ++l)
569 for (
size_t l=0; l<this->
N_sites-abs(Nshift)*Lcell; ++l)
572 Anew [Lleft+l] =
A[l+Lright];
573 qloc_new[Lleft+l] =
qloc[l+Lright];
575 for (
size_t l=0; l<Lright; ++l)
595 if (
Qtot != Symmetry::qvacuum())
597 for (
size_t l=0; l<
qloc.size(); ++l)
598 for (
size_t i=0; i<
qloc[l].size(); ++i)
599 for (
size_t q=0; q<Symmetry::Nq; ++q)
601 if (Symmetry::kind()[q] != Sym::KIND::S and Symmetry::kind()[q] != Sym::KIND::T)
615 vector<vector<qarray<Nq> > >
qloc;
624 vector<vector<Biped<Symmetry,MatrixType> > >
A;
667template<
typename Symmetry,
typename Scalar>
675 ss <<
", " << Symmetry::name() <<
", ";
680 for (
size_t q=0; q<
Nq; ++q)
682 ss << Symmetry::kind()[q];
683 if (q!=
Nq-1) {ss <<
",";}
685 ss <<
")=(" << Sym::format<Symmetry>(
Qtot) <<
"), ";
688 ss <<
"pivot=" << this->
pivot <<
", ";
691 if (Symmetry::NON_ABELIAN)
705 if (this->N_sites > 1)
708 if (!std::isnan(
S(lSmax)) and
S(lSmax) > 0)
710 ss <<
"Smax(l=" << lSmax <<
")=" <<
S(lSmax) <<
", ";
713 ss <<
"mem=" << round(
memory(GB),3) <<
"GB";
722template<
typename Symmetry,
typename Scalar>
728template<
typename Symmetry,
typename Scalar>
730Mps (
size_t L_input, vector<vector<
qarray<Nq> > > qloc_input,
qarray<Nq> Qtot_input,
size_t N_phys_input,
int Qmax_input,
bool TRIVIAL_BOUNDARIES)
736 outerResize(L_input, qloc_input, Qtot_input, Qmax_input);
741template<
typename Symmetry,
typename Scalar>
742template<
typename Hamiltonian>
744Mps (
const Hamiltonian &H,
size_t Mmax,
qarray<Nq> Qtot_input,
int Nqmax_input)
750 outerResize(H.length(), H.locBasis(), Qtot_input, Nqmax_input);
755 if (max(Mmax,
calc_Nqmax()) > Mmax) lout <<
"DmrgSolver: Adjusting Minit to match Qinit: " << Mmax <<
"→" <<
calc_Nqmax() << endl;
758 for (
size_t l=0; l<this->
N_sites; ++l)
759 for (
size_t s=0; s<
qloc[l].size(); ++s)
761 A[l][s] =
A[l][s].cleaned();
768template<
typename Symmetry,
typename Scalar>
770Mps (
size_t L_input,
const vector<vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > > &As,
776 assert(As.size() == L_input and qloc_input.size() == L_input);
782template<
typename Symmetry,
typename Scalar>
783template<
typename Hamiltonian>
789 outerResize(H.length(), H.locBasis(), Qtot_input, Nqmax_input);
792template<
typename Symmetry,
typename Scalar>
793template<
typename OtherMatrixType>
812 A.resize(this->N_sites);
815 S.resize(this->N_sites-1);
S.setConstant(numeric_limits<double>::quiet_NaN());
816 SVspec.resize(this->N_sites-1);
818 for (
size_t l=0; l<V.
N_sites; ++l)
820 A[l].resize(
qloc[l].size());
822 for (
size_t s=0; s<
qloc[l].size(); ++s)
824 A[l][s].in = V.
A[l][s].in;
825 A[l][s].out = V.
A[l][s].out;
826 A[l][s].block.resize(V.
A[l][s].dim);
827 A[l][s].dict = V.
A[l][s].dict;
828 A[l][s].dim = V.
A[l][s].dim;
833template<
typename Symmetry,
typename Scalar>
837 A.resize(this->N_sites);
839 for (
size_t l=0; l<this->
N_sites; ++l)
841 A[l].resize(
qloc[l].size());
844 inbase.resize(this->N_sites);
848 S.resize(this->N_sites-1);
S.setConstant(numeric_limits<double>::quiet_NaN());
849 SVspec.resize(this->N_sites-1);
852template<
typename Symmetry,
typename Scalar>
857 bool NEED_WORKAROUND =
false;
858 for (
int q=0; q<Symmetry::Nq; ++q)
860 if (Symmetry::kind()[q] == Sym::KIND::N and
Qtot[q] == 0)
862 NEED_WORKAROUND =
true;
885 auto lowest_q = [] (
const vector<qarray<Nq> > &qs) ->
qarray<Nq>
888 array<vector<int>,
Nq> tmp;
889 for (
size_t q=0; q<
Nq; q++)
891 tmp[q].resize(qs.size());
892 for (
size_t i=0; i<qs.size(); i++)
894 tmp[q][i] = qs[i][q];
897 for (
size_t q=0; q<
Nq; q++)
899 sort(tmp[q].begin(),tmp[q].end());
907 if (!Symmetry::IS_TRIVIAL)
909 for (
size_t l=0; l<this->
N_sites; ++l)
910 for (
size_t s=0; s<
qloc[l].size(); ++s)
912 if (ceil(0.5*(
qloc[l][s][0]-1.)) > Smax) {Smax = ceil(0.5*(
qloc[l][s][0]-1.));}
917 auto lowest_qs = [Smax] (
const vector<qarray<Nq> > &qs) -> vector<
qarray<Nq> >
919 if (Symmetry::IS_TRIVIAL)
921 vector<qarray<Nq> > out(1);
922 out[0] = Symmetry::qvacuum();
934 array<vector<int>,
Nq> tmp;
935 for (
size_t q=0; q<
Nq; q++)
937 tmp[q].resize(qs.size());
938 for (
size_t i=0; i<qs.size(); i++)
940 tmp[q][i] = qs[i][q];
942 sort(tmp[q].begin(),tmp[q].end());
943 tmp[q].erase(unique(tmp[q].begin(), tmp[q].end()), tmp[q].end());
947 Array<size_t,Dynamic,1> tmp_sizes(
Nq);
948 for (
size_t q=0; q<
Nq; q++)
950 tmp_sizes(q) = tmp[q].size();
953 vector<qarray<Nq> > out(min(Smax+1, tmp_sizes.minCoeff()));
955 for (
size_t q=0; q<
Nq; q++)
956 for (
size_t i=0; i<out.size(); ++i)
958 out[i][q] = tmp[q][i];
972 auto highest_q = [] (
const vector<qarray<Nq> > &qs) ->
qarray<Nq>
975 array<vector<int>,
Nq> tmp;
976 for (
size_t q=0; q<
Nq; q++)
978 tmp[q].resize(qs.size());
979 for (
size_t i=0; i<qs.size(); i++)
981 tmp[q][i] = qs[i][q];
984 for (
size_t q=0; q<
Nq; q++)
986 sort(tmp[q].begin(),tmp[q].end());
987 out[q] = tmp[q][qs.size()-1];
992 QinTop.resize(this->N_sites);
993 QinBot.resize(this->N_sites);
1005 vector<vector<qarray<Symmetry::Nq> > > QinBotRange(this->N_sites);
1006 vector<vector<qarray<Symmetry::Nq> > > QoutBotRange(this->N_sites);
1008 QinTop[0] = Symmetry::qvacuum();
1009 QinBot[0] = Symmetry::qvacuum();
1010 QinBotRange[0] = {Symmetry::qvacuum()};
1012 for (
size_t l=1; l<this->
N_sites; ++l)
1014 auto new_tops = Symmetry::reduceSilent(
qloc[l-1],
QinTop[l-1]);
1015 auto new_bots = Symmetry::reduceSilent(
qloc[l-1], QinBotRange[l-1],
true);
1019 QinTop[l] = highest_q(new_tops);
1021 QinBot[l] = lowest_q(new_bots);
1023 QinBotRange[l] = lowest_qs(new_bots);
1031 QoutBotRange[this->N_sites-1] =
Qmulti;
1033 for (
int l=this->N_sites-2; l>=0; --l)
1035 vector<qarray<Symmetry::Nq> > qlocflip;
1036 for (
size_t q=0; q<
qloc[l+1].size(); ++q)
1038 qlocflip.push_back(Symmetry::flip(
qloc[l+1][q]));
1040 auto new_tops = Symmetry::reduceSilent(qlocflip,
QoutTop[l+1]);
1041 auto new_bots = Symmetry::reduceSilent(qlocflip, QoutBotRange[l+1]);
1043 QoutTop[l] = highest_q(new_tops);
1044 QoutBot[l] = lowest_q(new_bots);
1045 QoutBotRange[l] = lowest_qs(new_bots);
1048 for (
size_t l=0; l<this->
N_sites; ++l)
1052 for (
size_t q=0; q<
Nq; q++)
1056 if (Symmetry::kind()[q] == Sym::KIND::K)
1058 QinTop[l][q] = Symmetry::mod()[q]-1;
1063 if (l!=this->N_sites-1)
1065 for (
size_t q=0; q<
Nq; q++)
1069 if (Symmetry::kind()[q] == Sym::KIND::K)
1071 QoutTop[l][q] = Symmetry::mod()[q]-1;
1086template<
typename Symmetry,
typename Scalar>
1089 lout << termcolor::blue <<
"Setting Qlimits to infinity!" << termcolor::reset << endl;
1090 QinTop.resize(this->N_sites);
1091 QinBot.resize(this->N_sites);
1092 QoutTop.resize(this->N_sites);
1093 QoutBot.resize(this->N_sites);
1095 for (
size_t l=0; l<this->
N_sites; ++l)
1096 for (
size_t q=0; q<
Nq; q++)
1099 if (Symmetry::kind()[q] == Sym::KIND::K)
1101 QinTop[l][q] = Symmetry::mod()[q]-1;
1103 QoutTop[l][q] = Symmetry::mod()[q]-1;
1106 else if (Symmetry::kind()[q] == Sym::KIND::N)
1115 QinTop[l][q] = std::numeric_limits<int>::max();
1116 QinBot[l][q] = std::numeric_limits<int>::min();
1117 QoutTop[l][q] = std::numeric_limits<int>::max();
1118 QoutBot[l][q] = std::numeric_limits<int>::min();
1123template<
typename Symmetry,
typename Scalar>
1127 if (Nqmax_input == -1)
1133 this->N_sites = L_input;
1142 auto take_first_elems = [
this,Nqmax_input] (
const vector<qarray<Nq> > &qs, array<double,Nq> mean,
const size_t &loc) -> vector<
qarray<Nq> >
1144 vector<qarray<Nq> > out = qs;
1146 if (out.size() > Nqmax_input)
1151 VectorXd dist_q1(Nq);
1152 VectorXd dist_q2(Nq);
1153 for (size_t q=0; q<Nq; q++)
1155 if (Symmetry::kind()[q] == Sym::KIND::K)
1157 double Delta = 0.5*Symmetry::mod()[q];
1158 dist_q1(q) = min( posmod(q1[q]-Qtot[q],Symmetry::mod()[q]), posmod(Qtot[q]-q1[q],Symmetry::mod()[q]) ) / Delta;
1159 dist_q2(q) = min( posmod(q2[q]-Qtot[q],Symmetry::mod()[q]), posmod(Qtot[q]-q2[q],Symmetry::mod()[q]) ) / Delta;
1165 double Delta = QinTop[loc][q] - QinBot[loc][q];
1166 dist_q1(q) = (q1[q]-mean[q]) / Delta;
1167 dist_q2(q) = (q2[q]-mean[q]) / Delta;
1170 return (dist_q1.norm() < dist_q2.norm())?
true:
false;
1173 out.erase(out.begin()+Nqmax_input, out.end());
1179 vector<vector<qarray<Nq> > > Qin_trunc(this->N_sites+1);
1182 Qin_trunc[0].push_back(Symmetry::qvacuum());
1183 for (
size_t l=1; l<this->
N_sites; l++)
1185 auto new_qs = Symmetry::reduceSilent(Qin_trunc[l-1],
qloc[l-1],
true);
1192 assert(new_qs.size() > 0);
1193 array<double,Nq> mean;
1195 for (
size_t q=0; q<
Nq; q++)
1197 mean[q] =
static_cast<double>(
Qtot[q])*
static_cast<double>(l)/
static_cast<double>(this->
N_sites);
1203 auto candidates = take_first_elems(new_qs,mean,l);
1204 assert(candidates.size() > 0);
1205 for (
const auto &candidate:candidates)
1208 array<bool,Nq> WITHIN_RANGE;
1209 for (
size_t q=0; q<
Nq; ++q)
1212 WITHIN_RANGE[q] = (candidate[q] <=
QinTop[l][q] and candidate[q] >=
QinBot[l][q]);
1214 if (all_of(WITHIN_RANGE.begin(), WITHIN_RANGE.end(), [] (
bool x) {return x;}))
1216 Qin_trunc[l].push_back(candidate);
1220 assert(Qin_trunc[l].size() > 0);
1224 if constexpr (Nq == 0)
1232 for (
size_t l=0; l<this->
N_sites; ++l)
1233 for (
size_t s=0; s<
qloc[l].size(); ++s)
1235 for (
size_t q=0; q<Qin_trunc[l].size(); ++q)
1238 auto qouts = Symmetry::reduceSilent(
qloc[l][s],qin);
1239 for (
const auto &qout:qouts)
1241 auto it = find(Qin_trunc[l+1].begin(), Qin_trunc[l+1].end(), qout);
1242 if (it != Qin_trunc[l+1].end())
1244 std::array<qType,2> qinout = {qin,qout};
1245 if (
A[l][s].dict.find(qinout) ==
A[l][s].dict.end())
1247 A[l][s].in.push_back(qin);
1248 A[l][s].out.push_back(qout);
1249 A[l][s].dict.insert({qinout,
A[l][s].size()});
1256 A[l][s].block.resize(
A[l][s].size());
1262template<
typename Symmetry,
typename Scalar>
1266 this->N_sites = L_input;
1274 vector<vector<qarray<Nq> > > Qin(this->N_sites+1);
1275 Qin[0].push_back(Symmetry::qvacuum());
1277 for (
size_t l=1; l<this->
N_sites; l++)
1279 auto candidates = Symmetry::reduceSilent(Qin[l-1],
qloc[l-1],
true);
1280 assert(candidates.size() > 0);
1282 for (
const auto &candidate:candidates)
1284 array<bool,Nq> WITHIN_RANGE;
1285 for (
size_t q=0; q<
Nq; ++q)
1287 WITHIN_RANGE[q] = (candidate[q] <=
QinTop[l][q] and candidate[q] >=
QinBot[l][q]);
1289 if (all_of(WITHIN_RANGE.begin(), WITHIN_RANGE.end(), [] (
bool x) {return x;}))
1291 Qin[l].push_back(candidate);
1297 vector<vector<qarray<Nq> > > Qin_(this->N_sites+1);
1298 Qin_[0].push_back(Symmetry::qvacuum());
1301 for (
size_t l=this->N_sites-1; l>=1; l--)
1303 set<qarray<Nq> > invalids;
1305 for (
size_t q=0; q<Qin[l].size(); ++q)
1308 auto qouts = Symmetry::reduceSilent(
qloc[l],Qin[l][q]);
1309 for (
const auto &qout:qouts)
1311 if (find(Qin[l+1].begin(), Qin[l+1].end(), qout) != Qin[l+1].end())
1313 Qin_[l].push_back(Qin[l][q]);
1321 if constexpr (
Nq == 0)
1329 for (
size_t l=0; l<this->
N_sites; ++l)
1330 for (
size_t s=0; s<
qloc[l].size(); ++s)
1332 for (
size_t q=0; q<Qin[l].size(); ++q)
1335 auto qouts = Symmetry::reduceSilent(
qloc[l][s],qin);
1336 for (
const auto &qout:qouts)
1338 auto it = find(Qin[l+1].begin(), Qin[l+1].end(), qout);
1339 if (it != Qin[l+1].end())
1341 std::array<qType,2> qinout = {qin,qout};
1342 if (
A[l][s].dict.find(qinout) ==
A[l][s].dict.end())
1344 A[l][s].in.push_back(qin);
1345 A[l][s].out.push_back(qout);
1346 A[l][s].dict.insert({qinout,
A[l][s].size()});
1353 A[l][s].block.resize(
A[l][s].size());
1358template<
typename Symmetry,
typename Scalar>
1362 assert (
Nq == 0 and
"Must have Nq=0 to call outerResizeNoSymm!");
1366 for (
size_t l=0; l<this->
N_sites; ++l)
1368 for (
size_t s=0; s<
qloc[l].size(); ++s)
1370 A[l][s].in.push_back(Symmetry::qvacuum());
1371 A[l][s].out.push_back(Symmetry::qvacuum());
1372 A[l][s].dict.insert({
qarray2<Nq>{Symmetry::qvacuum(),Symmetry::qvacuum()},
A[l][s].dim});
1374 A[l][s].block.resize(1);
1379template<
typename Symmetry,
typename Scalar>
1383 if constexpr (
Nq == 0)
1385 size_t Ml =
qloc[0].size();
1386 size_t Mr =
qloc[this->N_sites-1].size();
1388 for (
size_t s=0; s<Ml; ++s)
1390 A[0][s].block[0].resize(1,min(Ml,Mmax));
1392 for (
size_t s=0; s<Mr; ++s)
1394 A[this->N_sites-1][s].block[0].resize(min(Mr,Mmax),1);
1397 for (
size_t l=1; l<this->N_sites/2; ++l)
1399 size_t Ml =
qloc[l].size();
1400 size_t Mr =
qloc[this->N_sites-l-1].size();
1402 size_t Nlrows = min(Mmax, (
size_t)
A[l-1][0].block[0].cols());
1403 size_t Nlcols = min(Mmax, Nlrows*Ml);
1405 size_t Nrcols = min(Mmax, (
size_t)
A[this->N_sites-l][0].block[0].rows());
1406 size_t Nrrows = min(Mmax, Nrcols*Mr);
1408 for (
size_t s=0; s<Ml; ++s)
1410 A[l][s].block[0].resize(Nlrows,Nlcols);
1412 for (
size_t s=0; s<Mr; ++s)
1414 A[this->N_sites-l-1][s].block[0].resize(Nrrows,Nrcols);
1419 if (this->N_sites%2==1)
1421 size_t centre = this->N_sites/2;
1422 int Nrows =
A[centre-1][0].block[0].cols();
1423 int Ncols =
A[centre+1][0].block[0].rows();
1425 for (
size_t s=0; s<
qloc[centre].size(); ++s)
1427 A[centre][s].block[0].resize(Nrows,Ncols);
1433 vector<map<qarray<Nq>,
size_t> > fromL(this->N_sites+1);
1434 vector<map<qarray<Nq>,
size_t> > fromR(this->N_sites+1);
1436 fromL[0].insert({Symmetry::qvacuum(),1});
1437 for (
size_t l=1; l<this->N_sites+1; ++l)
1439 assert(Mmax >=
outbase[l-1].
Nq() and
"Choose a greater Minit to have at least one state per QN block.");
1440 assert(
outbase[l-1].
Nq() != 0 and
"Probably failed to build correct quantum number graph!");
1441 size_t Dmax_in = Mmax /
outbase[l-1].Nq();
1442 size_t Dmax_in_remainder = Mmax%
outbase[l-1].Nq();
1443 for (
size_t qout=0; qout<
outbase[l-1].Nq(); ++qout)
1445 fromL[l].insert({
outbase[l-1][qout],0});
1446 for (
size_t s=0; s<
qloc[l-1].size(); ++s)
1447 for (
size_t q=0; q<
A[l-1][s].dim; ++q)
1449 if (
A[l-1][s].out[q] ==
outbase[l-1][qout])
1452 fromL[l][
outbase[l-1][qout]] += fromL[l-1][qin];
1455 if (
outbase[l-1][qout] == Symmetry::qvacuum())
1457 fromL[l][
outbase[l-1][qout]] = min(fromL[l][
outbase[l-1][qout]], Dmax_in+Dmax_in_remainder);
1461 fromL[l][
outbase[l-1][qout]] = min(fromL[l][
outbase[l-1][qout]], Dmax_in);
1476 for (
const auto &Qval:
Qmulti)
1478 fromR[this->
N_sites].insert({Qval,1});
1480 for (
size_t l=this->N_sites; l-->0;)
1482 assert(Mmax >=
inbase[l].
Nq() and
"Choose a greater Minit to have at least one state per QN block.");
1483 size_t Dmax_out = Mmax /
inbase[l].Nq();
1484 size_t Dmax_out_remainder = Mmax%
inbase[l].Nq();
1486 for (
size_t qin=0; qin<
inbase[l].Nq(); ++qin)
1488 fromR[l].insert({
inbase[l][qin],0});
1489 for (
size_t s=0; s<
qloc[l].size(); ++s)
1490 for (
size_t q=0; q<
A[l][s].dim; ++q)
1492 if (
A[l][s].in[q] ==
inbase[l][qin])
1495 fromR[l][
inbase[l][qin]] += fromR[l+1][qout];
1498 if (
inbase[l][qin] == Symmetry::qvacuum())
1500 fromR[l][
inbase[l][qin]] = min(fromR[l][
inbase[l][qin]], Dmax_out+Dmax_out_remainder);
1504 fromR[l][
inbase[l][qin]] = min(fromR[l][
inbase[l][qin]], Dmax_out);
1518 vector<map<qarray<Nq>,
size_t> > lrmin(this->N_sites+1);
1519 for (
size_t l=0; l<this->N_sites+1; ++l)
1521 for (
auto it=fromL[l].begin(); it!=fromL[l].end(); ++it)
1524 size_t Nql = it->second;
1525 size_t Nqr = fromR[l][Qout];
1526 lrmin[l].insert({Qout,min(Nql,Nqr)});
1530 for (
size_t l=0; l<this->
N_sites; ++l)
1532 size_t Dmax_out = Mmax /
outbase[l].Nq();
1533 size_t Dmax_out_remainder = Mmax%
outbase[l].Nq();
1534 size_t Dmax_in = Mmax /
inbase[l].Nq();
1535 size_t Dmax_in_remainder = Mmax%
inbase[l].Nq();
1536 for (
size_t s=0; s<
qloc[l].size(); ++s)
1537 for (
size_t q=0; q<
A[l][s].dim; ++q)
1541 size_t Drow_lim=0;
size_t Dcol_lim=0;
1542 if (Qin == Symmetry::qvacuum() and Qout == Symmetry::qvacuum())
1544 Drow_lim = Dmax_in+Dmax_in_remainder;
1545 Dcol_lim = Dmax_out+Dmax_out_remainder;
1547 else if (Qin == Symmetry::qvacuum() and Qout != Symmetry::qvacuum())
1549 Drow_lim = Dmax_in+Dmax_in_remainder;
1550 Dcol_lim = Dmax_out;
1552 else if (Qin != Symmetry::qvacuum() and Qout == Symmetry::qvacuum())
1555 Dcol_lim = Dmax_out+Dmax_out_remainder;
1560 Dcol_lim = Dmax_out;
1562 size_t Nrows = min(lrmin[l][Qin], Drow_lim);
1563 size_t Ncols = min(lrmin[l+1][Qout], Dcol_lim);
1564 A[l][s].block[q].resize(Nrows,Ncols);
1573template<
typename Symmetry,
typename Scalar>
1574template<
typename Hamiltonian>
1578 assert(H.length() == config.size());
1579 assert(!Symmetry::NON_ABELIAN);
1581 this->N_sites = config.size();
1583 qloc = H.locBasis();
1584 Qtot = accumulate(config.begin(),config.end(),Symmetry::qvacuum());
1590 vector<qarray<Nq> > qouts(this->N_sites+1);
1591 qouts[0] = Symmetry::qvacuum();
1592 for (
size_t l=0; l<this->
N_sites; ++l)
1594 qouts[l+1] = accumulate(config.begin(), config.begin()+l+1, Symmetry::qvacuum());
1597 for (
size_t l=0; l<this->
N_sites; ++l)
1599 for (
size_t s=0; s<
qloc[l].size(); ++s)
1602 qarray<Nq> qin = Symmetry::reduceSilent(qout, Symmetry::flip(
qloc[l][s]))[0];
1604 if (qin == qouts[l])
1606 std::array<qType,2> qinout = {qin,qout};
1607 if (
A[l][s].dict.find(qinout) ==
A[l][s].dict.end())
1609 A[l][s].in.push_back(qin);
1610 A[l][s].out.push_back(qout);
1611 A[l][s].dict.insert({qinout,
A[l][s].size()});
1615 A[l][s].block.resize(
A[l][s].size());
1622 for (
size_t l=0; l<this->
N_sites; ++l)
1628 for (
size_t l=0; l<this->
N_sites; ++l)
1629 for (
size_t s=0; s<
qloc[l].size(); ++s)
1630 for (
size_t q=0; q<
A[l][s].dim; ++q)
1632 A[l][s].block[q].resize(1,1);
1633 A[l][s].block[q].setConstant(1.);
1637template<
typename Symmetry,
typename Scalar>
1641 for (
size_t l=0; l<this->
N_sites; ++l)
1642 for (
size_t s=0; s<
qloc[l].size(); ++s)
1643 for (
size_t q=0; q<
A[l][s].dim; ++q)
1644 for (
size_t a1=0; a1<
A[l][s].block[q].rows(); ++a1)
1645 for (
size_t a2=0; a2<
A[l][s].block[q].cols(); ++a2)
1647 A[l][s].block[q](a1,a2) = threadSafeRandUniform<Scalar>(-1.,1.,
true);
1653template<
typename Symmetry,
typename Scalar>
1657 for (
size_t s=0; s<
qloc[loc].size(); ++s)
1658 for (
size_t q=0; q<
A[loc][s].dim; ++q)
1659 for (
size_t a1=0; a1<
A[loc][s].block[q].rows(); ++a1)
1660 for (
size_t a2=0; a2<
A[loc][s].block[q].cols(); ++a2)
1662 A[loc][s].block[q](a1,a2) = threadSafeRandUniform<Scalar>(-1.,1.,
true);
1666template<
typename Symmetry,
typename Scalar>
1670 for (
size_t l=0; l<this->
N_sites; ++l)
1671 for (
size_t s=0; s<
qloc[l].size(); ++s)
1672 for (
size_t q=0; q<
A[l][s].dim; ++q)
1674 A[l][s].block[q].setZero();
1678template<
typename Symmetry,
typename Scalar>
1694#ifdef USE_HDF5_STORAGE
1695template<
typename Symmetry,
typename Scalar>
1697save (
string filename,
string info,
double energy)
1701 std::string append_str =
".h5";
1702 size_t pos = filename.rfind(append_str);
1703 if (pos == std::string::npos || pos != filename.size() - append_str.size())
1705 filename += append_str;
1708 HDF5Interface target(filename, WRITE);
1709 target.create_group(
"mps");
1710 target.create_group(
"qloc");
1711 target.create_group(
"Qtot");
1712 target.create_group(
"Qmulti");
1714 string DmaxLabel =
"Dmax";
1715 string NqmaxLabel =
"Nqmax";
1716 string eps_svdLabel =
"eps_svd";
1717 string eps_truncWeightLabel =
"eps_truncWeightLabel";
1718 string alpha_rsvdLabel =
"alpha_rsvd";
1719 string add_infoLabel =
"add_info";
1724 target.save_scalar(energy,
"energy");
1726 target.save_scalar(this->N_sites,
"L");
1727 target.save_scalar(this->
N_phys,
"Nphys");
1728 for (
size_t q=0; q<
Nq; q++)
1730 stringstream ss; ss <<
"q=" << q;
1731 target.save_scalar(this->
Qtot[q],ss.str(),
"Qtot");
1733 target.save_scalar(
Qmulti.size(),
"QmultiSize");
1734 for (
size_t i=0; i<
Qmulti.size(); i++)
1735 for (
size_t q=0; q<
Nq; q++)
1737 stringstream ss; ss <<
"q=" << q <<
",i=" << i;
1738 target.save_scalar(this->Qmulti[i][q],ss.str(),
"Qmulti");
1740 target.save_scalar(this->
calc_Dmax(),DmaxLabel);
1741 target.save_scalar(this->
calc_Nqmax(),NqmaxLabel);
1742 target.save_scalar(this->
min_Nsv,
"min_Nsv");
1743 target.save_scalar(this->
max_Nsv,
"max_Nsv");
1744 target.save_scalar(this->
eps_svd,eps_svdLabel);
1745 target.save_scalar(this->eps_truncWeight,eps_truncWeightLabel);
1746 target.save_scalar(this->
alpha_rsvd,alpha_rsvdLabel);
1747 target.save_scalar(this->
get_pivot(),
"pivot");
1748 target.save_char(
info,add_infoLabel.c_str());
1751 for (
size_t l=0; l<this->
N_sites; ++l)
1753 stringstream ss; ss <<
"l=" << l;
1754 target.save_scalar(
qloc[l].size(),ss.str(),
"qloc");
1755 for (
size_t s=0; s<
qloc[l].size(); ++s)
1756 for (
size_t q=0; q<
Nq; q++)
1758 stringstream tt; tt <<
"l=" << l <<
",s=" << s <<
",q=" << q;
1759 target.save_scalar((
qloc[l][s])[q],tt.str(),
"qloc");
1765 for (
size_t l=0; l<this->
N_sites; ++l)
1766 for (
size_t s=0; s<
qloc[l].size(); ++s)
1768 stringstream tt; tt <<
"l=" << l <<
",s=" << s;
1769 target.save_scalar(
A[l][s].
dim,tt.str());
1770 for (
size_t q=0; q<
A[l][s].dim; ++q)
1772 for (
size_t p=0; p<
Nq; p++)
1774 stringstream in; in <<
"in,l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
1775 stringstream out; out <<
"out,l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
1776 target.save_scalar((
A[l][s].in[q])[p],in.str(),
"mps");
1777 target.save_scalar((
A[l][s].out[q])[p],out.str(),
"mps");
1780 ss << l <<
"_" << s <<
"_" <<
"(" <<
A[l][s].in[q] <<
"," <<
A[l][s].out[q] <<
")";
1782 if constexpr (std::is_same<Scalar,complex<double>>::value)
1784 MatrixXd Re =
A[l][s].block[q].real();
1785 MatrixXd Im =
A[l][s].block[q].imag();
1786 target.save_matrix(Re,label+
"Re",
"mps");
1787 target.save_matrix(Im,label+
"Im",
"mps");
1791 target.save_matrix(
A[l][s].block[q],label,
"mps");
1798template<
typename Symmetry,
typename Scalar>
1800load (
string filename,
double &energy)
1802 std::string append_str =
".h5";
1803 size_t pos = filename.rfind(append_str);
1804 if (pos == std::string::npos || pos != filename.size() - append_str.size())
1806 filename += append_str;
1808 HDF5Interface source(filename, READ);
1810 string eps_svdLabel =
"eps_svd";
1811 string eps_truncWeightLabel =
"eps_truncWeightLabel";
1812 string alpha_rsvdLabel =
"alpha_rsvd";
1816 if (source.CHECK(
"energy"))
1818 source.load_scalar(energy,
"energy");
1820 source.load_scalar(this->N_sites,
"L");
1821 source.load_scalar(this->
N_phys,
"Nphys");
1822 for (
size_t q=0; q<
Nq; q++)
1824 stringstream ss; ss <<
"q=" << q;
1825 source.load_scalar(this->
Qtot[q],ss.str(),
"Qtot");
1827 source.load_scalar(QmultiSize,
"QmultiSize");
1829 this->Qmulti.resize(QmultiSize);
1830 for (
size_t i=0; i<QmultiSize; i++)
1831 for (
size_t q=0; q<
Nq; q++)
1833 stringstream ss; ss <<
"q=" << q <<
",i=" << i;
1835 source.load_scalar(this->Qmulti[i][q],ss.str(),
"Qmulti");
1837 source.load_scalar(this->
eps_svd,eps_svdLabel);
1840 if (source.HAS_GROUP(eps_truncWeightLabel)) source.load_scalar(this->eps_truncWeight,eps_truncWeightLabel);
1841 source.load_scalar(this->
alpha_rsvd,alpha_rsvdLabel);
1842 source.load_scalar(this->pivot,
"pivot");
1843 source.load_scalar(this->
min_Nsv,
"min_Nsv");
1844 source.load_scalar(this->
max_Nsv,
"max_Nsv");
1847 qloc.resize(this->N_sites);
1848 for (
size_t l=0; l<this->
N_sites; ++l)
1850 stringstream ss; ss <<
"l=" << l;
1852 source.load_scalar(qloc_size,ss.str(),
"qloc");
1853 qloc[l].resize(qloc_size);
1854 for (
size_t s=0; s<
qloc[l].size(); ++s)
1855 for (
size_t q=0; q<
Nq; q++)
1857 stringstream tt; tt <<
"l=" << l <<
",s=" << s <<
",q=" << q;
1859 source.load_scalar(Q,tt.str(),
"qloc");
1860 (
qloc[l][s])[q] = Q;
1867 for (
size_t l=0; l<this->
N_sites; ++l)
1868 for (
size_t s=0; s<
qloc[l].size(); ++s)
1871 stringstream tt; tt <<
"l=" << l <<
",s=" << s;
1872 source.load_scalar(Asize,tt.str());
1873 for (
size_t q=0; q<Asize; ++q)
1876 for (
size_t p=0; p<
Nq; p++)
1878 stringstream in; in <<
"in,l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
1879 stringstream out; out <<
"out,l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
1880 source.load_scalar(qin[p],in.str(),
"mps");
1881 source.load_scalar(qout[p],out.str(),
"mps");
1884 ss << l <<
"_" << s <<
"_" <<
"(" << qin <<
"," << qout <<
")";
1887 if constexpr (std::is_same<Scalar,complex<double>>::value)
1890 source.load_matrix(Re, label+
"Re",
"mps");
1891 source.load_matrix(Im, label+
"Im",
"mps");
1896 source.load_matrix(mat, label,
"mps");
1898 A[l][s].push_back(qin,qout,mat);
1909template<
typename Symmetry,
typename Scalar>
1914 for (
size_t l=0; l<this->
N_sites; ++l)
1922template<
typename Symmetry,
typename Scalar>
1929template<
typename Symmetry,
typename Scalar>
1936template<
typename Symmetry,
typename Scalar>
1941 for (
size_t l=0; l<this->
N_sites; ++l)
1943 if (
inbase[l].fullM() > res) {res =
inbase[l].fullM();}
1949template<
typename Symmetry,
typename Scalar>
1954 for (
size_t l=0; l<this->
N_sites; ++l)
1962template<
typename Symmetry,
typename Scalar>
1967 for (
size_t l=0; l<this->
N_sites; ++l)
1975template<
typename Symmetry,
typename Scalar>
1980 for (
size_t l=0; l<this->
N_sites; ++l)
1987template<
typename Symmetry,
typename Scalar>
1992 inbase[loc].pullData(
A[loc],0);
1995template<
typename Symmetry,
typename Scalar>
2012template<
typename Symmetry,
typename Scalar>
2020 ArrayXd truncWeightSub(
inbase[loc].
Nq()); truncWeightSub.setZero();
2021 ArrayXd entropySub(
inbase[loc].
Nq()); entropySub.setZero();
2022 if (loc != 0) {
SVspec[loc-1].clear();}
2024 vector<Biped<Symmetry,MatrixType> > Aloc;
2025 Aloc.resize(
qloc[loc].size());
2026 vector<Biped<Symmetry,MatrixType> > Aprev;
2027 if (loc != 0 and DISCARD_U ==
false)
2029 Aprev.resize(
qloc[loc-1].size());
2035 bool RETURN_SPEC =
false;
2036 if (loc != 0) RETURN_SPEC =
true;
2039 map<qarray<Nq>,ArrayXd> SVspec_;
2055 auto [Q,R] = Aclump.adjoint().QR(
true);
2061 if (loc != 0 and DISCARD_U ==
false)
2063 for (
size_t s=0; s<
qloc[loc-1].size(); ++s)
2064 for (
size_t q=0; q<
A[loc-1][s].dim; ++q)
2067 auto itleft = left.
dict.find({
A[loc-1][s].out[q],
A[loc-1][s].out[q]});
2068 if (itleft != left.
dict.end())
2070 Mtmp =
A[loc-1][s].block[q] * left.
block[itleft->second];
2071 auto it = Aprev[s].dict.find(
qarray2<Nq>{
A[loc-1][s].in[q],
A[loc-1][s].out[q]});
2072 if (Mtmp.size() != 0)
2074 Aprev[s].try_push_back(
A[loc-1][s].in[q],
A[loc-1][s].out[q], Mtmp);
2247 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2249 A[loc][s] = Aloc[s].cleaned();
2251 if (loc != 0 and DISCARD_U ==
false)
2253 for (
size_t s=0; s<
qloc[loc-1].size(); ++s)
2255 A[loc-1][s] = Aprev[s].cleaned();
2260 if (loc != 0 and DISCARD_U ==
false)
2280 this->pivot = (loc==0)? 0 : loc-1;
2283template<
typename Symmetry,
typename Scalar>
2292 ArrayXd truncWeightSub(
outbase[loc].
Nq()); truncWeightSub.setZero();
2293 ArrayXd entropySub(
outbase[loc].
Nq()); entropySub.setZero();
2294 if (loc != this->N_sites-1) {
SVspec[loc].clear();}
2295 map<qarray<Nq>,ArrayXd> SVspec_;
2298 vector<Biped<Symmetry,MatrixType> > Aloc(
qloc[loc].size());
2299 vector<Biped<Symmetry,MatrixType> > Anext;
2300 if (loc != this->N_sites-1 and DISCARD_V ==
false)
2302 Anext.resize(
qloc[loc+1].size());
2311 if (loc != this->N_sites-1)
2321 auto [Q,R] = Aclump.QR();
2328 if (loc != this->N_sites-1 and DISCARD_V ==
false)
2330 for (
size_t s=0; s<
qloc[loc+1].size(); ++s)
2331 for (
size_t q=0; q<
A[loc+1][s].dim; ++q)
2334 auto itright = right.
dict.find({
A[loc+1][s].in[q],
A[loc+1][s].in[q]});
2335 if (itright != right.
dict.end())
2337 Mtmp = right.
block[itright->second] *
A[loc+1][s].block[q];
2338 auto it = Anext[s].dict.find(
qarray2<Nq>{
A[loc+1][s].in[q],
A[loc+1][s].out[q]});
2339 if (Mtmp.size() != 0)
2341 Anext[s].try_push_back(
A[loc+1][s].in[q],
A[loc+1][s].out[q], Mtmp);
2483 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2485 A[loc][s] = Aloc[s].cleaned();
2487 if (loc != this->N_sites-1 and DISCARD_V ==
false)
2489 for (
size_t s=0; s<
qloc[loc+1].size(); ++s)
2491 A[loc+1][s] = Anext[s].cleaned();
2496 if (loc != this->N_sites-1 and DISCARD_V ==
false)
2516 this->pivot = (loc==this->N_sites-1)? this->N_sites-1 : loc+1;
2519template<
typename Symmetry,
typename Scalar>
2524 N.resize(
qloc[loc].size());
2528 for (
size_t qin=0; qin<
inbase[loc].Nq(); ++qin)
2531 vector<size_t> svec, qvec, Ncolsvec;
2532 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2533 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2535 if (
A[loc][s].in[q] ==
inbase[loc][qin])
2539 Ncolsvec.push_back(
A[loc][s].block[q].cols());
2543 if (Ncolsvec.size() > 0)
2546 size_t Nrows =
A[loc][svec[0]].block[qvec[0]].rows();
2547 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[loc][svec[i]].block[qvec[i]].rows() == Nrows);}
2548 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
2552 for (
size_t i=0; i<svec.size(); ++i)
2554 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) =
A[loc][svec[i]].block[qvec[i]]*
2555 Symmetry::coeff_leftSweep(
2556 A[loc][svec[i]].out[qvec[i]],
2557 A[loc][svec[i]].in[qvec[i]]);
2558 stitch += Ncolsvec[i];
2561 HouseholderQR<MatrixType> Quirinus(Aclump.adjoint());
2562 MatrixType Qmatrix = Quirinus.householderQ().adjoint();
2563 size_t Nret = Nrows;
2567 for (
size_t i=0; i<svec.size(); ++i)
2569 if (Qmatrix.rows() > Nret)
2571 size_t Nnull = Qmatrix.rows()-Nret;
2572 MatrixType Mtmp = Qmatrix.block(Nret,stitch, Nnull,Ncolsvec[i])*
2573 Symmetry::coeff_leftSweep(
2574 A[loc][svec[i]].in[qvec[i]],
2575 A[loc][svec[i]].out[qvec[i]]);
2576 N[svec[i]].try_push_back(
A[loc][svec[i]].in[qvec[i]],
A[loc][svec[i]].out[qvec[i]], Mtmp);
2578 stitch += Ncolsvec[i];
2585 for (
size_t qout=0; qout<
outbase[loc].Nq(); ++qout)
2588 vector<size_t> svec, qvec, Nrowsvec;
2589 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2590 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2592 if (
A[loc][s].out[q] ==
outbase[loc][qout])
2596 Nrowsvec.push_back(
A[loc][s].block[q].rows());
2600 if (Nrowsvec.size() > 0)
2603 size_t Ncols =
A[loc][svec[0]].block[qvec[0]].cols();
2604 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[loc][svec[i]].block[qvec[i]].cols() == Ncols);}
2605 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
2610 for (
size_t i=0; i<svec.size(); ++i)
2612 Aclump.block(stitch,0, Nrowsvec[i],Ncols) =
A[loc][svec[i]].block[qvec[i]];
2613 stitch += Nrowsvec[i];
2616 HouseholderQR<MatrixType> Quirinus(Aclump);
2617 MatrixType Qmatrix = Quirinus.householderQ();
2618 size_t Nret = Ncols;
2622 for (
size_t i=0; i<svec.size(); ++i)
2624 if (Qmatrix.cols() > Nret)
2626 size_t Nnull = Qmatrix.cols()-Nret;
2628 MatrixType Mtmp = Qmatrix.block(stitch,Nret, Nrowsvec[i],Nnull);
2629 N[svec[i]].try_push_back(
A[loc][svec[i]].in[qvec[i]],
A[loc][svec[i]].out[qvec[i]], Mtmp);
2631 stitch += Nrowsvec[i];
2638template<
typename Symmetry,
typename Scalar>
2645 for (
size_t qin=0; qin<
inbase[loc].Nq(); ++qin)
2648 vector<size_t> svec, qvec, Ncolsvec;
2649 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2650 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2652 if (
A[loc][s].in[q] ==
inbase[loc][qin])
2656 Ncolsvec.push_back(
A[loc][s].block[q].cols());
2660 if (svec.size() > 0)
2663 size_t Nrows =
A[loc][svec[0]].block[qvec[0]].rows();
2664 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[loc][svec[i]].block[qvec[i]].rows() == Nrows);}
2665 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
2669 for (
size_t i=0; i<svec.size(); ++i)
2671 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) =
A[loc][svec[i]].block[qvec[i]] *
2672 Symmetry::coeff_leftSweep(
A[loc][svec[i]].out[qvec[i]],
2673 A[loc][svec[i]].in[qvec[i]]);
2674 stitch += Ncolsvec[i];
2677 HouseholderQR<MatrixType> Quirinus;
MatrixType Qmatrix, Rmatrix;
2679 Quirinus.compute(Aclump.adjoint());
2680 Qmatrix = (Quirinus.householderQ() * MatrixType::Identity(Aclump.cols(),Aclump.rows())).adjoint();
2681 Rmatrix = (MatrixType::Identity(Aclump.rows(),Aclump.cols()) * Quirinus.matrixQR().template triangularView<Upper>()).adjoint();
2685 for (
size_t i=0; i<svec.size(); ++i)
2687 A[loc][svec[i]].block[qvec[i]] = Qmatrix.block(0,stitch, Nrows,Ncolsvec[i])*
2688 Symmetry::coeff_leftSweep(
A[loc][svec[i]].in[qvec[i]],
2689 A[loc][svec[i]].out[qvec[i]]);
2690 stitch += Ncolsvec[i];
2695 auto qC = C.
dict.find(quple);
2697 if (qC != C.
dict.end())
2699 C.
block[qC->second] += Rmatrix;
2708 this->pivot = (loc==0)? 0 : loc-1;
2711template<
typename Symmetry,
typename Scalar>
2718 for (
size_t qout=0; qout<
outbase[loc].Nq(); ++qout)
2721 vector<size_t> svec, qvec, Nrowsvec;
2722 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2723 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2725 if (
A[loc][s].out[q] ==
outbase[loc][qout])
2729 Nrowsvec.push_back(
A[loc][s].block[q].rows());
2733 if (svec.size() > 0)
2736 size_t Ncols =
A[loc][svec[0]].block[qvec[0]].cols();
2737 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[loc][svec[i]].block[qvec[i]].cols() == Ncols);}
2738 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
2743 for (
size_t i=0; i<svec.size(); ++i)
2745 Aclump.block(stitch,0, Nrowsvec[i],Ncols) =
A[loc][svec[i]].block[qvec[i]];
2746 stitch += Nrowsvec[i];
2749 HouseholderQR<MatrixType> Quirinus;
MatrixType Qmatrix, Rmatrix;
2751 Quirinus.compute(Aclump);
2752 Qmatrix = Quirinus.householderQ() * MatrixType::Identity(Aclump.rows(),Aclump.cols());
2753 Rmatrix = MatrixType::Identity(Aclump.cols(),Aclump.rows()) * Quirinus.matrixQR().template triangularView<Upper>();
2757 for (
size_t i=0; i<svec.size(); ++i)
2759 A[loc][svec[i]].block[qvec[i]] = Qmatrix.block(stitch,0, Nrowsvec[i],Ncols);
2760 stitch += Nrowsvec[i];
2765 auto qC = C.
dict.find(quple);
2767 if (qC != C.
dict.end())
2769 C.
block[qC->second] += Rmatrix;
2778 this->pivot = (loc==this->N_sites-1)? this->N_sites-1 : loc+1;
2781template<
typename Symmetry,
typename Scalar>
2785 for (
size_t qC=0; qC<C.
dim; ++qC)
2789 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2790 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2792 if (
A[loc][s].in[q] == C.
out[qC])
2794 A[loc][s].block[q] = C.
block[qC] *
A[loc][s].block[q];
2800 for (
size_t s=0; s<
qloc[loc].size(); ++s)
2801 for (
size_t q=0; q<
A[loc][s].dim; ++q)
2803 if (
A[loc][s].out[q] == C.
in[qC])
2805 A[loc][s].block[q] =
A[loc][s].block[q] * C.
block[qC];
2812template<
typename Symmetry,
typename Scalar>
2818 map<qarray<Nq>,ArrayXd> SV;
2822 auto combined_basis = qloc_l.
combine(qloc_r);
2841 this->pivot = (loc==this->N_sites-1)? this->N_sites-1 : loc+1;
2845 this->pivot = (loc==0)? 0 : loc;
2849 int bond = (loc==this->N_sites-1)? -1 : loc;
2858 int bond = (loc==0)? -1 : loc;
3179template<
typename Symmetry,
typename Scalar>
3183 if (this->
alpha_rsvd > mynumeric_limits<Scalar>::epsilon())
3185 std::vector<Biped<Symmetry,MatrixType> > P(
qloc[loc].size());
3299 vector<vector<Biped<Symmetry,MatrixType> > > Pt(H->
Terms.size());
3300 for (
size_t t=0; t<H->
Terms.size(); ++t)
3302 Pt[t].resize(
qloc[loc].size());
3305 for (
size_t t=0; t<H->
Terms.size(); ++t)
3309 auto QbasisP =
inbase[loc].combine(QbasisW);
3311 for (
size_t s1=0; s1<
qloc[loc].size(); ++s1)
3312 for (
size_t s2=0; s2<
qloc[loc].size(); ++s2)
3313 for (
size_t k=0; k<H->
Terms[t].qOp.size(); ++k)
3315 if (H->
Terms[t].W[s1][s2][k].size() == 0) {
continue;}
3316 for (
size_t qR=0; qR<H->
Terms[t].R.size(); ++qR)
3318 auto qAs = Symmetry::reduceSilent(H->
Terms[t].R.in(qR),Symmetry::flip(
qloc[loc][s2]));
3319 for (
const auto& qA : qAs)
3322 auto itA =
A[loc][s2].dict.find(quple1);
3324 if (itA !=
A[loc][s2].dict.end())
3326 auto qWs = Symmetry::reduceSilent(H->
Terms[t].R.mid(qR), Symmetry::flip(H->
Terms[t].qOp[k]));
3328 for (
const auto& qW : qWs)
3330 auto qPs = Symmetry::reduceSilent(qA,qW);
3332 for (
const auto& qP : qPs)
3336 Scalar factor_cgc = Symmetry::coeff_HPsi(
A[loc][s2].in[itA->second],
qloc[loc][s2],
A[loc][s2].out[itA->second],
3337 qW, H->
Terms[t].qOp[k], H->
Terms[t].R.mid(qR),
3338 qP,
qloc[loc][s1], H->
Terms[t].R.out(qR));
3340 if (std::abs(factor_cgc) < std::abs(mynumeric_limits<Scalar>::epsilon())) {
continue;}
3342 auto dict_entry = H->
Terms[t].W[s1][s2][k].dict.find({qW,H->
Terms[t].R.mid(qR)});
3343 if(dict_entry == H->
Terms[t].W[s1][s2][k].dict.end())
continue;
3344 for (
int spInd=0; spInd<H->
Terms[t].W[s1][s2][k].block[dict_entry->second].outerSize(); ++spInd)
3345 for (
typename SparseMatrix<Scalar>::InnerIterator iW(H->
Terms[t].W[s1][s2][k].block[dict_entry->second],spInd); iW; ++iW)
3347 size_t a = iW.row();
3348 size_t b = iW.col();
3349 size_t Prows = QbasisP.inner_dim(qP);
3350 if(Prows==0) {
continue;}
3351 size_t Pcols = H->
Terms[t].R.block[qR][b][0].cols();
3352 if(Pcols==0) {
continue;}
3353 size_t Arows =
A[loc][s2].block[itA->second].rows();
3354 size_t stitch = QbasisP.leftAmount(qP,{qA,qW});
3359 if (stitch >= Prows) {
continue;}
3360 if (H->
Terms[t].R.block[qR][b][0].size() != 0)
3362 Mtmp.block(stitch + a*Arows,0, Arows,Pcols) += (this->
alpha_rsvd *
3365 A[loc][s2].block[itA->second] *
3366 H->
Terms[t].R.block[qR][b][0];
3369 int Nret = (this->
max_Nrich<0)? Mtmp.rows():
3370 min(
static_cast<int>(Mtmp.rows()), this->max_Nrich);
3372 if( Nret < Mtmp.rows() ) { Mtmp = Mtmp.topRows(Nret).eval(); }
3373 if (Mtmp.size() != 0)
3376 auto it = Pt[t][s1].dict.find(qupleP);
3377 if (it != Pt[t][s1].dict.end())
3379 if (Pt[t][s1].block[it->second].rows() == 0)
3381 Pt[t][s1].block[it->second] = Mtmp;
3385 Pt[t][s1].block[it->second] += Mtmp;
3390 Pt[t][s1].push_back(qupleP, Mtmp);
3402 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3407 for (
size_t t=1; t<H->
Terms.size(); ++t)
3408 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3410 P[s].addScale_extend(1.,Pt[t][s]);
3413 if (H->
Terms.size() > 0)
for (
size_t s=0; s<
qloc[loc].size(); ++s) P[s] = P[s].cleaned();
3416 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3417 for (
size_t qP=0; qP<P[s].size(); ++qP)
3420 auto qA =
A[loc][s].dict.find(quple);
3422 if (qA !=
A[loc][s].dict.end())
3424 addBottom(P[s].block[qP],
A[loc][s].block[qA->second]);
3428 if (
inbase[loc].find(P[s].in[qP]))
3430 MatrixType Mtmp(
inbase[loc].inner_dim(P[s].in[qP]), P[s].block[qP].cols());
3433 A[loc][s].push_back(quple, Mtmp);
3439 bool BLOCK_INSERTED_AT_LOC =
false;
3441 for (
size_t qin=0; qin<
inbase[loc-1].Nq(); ++qin)
3442 for (
size_t sprev=0; sprev<
qloc[loc-1].size(); ++sprev)
3444 auto qCandidates = Symmetry::reduceSilent(
inbase[loc-1][qin],
qloc[loc-1][sprev]);
3445 auto it = find(qCandidates.begin(), qCandidates.end(), P[s].in[qP]);
3447 if (it != qCandidates.end())
3449 if (!BLOCK_INSERTED_AT_LOC)
3451 A[loc][s].push_back(quple, P[s].block[qP]);
3452 BLOCK_INSERTED_AT_LOC =
true;
3456 A[loc-1][sprev].try_push_back(
inbase[loc-1][qin], P[s].in[qP], Mtmp);
3462 if (P[s].in[qP] == Symmetry::qvacuum())
3464 A[loc][s].push_back(quple, P[s].block[qP]);
3473 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3474 for (
size_t qA=0; qA<
A[loc][s].dim; ++qA)
3475 for (
size_t sprev=0; sprev<
qloc[loc-1].size(); ++sprev)
3476 for (
size_t qAprev=0; qAprev<
A[loc-1][sprev].size(); ++qAprev)
3478 if (
A[loc-1][sprev].out[qAprev] ==
A[loc][s].in[qA] and
3479 A[loc-1][sprev].block[qAprev].cols() !=
A[loc][s].block[qA].rows())
3481 size_t rows =
A[loc-1][sprev].block[qAprev].rows();
3482 size_t cols =
A[loc-1][sprev].block[qAprev].cols();
3483 int dcols =
A[loc][s].block[qA].rows()-cols;
3485 A[loc-1][sprev].block[qAprev].conservativeResize(rows, cols+dcols);
3489 A[loc-1][sprev].block[qAprev].rightCols(dcols).setZero();
3503template<
typename Symmetry,
typename Scalar>
3507 if (this->
alpha_rsvd > mynumeric_limits<Scalar>::epsilon())
3509 std::vector<Biped<Symmetry,MatrixType> > P(
qloc[loc].size());
3626 vector<vector<Biped<Symmetry,MatrixType> > > Pt(H->
Terms.size());
3627 for (
size_t t=0; t<H->
Terms.size(); ++t) Pt[t].resize(
qloc[loc].size());
3629 #ifndef DMRG_DONT_USE_OPENMP
3630 #pragma omp parallel for
3632 for (
size_t t=0; t<H->
Terms.size(); ++t)
3636 auto QbasisP =
outbase[loc].combine(QbasisW);
3638 for (
size_t s1=0; s1<
qloc[loc].size(); ++s1)
3639 for (
size_t s2=0; s2<
qloc[loc].size(); ++s2)
3640 for (
size_t k=0; k<H->
Terms[t].qOp.size(); ++k)
3642 if (H->
Terms[t].W[s1][s2][k].size() == 0) {
continue;}
3643 for (
size_t qL=0; qL<H->
Terms[t].L.size(); ++qL)
3645 auto qAs = Symmetry::reduceSilent(H->
Terms[t].L.out(qL),
qloc[loc][s2]);
3646 for (
const auto& qA : qAs)
3649 auto itA =
A[loc][s2].dict.find(quple1);
3651 if (itA !=
A[loc][s2].dict.end())
3653 auto qWs = Symmetry::reduceSilent(H->
Terms[t].L.mid(qL), H->
Terms[t].qOp[k]);
3655 for (
const auto& qW : qWs)
3657 auto qPs = Symmetry::reduceSilent(qA,qW);
3659 for (
const auto& qP : qPs)
3663 Scalar factor_cgc = Symmetry::coeff_HPsi(
A[loc][s2].in[itA->second],
qloc[loc][s2],
A[loc][s2].out[itA->second],
3664 H->
Terms[t].L.mid(qL), H->
Terms[t].qOp[k], qW,
3665 H->
Terms[t].L.in(qL),
qloc[loc][s1], qP);
3667 if (std::abs(factor_cgc) < std::abs(mynumeric_limits<Scalar>::epsilon())) {
continue;}
3669 auto dict_entry = H->
Terms[t].W[s1][s2][k].dict.find({H->
Terms[t].L.mid(qL),qW});
3670 if(dict_entry == H->
Terms[t].W[s1][s2][k].dict.end())
continue;
3671 for (
int spInd=0; spInd<H->
Terms[t].W[s1][s2][k].block[dict_entry->second].outerSize(); ++spInd)
3672 for (
typename SparseMatrix<Scalar>::InnerIterator iW(H->
Terms[t].W[s1][s2][k].block[dict_entry->second],spInd); iW; ++iW)
3674 size_t a = iW.row();
3675 size_t b = iW.col();
3677 size_t Prows = H->
Terms[t].L.block[qL][a][0].rows();
3678 if(Prows==0) {
continue; }
3679 size_t Pcols = QbasisP.inner_dim(qP);
3680 if(Pcols==0) {
continue; }
3681 size_t Acols =
A[loc][s2].block[itA->second].cols();
3682 size_t stitch = QbasisP.leftAmount(qP,{qA,qW});
3687 if (stitch >= Pcols) {
continue;}
3688 if (H->
Terms[t].L.block[qL][a][0].rows() != 0 and
3689 H->
Terms[t].L.block[qL][a][0].cols() != 0)
3691 Mtmp.block(0,stitch+b*Acols, Prows,Acols) += (this->
alpha_rsvd *
3694 H->
Terms[t].L.block[qL][a][0] *
3695 A[loc][s2].block[itA->second];
3698 int Nret = (this->
max_Nrich<0)? Mtmp.cols():
3699 min(
static_cast<int>(Mtmp.cols()), this->max_Nrich);
3701 if( Nret < Mtmp.cols() ) { Mtmp = Mtmp.leftCols(Nret).eval(); }
3703 if (Mtmp.size() != 0)
3706 auto it = Pt[t][s1].dict.find(qupleP);
3707 if (it != Pt[t][s1].dict.end())
3709 if (Pt[t][s1].block[it->second].rows() == 0)
3711 Pt[t][s1].block[it->second] = Mtmp;
3715 Pt[t][s1].block[it->second] += Mtmp;
3720 Pt[t][s1].push_back(qupleP, Mtmp);
3732 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3737 for (
size_t t=1; t<H->
Terms.size(); ++t)
3738 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3740 P[s].addScale_extend(1.,Pt[t][s]);
3743 if (H->
Terms.size() > 0)
for (
size_t s=0; s<
qloc[loc].size(); ++s) P[s] = P[s].cleaned();
3746 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3747 for (
size_t qP=0; qP<P[s].size(); ++qP)
3750 auto qA =
A[loc][s].dict.find(quple);
3752 if (qA !=
A[loc][s].dict.end())
3754 addRight(P[s].block[qP],
A[loc][s].block[qA->second]);
3758 if (
outbase[loc].find(P[s].out[qP]))
3763 A[loc][s].push_back(quple, Mtmp);
3767 if (loc != this->N_sites-1)
3769 bool BLOCK_INSERTED_AT_LOC =
false;
3771 for (
size_t qout=0; qout<
outbase[loc+1].Nq(); ++qout)
3772 for (
size_t snext=0; snext<
qloc[loc+1].size(); ++snext)
3774 auto qCandidates = Symmetry::reduceSilent(
outbase[loc+1][qout], Symmetry::flip(
qloc[loc+1][snext]));
3775 auto it = find(qCandidates.begin(), qCandidates.end(), P[s].out[qP]);
3777 if (it != qCandidates.end())
3779 if (!BLOCK_INSERTED_AT_LOC)
3781 A[loc][s].push_back(quple, P[s].block[qP]);
3782 BLOCK_INSERTED_AT_LOC =
true;
3786 A[loc+1][snext].try_push_back(P[s].out[qP],
outbase[loc+1][qout], Mtmp);
3792 if (P[s].out[qP] ==
Qtarget())
3794 A[loc][s].push_back(quple, P[s].block[qP]);
3801 if (loc != this->N_sites-1)
3803 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3804 for (
size_t qA=0; qA<
A[loc][s].size(); ++qA)
3805 for (
size_t snext=0; snext<
qloc[loc+1].size(); ++snext)
3806 for (
size_t qAnext=0; qAnext<
A[loc+1][snext].size(); ++qAnext)
3808 if (
A[loc+1][snext].in[qAnext] ==
A[loc][s].out[qA] and
3809 A[loc+1][snext].block[qAnext].rows() !=
A[loc][s].block[qA].cols())
3811 size_t rows =
A[loc+1][snext].block[qAnext].rows();
3812 size_t cols =
A[loc+1][snext].block[qAnext].cols();
3813 int drows =
A[loc][s].block[qA].cols()-rows;
3815 A[loc+1][snext].block[qAnext].conservativeResize(rows+drows, cols);
3818 A[loc+1][snext].block[qAnext].bottomRows(drows).setZero();
3825 if (loc != this->N_sites-1)
3832template<
typename Symmetry,
typename Scalar>
3838 lout <<
"calculating <φ|ψ> with different quantum numbers, " <<
"bra: " <<
Qtot <<
", ket:" << Vket.
Qtarget() << endl;
3846 for (
size_t l=0; l<this->
N_sites; ++l)
3859template<
typename Symmetry,
typename Scalar>
3860template<
typename MpoScalar>
3865 assert(this->pivot != -1 and
"This function can only compute averages for Mps in mixed canonical form. Use avg() instead.");
3868 size_t loc1 = this->
pivot;
3869 size_t loc2 = this->pivot+distance;
3879 for (
size_t l=loc1; l<loc1+distance+1; ++l)
3892template<
typename Symmetry,
typename Scalar>
3898 if (this->pivot != -1)
3901 for (
size_t s=0; s<
qloc[this->
pivot].size(); s++)
3902 for (
size_t q=0; q<
A[this->
pivot][s].dim; ++q)
3904 res +=
isReal((
A[this->pivot][s].block[q].adjoint() *
A[this->pivot][s].block[q]).trace()) * Symmetry::coeff_dot(
A[this->pivot][s].out[q]);
3917template<
typename Symmetry,
typename Scalar>
3932 std::swap(this->pivot, V.
pivot);
3933 std::swap(this->N_sites, V.
N_sites);
3940 std::swap(this->
S, V.
S);
3942 for (
size_t l=0; l<this->
N_sites; ++l)
3943 for (
size_t s=0; s<
qloc[l].size(); ++s)
3945 A[l][s].in.swap(V.
A[l][s].in);
3946 A[l][s].out.swap(V.
A[l][s].out);
3947 A[l][s].dict.swap(V.
A[l][s].dict);
3948 std::swap(
A[l][s].
dim, V.
A[l][s].dim);
3950 for (
size_t q=0; q<
A[l][s].dim; ++q)
3952 A[l][s].block[q].swap(V.
A[l][s].block[q]);
3957template<
typename Symmetry,
typename Scalar>
3967template<
typename Symmetry,
typename Scalar>
3968template<
typename OtherScalar>
3973 int loc = (this->pivot == -1)? 0 : this->pivot;
3974 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3975 for (
size_t q=0; q<
A[loc][s].dim; ++q)
3977 A[loc][s].block[q] *= alpha;
3982template<
typename Symmetry,
typename Scalar>
3983template<
typename OtherScalar>
3988 int loc = (this->pivot == -1)? 0 : this->pivot;
3989 for (
size_t s=0; s<
qloc[loc].size(); ++s)
3990 for (
size_t q=0; q<
A[loc][s].dim; ++q)
3992 A[loc][s].block[q] /= alpha;
3997template<
typename Symmetry,
typename Scalar,
typename OtherScalar>
4005template<
typename Symmetry,
typename Scalar,
typename OtherScalar>
4013template<
typename Symmetry,
typename Scalar>
4017 assert(l < this->
N_sites-1 and
"Can not apply a gate because l is too large.");
4018 assert(
qloc[l] == gate.
leftBasis().qloc() and
"Mismatching basis at left site from gate.");
4019 assert(
qloc[l+1] == gate.
rightBasis().qloc() and
"Mismatching basis at right site from gate.");
4026 auto qmid = locBasis_m.qs();
4029 vector<Biped<Symmetry,MatrixType> > Apair(locBasis_m.size());
4030 for (
size_t s1=0; s1<
qloc[l].size(); s1++)
4031 for (
size_t s2=0; s2<
qloc[l+1].size(); s2++)
4032 for (
size_t k=0; k<qmid.size(); k++)
4033 for (
size_t s1p=0; s1p<
qloc[l].size(); s1p++)
4034 for (
size_t s2p=0; s2p<
qloc[l+1].size(); s2p++)
4038 if (gate.
data[s1][s2][s1p][s2p][k] == 0.) {
continue;}
4039 for (
size_t ql=0; ql<
A[l][s1p].size(); ql++)
4041 typename Symmetry::qType qm =
A[l][s1p].out[ql];
4042 auto qrs = Symmetry::reduceSilent(qm,
qloc[l+1][s2p]);
4043 for (
const auto &qr : qrs)
4045 auto it_qr =
A[l+1][s2p].dict.find({qm,qr});
4046 if ( it_qr ==
A[l+1][s2p].dict.end()) {
continue;}
4047 MatrixType Mtmp(
A[l][s1p].block[ql].rows(),
A[l+1][s2p].block[it_qr->second].cols());
4048 Scalar factor_cgc = Symmetry::coeff_twoSiteGate(
A[l][s1p].in[ql],
qloc[l][s1p], qm,
4049 qloc[l+1][s2p] , qr , qmid[k]);
4050 if (abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue;}
4055 Mtmp = factor_cgc * gate.
data[s1][s2][s1p][s2p][k] *
A[l][s1p].block[ql] *
A[l+1][s2p].block[it_qr->second];
4056 size_t s1s2 = locBasis_m.outer_num(qmid[k]) + locBasis_m.leftAmount(qmid[k],{
qloc[l][s1],
qloc[l+1][s2]}) + locBasis_l.inner_num(s1) + locBasis_r.inner_num(s2)*locBasis_l.inner_dim(
qloc[l][s1]);
4057 auto it_pair = Apair[s1s2].dict.find({
A[l][s1p].in[ql],qr});
4058 if (it_pair == Apair[s1s2].dict.end())
4060 Apair[s1s2].push_back(
A[l][s1p].in[ql],qr,Mtmp);
4064 Apair[s1s2].block[it_pair->second] += Mtmp;
4072 double trunc, Sdumb;
4073 map<qarray<Nq>,ArrayXd> SV_dumb;
4074 split_AA2(DIR, locBasis_m, Apair,
qloc[l],
A[l],
qloc[l+1],
A[l+1],
QoutTop[l],
QoutBot[l], Cdumb,
false, trunc, Sdumb, SV_dumb, this->eps_truncWeight, this->
min_Nsv, this->
max_Nsv);
4081template<
typename Symmetry,
typename Scalar>
4082template<
typename OtherScalar>
4089 for (
size_t l=0; l<this->
N_sites; ++l)
4090 for (
size_t s=0; s<
qloc[l].size(); ++s)
4091 for (
size_t q=0; q<
A[l][s].dim; ++q)
4093 Vout.
A[l][s].block[q] =
A[l][s].block[q].template cast<OtherScalar>();
4124template<
typename Symmetry,
typename Scalar>
4132template<
typename Symmetry,
typename Scalar>
4140template<
typename Symmetry,
typename Scalar>
4141template<
typename OtherScalar>
4179 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4181 A[loc][s].addScale(alpha, Vin.
A[loc][s],
RIGHT);
4184 else if (loc == this->N_sites-1)
4186 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4188 A[loc][s].addScale(
static_cast<OtherScalar
>(1.), Vin.
A[loc][s],
BOTTOM);
4193 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4195 A[loc][s].addScale(
static_cast<OtherScalar
>(1.), Vin.
A[loc][s],
BOTTOM_RIGHT);
4200template<
typename Symmetry,
typename Scalar>
4201template<
typename OtherScalar>
4206 "Mismatched quantum numbers in addition of Mps!");
4221 for (
size_t l=2; l<this->
N_sites; ++l)
4269template<
typename Symmetry,
typename Scalar>
4273 lout << termcolor::red <<
"set_A_from_C is highly deprecated!" << termcolor::reset << endl;
4274 if (loc == this->N_sites-1)
4276 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4277 for (
size_t q=0; q<C[s].
dim; ++q)
4280 C[s].
out(q)+C[s].mid(q)};
4281 auto qA =
A[this->N_sites-1][s].dict.find(cmpA);
4283 if (qA !=
A[this->N_sites-1][s].dict.end())
4286 size_t w=0;
while (C[s].block[q][w][0].rows() == 0) {++w;}
4287 A[this->N_sites-1][s].block[qA->second] = C[s].
block[q][w][0];
4293 vector<vector<MatrixType> > Omega(
qloc[loc].size());
4294 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4296 Omega[s].resize(C[s].
dim);
4297 for (
size_t q=0; q<C[s].
dim; ++q)
4299 size_t r=0;
while (C[s].block[q][r][0].rows()==0 or C[s].block[q][r][0].cols()==0) {++r;}
4300 typename MatrixType::Index Crows = C[s].
block[q][r][0].rows();
4301 typename MatrixType::Index Ccols = C[s].
block[q][r][0].cols();
4303 for (
size_t w=0; w<C[s].
block[q].size(); ++w)
4305 if (C[s].block[q][w][0].rows() != 0)
4307 addRight(C[s].block[q][w][0], Omega[s][q]);
4319 ArrayXd truncWeightSub(
outbase[loc].
Nq());
4320 truncWeightSub.setZero();
4325 for (
size_t qout=0; qout<
outbase[loc].Nq(); ++qout)
4327 map<tuple<size_t,size_t,size_t>,vector<size_t> > sqmap;
4328 for (
size_t s=0; s<
qloc[loc].size(); ++s)
4329 for (
size_t q=0; q<C[s].
dim; ++q)
4332 auto qA =
A[loc][s].dict.find(cmpA);
4334 if (C[s].mid(q)+C[s].out(q) ==
outbase[loc][qout])
4337 tuple<size_t,size_t,size_t> key = make_tuple(s, qA->second, Omega[s][q].rows());
4338 sqmap[key].push_back(q);
4342 vector<size_t> svec;
4343 vector<size_t> qAvec;
4344 vector<size_t> Nrowsvec;
4345 vector<vector<size_t> > qmidvec;
4346 for (
auto it=sqmap.begin(); it!=sqmap.end(); ++it)
4348 svec.push_back(get<0>(it->first));
4349 qAvec.push_back(get<1>(it->first));
4350 Nrowsvec.push_back(get<2>(it->first));
4351 qmidvec.push_back(it->second);
4354 if (Nrowsvec.size() != 0)
4356 size_t Nrows = accumulate(Nrowsvec.begin(), Nrowsvec.end(), 0);
4358 vector<vector<size_t> > Ncolsvec(qmidvec.size());
4359 for (
size_t i=0; i<qmidvec.size(); ++i)
4362 for (
size_t j=0; j<qmidvec[i].size(); ++j)
4364 size_t q = qmidvec[i][j];
4365 Ncolsvec[i].push_back(Omega[s][q].cols());
4369 size_t Ncols = accumulate(Ncolsvec[0].begin(), Ncolsvec[0].end(), 0);
4370 for (
size_t i=0; i<Ncolsvec.size(); ++i)
4372 size_t Ncols_new = accumulate(Ncolsvec[i].begin(), Ncolsvec[i].end(), 0);
4373 if (Ncols_new > Ncols) {Ncols = Ncols_new;}
4380 for (
size_t i=0; i<Nrowsvec.size(); ++i)
4382 for (
size_t j=0; j<Ncolsvec[i].size(); ++j)
4384 Cclump.block(istitch,jstitch, Nrowsvec[i],Ncolsvec[i][j]) = Omega[svec[i]][qmidvec[i][j]];
4385 jstitch += Ncolsvec[i][j];
4387 istitch += Nrowsvec[i];
4393 for (
size_t i=0; i<Cclump.cols(); ++i)
4395 if (Cclump.col(i).norm() == 0 and Cclump.cols() > 1)
4414 #ifdef DONT_USE_BDCSVD
4415 JacobiSVD<MatrixType> Jack(Cclump,ComputeThinU);
4417 BDCSVD<MatrixType> Jack(Cclump,ComputeThinU);
4423 Nret = (Jack.singularValues().array() > 0.).count();
4424 Nret = min(Nret, this->
max_Nsv);
4428 Nret = (Jack.singularValues().array() > this->
eps_svd).count();
4430 Nret = max(Nret,1ul);
4431 truncWeightSub(qout) = Jack.singularValues().tail(Jack.singularValues().rows()-Nret).cwiseAbs2().sum();
4434 for (
size_t i=0; i<svec.size(); ++i)
4438 Nret = min(
A[loc][svec[i]].block[qAvec[i]].cols(), Jack.matrixU().cols());
4440 A[loc][svec[i]].block[qAvec[i]] = Jack.matrixU().block(stitch,0, Nrowsvec[i],Nret);
4441 stitch += Nrowsvec[i];
4450template<
typename Symmetry,
typename Scalar>
4454 for (
size_t l=0; l<this->
N_sites; ++l)
4455 for (
size_t s=0; s<
qloc[l].size(); ++s)
4456 for (
size_t q=0; q<
A[l][s].dim; ++q)
4458 if (
A[l][s].block[q].rows()==0 and
A[l][s].block[q].cols()==0)
4466 bool GOT_A_MATCH =
false;
4467 while (GOT_A_MATCH ==
false and sm<
qloc[l-1].size())
4470 auto qm =
A[l-1][sm].dict.find(cmpm);
4471 if (qm !=
A[l-1][sm].dict.end())
4473 rows = max(
static_cast<size_t>(
A[l-1][sm].block[qm->second].cols()),1ul);
4480 if (l != this->N_sites-1)
4483 bool GOT_A_MATCH =
false;
4484 while (GOT_A_MATCH ==
false and sp<
qloc[l+1].size())
4487 auto qp =
A[l+1][sp].dict.find(cmpp);
4488 if (qp !=
A[l+1][sp].dict.end())
4490 cols = max(
static_cast<size_t>(
A[l+1][sp].block[qp->second].rows()),1ul);
4497 A[l][s].block[q].resize(rows,cols);
4498 A[l][s].block[q].setZero();
4503template<
typename Symmetry,
typename Scalar>
4639template<
typename Symmetry,
typename Scalar>
4654 for (
size_t l=0; l<this->N_sites-1; ++l)
4655 for (
size_t s1=0; s1<
qloc[l].size(); ++s1)
4656 for (
size_t q1=0; q1<
A[l][s1].dim; ++q1)
4657 for (
size_t s2=0; s2<
qloc[l+1].size(); ++s2)
4658 for (
size_t q2=0; q2<
A[l+1][s2].dim; ++q2)
4660 if (
A[l][s1].out[q1] ==
A[l+1][s2].in[q2])
4662 if (
A[l][s1].block[q1].cols()-
A[l+1][s2].block[q2].rows() != 0)
4664 ss << name <<
" has wrong dimensions at: l=" << l <<
"→" << l+1
4665 <<
", qnum=" <<
A[l][s1].out[q1]
4666 <<
", s1=" << Sym::format<Symmetry>(
qloc[l][s1]) <<
", s2=" << Sym::format<Symmetry>(
qloc[l+1][s1])
4667 <<
", cols=" <<
A[l][s1].block[q1].cols() <<
" → rows=" <<
A[l+1][s2].block[q2].rows() << endl;
4669 if (
A[l][s1].block[q1].cols() == 0 or
A[l+1][s2].block[q2].rows() == 0)
4671 ss << name <<
" has zero dimensions at: l=" << l <<
"→" << l+1
4672 <<
", qnum=" <<
A[l][s1].out[q1]
4673 <<
", s1=" << Sym::format<Symmetry>(
qloc[l][s1]) <<
", s2=" << Sym::format<Symmetry>(
qloc[l+1][s1])
4674 <<
", cols=" <<
A[l][s1].block[q1].cols() <<
" → rows=" <<
A[l+1][s2].block[q2].rows() << endl;
4688 if (ss.str().size() == 0)
4690 ss << name <<
" looks okay!";
4695template<
typename Symmetry,
typename Scalar>
4700 std::array<string,4> normal_token = {
"A",
"B",
"M",
"X"};
4701 std::array<string,4> special_token = {
"\e[4mA\e[0m",
"\e[4mB\e[0m",
"\e[4mM\e[0m",
"\e[4mX\e[0m"};
4703 std::array<string,4> normal_token_for_nullspace = {
"F",
"G",
"M",
"X"};
4704 std::array<string,4> special_token_for_nullspace = {
"\e[4mF\e[0m",
"\e[4mG\e[0m",
"\e[4mM\e[0m",
"\e[4mX\e[0m"};
4706 for (
int l=0; l<this->
N_sites; ++l)
4710 for (
size_t s=1; s<
qloc[l].size(); ++s)
4712 Test +=
A[l][s].adjoint().contract(
A[l][s]);
4715 vector<bool> A_CHECK(Test.
dim);
4716 vector<double> A_infnorm(Test.
dim);
4717 for (
size_t q=0; q<Test.
dim; ++q)
4723 Test.
block[q] -= MatrixType::Identity(Test.
block[q].rows(), Test.
block[q].cols());
4724 A_CHECK[q] = Test.
block[q].template lpNorm<Infinity>()<tol ? true :
false;
4725 A_infnorm[q] = Test.
block[q].template lpNorm<Infinity>();
4731 for (
size_t s=1; s<
qloc[l].size(); ++s)
4736 vector<bool> B_CHECK(Test.
dim);
4737 vector<double> B_infnorm(Test.
dim);
4738 for (
size_t q=0; q<Test.
dim; ++q)
4744 Test.
block[q] -= MatrixType::Identity(Test.
block[q].rows(), Test.
block[q].cols());
4745 B_CHECK[q] = Test.
block[q].template lpNorm<Infinity>()<tol ? true :
false;
4746 B_infnorm[q] = Test.
block[q].template lpNorm<Infinity>();
4750 if (all_of(A_CHECK.begin(),A_CHECK.end(),[](
bool x){return x;}) and
4751 all_of(B_CHECK.begin(),B_CHECK.end(),[](
bool x){return x;}))
4753 sout << termcolor::magenta;
4754 sout << ((l==this->
pivot) ? special_token[3] : normal_token[3]);
4756 else if (all_of(A_CHECK.begin(),A_CHECK.end(),[](
bool x){return x;}))
4758 sout << termcolor::red;
4759 sout << ((l==this->
pivot) ? special_token[0] : normal_token[0]);
4761 else if (all_of(B_CHECK.begin(),B_CHECK.end(),[](
bool x){return x;}))
4763 sout << termcolor::blue;
4764 sout << ((l==this->
pivot) ? special_token[1] : normal_token[1]);
4768 sout << termcolor::green;
4769 sout << ((l==this->
pivot) ? special_token[2] : normal_token[2]);
4772 sout << termcolor::reset;
4776template<
typename Symmetry,
typename Scalar>
4780 vector<pair<qarray<Nq>,
double> > Svals;
4781 for (
const auto &x :
SVspec[loc])
4782 for (
int i=0; i<x.second.size(); ++i)
4784 Svals.push_back(std::make_pair(x.first,x.second(i)));
4786 sort(Svals.begin(), Svals.end(), [] (
const pair<
qarray<Nq>,
double> &p1,
const pair<
qarray<Nq>,
double> &p2) { return p2.second < p1.second;});
4789 ArrayXd Sout(Svals.size());
4790 vector<qarray<Nq> > Qout(Svals.size());
4791 for (
int i=0; i<Svals.size(); ++i)
4793 Sout(i) = Svals[i].second;
4794 Qout[i] = Svals[i].first;
4796 return std::make_pair(Qout,Sout);
4799template<
typename Symmetry,
typename Scalar>
4801graph (
string filename)
const
4805 ss <<
"#!/usr/bin/dot dot -Tpdf -o " << filename <<
".pdf\n\n";
4806 ss <<
"digraph G\n{\n";
4807 ss <<
"rankdir = LR;\n";
4808 ss <<
"labelloc=\"t\";\n";
4809 ss <<
"label=\"MPS: L=" << this->N_sites <<
", (";
4810 for (
size_t q=0; q<
Nq; ++q)
4812 ss << Symmetry::kind()[q];
4813 if (q!=
Nq-1) {ss <<
",";}
4815 ss <<
")=" << Sym::format<Symmetry>(
Qtot) <<
"\";\n";
4818 ss <<
"\"l=" << 0 <<
", " << Sym::format<Symmetry>(Symmetry::qvacuum()) <<
"\"";
4819 ss <<
"[label=" <<
"\"" << Sym::format<Symmetry>(Symmetry::qvacuum()) <<
"\"" <<
"];\n";
4822 for (
size_t l=0; l<this->
N_sites; ++l)
4824 ss <<
"subgraph" <<
" cluster_" << l <<
"\n{\n";
4825 for (
size_t s=0; s<
qloc[l].size(); ++s)
4826 for (
size_t q=0; q<
A[l][s].dim; ++q)
4828 string qin = Sym::format<Symmetry>(
A[l][s].in[q]);
4829 ss <<
"\"l=" << l <<
", " << qin <<
"\"";
4830 ss <<
"[label=" <<
"\"" << qin <<
"\"" <<
"];\n";
4832 if (l>0) {ss <<
"label=\"l=" << l <<
"\"\n";}
4833 else {ss <<
"label=\"vacuum\"\n";}
4838 ss <<
"subgraph" <<
" cluster_" << this->N_sites <<
"\n{\n";
4839 ss <<
"\"l=" << this->N_sites <<
", " << Sym::format<Symmetry>(
Qtot) <<
"\"";
4840 ss <<
"[label=" <<
"\"" << Sym::format<Symmetry>(
Qtot) <<
"\"" <<
"];\n";
4841 ss <<
"label=\"l=" << this->N_sites <<
"\"\n";
4845 for (
size_t l=0; l<this->
N_sites; ++l)
4847 for (
size_t s=0; s<
qloc[l].size(); ++s)
4848 for (
size_t q=0; q<
A[l][s].dim; ++q)
4850 string qin = Sym::format<Symmetry>(
A[l][s].in[q]);
4851 string qout = Sym::format<Symmetry>(
A[l][s].out[q]);
4852 ss <<
"\"l=" << l <<
", " << qin <<
"\"";
4854 ss <<
"\"l=" << l+1 <<
", " << qout <<
"\"";
4855 ss <<
" [label=\"" <<
A[l][s].block[q].rows() <<
"x" <<
A[l][s].block[q].cols() <<
"\"";
4862 ofstream f(filename+
".dot");
4867template<
typename Symmetry,
typename Scalar>
4872 ss << endl <<
"Asizes:" << endl;
4873 for (
size_t l=0; l<this->
N_sites; ++l)
4875 ss <<
"\tl=" << l <<
": ";
4876 for (
size_t s=0; s<
qloc[l].size(); ++s)
4878 ss <<
"s=" << s <<
": ";
4879 for (
size_t q=0; q<
A[l][s].dim; ++q)
4881 ss <<
"(" <<
A[l][s].block[q].rows() <<
"," <<
A[l][s].block[q].cols() <<
") ";
4884 if (l!=this->N_sites-1) {ss << endl;}
4889template<
typename Symmetry,
typename Scalar>
4891memory (MEMUNIT memunit)
const
4894 for (
size_t l=0; l<this->
N_sites; ++l)
4895 for (
size_t s=0; s<
qloc[l].size(); ++s)
4897 res +=
A[l][s].memory(memunit);
4902template<
typename Symmetry,
typename Scalar>
4905 os << setfill(
'-') << setw(30) <<
"-" << setfill(
' ');
4906 os <<
"Mps: L=" << V.
length();
4907 os << setfill(
'-') << setw(30) <<
"-" << endl << setfill(
' ');
4909 for (
size_t l=0; l<V.
length(); ++l)
4911 for (
size_t s=0; s<V.
locBasis(l).size(); ++s)
4913 os <<
"l=" << l <<
"\ts=" << Sym::format<Symmetry>(V.
locBasis(l)[s]) << endl;
4914 os << V.
A_at(l)[s].print(
true);
4917 os << setfill(
'-') << setw(80) <<
"-" << setfill(
' ');
4918 if (l != V.
length()-1) {os << endl;}
void addBottom(const MatrixType1 &Min, MatrixType2 &Mout)
void addRight(const MatrixType1 &Min, MatrixType2 &Mout)
void remove_col(size_t i, MatrixType &M)
void split_AA2(DMRG::DIRECTION::OPTION DIR, const Qbasis< Symmetry > &locBasis, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Apair, const vector< qarray< Symmetry::Nq > > &qloc_l, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Al, const vector< qarray< Symmetry::Nq > > &qloc_r, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Ar, const qarray< Symmetry::Nq > &qtop, const qarray< Symmetry::Nq > &qbot, double eps_svd, size_t min_Nsv, size_t max_Nsv)
Scalar dot(const Mps< Symmetry, Scalar > &Vbra, const Mps< Symmetry, Scalar > &Vket)
void addScale(const OtherScalar alpha, const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout, DMRG::VERBOSITY::OPTION VERBOSITY=DMRG::VERBOSITY::SILENT)
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
Mps< Symmetry, OtherScalar > operator*(const OtherScalar &alpha, const Mps< Symmetry, Scalar > &Vin)
ostream & operator<<(ostream &os, const Mps< Symmetry, Scalar > &V)
Mps< Symmetry, OtherScalar > operator/(const Mps< Symmetry, Scalar > &Vin, const OtherScalar &alpha)
Base class for all the sweeping stuff. Needs to know PivotMatrixType because sweeps using DMRG::BROOM...
void sweep(size_t loc, DMRG::BROOM::OPTION TOOL, PivotMatrixType *H=NULL)
const std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > & W_at(const std::size_t loc) const
const std::vector< std::vector< qType > > & locBasis() const
const std::vector< std::vector< qType > > & opBasis() const
friend void HxV(const Mpo< Symmetry_, S1 > &H, const Mps< Symmetry_, S2 > &Vin, Mps< Symmetry_, S2 > &Vout, DMRG::VERBOSITY::OPTION VERBOSITY)
Mps< Symmetry, OtherScalar > cast() const
void canonize(DMRG::DIRECTION::OPTION DIR=DMRG::DIRECTION::LEFT)
vector< qarray< Nq > > locBasis(size_t loc) const
void outerResize(const Mps< Symmetry, OtherMatrixType > &V)
void absorb(size_t loc, DMRG::DIRECTION::OPTION DIR, const Biped< Symmetry, MatrixType > &C)
size_t calc_fullMmax() const
void elongate_hetero(size_t Nleft=0, size_t Nright=0)
void leftSplitStep(size_t loc, Biped< Symmetry, MatrixType > &C)
void set_Qmultitarget(const vector< qarray< Nq > > &Qmulti_input)
void set_A_from_C(size_t loc, const vector< Tripod< Symmetry, MatrixType > > &C, DMRG::BROOM::OPTION TOOL=DMRG::BROOM::SVD)
void graph(string filename) const
void rightSweepStep(size_t loc, DMRG::BROOM::OPTION BROOM, PivotMatrix1< Symmetry, Scalar, Scalar > *H=NULL, bool DISCARD_V=false)
Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > get_boundaryTensor(DMRG::DIRECTION::OPTION DIR, size_t usePower=1ul) const
size_t calc_Nqmax() const
Scalar dot(const Mps< Symmetry, Scalar > &Vket) const
void addScale(OtherScalar alpha, const Mps< Symmetry, Scalar > &Vin, bool SVD_COMPRESS=false)
const vector< Biped< Symmetry, MatrixType > > & A_at(size_t loc) const
Mps< Symmetry, Scalar > & operator*=(const OtherScalar &alpha)
void rightSplitStep(size_t loc, Biped< Symmetry, MatrixType > &C)
void shift_hetero(int Nshift=0)
double calc_Nqavg() const
void transform_base(qarray< Symmetry::Nq > Qtot, int L, bool PRINT=false)
MpsBoundaries< Symmetry, Scalar > Boundaries
Mps< Symmetry, Scalar > & operator-=(const Mps< Symmetry, Scalar > &Vin)
void outerResize(size_t L_input, vector< vector< qarray< Nq > > > qloc_input, qarray< Nq > Qtot_input, int Nqmax_input=500)
void update_inbase(size_t loc)
vector< qarray< Nq > > QoutBot
void innerResize(size_t Mmax)
vector< qarray< Nq > > QoutTop
string validate(string name="Mps") const
void setProductState(const Hamiltonian &H, const vector< qarray< Nq > > &config)
vector< vector< qarray< Nq > > > locBasis() const
void enrich_right(size_t loc, PivotMatrix1< Symmetry, Scalar, Scalar > *H)
double squaredNorm() const
vector< map< qarray< Nq >, ArrayXd > > SVspec
vector< Qbasis< Symmetry > > outbase
void outerResizeAll(size_t L_input, vector< vector< qarray< Nq > > > qloc_input, qarray< Nq > Qtot_input)
friend void OxV_exact(const Mpo< Symmetry_, S1 > &H, const Mps< Symmetry_, S2 > &Vin, Mps< Symmetry_, S2 > &Vout, double tol_compr, DMRG::VERBOSITY::OPTION VERBOSITY, int max_halfsweeps, int min_halfsweeps, int Minit)
void calc_N(DMRG::DIRECTION::OPTION DIR, size_t loc, vector< Biped< Symmetry, MatrixType > > &N)
void outerResize(const Hamiltonian &H, qarray< Nq > Qtot_input, int Nqmax_input=500)
void update_outbase(size_t loc)
vector< qarray< Nq > > QinTop
void leftSweepStep(size_t loc, DMRG::BROOM::OPTION BROOM, PivotMatrix1< Symmetry, Scalar, Scalar > *H=NULL, bool DISCARD_U=false)
size_t get_Min(size_t loc) const
Qbasis< Symmetry > inBasis(size_t loc) const
friend void OxV(const Mpo< Symmetry_, S1 > &H, const Mps< Symmetry_, S2 > &Vin, Mps< Symmetry_, S2 > &Vout, DMRG::BROOM::OPTION TOOL)
vector< Qbasis< Symmetry > > inbase
Mps(size_t L_input, vector< vector< qarray< Nq > > > qloc_input, qarray< Nq > Qtot_input, size_t N_phys_input, int Nqmax_input, bool TRIVIAL_BOUNDARIES=true)
vector< qarray< Nq > > Qmulti
vector< qarray< Nq > > QinBot
size_t get_Mout(size_t loc) const
void swap(Mps< Symmetry, Scalar > &V)
static constexpr size_t Nq
void set_Qlimits_to_inf()
vector< Qbasis< Symmetry > > inBasis() const
Mps(size_t L_input, const vector< vector< Biped< Symmetry, MatrixType > > > &As, const vector< vector< qarray< Nq > > > &qloc_input, qarray< Nq > Qtot_input, size_t N_phys_input)
vector< map< qarray< Nq >, ArrayXd > > entanglementSpectrum() const
void applyGate(const TwoSiteGate< Symmetry, Scalar > &gate, size_t l, DMRG::DIRECTION::OPTION DIR)
vector< vector< qarray< Nq > > > qloc
double memory(MEMUNIT memunit=GB) const
vector< qarray< Nq > > Qmultitarget() const
void enrich_left(size_t loc, PivotMatrix1< Symmetry, Scalar, Scalar > *H)
ArrayXd get_truncWeight() const
void add_site(size_t loc, OtherScalar alpha, const Mps< Symmetry, Scalar > &Vin)
void sweepStep2(DMRG::DIRECTION::OPTION DIR, size_t loc, const vector< Biped< Symmetry, MatrixType > > &Apair, bool SEPARATE_SV=false)
Mps(const Hamiltonian &H, size_t Mmax, qarray< Nq > Qtot_input, int Nqmax_input)
string test_ortho(double tol=1e-8) const
Qbasis< Symmetry > outBasis(size_t loc) const
qarray< Nq > Qtarget() const
vector< Qbasis< Symmetry > > outBasis() const
void setRandom(size_t loc)
vector< Biped< Symmetry, MatrixType > > & A_at(size_t loc)
Matrix< Scalar, Dynamic, Dynamic > MatrixType
Mps< Symmetry, Scalar > & operator/=(const OtherScalar &alpha)
std::pair< vector< qarray< Symmetry::Nq > >, ArrayXd > entanglementSpectrumLoc(size_t loc) const
Mps< Symmetry, Scalar > & operator+=(const Mps< Symmetry, Scalar > &Vin)
void get_controlParams(const Mps< Symmetry, Scalar > &V)
vector< vector< Biped< Symmetry, MatrixType > > > A
Scalar locAvg(const Mpo< Symmetry, MpoScalar > &O, size_t distance=0) const
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
Qbasis< Symmetry > rightBasis() const
Qbasis< Symmetry > midBasis() const
Qbasis< Symmetry > leftBasis() const
vector< vector< vector< vector< vector< Scalar > > > > > data
void contract_L(const Tripod< Symmetry, MatrixType2 > &Lold, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, MatrixType > > &Aket, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp, Tripod< Symmetry, MatrixType2 > &Lnew, bool RANDOMIZE=false, tuple< CONTRACT_LR_MODE, size_t > MODE_input=make_pair(FULL, 0), const std::unordered_map< pair< qarray< Symmetry::Nq >, size_t >, size_t > &basis_order_map={})
Scalar contract_LR(const Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > &L, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Aket, const Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > &R, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp)
std::array< qarray< Nq >, 2 > qarray2
std::array< qarray< Nq >, 3 > qarray3
std::unordered_map< std::array< qType, 2 >, std::size_t > dict
std::vector< MatrixType_ > block
Biped< Symmetry, MatrixType_ > contract(const Biped< Symmetry, MatrixType_ > &A, const contract::MODE MODE=contract::MODE::UNITY) const
void push_back(qType qin, qType qout, const MatrixType_ &M)
tuple< Biped< Symmetry, MatrixType_ >, Biped< Symmetry, MatrixType_ >, Biped< Symmetry, MatrixType_ > > truncateSVD(size_t minKeep, size_t maxKeep, EpsScalar eps_svd, double &truncWeight, double &entropy, map< qarray< Symmetry::Nq >, Eigen::ArrayXd > &SVspec, bool PRESERVE_MULTIPLETS=true, bool RETURN_SPEC=true) const
void setIdentity(const Qbasis< Symmetry > &base1, const Qbasis< Symmetry > &base2, qType Q=Symmetry::qvacuum())
void setIdentity(size_t Drows, size_t Dcols, size_t amax=1, size_t bmax=1)
vector< PivotMatrix1Terms< Symmetry, Scalar, MpoScalar > > Terms