working on permutation

This commit is contained in:
Jiri Pittner 2024-01-17 17:59:19 +01:00
parent 1e83fcfaf9
commit 32f2a1abd5
4 changed files with 124 additions and 18 deletions

View File

@ -163,12 +163,19 @@ return q.inverse()*((*this)*q);
} }
//NOTE: for larger permutations it might be more efficient to use cycle decomposition but where exactly the breakeven is?
//at the moment we do it the trivial way for small permutations and using sort for larger ones
template <typename T> template <typename T>
int NRPerm<T>::parity() const int NRPerm<T>::parity() const
{ {
if(!this->is_valid()) return 0; if(!this->is_valid()) return 0;
T n=this->size(); T n=this->size();
if(n==1) return 1; if(n==1) return 1;
if(n>=10) //???
{
NRPerm<T> tmp(*this);
return (tmp.sort()&1) ? -1:1;
}
T count=0; T count=0;
for(T i=2;i<=n;i++) for(T j=1;j<i;j++) if((*this)[j]>(*this)[i]) count++; for(T i=2;i<=n;i++) for(T j=1;j<i;j++) if((*this)[j]>(*this)[i]) count++;
return (count&1)? -1:1; return (count&1)? -1:1;
@ -313,6 +320,17 @@ return ret;
} }
template <typename T, typename R>
bool PermutationAlgebra<T,R>::operator==(PermutationAlgebra<T,R> &rhs)
{
simplify();
rhs.simplify();
if(size()!=rhs.size()) return false;
for(int i=0; i<size(); ++i) if((*this)[i].weight!=rhs[i].weight || (*this)[i].perm!=rhs[i].perm) return false;
return true;
}
//Algorithm L2 from Knuth's volume 4 for multiset permutations //Algorithm L2 from Knuth's volume 4 for multiset permutations
//input must be initialized with (repeated) numbers in any order //input must be initialized with (repeated) numbers in any order
@ -755,6 +773,7 @@ PermutationAlgebra<T,R> res(this->size()*rhs.size());
for(int i=0; i<this->size(); ++i) for(int i=0; i<this->size(); ++i)
for(int j=0; j<rhs.size(); ++j) for(int j=0; j<rhs.size(); ++j)
res[i*rhs.size()+j] = (*this)[i]*rhs[j]; res[i*rhs.size()+j] = (*this)[i]*rhs[j];
res.simplify();
return res; return res;
} }
@ -762,17 +781,12 @@ template <typename T, typename R>
PermutationAlgebra<T,R> PermutationAlgebra<T,R>::operator+(const PermutationAlgebra<T,R> &rhs) const PermutationAlgebra<T,R> PermutationAlgebra<T,R>::operator+(const PermutationAlgebra<T,R> &rhs) const
{ {
if(this->size()>0 && rhs.size()>0 && (*this)[0].perm.size()!=rhs[0].perm.size()) laerror("permutation sizes do not match"); if(this->size()>0 && rhs.size()>0 && (*this)[0].perm.size()!=rhs[0].perm.size()) laerror("permutation sizes do not match");
return this->concat(rhs); PermutationAlgebra<T,R> res=this->concat(rhs);
res.simplify();
return res;
} }
template <typename T, typename R>
void PermutationAlgebra<T,R>::simplify()
{
copyonwrite();
sort();
//@@@@implement merging weights of identical permutations and resize like we did in qubithamiltonian with other stuff
}

View File

