5#include <unordered_set>
7#include <unordered_map>
21template<
typename Symmetry,
typename MatrixType_>
struct Biped;
37template<
typename Symmetry>
40 typedef typename Symmetry::qType
qType;
50 template<
typename Container>
51 Qbasis (
const Container &qins,
const Eigen::Index &
dim)
53 for (
const auto &qin:qins)
64 map<qarray<Symmetry::Nq>,
size_t> counter;
65 for (
const auto &b:base_input)
69 for (
const auto &[val,count]:counter)
77 std::size_t
size()
const { std::size_t out = 0;
for(
const auto& [qVal,num,plain] :
data_) { out+=plain.size();}
return out; }
80 std::size_t
M()
const {
return size(); }
86 std::size_t
fullM()
const { std::size_t out = 0;
for(
const auto& [qVal,num,plain] :
data_) { out+=plain.size()*Symmetry::degeneracy(qVal);}
return out; }
92 std::size_t
Nq()
const {
return data_.size(); }
97 const std::vector<qType>
qloc()
const;
100 const std::vector<qType>
qs()
const;
127 Eigen::Index
location(
const std::string& ident )
const;
129 Eigen::Index
inner_dim(
const Eigen::Index& num_in )
const;
135 Eigen::Index
leftOffset(
const qType& qnew,
const std::array<qType,2>& qold,
const std::array<Eigen::Index,2>& plain_old )
const;
141 void push_back(
const std::tuple<
qType,Eigen::Index,std::vector<std::string> >& state );
153 template<
typename MatrixType>
156 template<
typename MatrixType>
159 void pullData (
const std::vector<std::array<qType,3> > &qvec,
const std::size_t& leg,
const Eigen::Index &inner_dim_in);
186 typename std::vector<std::tuple<qType,Eigen::Index,Basis> >::iterator
begin() {
return data_.begin();}
187 typename std::vector<std::tuple<qType,Eigen::Index,Basis> >::iterator
end() {
return data_.end();}
189 typename std::vector<std::tuple<qType,Eigen::Index,Basis> >::const_iterator
cbegin()
const {
return data_.cbegin();}
190 typename std::vector<std::tuple<qType,Eigen::Index,Basis> >::const_iterator
cend()
const {
return data_.cend();}
207 std::vector<std::tuple<qType,Eigen::Index,Basis> >
data_;
209 std::unordered_map<qType,std::vector<fuseData> >
history;
212template<
typename Symmetry>
214push_back(
const std::tuple<
qType,Eigen::Index,std::vector<std::string> >& state)
216 auto [ q_number, inner_dim, ident ] = state;
217 push_back(q_number, inner_dim, ident);
220template<
typename Symmetry>
224 std::vector<std::string> dummy_idents(inner_dim,
"");
225 push_back(q_number, inner_dim, dummy_idents);
228template<
typename Symmetry>
230push_back(
const qType& q_number,
const Eigen::Index& inner_dim,
const std::vector<std::string>& idents)
233 auto it = std::find_if(data_.begin(), data_.end(), [&q_number] (
const tuple<qType,Eigen::Index,Basis> &entry) {return std::get<0>(entry) == q_number;});
235 if (it == data_.end())
237 Basis plain_basis(idents,inner_dim);
238 auto entry = std::make_tuple(q_number,curr_dim,plain_basis);
239 data_.push_back(entry);
246 std::get<2>(*it).push_back(idents);
247 for (
auto loop=it++; loop==data_.end(); loop++)
249 std::get<1>(*loop) += inner_dim;
252 curr_dim += inner_dim;
255template<
typename Symmetry>
260 for (
const auto& entry : data_)
262 auto [qVal,num,plain] = entry;
263 if (plain.size() > out) {out = plain.size();}
268template<
typename Symmetry>
272 std::vector<qType> out;
273 for(
const auto& [q,num,plain] : data_) {
for(std::size_t c=0; c<plain.size(); c++) {out.push_back(q);} }
277template<
typename Symmetry>
281 std::vector<qType> out;
282 for(
const auto& [q,num,plain] : data_) { out.push_back(q); }
286template<
typename Symmetry>
290 std::unordered_set<qType> out;
291 for(
const auto& [q,num,plain] : data_) { out.insert(q); }
295template<
typename Symmetry>
297find(
const std::string& ident)
const
299 for (
const auto& q : data_ )
301 auto [qVal,num,basis] = q;
302 if(basis.find(ident)) {
return qVal;}
304 assert(1!=1 and
"The ident is not in the basis");
307template<
typename Symmetry>
309find(
const Eigen::Index& num_in )
const
311 assert( num_in < size() and
"The number is larger than the size of this basis." );
312 Eigen::Index check = num_in;
313 for (
const auto& q : data_)
315 auto [qVal,num,basis] = q;
316 if (check < num+basis.size()) {
return qVal; }
318 assert(
false and
"Something went wrong in Qbasis::find(Eigen::Index num_in)");
321template<
typename Symmetry>
325 for (
const auto& entry : data_)
327 auto [qVal,num,basis] = entry;
328 if (qVal == q) {
return true;}
333template<
typename Symmetry>
335inner_num(
const Eigen::Index& outer_num)
const
337 assert( outer_num < size() and
"The number larger than the size of this basis." );
338 Eigen::Index check = outer_num;
339 for (
const auto& q : data_)
341 auto [qVal,num,plain] = q;
342 for (
const auto& elem : plain)
344 auto [ident,inner_num] = elem;
345 if (check == num+inner_num) {
return inner_num; }
348 assert(
false and
"Something went wrong in Qbasis::inner_num");
351template<
typename Symmetry>
353location(
const std::string& ident)
const
355 for(
const auto& elem : data_)
357 auto [qVal,num,plain] = elem;
358 if(plain.location(ident) != std::numeric_limits<Eigen::Index>::max()) {
return plain.location(ident);}
360 assert( 1!=1 and
"The ident is not in the basis" );
363template<
typename Symmetry>
367 for(
const auto& elem : data_)
369 auto [qVal,num,plain] = elem;
370 if (qVal == q) {
return plain.size();}
376template<
typename Symmetry>
380 for(
const auto& elem : data_)
382 auto [qVal,num,plain] = elem;
383 if (qVal == q) {
return num;}
386 assert( 1!=1 and
"The qType is not in the basis" );
389template<
typename Symmetry>
391inner_dim(
const Eigen::Index& num_in)
const
393 for(
const auto& elem : data_)
395 auto [qVal,num,plain] = elem;
396 if (num == num_in) {
return plain.size();}
398 assert( 1!=1 and
"This number is not in the basis" );
401template<
typename Symmetry>
405 assert( history.size() == data_.size() and
"The history for this basis is not defined properly");
406 auto it = history.find(qnew);
407 assert( it != history.end() and
"The history for this basis is not defined properly");
411 for(
const auto& i: it->second )
413 if(i.source != qold and SCHALTER==
true) { out+=i.dim; }
414 if(i.source == qold) { SCHALTER =
true; }
419template<
typename Symmetry>
423 assert( history.size() == data_.size() and
"The history for this basis is not defined properly");
425 auto it = history.find(qnew);
426 assert( it != history.end() and
"The history for this basis is not defined properly");
430 for(
const auto& i: it->second )
432 if(i.source != qold and SCHALTER==
false) { out+=i.dim; }
433 if(i.source == qold) {
break; }
438template<
typename Symmetry>
440leftOffset(
const qType& qnew,
const std::array<qType,2>& qold,
const std::array<Eigen::Index,2>& plain_old)
const
442 assert( history.size() == data_.size() and
"The history for this basis is not defined properly");
444 auto it = history.find(qnew);
445 assert( it != history.end() and
"The history for this basis is not defined properly");
449 for(
const auto& i: it->second )
451 if(i.source != qold) { out+=i.dim; }
454 for (
size_t j=0; j<i.plainHistory.dim1*i.plainHistory.dim2; j++)
456 if(i.plainHistory.source(j) != plain_old) { out+=1; }
457 if(i.plainHistory.source(j) == plain_old) {
break; }
483template<
typename Symmetry>
484template<
typename MatrixType>
488 std::unordered_set<qType> unique_controller;
489 for (std::size_t s=0; s<
A.size(); s++)
490 for (std::size_t q=0; q<
A[s].size(); q++)
494 auto it = unique_controller.find(
A[s].in[q]);
495 if( it==unique_controller.end() )
497 qType q_number =
A[s].in[q];
498 Eigen::Index inner_dim =
A[s].block[q].rows();
499 push_back(q_number,inner_dim);
500 unique_controller.insert(q_number);
505 auto it = unique_controller.find(
A[s].out[q]);
506 if( it==unique_controller.end() )
508 qType q_number =
A[s].out[q];
509 Eigen::Index inner_dim =
A[s].block[q].cols();
510 push_back(q_number,inner_dim);
511 unique_controller.insert(q_number);
517template<
typename Symmetry>
518template<
typename MatrixType>
522 std::unordered_set<qType> unique_controller;
523 for (std::size_t s1=0; s1<W.size(); s1++)
524 for(std::size_t s2=0; s2<W[s1].size(); s2++)
525 for(std::size_t k=0; k<W[s1][s2].size(); k++)
526 for (std::size_t q=0; q<W[s1][s2][k].size(); q++)
530 auto it = unique_controller.find(W[s1][s2][k].in[q]);
531 if( it==unique_controller.end() )
533 qType q_number = W[s1][s2][k].in[q];
534 Eigen::Index inner_dim = W[s1][s2][k].block[q].rows();
535 push_back(q_number,inner_dim);
536 unique_controller.insert(q_number);
541 auto it = unique_controller.find(W[s1][s2][k].out[q]);
542 if( it==unique_controller.end() )
544 qType q_number = W[s1][s2][k].out[q];
545 Eigen::Index inner_dim = W[s1][s2][k].block[q].cols();
546 push_back(q_number,inner_dim);
547 unique_controller.insert(q_number);
553template<
typename Symmetry>
555pullData (
const std::vector<std::array<qType,3> > &qvec,
const std::size_t &leg,
const Eigen::Index &inner_dim_in)
557 std::unordered_set<qType> unique_controller;
558 Eigen::Index inner_dim = inner_dim_in;
559 for (std::size_t nu=0; nu<qvec.size(); nu++)
561 auto it = unique_controller.find(qvec[nu][leg]);
562 if( it==unique_controller.end() )
564 qType q_number = qvec[nu][leg];
565 push_back(q_number,inner_dim);
566 unique_controller.insert(q_number);
571template<
typename Symmetry>
577 for (
const auto & q : qs)
599template<
typename Symmetry>
604 std::vector<std::size_t> index_sort(data_.size());
605 std::iota(index_sort.begin(),index_sort.end(),0);
606 std::sort (index_sort.begin(), index_sort.end(),
607 [&] (std::size_t n1, std::size_t n2)
609 qarray<Symmetry::Nq> q1 = std::get<0>(data_[n1]);
610 qarray<Symmetry::Nq> q2 = std::get<0>(data_[n2]);
611 return Symmetry::compare(std::array{q1},std::array{q2});
614 auto new_data_ = data_;
615 for (std::size_t i=0; i<data_.size(); i++)
617 new_data_[i] = data_[index_sort[i]];
619 std::get<1>(new_data_[0]) = 0;
620 for (std::size_t i=1; i<data_.size(); i++)
622 std::get<1>(new_data_[i]) = 0;
623 for (std::size_t j=0; j<i; j++)
625 std::get<1>(new_data_[i]) += std::get<2>(new_data_[j]).size();
631template<
typename Symmetry>
635 return (this->data_ == other.
data_);
638template<
typename Symmetry>
643 std::unordered_set<qType> uniqueController;
645 for(
const auto& [q1,num1,plain1] : this->data_)
648 auto it_other = std::find_if(other.
data_.begin(), other.
data_.end(), [qtmp] (std::tuple<qType,Eigen::Index,Basis> entry) { return std::get<0>(entry) == qtmp; });
649 if (it_other != other.
data_.end())
651 out.
push_back(q1,plain1.add(std::get<2>(*it_other)).size());
659 for(
const auto& [q2,num2,plain2] : other.
data_)
662 auto it_this = std::find_if(data_.begin(), data_.end(), [qtmp] (std::tuple<qType,Eigen::Index,Basis> entry) { return std::get<0>(entry) == qtmp; });
663 if (it_this == data_.end())
672template<
typename Symmetry>
676 vector<fuseData> history_;
680 history_.push_back(entry);
681 history.insert(std::make_pair(Qval,history_));
684template<
typename Symmetry>
690 for(
const auto& elem1 : this->data_)
692 auto [q1,num1,plain1] = elem1;
693 for(
const auto& elem2 : other.
data_)
695 auto [q2,num2,plain2] = elem2;
698 q2 = Symmetry::flip(q2);
700 auto plain = plain1.combine(plain2);
701 auto qVec = Symmetry::reduceSilent(q1,q2);
702 for (
const auto& q: qVec)
707 std::vector<fuseData> history_;
710 entry.
dim = plain1.size() * plain2.size();
720 history_.push_back(entry);
721 out.
history.insert(std::make_pair(q,history_));
725 bool DONT_COUNT=
false;
726 for(
const auto& entry: it->second )
728 std::array<qType,2> tmp = {q1,q2};
729 if ( entry.source == tmp )
734 if ( DONT_COUNT ==
false )
738 entry.
dim = plain1.size() * plain2.size();
748 (it->second).push_back(entry);
758 std::vector<std::size_t> index_sort((it->second).size());
759 std::iota(index_sort.begin(),index_sort.end(),0);
760 std::sort (index_sort.begin(), index_sort.end(),
761 [&] (std::size_t n1, std::size_t n2)
763 return Symmetry::compare((it->second)[n1].source,(it->second)[n2].source);
766 std::vector<fuseData> entry2 = it->second;
767 for (std::size_t i=0; i<entry2.size(); i++)
769 (it->second)[i] = entry2[index_sort[i]];
776 Eigen::Index inner_dim = 0;
777 std::vector<string> idents;
778 for(
const auto& i: it->second)
800template<
typename Symmetry>
804 std::stringstream out;
805 #ifdef TOOLS_IO_TABLE
806 TextTable t(
'-',
'|',
'+' );
811 for(
const auto& entry : data_)
813 auto [q_Phys,curr_num,plain] = entry;
814 std::stringstream ss, tt, uu;
815 ss << Sym::format<Symmetry>(q_Phys);
839 out <<
"The stream operator for Qbasis needs the TextTable library.";
844template<
typename Symmetry>
848 std::stringstream out;
849 for(
auto it=history.begin(); it!=history.end(); it++)
851 out << it->second.size() <<
" quantumnumber pair(s) merge to Q=" << it->first << std::endl;
852 for(
const auto& i: it->second)
854 out << i.source[0] <<
"," << i.source[1] <<
"\t→\t" << it->first <<
": dim=" << i.dim << std::endl;
855 assert(i.dim == i.plainHistory.dim1*i.plainHistory.dim2);
856 for (std::size_t j=0; j<i.dim; j++)
858 out <<
"j=" << j <<
" results from(" << i.plainHistory.source(j)[0] <<
"," << i.plainHistory.source(j)[1] <<
")" << std::endl;
867template<
typename Symmetry>
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
std::ostream & operator<<(std::ostream &os, const Qbasis< Symmetry > &basis)
void pullData(const std::vector< std::array< qType, 3 > > &qvec, const std::size_t &leg, const Eigen::Index &inner_dim_in)
void push_back(const std::tuple< qType, Eigen::Index, std::vector< std::string > > &state)
void push_back(const qType &q_number, const Eigen::Index &inner_dim, const std::vector< std::string > &idents)
Eigen::Index inner_dim(const qType &q) const
Eigen::Index leftAmount(const qType &qnew, const std::array< qType, 2 > &qold) const
const std::vector< qType > qs() const
std::vector< std::tuple< qType, Eigen::Index, Basis > >::iterator end()
qType operator[](const std::size_t index) const
Eigen::Index rightAmount(const qType &qnew, const std::array< qType, 2 > &qold) const
void push_back(const qType &q_number, const Eigen::Index &inner_dim)
std::string printHistory() const
std::size_t fullM() const
qType find(const std::string &ident) const
Eigen::Index inner_num(const Eigen::Index &outer_num) const
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
Qbasis(const vector< qarray< Symmetry::Nq > > &base_input)
Eigen::Index location(const std::string &ident) const
std::vector< std::tuple< qType, Eigen::Index, Basis > >::const_iterator cbegin() const
Qbasis< Symmetry > add(const Qbasis< Symmetry > &other) const
Eigen::Index leftOffset(const qType &qnew, const std::array< qType, 2 > &qold, const std::array< Eigen::Index, 2 > &plain_old) const
Qbasis(const Container &qins, const Eigen::Index &dim)
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
bool operator==(const Qbasis< Symmetry > &other) const
void setHistoryEntry(const qType &Qval, const qType &Q1, const qType &Q2, Eigen::Index dim)
void swap(Qbasis< Symmetry > &other)
std::vector< std::tuple< qType, Eigen::Index, Basis > > data_
const std::vector< qType > qloc() const
std::vector< std::tuple< qType, Eigen::Index, Basis > >::const_iterator cend() const
bool find(const qType &q) const
void pullData(const vector< vector< vector< Biped< Symmetry, MatrixType > > > > &W, const Eigen::Index &leg)
qType find(const Eigen::Index &num) const
std::string print() const
const std::unordered_set< qType > unordered_qs() const
std::vector< std::tuple< qType, Eigen::Index, Basis > >::iterator begin()
std::unordered_map< qType, std::vector< fuseData > > history
void pullData(const std::vector< qarray< Symmetry::Nq > > &qs)
Eigen::Index outer_num(const qType &q) const
Eigen::Index inner_dim(const Eigen::Index &num_in) const
std::array< qType, 2 > source
Basis::fuseData plainHistory