permutation generation outputting explicitly PermutationAlgebra class

This commit is contained in:
Jiri Pittner 2024-01-16 15:52:43 +01:00
parent 0fa4f9fc2e
commit 41e9c359d5
3 changed files with 70 additions and 12 deletions

View File

@ -262,7 +262,7 @@ PERM_RANK_TYPE sumperm=0;
p2:
sumperm++;
if(!select || (select&1) == (sumperm&1)) (*callback)(*this);
if(callback) {if(!select || (select&1) == (sumperm&1)) {(*callback)(*this); this->copyonwrite();}}
j=n; s=0;
p4:
q=c[j]+d[j];
@ -284,6 +284,36 @@ end:
return select? sumperm/2:sumperm;
}
template <typename T>
static PermutationAlgebra<T,T> *list_all_return;
static PERM_RANK_TYPE list_all_index;
template <typename T>
static void list_all_callback(const NRPerm<T> &p)
{
(*list_all_return<T>)[list_all_index].weight= (list_all_index&1)?-1:1;
(*list_all_return<T>)[list_all_index].perm=p;
(*list_all_return<T>)[list_all_index].perm.copyonwrite();
++list_all_index;
}
template <typename T>
PermutationAlgebra<T,T> NRPerm<T>::list_all(int parity_sel)
{
PERM_RANK_TYPE number = factorial(this->size());
if(parity_sel) number/=2;
PermutationAlgebra<T,T> ret(number);
list_all_return<T> = &ret;
list_all_index=0;
this->generate_all(list_all_callback,parity_sel);
return ret;
}
//Algorithm L2 from Knuth's volume 4 for multiset permutations
//input must be initialized with (repeated) numbers in any order
template <typename T>
@ -298,7 +328,7 @@ while(1)
T t;
sumperm++;
(*callback)(*this);
if(callback) (*callback)(*this);
j=this->size()-1;
while(j>0 && (*this)[j]>=(*this)[j+1]) j--;
if(j==0) break; /*finished*/
@ -347,7 +377,7 @@ if(n<= _n<T>)
else
{
_sumperm++;
(*_callback<T>)(*_perm<T>);
if(_callback<T>) (*_callback<T>)(*_perm<T>);
}
}
@ -373,7 +403,7 @@ PERM_RANK_TYPE np=0;
this->identity();
do{
++np;
(*callback)(*this);
if(callback) (*callback)(*this);
}while(this->next());
return np;
}
@ -429,12 +459,13 @@ if(n<=_n2<T>)
else
{
_sumperm2++;
(*_callback2<T>)(*_perm2<T>);
if(_callback2<T>) {(*_callback2<T>)(*_perm2<T>); _perm2<T> -> copyonwrite();}
}
}
template <typename T>
PERM_RANK_TYPE NRPerm<T>::generate_restricted(void (*callback)(const NRPerm<T>&), const NRVec_from1<T> &classes, int restriction_type)
{
@ -451,6 +482,30 @@ permg2<T>(1);
return _sumperm2;
}
template <typename T>
static PermutationAlgebra<T,T> *list_restricted_return;
static PERM_RANK_TYPE list_restricted_index;
template <typename T>
static void list_restricted_callback(const NRPerm<T> &p)
{
(*list_restricted_return<T>)[list_restricted_index].weight=p.parity();
(*list_restricted_return<T>)[list_restricted_index].perm=p;
(*list_restricted_return<T>)[list_restricted_index].copyonwrite();
++list_restricted_index;
}
template <typename T>
PermutationAlgebra<T,T> NRPerm<T>::list_restricted(const NRVec_from1<T> &classes, int restriction_type)
{
PERM_RANK_TYPE number = this->generate_restricted(NULL,classes,restriction_type);
PermutationAlgebra<T,T> ret(number);
list_restricted_return<T> = &ret;
list_restricted_index=0;
generate_restricted(list_restricted_callback,classes,restriction_type);
return ret;
}
template <typename T>
@ -1140,7 +1195,7 @@ template <typename T>
void partgen(int remain, int pos)
{
int hi,lo;
if(remain==0) {++partitioncount; (*_pcallback<T>)(*partition<T>); return;}
if(remain==0) {++partitioncount; if(_pcallback<T>) (*_pcallback<T>)(*partition<T>); return;}
if(partitiontyp) lo=(remain+partitiontypabs-pos)/(partitiontypabs-pos+1); else lo=1;
hi=remain;
if(partitiontyp>0) hi -= partitiontypabs-pos;
@ -1539,7 +1594,7 @@ if(ncyc> _ncycles<T>)
{
if(_callyoung)
{
_young_callback<T>(*_tchi<T>);
if(_young_callback<T>) _young_callback<T>(*_tchi<T>);
_character<T> ++;
}
else _character<T> += _tchi<T>->character_contribution(_ncycles<T>);

View File

@ -69,10 +69,12 @@ public:
void randomize(void); //uniformly random by Fisher-Yates shuffle
bool next(); //generate next permutation in lex order
PERM_RANK_TYPE generate_all(void (*callback)(const NRPerm<T>&), int parity_select=0); //Algorithm L from Knuth's vol.4, efficient but not in lex order!
PERM_RANK_TYPE generate_all_multi(void (*callback)(const NRPerm<T>&)); //Algorithm L2 from Knuth's vol.4, for multiset (repeated numbers, not really permutations)
PermutationAlgebra<T,T> list_all(int parity_select=0);
PERM_RANK_TYPE generate_all_multi(void (*callback)(const NRPerm<T>&)); //Algorithm L2 from Knuth's vol.4, for a multiset (repeated numbers, not really permutations)
PERM_RANK_TYPE generate_all2(void (*callback)(const NRPerm<T>&)); //recursive method, also not lexicographic
PERM_RANK_TYPE generate_all_lex(void (*callback)(const NRPerm<T>&)); //generate in lex order using next()
PERM_RANK_TYPE generate_restricted(void (*callback)(const NRPerm<T>&), const NRVec_from1<T> &classes, int restriction_type=0);
PermutationAlgebra<T,T> list_restricted(const NRVec_from1<T> &classes, int restriction_type=0); //weight is set to parity (antisymmetrizer) by default
PERM_RANK_TYPE rank() const; //counted from 0 to n!-1
NRVec_from1<T> inversions(const int type, PERM_RANK_TYPE *prank=NULL) const; //inversion tables
explicit NRPerm(const int type, const NRVec_from1<T> &inversions); //compute permutation from inversions

9
t.cc
View File

@ -2211,18 +2211,19 @@ int tot=p.generate_all_multi(printme0);
cout <<"generated "<<tot<<endl;
}
if(0)
if(1)
{
int n; cin >>n;
NRPerm<int> p(n);
NRVec_from1<int> classes; cin>>classes;
if(classes.size()!=p.size()) laerror("sizes do not match");
int tot=p.generate_restricted(printme1,classes,-2);
cout <<"generated "<<tot<<endl;
PermutationAlgebra<int,int> tot = p.list_restricted(classes,-2);
cout <<"generated\n"<<tot<<endl;
cout <<"ALL\n"<<p.list_all();
}
if(1)
if(0)
{
int n;;
cin >>n >>unitary_n;