@ -107,6 +107,9 @@ public:
NRPerm<T> perm; NRPerm<T> perm;
int size() const {return perm.size();}; int size() const {return perm.size();};
bool is_zero() const {return weight==0;}
bool is_scaledidentity() const {return perm.is_identity();}
bool is_identity() const {return weight==1 && is_scaledidentity();}
bool is_plaindata() const {return false;}; bool is_plaindata() const {return false;};
WeightPermutation() : weight(0) {}; WeightPermutation() : weight(0) {};
WeightPermutation(const R w, const NRPerm<T> &p) : weight(w), perm(p) {}; WeightPermutation(const R w, const NRPerm<T> &p) : weight(w), perm(p) {};
@ -116,7 +119,6 @@ public:
WeightPermutation operator|(const WeightPermutation &rhs) const {return WeightPermutation(weight*rhs.weight,perm|rhs.perm);}; WeightPermutation operator|(const WeightPermutation &rhs) const {return WeightPermutation(weight*rhs.weight,perm|rhs.perm);};
WeightPermutation operator*(const WeightPermutation &rhs) const {return WeightPermutation(weight*rhs.weight,perm*rhs.perm);}; WeightPermutation operator*(const WeightPermutation &rhs) const {return WeightPermutation(weight*rhs.weight,perm*rhs.perm);};
WeightPermutation operator*(const R &x) const {return WeightPermutation(weight*x,perm); } WeightPermutation operator*(const R &x) const {return WeightPermutation(weight*x,perm); }
//@@@operator+ and - yielding Permutationalgebra
bool operator==(const WeightPermutation &rhs) const {return this->perm == rhs.perm;}; //NOTE for sorting, compares only the permutation not the weight! bool operator==(const WeightPermutation &rhs) const {return this->perm == rhs.perm;}; //NOTE for sorting, compares only the permutation not the weight!
bool operator>(const WeightPermutation &rhs) const {return this->perm > rhs.perm;}; bool operator>(const WeightPermutation &rhs) const {return this->perm > rhs.perm;};
@ -135,9 +137,13 @@ public:
static bool is_plaindata() {return false;}; static bool is_plaindata() {return false;};
static void copyonwrite(WeightPermutation<T,R>& x) {x.perm.copyonwrite();}; static void copyonwrite(WeightPermutation<T,R>& x) {x.perm.copyonwrite();};
typedef typename LA_traits<R>::normtype normtype; typedef typename LA_traits<R>::normtype normtype;
typedef R coefficienttype;
typedef NRPerm<T> elementtype;
static inline bool smaller(const WeightPermutation<T,R>& x, const WeightPermutation<T,R>& y) {return x.perm<y.perm;}; static inline bool smaller(const WeightPermutation<T,R>& x, const WeightPermutation<T,R>& y) {return x.perm<y.perm;};
static inline bool bigger(const WeightPermutation<T,R>& x, const WeightPermutation<T,R>& y) {return x.perm>y.perm;}; static inline bool bigger(const WeightPermutation<T,R>& x, const WeightPermutation<T,R>& y) {return x.perm>y.perm;};
static R coefficient(const WeightPermutation<T,R>& x){return x.weight;};
static R& coefficient(WeightPermutation<T,R>& x) {return x.weight;};
static typename LA_traits<R>::normtype abscoefficient(const WeightPermutation<T,R>& x){return LA_traits<R>::abs2(x.weight);};
}; };
@ -168,7 +174,7 @@ public:
PermutationAlgebra(const NRVec<WeightPermutation<T,R> > &x) : NRVec<WeightPermutation<T,R> >(x) {}; PermutationAlgebra(const NRVec<WeightPermutation<T,R> > &x) : NRVec<WeightPermutation<T,R> >(x) {};
int size() const {return NRVec<WeightPermutation<T,R> >::size();}; int size() const {return NRVec<WeightPermutation<T,R> >::size();};
void copyonwrite() {NRVec<WeightPermutation<T,R> >::copyonwrite();}; void copyonwrite() {NRVec<WeightPermutation<T,R> >::copyonwrite();};
void sort(int direction = 0, int from = 0, int to = -1, int *permut = NULL, bool stable=false) {NRVec<WeightPermutation<T,R> >::sort(direction,from, to,permut,stable);}; int sort(int direction = 0, int from = 0, int to = -1, int *permut = NULL, bool stable=false) {return NRVec<WeightPermutation<T,R> >::sort(direction,from, to,permut,stable);};
PermutationAlgebra operator&(const PermutationAlgebra &rhs) const; PermutationAlgebra operator&(const PermutationAlgebra &rhs) const;
PermutationAlgebra operator|(const PermutationAlgebra &rhs) const; PermutationAlgebra operator|(const PermutationAlgebra &rhs) const;
@ -176,10 +182,13 @@ public:
PermutationAlgebra operator+(const PermutationAlgebra &rhs) const; PermutationAlgebra operator+(const PermutationAlgebra &rhs) const;
PermutationAlgebra &operator*=(const R &x) {this->copyonwrite(); for(int i=1; i<=size(); ++i) (*this)[i].weight *= x; return *this;}; PermutationAlgebra &operator*=(const R &x) {this->copyonwrite(); for(int i=1; i<=size(); ++i) (*this)[i].weight *= x; return *this;};
PermutationAlgebra operator*(const R &x) const {PermutationAlgebra r(*this); return r*=x;}; PermutationAlgebra operator*(const R &x) const {PermutationAlgebra r(*this); return r*=x;};
void simplify(); void simplify(const typename LA_traits<R>::normtype thr=0) {NRVec_simplify(*this,thr);};
bool operator==(PermutationAlgebra &rhs); //do NOT inherit from NRVec, as the underlying one ignores weights for the simplification; also we have to simplify before comparison
bool is_zero() const {return size()==0;}; //assume it was simplified
bool is_scaled_identity() const {return size()==1 && (*this)[0]. is_scaledidentity();}; //assume it was simplified
bool is_identity() const {return size()==1 && (*this)[0]. is_identity();}; //assume it was simplified
}; };
//TODO@@@ also simplification after operation
//TODO@@@ permutationalgebra for Kucharski style antisymmetrizers //TODO@@@ permutationalgebra for Kucharski style antisymmetrizers
@ -343,6 +352,8 @@ NRMat_from1<T> chi; //characters
Sn_characters(const int n0); //compute the table Sn_characters(const int n0); //compute the table
bool is_valid() const; //check internal consistency bool is_valid() const; //check internal consistency
T irrepdim(T i) const {return chi(i,1);};
T sumirrepdims() const {T s=0; for(T i=1; i<=chi.nrows(); ++i) s+=irrepdim(i); return s;};
}; };
template <typename T> class Polynomial; //forward declaration template <typename T> class Polynomial; //forward declaration

