189 lines
4.4 KiB
Plaintext
189 lines
4.4 KiB
Plaintext
@q $Id: permutation.cweb 332 2005-07-15 13:41:48Z kamenik $ @>
|
|
@q Copyright 2004, Ondra Kamenik @>
|
|
|
|
@ Start of {\tt permutation.cweb} file.
|
|
@c
|
|
|
|
#include "permutation.h"
|
|
#include "tl_exception.h"
|
|
|
|
@<|Permutation::apply| code@>;
|
|
@<|Permutation::inverse| code@>;
|
|
@<|Permutation::tailIdentity| code@>;
|
|
@<|Permutation::computeSortingMap| code@>;
|
|
@<|PermutationSet| constructor code 1@>;
|
|
@<|PermutationSet| constructor code 2@>;
|
|
@<|PermutationSet| destructor code@>;
|
|
@<|PermutationSet::getPreserving| code@>;
|
|
@<|PermutationBundle| constructor code@>;
|
|
@<|PermutationBundle| destructor code@>;
|
|
@<|PermutationBundle::get| code@>;
|
|
@<|PermutationBundle::generateUpTo| code@>;
|
|
|
|
|
|
@ This is easy, we simply apply the map in the fashion $s\circ m$..
|
|
@<|Permutation::apply| code@>=
|
|
void Permutation::apply(const IntSequence& src, IntSequence& tar) const
|
|
{
|
|
TL_RAISE_IF(src.size() != permap.size() || tar.size() != permap.size(),
|
|
"Wrong sizes of input or output in Permutation::apply");
|
|
for (int i = 0; i < permap.size(); i++)
|
|
tar[i] = src[permap[i]];
|
|
}
|
|
|
|
|
|
void Permutation::apply(IntSequence& tar) const
|
|
{
|
|
IntSequence tmp(tar);
|
|
apply(tmp, tar);
|
|
}
|
|
|
|
@
|
|
@<|Permutation::inverse| code@>=
|
|
void Permutation::inverse()
|
|
{
|
|
IntSequence former(permap);
|
|
for (int i = 0; i < size(); i++)
|
|
permap[former[i]] = i;
|
|
}
|
|
|
|
|
|
@ Here we find a number of trailing indices which are identical with
|
|
the permutation.
|
|
|
|
@<|Permutation::tailIdentity| code@>=
|
|
int Permutation::tailIdentity() const
|
|
{
|
|
int i = permap.size();
|
|
while (i > 0 && permap[i-1] == i-1)
|
|
i--;
|
|
return permap.size() - i;
|
|
}
|
|
|
|
@ This calculates a map which corresponds to sorting in the following
|
|
sense: $(\hbox{sorted }s)\circ m = s$, where $s$ is a given sequence.
|
|
|
|
We go through |s| and find an the same item in sorted |s|. We
|
|
construct the |permap| from the found pair of indices. We have to be
|
|
careful, to not assign to two positions in |s| the same position in
|
|
sorted |s|, so we maintain a bitmap |flag|, in which we remember
|
|
indices from the sorted |s| already assigned.
|
|
|
|
@<|Permutation::computeSortingMap| code@>=
|
|
void Permutation::computeSortingMap(const IntSequence& s)
|
|
{
|
|
IntSequence srt(s);
|
|
srt.sort();
|
|
IntSequence flags(s.size(),0);
|
|
|
|
for (int i = 0; i < s.size(); i++) {
|
|
int j = 0;
|
|
while (j < s.size() && (flags[j] || srt[j] != s[i]))
|
|
j++;
|
|
TL_RAISE_IF(j == s.size(),
|
|
"Internal algorithm error in Permutation::computeSortingMap");
|
|
flags[j] = 1;
|
|
permap[i] = j;
|
|
}
|
|
}
|
|
|
|
@
|
|
@<|PermutationSet| constructor code 1@>=
|
|
PermutationSet::PermutationSet()
|
|
: order(1), size(1), pers(new const Permutation*[size])
|
|
{
|
|
pers[0] = new Permutation(1);
|
|
}
|
|
|
|
@
|
|
@<|PermutationSet| constructor code 2@>=
|
|
PermutationSet::PermutationSet(const PermutationSet& sp, int n)
|
|
: order(n), size(n*sp.size),
|
|
pers(new const Permutation*[size])
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
pers[i] = NULL;
|
|
|
|
TL_RAISE_IF(n != sp.order+1,
|
|
"Wrong new order in PermutationSet constructor");
|
|
|
|
int k = 0;
|
|
for (int i = 0; i < sp.size; i++) {
|
|
for (int j = 0; j < order; j++,k++) {
|
|
pers[k] = new Permutation(*(sp.pers[i]), j);
|
|
}
|
|
}
|
|
}
|
|
|
|
@
|
|
@<|PermutationSet| destructor code@>=
|
|
PermutationSet::~PermutationSet()
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
if (pers[i])
|
|
delete pers[i];
|
|
delete [] pers;
|
|
}
|
|
|
|
@
|
|
@<|PermutationSet::getPreserving| code@>=
|
|
vector<const Permutation*> PermutationSet::getPreserving(const IntSequence& s) const
|
|
{
|
|
TL_RAISE_IF(s.size() != order,
|
|
"Wrong sequence length in PermutationSet::getPreserving");
|
|
|
|
vector<const Permutation*> res;
|
|
IntSequence tmp(s.size());
|
|
for (int i = 0; i < size; i++) {
|
|
pers[i]->apply(s, tmp);
|
|
if (s == tmp) {
|
|
res.push_back(pers[i]);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
@
|
|
@<|PermutationBundle| constructor code@>=
|
|
PermutationBundle::PermutationBundle(int nmax)
|
|
{
|
|
nmax = max(nmax, 1);
|
|
generateUpTo(nmax);
|
|
}
|
|
|
|
@
|
|
@<|PermutationBundle| destructor code@>=
|
|
PermutationBundle::~PermutationBundle()
|
|
{
|
|
for (unsigned int i = 0; i < bundle.size(); i++)
|
|
delete bundle[i];
|
|
}
|
|
|
|
@
|
|
@<|PermutationBundle::get| code@>=
|
|
const PermutationSet& PermutationBundle::get(int n) const
|
|
{
|
|
if (n > (int)(bundle.size()) || n < 1) {
|
|
TL_RAISE("Permutation set not found in PermutationSet::get");
|
|
return *(bundle[0]);
|
|
} else {
|
|
return *(bundle[n-1]);
|
|
}
|
|
}
|
|
|
|
@
|
|
@<|PermutationBundle::generateUpTo| code@>=
|
|
void PermutationBundle::generateUpTo(int nmax)
|
|
{
|
|
if (bundle.size() == 0)
|
|
bundle.push_back(new PermutationSet());
|
|
|
|
int curmax = bundle.size();
|
|
for (int n = curmax+1; n <= nmax; n++) {
|
|
bundle.push_back(new PermutationSet(*(bundle.back()), n));
|
|
}
|
|
}
|
|
|
|
@ End of {\tt permutation.cweb} file.
|