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