continue implementing permutations
This commit is contained in:
parent
60e8a379f5
commit
83b9463334
1
mat.h
1
mat.h
@ -26,6 +26,7 @@ namespace LA {
|
|||||||
|
|
||||||
//forward declaration
|
//forward declaration
|
||||||
template<typename T> class NRPerm;
|
template<typename T> class NRPerm;
|
||||||
|
template<typename T> class CyclePerm;
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
|
162
permutation.cc
162
permutation.cc
@ -117,11 +117,173 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NRPerm<T>::NRPerm(const CyclePerm<T> &rhs, int n)
|
||||||
|
: NRVec_from1<T>(n)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!rhs.is_valid()) laerror("invalid cycle permutation");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
identity();
|
||||||
|
T ncycles=rhs.size();
|
||||||
|
for(T j=1; j<=ncycles; ++j)
|
||||||
|
{
|
||||||
|
T length= rhs[j].size();
|
||||||
|
for(T i=1; i<=length; ++i) (*this)[rhs[j][i]] = rhs[j][i%length+1];
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!is_valid()) laerror("internal error in NRPerm constructor from CyclePerm");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
CyclePerm<T>:: CyclePerm(const NRPerm<T> &p)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!p.is_valid()) laerror("invalid permutation");
|
||||||
|
#endif
|
||||||
|
T n=p.size();
|
||||||
|
NRVec_from1<T> used(0,n),tmp(n);
|
||||||
|
T firstunused=1;
|
||||||
|
T currentcycle=0;
|
||||||
|
std::list<NRVec<T> > cyclelist={};
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//find a cycle starting with first unused element
|
||||||
|
T cyclelength=0;
|
||||||
|
T next = firstunused;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
++cyclelength;
|
||||||
|
used[next]=1;
|
||||||
|
tmp[cyclelength] = next;
|
||||||
|
next = p[next];
|
||||||
|
}
|
||||||
|
while(used[next]==0);
|
||||||
|
if(cyclelength>1) //nontrivial cycle
|
||||||
|
{
|
||||||
|
NRVec_from1<T> cycle(&tmp[1],cyclelength);
|
||||||
|
cyclelist.push_front(cycle);
|
||||||
|
++currentcycle;
|
||||||
|
}
|
||||||
|
while(used[firstunused]) {++firstunused; if(firstunused>n) break;} //find next unused element
|
||||||
|
}
|
||||||
|
while(firstunused<=n);
|
||||||
|
//convert list to NRVec
|
||||||
|
this->resize(currentcycle);
|
||||||
|
T i=1;
|
||||||
|
for(auto l=cyclelist.begin(); l!=cyclelist.end(); ++l) (*this)[i++] = *l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool CyclePerm<T>::is_valid() const
|
||||||
|
{
|
||||||
|
for(T i=1; i<=this->size(); ++i)
|
||||||
|
{
|
||||||
|
T n=(*this)[i].size();
|
||||||
|
if(n<=0) return false;
|
||||||
|
for(T j=1; j<=n; ++j)
|
||||||
|
{
|
||||||
|
T x=(*this)[i][j];
|
||||||
|
if(x<=0) return false;
|
||||||
|
|
||||||
|
//now check for illegal duplicity of numbers withis a cycle or across cycles
|
||||||
|
for(T ii=i; ii<=this->size(); ++ii)
|
||||||
|
{
|
||||||
|
T nn=(*this)[ii].size();
|
||||||
|
for(T jj=1; jj<=nn; ++jj)
|
||||||
|
{
|
||||||
|
T xx=(*this)[ii][jj];
|
||||||
|
if(x==xx) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool CyclePerm<T>::is_identity() const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!this->is_valid()) laerror("operation with an invalid cycleperm");
|
||||||
|
#endif
|
||||||
|
for(T i=1; i<=this->size(); ++i) if((*this)[i].size()>1) return false; //at least one nontrivial cycle
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
CyclePerm<T> CyclePerm<T>::inverse() const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!this->is_valid()) laerror("operation with an invalid cycleperm");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CyclePerm<T> r;
|
||||||
|
T ncycles=this->size();
|
||||||
|
r.resize(ncycles);
|
||||||
|
for(T i=1; i<=ncycles; ++i)
|
||||||
|
{
|
||||||
|
T length=(*this)[i].size();
|
||||||
|
r[i].resize(length);
|
||||||
|
for(T j=1; j<=length; ++j) r[i][j] = (*this)[i][length-j+1];
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int CyclePerm<T>::parity() const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!this->is_valid()) laerror("operation with an invalid cycleperm");
|
||||||
|
#endif
|
||||||
|
int n_even_cycles=0;
|
||||||
|
T ncycles=this->size();
|
||||||
|
for(T i=1; i<=ncycles; ++i)
|
||||||
|
{
|
||||||
|
T length=(*this)[i].size();
|
||||||
|
if((length&1)==0) ++n_even_cycles;
|
||||||
|
}
|
||||||
|
return (n_even_cycles&1)?-1:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Partition<T> CyclePerm<T>::cycles(const T n) const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!this->is_valid()) laerror("operation with an invalid cycleperm");
|
||||||
|
#endif
|
||||||
|
Partition<T> r(n); r.clear();
|
||||||
|
T ncycles=this->size();
|
||||||
|
for(T i=1; i<=ncycles; ++i)
|
||||||
|
{
|
||||||
|
T length=(*this)[i].size();
|
||||||
|
if(length<=0||length>n) laerror("unexpected cycle length in permutation");
|
||||||
|
r[length]++;
|
||||||
|
}
|
||||||
|
//fill in trivial cycles of length one
|
||||||
|
r[1] = n - r.sum();
|
||||||
|
if(r[1]<0) laerror("inconsistent cycle lengths in CyclePerm::cycles");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* forced instantization in the corresponding object file
|
* forced instantization in the corresponding object file
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
template class NRPerm<int>;
|
template class NRPerm<int>;
|
||||||
|
template class CyclePerm<int>;
|
||||||
|
template class Partition<int>;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include "la_traits.h"
|
#include "la_traits.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
#include "mat.h"
|
|
||||||
|
|
||||||
//permutations are always numbered from 1; offset is employed when applied to vectors and matrices
|
//permutations are always numbered from 1; offset is employed when applied to vectors and matrices
|
||||||
|
|
||||||
@ -30,6 +29,8 @@ namespace LA {
|
|||||||
|
|
||||||
//forward declaration
|
//forward declaration
|
||||||
template <typename T> class NRVec_from1;
|
template <typename T> class NRVec_from1;
|
||||||
|
template <typename T> class CyclePerm;
|
||||||
|
template <typename T> class Partition;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class NRPerm : public NRVec_from1<T> {
|
class NRPerm : public NRVec_from1<T> {
|
||||||
@ -40,6 +41,7 @@ public:
|
|||||||
NRPerm(const NRVec_from1<T> &rhs): NRVec_from1<T>(rhs) {};
|
NRPerm(const NRVec_from1<T> &rhs): NRVec_from1<T>(rhs) {};
|
||||||
NRPerm(const T &a, const int n): NRVec_from1<T>(a, n) {};
|
NRPerm(const T &a, const int n): NRVec_from1<T>(a, n) {};
|
||||||
NRPerm(const T *a, const int n): NRVec_from1<T>(a, n) {};
|
NRPerm(const T *a, const int n): NRVec_from1<T>(a, n) {};
|
||||||
|
NRPerm(const CyclePerm<T> &rhs, int n);
|
||||||
|
|
||||||
//specific operations
|
//specific operations
|
||||||
void identity();
|
void identity();
|
||||||
@ -57,10 +59,44 @@ public:
|
|||||||
//@@@next permutation
|
//@@@next permutation
|
||||||
//@@@lex rank
|
//@@@lex rank
|
||||||
//@@@inversion tables
|
//@@@inversion tables
|
||||||
//@@@conversion to cycle structure and back
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//permutations represented in the cycle format
|
||||||
|
template <typename T>
|
||||||
|
class CyclePerm : public NRVec_from1<NRVec_from1<T> > {
|
||||||
|
public:
|
||||||
|
CyclePerm() : NRVec_from1<NRVec_from1<T> >() {};
|
||||||
|
CyclePerm(const NRPerm<T> &rhs);
|
||||||
|
|
||||||
|
bool is_valid() const; //is it really a permutation
|
||||||
|
bool is_identity() const; //no cycles of length > 1
|
||||||
|
CyclePerm inverse() const; //reverse all cycles
|
||||||
|
int parity() const; //negative if having odd number of even-length cycles
|
||||||
|
Partition<T> cycles(const T n) const;
|
||||||
|
//@@@efficient algorithm for multiplication?
|
||||||
|
//@@@operator >> and <<
|
||||||
|
//@@@operation in place on matrix and vector
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//partitions stored as #of 1s, #of 2s, etc.
|
||||||
|
template <typename T>
|
||||||
|
class Partition : public NRVec_from1<T> {
|
||||||
|
public:
|
||||||
|
Partition(): NRVec_from1<T>() {};
|
||||||
|
Partition(const int n) : NRVec_from1<T>(n) {};
|
||||||
|
T sum() const {T s=0; for(T i=1; i<=this->size(); ++i) s += i*(*this)[i]; return s;}
|
||||||
|
T nparts() const {T s=0; for(T i=1; i<=this->size(); ++i) s += (*this)[i]; return s;}
|
||||||
|
T nclasses() const {T s=0; for(T i=1; i<=this->size(); ++i) if((*this)[i]) ++s; return s;}
|
||||||
|
bool is_valid() const {return this->size() == this->sum();}
|
||||||
|
|
||||||
|
//@@@generate all partitions,
|
||||||
|
//@@@enumerator of partitions of n to r parts and total
|
||||||
|
//@@@adjoint partition,
|
||||||
|
//@@@ output as in the group character table
|
||||||
|
//@@@Sn character table
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}//namespace
|
}//namespace
|
||||||
|
12
vec.h
12
vec.h
@ -31,6 +31,7 @@ template <typename T> void lawritemat(FILE *file, const T *a, int r, int c,
|
|||||||
const char *form0, int nodim, int modulo, int issym);
|
const char *form0, int nodim, int modulo, int issym);
|
||||||
|
|
||||||
template <typename T> class NRPerm;
|
template <typename T> class NRPerm;
|
||||||
|
template <typename T> class CyclePerm;
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* static constants used in several cblas-routines
|
* static constants used in several cblas-routines
|
||||||
@ -257,11 +258,18 @@ public:
|
|||||||
|
|
||||||
//! compute the sum of the vector elements
|
//! compute the sum of the vector elements
|
||||||
inline const T sum() const {
|
inline const T sum() const {
|
||||||
T sum(0);
|
T sum(v[0]);
|
||||||
for(register int i=0; i<nn; i++){ sum += v[i];}
|
for(register int i=1; i<nn; i++){ sum += v[i];}
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! compute the product of the vector elements
|
||||||
|
inline const T prod() const {
|
||||||
|
T prod(v[0]);
|
||||||
|
for(register int i=1; i<nn; i++){ prod *= v[i];}
|
||||||
|
return prod;
|
||||||
|
};
|
||||||
|
|
||||||
//! permute vector elements
|
//! permute vector elements
|
||||||
const NRVec permute(const NRPerm<int> &p) const;
|
const NRVec permute(const NRPerm<int> &p) const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user