46
t.cc
View File

@ -90,28 +90,38 @@ cout<<p;
static int unitary_n; static int unitary_n;
static PERM_RANK_TYPE space_dim; static PERM_RANK_TYPE space_dim;
static NRVec<PermutationAlgebra<int,int> > allyoung;
static NRVec<int> allyoung_irrep;
int current_irrep;
int allyoung_index;
void yprintme(const YoungTableaux<int>&y) void yprintme(const YoungTableaux<int>&y)
{ {
cout <<y; cout <<y;
if(!y.is_standard()) laerror("internal error in young"); if(!y.is_standard()) laerror("internal error in young");
cout << y.young_operator(); allyoung[allyoung_index] = y.young_operator();
cout <<"Young "<<allyoung_index<<" (irrep "<<current_irrep<<") = "<<allyoung[allyoung_index]<<endl;
allyoung_irrep[allyoung_index]=current_irrep;
allyoung_index++;
} }
void pprintme(const Partition<int> &p) void pprintme(const Partition<int> &p)
{ {
CompressedPartition<int> pc(p); CompressedPartition<int> pc(p);
++current_irrep;
cout<<'['<<pc<<"]\n"; cout<<'['<<pc<<"]\n";
PERM_RANK_TYPE snd=p.Sn_irrep_dim();
cout<<"Sn IR dim "<<snd<<endl;
YoungTableaux<int> y(p); YoungTableaux<int> y(p);
PERM_RANK_TYPE dim=y.generate_all_standard(yprintme); PERM_RANK_TYPE dim=y.generate_all_standard(yprintme);
Partition<int> q=p.adjoint(); Partition<int> q=p.adjoint();
PERM_RANK_TYPE snd=p.Sn_irrep_dim();
cout<<"IR dim "<<snd<<endl;
if(dim!=snd) laerror("inconsistency in standard tableaux generation"); if(dim!=snd) laerror("inconsistency in standard tableaux generation");
PERM_RANK_TYPE und=p.Un_irrep_dim(unitary_n); PERM_RANK_TYPE und=p.Un_irrep_dim(unitary_n);
cout<<"U("<<unitary_n<<") ir dim "<<und<<endl; cout<<"U("<<unitary_n<<") IR dim "<<und<<endl;
space_dim += und*snd; space_dim += und*snd;
CompressedPartition<int> qc(q); CompressedPartition<int> qc(q);
cout <<"("<<qc<<')'; cout <<"("<<qc<<')';
@ -2211,7 +2221,7 @@ int tot=p.generate_all_multi(printme0);
cout <<"generated "<<tot<<endl; cout <<"generated "<<tot<<endl;
} }
if(1) if(0)
{ {
int n; cin >>n; int n; cin >>n;
NRPerm<int> p(n); NRPerm<int> p(n);
@ -2230,13 +2240,35 @@ if(0)
{ {
int n;; int n;;
cin >>n >>unitary_n; cin >>n >>unitary_n;
Sn_characters<int> Sn(n);
cout <<Sn;
if(!Sn.is_valid()) laerror("internal error in Sn character calculation");
cout <<"allyoung.resize "<<Sn.sumirrepdims()<<endl;
allyoung.resize(Sn.sumirrepdims());
allyoung_irrep.resize(Sn.sumirrepdims());
allyoung_index=0;
Partition<int> p(n); Partition<int> p(n);
space_dim=0; space_dim=0;
int tot=p.generate_all(pprintme,0); int tot=p.generate_all(pprintme,0);
cout <<"partitions generated "<<tot<<endl; cout <<"partitions generated "<<tot<<endl;
if(tot!=partitions(n)) laerror("internal error in partition generation or enumerations"); if(tot!=partitions(n)) laerror("internal error in partition generation or enumerations");
if(space_dim!=longpow(unitary_n,n)) {cout<<space_dim<<" "<<ipow(unitary_n,n)<<endl;laerror("integer overflow or internal error in space dimensions");} if(space_dim!=longpow(unitary_n,n)) {cout<<space_dim<<" "<<ipow(unitary_n,n)<<endl;laerror("integer overflow or internal error in space dimensions");}
for(int i=0; i<allyoung.size(); ++i)
for(int j=0; j<allyoung.size(); ++j)
{
PermutationAlgebra<int,int> r=allyoung[i]*allyoung[j];
//cout <<"Young "<<i<<" "<<allyoung[i]<<endl;
//cout <<"Young "<<j<<" "<<allyoung[j]<<endl;
cout <<"Product of Young "<<i<<" and "<<j<<" = "<<r<<"\n";
if(i!=j && !r.is_zero()) cout <<"NONORTHOGONAL Young operators found "<<i<< " "<<j<<" (irreps "<<allyoung_irrep[i]<<" "<<allyoung_irrep[j]<<")\n";
if(allyoung_irrep[i]!=allyoung_irrep[j] && !r.is_zero()) laerror("internal error in PermutationAlgebra");
} }
}
if(0) if(0)
{ {
@ -3051,4 +3083,8 @@ if(!dif.is_zero()) laerror("error in gf 2^n sqrt");
} }
if(1)
{
}
} }

