1#ifndef STRAWBERRY_MULTIPEDE
2#define STRAWBERRY_MULTIPEDE
7#include <unordered_map>
9#include "boost/multi_array.hpp"
15#include "HDF5Interface.h"
31template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
34typedef typename Symmetry::qType
qType;
35typedef typename MatrixType::Scalar
Scalar;
46 for (
size_t q=0; q<
B.dim; ++q)
51 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[1][1]);
52 Mtmpvec[0][0] =
B.block[q];
59 inline constexpr size_t rank()
const {
return Nlegs;}
67 inline std::size_t
size()
const {
return dim;}
77 vector<std::array<qType,Nlegs> >
index;
88 vector<boost::multi_array<MatrixType,LEGLIMIT> >
block;
95 unordered_map<std::array<qType,Nlegs>,
size_t>
dict;
100 double memory (MEMUNIT memunit=GB)
const;
108 string print (
const bool &SHOW_MATRICES=
false,
const size_t &precision=3)
const;
134 void setIdentity (
size_t Drows,
size_t Dcols,
size_t amax=1,
size_t bmax=1);
142 void save (
string filename,
bool PRINT=
false)
const;
144 void load (
string filename,
bool PRINT=
false);
165 void push_back (std::array<qType,Nlegs> quple,
const boost::multi_array<MatrixType,LEGLIMIT> &M);
172 void push_back (std::initializer_list<qType> qlist,
const boost::multi_array<MatrixType,LEGLIMIT> &M);
179 template<
typename OtherMatrixType>
190 for (
size_t q=0; q<
dim; ++q)
192 Vout.
block[q].resize(boost::extents[
block[q].shape()[0]][
block[q].shape()[1]]);
193 for (
size_t a=0; a<
block[q].shape()[0]; ++a)
194 for (
size_t b=0; b<
block[q].shape()[1]; ++b)
196 Vout.
block[q][a][b] =
block[q][a][b].template cast<typename OtherMatrixType::Scalar>();
224 for (
size_t q=0; q<
dim; ++q)
226 block[q].resize(boost::extents[Vin.
block[q].shape()[0]][Vin.
block[q].shape()[1]]);
227 for (
size_t a=0; a<
block[q].shape()[0]; ++a)
228 for (
size_t b=0; b<
block[q].shape()[1]; ++b)
238template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
242 for (
size_t q=0; q<M1.
dim; ++q)
245 auto it = M2.
dict.find(quple);
246 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[M1.
block[q].shape()[0]][1]);
247 for (
size_t a=0; a<M1.
block[q].shape()[0]; ++a)
249 Mtmpvec[a][0] = M1.
block[q][a][0]-M2.
block[it->second][a][0];
256template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
260 if (abs(factor) < 1.e-14) {
return;}
261 vector<qarray3<Symmetry::Nq> > matching_blocks;
264 for (
size_t q=0; q<
dim; ++q)
267 auto it = Mrhs.
dict.find(quple);
268 if (it != Mrhs.
dict.end())
270 matching_blocks.push_back(quple);
273 for (
size_t a=0; a<block[q].shape()[0]; ++a)
276 if (it != Mrhs.
dict.end())
278 assert(block[q].shape()[0] == Mrhs.
block[it->second].shape()[0]);
280 if (block[q][a][0].size() != 0 and Mrhs.
block[it->second][a][0].size() != 0)
283 Mtmp = block[q][a][0] + factor * Mrhs.
block[it->second][a][0];
285 else if (block[q][a][0].size() == 0 and Mrhs.
block[it->second][a][0].size() != 0)
288 Mtmp = factor * Mrhs.
block[it->second][a][0];
290 else if (block[q].size() != 0 and Mrhs.
block[it->second][a][0].size() == 0)
293 Mtmp = block[q][a][0];
300 Mtmp = block[q][a][0];
303 if (Mtmp.size() != 0)
305 auto ip = Mout.
dict.find(quple);
306 if (ip != Mout.
dict.end())
308 assert(1==0 and
"Error in Multipede::addScale, block already exists!");
312 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[block[q].shape()[0]][1]);
313 Mtmpvec[a][0] = Mtmp;
321 if (matching_blocks.size() != Mrhs.
dim)
323 for (
size_t qrhs=0; qrhs<Mrhs.
size(); ++qrhs)
326 auto it = find(matching_blocks.begin(), matching_blocks.end(), quple);
327 if (it == matching_blocks.end())
329 for (
size_t a=0; a<Mrhs.
block[qrhs].shape()[0]; ++a)
331 if (Mrhs.
block[qrhs][a][0].size() != 0)
333 MatrixType Mtmp = factor * Mrhs.
block[qrhs][a][0];
335 auto ip = Mout.
dict.find(quple);
336 if (ip != Mout.
dict.end())
338 assert(1==0 and
"Error in Multipede::addScale, block already exists!");
342 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[Mrhs.
block[qrhs].shape()[0]][1]);
343 Mtmpvec[a][0] = Mtmp;
358template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
363 for (
auto it=dict.begin(); it!=dict.end(); ++it)
365 if (Nlegs==2) {ss <<
"in: " << it->first[0] <<
", out: " << it->first[1];}
366 if (Nlegs==3) {ss <<
"in: " << it->first[0] <<
", out: " << it->first[1] <<
", mid:" << it->first[2];}
367 if (Nlegs==4) {ss <<
"in: " << it->first[0] <<
", out: " << it->first[1] <<
", bot:" << it->first[2] <<
", top:" << it->first[3];}
368 ss <<
"\t→\t" << it->second << endl;
373template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
375memory (MEMUNIT memunit)
const
378 for (
size_t q=0; q<
dim; ++q)
379 for (
auto B=block[q].data();
B!=block[q].data()+block[q].num_elements(); ++
B)
381 res += calc_memory(*
B, memunit);
386template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
391 res += 2. * Nlegs * Symmetry::Nq * calc_memory<int>(
dim, memunit);
392 res += Symmetry::Nq * calc_memory<size_t>(
dim, memunit);
396template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
400 for (
size_t q=0; q<
dim; ++q)
401 for (
auto B=block[q].data();
B!=block[q].data()+block[q].num_elements(); ++
B)
407template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
437template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
439push_back (std::array<qType,Nlegs> quple,
const boost::multi_array<MatrixType,LEGLIMIT> &M)
445 index.push_back(quple);
447 dict.insert({quple,
dim});
451template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
453push_back (std::initializer_list<qType> qlist,
const boost::multi_array<MatrixType,LEGLIMIT> &M)
455 assert(qlist.size() == Nlegs);
456 std::array<qType,Nlegs> quple;
457 copy(qlist.begin(), qlist.end(), quple.data());
461template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
465 MatrixType Mtmp(1,1); Mtmp << 1.;
466 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[1][1]);
467 Mtmparray[0][0] = Mtmp;
469 std::array<qType,Nlegs> quple;
470 for (
size_t leg=0; leg<Nlegs; ++leg)
472 quple[leg] = Symmetry::qvacuum();
475 push_back(quple, Mtmparray);
478template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
482 MatrixType Mtmp(1,1);
485 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[1][1]);
486 Mtmparray[0][0] = Mtmp;
488 push_back(Q,Mtmparray);
491template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
493setTarget (vector<std::array<qType,Nlegs> > Q)
495 MatrixType Mtmp(1,1);
498 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[1][1]);
499 Mtmparray[0][0] = Mtmp;
501 for (
const auto &Qval:Q)
503 push_back(Qval,Mtmparray);
507template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
509setIdentity (
size_t Drows,
size_t Dcols,
size_t amax,
size_t bmax)
511 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[amax][bmax]);
512 for (
size_t a=0; a<amax; ++a)
513 for (
size_t b=0; b<bmax; ++b)
515 MatrixType Mtmp(Drows,Dcols);
517 Mtmparray[a][b] = Mtmp;
520 std::array<qType,Nlegs> quple;
521 for (
size_t leg=0; leg<Nlegs; ++leg)
523 quple[leg] = Symmetry::qvacuum();
525 push_back(quple, Mtmparray);
528template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
532 static_assert(Nlegs == 3);
533 if (amax == 0 or bmax ==0) {
return;}
535 for (
size_t q=0; q<base.
Nq(); ++q)
542 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[amax][bmax]);
543 for (
size_t a=0; a<amax; ++a)
544 for (
size_t b=0; b<bmax; ++b)
548 Mtmparray[a][b] = Mtmp;
550 push_back(quple, Mtmparray);
554template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
558 static_assert(Nlegs == 3);
560 for (
size_t q=0; q<Trhs.
dim; ++q)
562 if (Trhs.
mid(q) != ab.first) {
continue;}
564 if (Trhs.
block[q][ab.second][0].size() == 0) {
continue;}
567 auto it = dict.find(quple);
568 if (it != dict.end())
570 if (block[it->second][ab.second][0].rows() == Trhs.
block[q][ab.second][0].rows() and
571 block[it->second][ab.second][0].cols() == Trhs.
block[q][ab.second][0].cols())
574 block[it->second][ab.second][0] += Trhs.
block[q][ab.second][0];
579 block[it->second][ab.second][0] = Trhs.
block[q][ab.second][0];
585 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[Trhs.
block[q].shape()[0]][1]);
586 Mtmparray[ab.second][0] = Trhs.
block[q][ab.second][0];
587 push_back(quple, Mtmparray);
592template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
594print (
const bool &SHOW_MATRICES,
const std::size_t &precision)
const
596 #ifndef HELPERS_IO_TABLE
597 std::stringstream out;
598 out <<
"Texttable library is missing. -> no output" << std::endl;
601 std::stringstream out;
603 TextTable t(
'-',
'|',
'+' );
608 for (std::size_t nu=0; nu<
dim; nu++)
610 std::stringstream ss,tt,uu,vv;
613 for (std::size_t q=0; q<index[nu].size(); q++)
615 tt << Sym::format<Symmetry>(index[nu][q]);
616 if (q==index[nu].size()-1) {tt <<
")";}
else {tt <<
",";}
618 uu << block[nu].shape()[0] <<
":[";
620 for (std::size_t q=0; q<block[nu].shape()[0]; q++)
624 uu <<
"(" << block[nu][q][0].cols() <<
"x" << block[nu][q][0].rows() <<
")";
625 if(q==block[nu].shape()[0]-1) {uu <<
"";}
else {uu <<
",";}
634 t.setAlignment( 0, TextTable::Alignment::RIGHT );
639 out << termcolor::blue << termcolor::underline <<
"A-tensors:" << termcolor::reset << std::endl;
640 for (std::size_t nu=0; nu<
dim; nu++)
642 out << termcolor::blue <<
"ν=" << nu << std::endl;
643 for (std::size_t q=0; q<block[nu].shape()[0]; q++)
645 if(block[nu][q][0].size() == 0) {
continue;}
646 out << termcolor::green <<
"q=" << q << endl << std::setprecision(precision) << std::fixed << block[nu][q][0] << std::endl;
697template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
702 for (
size_t q=0; q<
dim; ++q)
705 auto it = Mrhs.
dict.find(quple);
706 if (it == Mrhs.
dict.end()) {
return std::numeric_limits<typename MatrixType::Scalar>::infinity();}
707 for (
size_t a=0; a<block[q].shape()[0]; ++a)
709 res += (block[q][a][0]-Mrhs.
block[it->second][a][0]).
norm();
715template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
722 for (
size_t q=0; q<
dim; ++q)
723 for (
size_t a=0; a<block[q].shape()[0]; ++a)
725 if (mid(q) == qslice)
727 Bout.
push_back(in(q), out(q), block[q][a][0]);
733template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
735save (
string filename,
bool PRINT)
const
740 if (PRINT) lout << termcolor::green <<
"Saving Multipede to: " << filename << termcolor::reset << std::endl;
741 remove(filename.c_str());
742 HDF5Interface target(filename, WRITE);
744 target.save_scalar<
size_t>(
dim,
"dim",
"");
746 for (
size_t q=0; q<
dim; ++q)
748 target.save_scalar<
size_t>(block[q].shape()[0], make_string(
"dima_q=",q),
"");
749 target.save_scalar<
size_t>(block[q].shape()[1], make_string(
"dimb_q=",q),
"");
752 for (
size_t q=0; q<
dim; ++q)
753 for (
size_t a=0; a<block[q].shape()[0]; ++a)
754 for (
size_t b=0; b<block[q].shape()[1]; ++b)
756 if constexpr (std::is_same<typename MatrixType::Scalar,complex<double>>::value)
758 MatrixXd Re = block[q][a][b].real();
759 MatrixXd Im = block[q][a][b].imag();
760 string label = make_string(
"block_q=",q,
"_a=",a,
"_b=",b);
761 target.save_matrix(Re,label+
"Re",
"");
762 target.save_matrix(Im,label+
"Im",
"");
766 target.save_matrix(block[q][a][b], make_string(
"block_q=",q,
"_a=",a,
"_b=",b),
"");
770 MatrixXi Min(
dim,Symmetry::Nq);
771 MatrixXi Mout(
dim,Symmetry::Nq);
772 MatrixXi Mmid(
dim,Symmetry::Nq);
774 for (
int i=0; i<
dim; ++i)
775 for (
int q=0; q<Symmetry::Nq; ++q)
778 Mout(i,q) = out(i)[q];
779 Mmid(i,q) = mid(i)[q];
787 target.save_matrix<
int>(Min,
"in",
"");
788 target.save_matrix<
int>(Mout,
"out",
"");
789 target.save_matrix<
int>(Mmid,
"mid",
"");
796template<
size_t Nlegs,
typename Symmetry,
typename MatrixType>
798load (
string filename,
bool PRINT)
803 if (PRINT) lout << termcolor::green <<
"Loading Multipede from: " << filename << termcolor::reset << std::endl;
804 HDF5Interface source(filename, READ);
806 source.load_scalar<
size_t>(
dim,
"dim",
"");
811 for (
size_t q=0; q<
dim; ++q)
814 source.load_scalar<
size_t>(dima, make_string(
"dima_q=",q),
"");
815 source.load_scalar<
size_t>(dimb, make_string(
"dimb_q=",q),
"");
816 block[q].resize(boost::extents[dima][dimb]);
820 for (
size_t q=0; q<
dim; ++q)
821 for (
size_t a=0; a<block[q].shape()[0]; ++a)
822 for (
size_t b=0; b<block[q].shape()[1]; ++b)
824 if constexpr (std::is_same<typename MatrixType::Scalar,complex<double>>::value)
827 string label = make_string(
"block_q=",q,
"_a=",a,
"_b=",b);
828 source.load_matrix(Re, label+
"Re",
"");
829 source.load_matrix(Im, label+
"Im",
"");
830 block[q][a][b] = Re+1.i*Im;
834 source.load_matrix(block[q][a][b], make_string(
"block_q=",q,
"_a=",a,
"_b=",b),
"");
838 MatrixXi Min, Mout, Mmid;
839 source.load_matrix<
int>(Min,
"in",
"");
840 source.load_matrix<
int>(Mout,
"out",
"");
841 source.load_matrix<
int>(Mmid,
"mid",
"");
843 assert(Min.rows() != 0);
849 for (
int i=0; i<
dim; ++i)
851 std::array<qType,Nlegs> quple;
852 for (
int q=0; q<Symmetry::Nq; ++q)
854 quple[0][q] = Min(i,q);
855 quple[1][q] = Mout(i,q);
856 quple[2][q] = Mmid(i,q);
859 dict.insert({quple,i});
double norm(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
Multipede< Nlegs, Symmetry, MatrixType > operator-(const Multipede< Nlegs, Symmetry, MatrixType > &M1, const Multipede< Nlegs, Symmetry, MatrixType > &M2)
Eigen::Index inner_dim(const Eigen::Index &num_in) const
std::array< qarray< Nq >, 3 > qarray3
void push_back(qType qin, qType qout, const MatrixType_ &M)
void save(string filename, bool PRINT=false) const
Biped< Symmetry, MatrixType > BipedSliceQmid(qType qslice=Symmetry::qvacuum()) const
void setIdentity(size_t amax, size_t bmax, const Qbasis< Symmetry > &base, const qarray< Symmetry::Nq > &Q=Symmetry::qvacuum())
vector< std::array< qType, Nlegs > > index
void setTarget(vector< std::array< qType, Nlegs > > Q)
unordered_map< std::array< qType, Nlegs >, size_t > dict
void insert(std::pair< qType, size_t > ab, const Multipede< Nlegs, Symmetry, MatrixType > &Trhs)
qType mid(size_t q) const
double memory(MEMUNIT memunit=GB) const
constexpr size_t rank() const
void push_back(std::initializer_list< qType > qlist, const boost::multi_array< MatrixType, LEGLIMIT > &M)
void setTarget(std::array< qType, Nlegs > Q)
string print(const bool &SHOW_MATRICES=false, const size_t &precision=3) const
qType top(size_t q) const
double overhead(MEMUNIT memunit=MB) const
qType out(size_t q) const
Multipede< Nlegs, Symmetry, MatrixType > & operator=(const Multipede< Nlegs, Symmetry, MatrixType > &Vin)
void push_back(std::array< qType, Nlegs > quple, const boost::multi_array< MatrixType, LEGLIMIT > &M)
MatrixType::Scalar Scalar
vector< boost::multi_array< MatrixType, LEGLIMIT > > block
Multipede(const Biped< Symmetry, MatrixType > &B, qType Q=Symmetry::qvacuum())
Scalar compare(const Multipede< Nlegs, Symmetry, MatrixType > &Mrhs) const
void load(string filename, bool PRINT=false)
Multipede< Nlegs, Symmetry, OtherMatrixType > cast() const
qType bot(size_t q) const
void addScale(const Scalar &factor, const Multipede< Nlegs, Symmetry, MatrixType > &Mrhs)
void setIdentity(size_t Drows, size_t Dcols, size_t amax=1, size_t bmax=1)