permutation generators for multiset and with restrictions
This commit is contained in:
parent
50b2447535
commit
6ea863627d
115
permutation.cc
115
permutation.cc
@ -21,6 +21,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include "qsort.h"
|
||||||
|
|
||||||
|
|
||||||
namespace LA {
|
namespace LA {
|
||||||
@ -246,6 +247,39 @@ end:
|
|||||||
return select? sumperm/2:sumperm;
|
return select? sumperm/2:sumperm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Algorithm L2 from Knuth's volume 4 for multiset permutations
|
||||||
|
//input must be initialized with (repeated) numbers in any order
|
||||||
|
template <typename T>
|
||||||
|
PERM_RANK_TYPE NRPerm<T>::generate_all_multi(void (*callback)(const NRPerm<T>&))
|
||||||
|
{
|
||||||
|
PERM_RANK_TYPE sumperm=0;
|
||||||
|
this->copyonwrite();
|
||||||
|
myheapsort(this->size(),&(*this)[1],1);
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int j,k,l;
|
||||||
|
T t;
|
||||||
|
|
||||||
|
sumperm++;
|
||||||
|
(*callback)(*this);
|
||||||
|
j=this->size()-1;
|
||||||
|
while(j>0 && (*this)[j]>=(*this)[j+1]) j--;
|
||||||
|
if(j==0) break; /*finished*/
|
||||||
|
l=this->size();
|
||||||
|
while((*this)[j]>=(*this)[l]) l--;
|
||||||
|
t=(*this)[j];(*this)[j]=(*this)[l];(*this)[l]=t;
|
||||||
|
k=j+1;
|
||||||
|
l=this->size();
|
||||||
|
while(k<l)
|
||||||
|
{
|
||||||
|
t=(*this)[k];(*this)[k]=(*this)[l];(*this)[l]=t;
|
||||||
|
k++;l--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sumperm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static T _n;
|
static T _n;
|
||||||
@ -253,13 +287,13 @@ static T _n;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static void (*_callback)(const NRPerm<T>& );
|
static void (*_callback)(const NRPerm<T>& );
|
||||||
|
|
||||||
PERM_RANK_TYPE _sumperm;
|
static PERM_RANK_TYPE _sumperm;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NRPerm<T> *_perm;
|
static NRPerm<T> *_perm;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void permg(T n)
|
static void permg(T n)
|
||||||
{
|
{
|
||||||
if(n<= _n<T>)
|
if(n<= _n<T>)
|
||||||
{
|
{
|
||||||
@ -307,6 +341,81 @@ do{
|
|||||||
return np;
|
return np;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T _n2;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void (*_callback2)(const NRPerm<T>& );
|
||||||
|
|
||||||
|
static PERM_RANK_TYPE _sumperm2;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static NRPerm<T> *_perm2;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static const T *pclasses2;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T *_pperm;
|
||||||
|
|
||||||
|
static int sameclass;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void permg2(T n) //place number n in a free box in all possible ways and according to restrictions
|
||||||
|
{
|
||||||
|
T i;
|
||||||
|
if(n<=_n2<T>)
|
||||||
|
{
|
||||||
|
T c=pclasses2<T>[n];
|
||||||
|
for(i=1;i<=_n2<T>;i++)
|
||||||
|
{
|
||||||
|
if(_pperm<T>[i]>=1) goto skipme; /*place already occupied*/
|
||||||
|
if (sameclass)
|
||||||
|
{
|
||||||
|
if(sameclass==1 && c!=pclasses2<T>[i]) goto skipme;
|
||||||
|
if(sameclass== -1 && c==pclasses2<T>[i] ) goto skipme;
|
||||||
|
if(sameclass== -2) /*allow only permutations which leave elements of each class sorted*/
|
||||||
|
{
|
||||||
|
T j,k;
|
||||||
|
for(j=i+1; j<=_n2<T>; j++)
|
||||||
|
if((k=_pperm<T>[j])>=1)
|
||||||
|
if(/* automatically fulfilled k<n &&*/ c==pclasses2<T>[k]) goto skipme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*put it there and next number*/
|
||||||
|
_pperm<T>[i]=n;
|
||||||
|
permg2(n+1);
|
||||||
|
_pperm<T>[i]=0;
|
||||||
|
skipme:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sumperm2++;
|
||||||
|
(*_callback2<T>)(*_perm2<T>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
PERM_RANK_TYPE NRPerm<T>::generate_restricted(void (*callback)(const NRPerm<T>&), const NRVec_from1<T> &classes, int restriction_type)
|
||||||
|
{
|
||||||
|
this->copyonwrite();
|
||||||
|
this->clear();
|
||||||
|
_n2<T> = this->size();
|
||||||
|
_callback2<T> =callback;
|
||||||
|
_sumperm2=0;
|
||||||
|
_perm2<T> = this;
|
||||||
|
_pperm<T> = &(*this)[1]-1;
|
||||||
|
pclasses2<T> = &classes[1]-1;
|
||||||
|
sameclass=restriction_type;
|
||||||
|
permg2<T>(1);
|
||||||
|
return _sumperm2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
PERM_RANK_TYPE NRPerm<T>::rank() const
|
PERM_RANK_TYPE NRPerm<T>::rank() const
|
||||||
{
|
{
|
||||||
|
@ -58,12 +58,14 @@ public:
|
|||||||
NRPerm operator*(const NRPerm q) const; //q is rhs and applied first, this applied second
|
NRPerm operator*(const NRPerm q) const; //q is rhs and applied first, this applied second
|
||||||
NRPerm operator*(const CyclePerm<T> &r) const;
|
NRPerm operator*(const CyclePerm<T> &r) const;
|
||||||
NRPerm conjugate_by(const NRPerm q) const; //q^-1 p q
|
NRPerm conjugate_by(const NRPerm q) const; //q^-1 p q
|
||||||
int parity() const;
|
int parity() const; //returns +/- 1
|
||||||
void randomize(void); //uniformly random by Fisher-Yates shuffle
|
void randomize(void); //uniformly random by Fisher-Yates shuffle
|
||||||
bool next(); //generate next permutation in lex order
|
bool next(); //generate next permutation in lex order
|
||||||
PERM_RANK_TYPE generate_all(void (*callback)(const NRPerm<T>&), int parity_select=0); //Algorithm from Knuth's vol.4, efficient but not 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)
|
||||||
PERM_RANK_TYPE generate_all2(void (*callback)(const NRPerm<T>&)); //recursive method, also not lexicographic
|
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_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);
|
||||||
PERM_RANK_TYPE rank() const; //counted from 0 to n!-1
|
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
|
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
|
explicit NRPerm(const int type, const NRVec_from1<T> &inversions); //compute permutation from inversions
|
||||||
|
38
qsort.h
38
qsort.h
@ -243,5 +243,43 @@ else
|
|||||||
return parity;
|
return parity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//heapsort
|
||||||
|
//DATA must have assignmend and comparison operators implemented
|
||||||
|
template<typename INDEX, typename DATA>
|
||||||
|
void myheapsort(INDEX n, DATA *ra,int typ=1)
|
||||||
|
{
|
||||||
|
INDEX l,j,ir,i;
|
||||||
|
DATA rra;
|
||||||
|
ra--; //below indexed from 1
|
||||||
|
|
||||||
|
l=(n >> 1)+1;
|
||||||
|
ir=n;
|
||||||
|
for (;;) {
|
||||||
|
if (l > 1) {
|
||||||
|
rra=ra[--l];
|
||||||
|
} else {
|
||||||
|
rra=ra[ir];
|
||||||
|
ra[ir]=ra[1];
|
||||||
|
if (--ir == 1) {
|
||||||
|
ra[1]=rra;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=l;
|
||||||
|
j=l << 1;
|
||||||
|
while (j <= ir) {
|
||||||
|
if (j < ir && (typ>0?ra[j] < ra[j+1]:ra[j]>ra[j+1])) ++j;
|
||||||
|
if (typ>0?rra < ra[j]:rra>ra[j]) {
|
||||||
|
ra[i]=ra[j];
|
||||||
|
j += (i=j);
|
||||||
|
}
|
||||||
|
else j=ir+1;
|
||||||
|
}
|
||||||
|
ra[i]=rra;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}//namespace
|
}//namespace
|
||||||
#endif
|
#endif
|
||||||
|
42
t.cc
42
t.cc
@ -75,6 +75,19 @@ for(int i=0; i<4; ++i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printme0(const NRPerm<int> &p)
|
||||||
|
{
|
||||||
|
cout<<p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printme1(const NRPerm<int> &p)
|
||||||
|
{
|
||||||
|
cout <<p.parity()<<' ';
|
||||||
|
cout<<p;
|
||||||
|
//cout<<p.inverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int unitary_n;
|
static int unitary_n;
|
||||||
static PERM_RANK_TYPE space_dim;
|
static PERM_RANK_TYPE space_dim;
|
||||||
|
|
||||||
@ -2187,6 +2200,33 @@ int tot=p.generate_all_lex(printme);
|
|||||||
cout <<"generated "<<tot<<endl;
|
cout <<"generated "<<tot<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
cin >>n;
|
||||||
|
NRPerm<int> p(n);
|
||||||
|
int seed;
|
||||||
|
int f=open("/dev/random",O_RDONLY);
|
||||||
|
if(sizeof(int)!=read(f,&seed,sizeof(int))) laerror("cannot read /dev/random");
|
||||||
|
close(f);
|
||||||
|
srand(seed);
|
||||||
|
for(int i=1; i<=n; ++i) p[i]=1+RANDINT32()%(n-1);
|
||||||
|
cout <<"Initial = "<<p<<endl;
|
||||||
|
int tot=p.generate_all_multi(printme0);
|
||||||
|
cout <<"generated "<<tot<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(0)
|
if(0)
|
||||||
{
|
{
|
||||||
int n,unitary_n;;
|
int n,unitary_n;;
|
||||||
@ -2969,7 +3009,7 @@ cout <<c%ir<<endl;
|
|||||||
cout <<cc<<endl;
|
cout <<cc<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1)
|
if(0)
|
||||||
{
|
{
|
||||||
int seed;
|
int seed;
|
||||||
int f=open("/dev/random",O_RDONLY);
|
int f=open("/dev/random",O_RDONLY);
|
||||||
|
Loading…
Reference in New Issue
Block a user