45
vec.h
View File

@ -1986,6 +1986,51 @@ for(typename std::list<T>::const_iterator i=l.begin(); i!=l.end(); ++i) (*this)[
} }
//general simplification template for a NRVec of a class consisting from a coefficient and an element
//the class T must have traits for sorting, normtype, elementtype, coefficienttype, coefficient, abscoefficient, and operator== which ignores the coefficient and uses just the element
//it is not a member function to avoid the need of extra traits when this is not needed
template<typename T>
void NRVec_simplify(NRVec<T> &x, const typename LA_traits<T>::normtype thr=0, bool alwayskeepfirst=false)
{
if(x.size()==0) return;
x.copyonwrite();
//first sort to identify identical terms
x.sort();
//the following operations conserve the sorting, so no need to reset the issorted flag
int newsize=1;
//add factors of identical elements
for(int next=1; next<x.size(); ++next)
{
if(x[next] == x[newsize-1])
{
LA_traits<T>::coefficient(x[newsize-1]) += LA_traits<T>::coefficient(x[next]);
}
else
{
if(next!=newsize) x[newsize] = x[next];
++newsize;
}
}
//now skip terms with zero coefficients
int newsize2=0;
for(int next=0; next<newsize; ++next)
{
if(next==0 && alwayskeepfirst || !(LA_traits<T>::coefficient(x[next])==0 || LA_traits<T>::abscoefficient(x[next]) <thr))
{
if(next!=newsize2) x[newsize2] = x[next];
++newsize2;
}
}
x.resize(newsize2,true);
}
}//namespace }//namespace