134 lines
3.1 KiB
C++
134 lines
3.1 KiB
C++
// Copyright 2004, Ondra Kamenik
|
|
|
|
#include "permutation.hh"
|
|
#include "tl_exception.hh"
|
|
|
|
/* This is easy, we simply apply the map in the fashion $s\circ m$.. */
|
|
|
|
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);
|
|
}
|
|
|
|
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. */
|
|
|
|
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. */
|
|
|
|
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::PermutationSet()
|
|
{
|
|
pers.emplace_back(1);
|
|
}
|
|
|
|
PermutationSet::PermutationSet(const PermutationSet &sp, int n)
|
|
: order(n), size(n*sp.size)
|
|
{
|
|
TL_RAISE_IF(n != sp.order+1,
|
|
"Wrong new order in PermutationSet constructor");
|
|
|
|
for (int i = 0; i < sp.size; i++)
|
|
for (int j = 0; j < order; j++)
|
|
pers.emplace_back(sp.pers[i], j);
|
|
}
|
|
|
|
std::vector<Permutation>
|
|
PermutationSet::getPreserving(const IntSequence &s) const
|
|
{
|
|
TL_RAISE_IF(s.size() != order,
|
|
"Wrong sequence length in PermutationSet::getPreserving");
|
|
|
|
std::vector<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::PermutationBundle(int nmax)
|
|
{
|
|
nmax = std::max(nmax, 1);
|
|
generateUpTo(nmax);
|
|
}
|
|
|
|
const PermutationSet &
|
|
PermutationBundle::get(int n) const
|
|
{
|
|
if (n > static_cast<int>(bundle.size()) || n < 1)
|
|
{
|
|
TL_RAISE("Permutation set not found in PermutationSet::get");
|
|
return bundle[0];
|
|
}
|
|
else
|
|
return bundle[n-1];
|
|
}
|
|
|
|
void
|
|
PermutationBundle::generateUpTo(int nmax)
|
|
{
|
|
if (bundle.size() == 0)
|
|
bundle.emplace_back();
|
|
|
|
int curmax = bundle.size();
|
|
for (int n = curmax+1; n <= nmax; n++)
|
|
bundle.emplace_back(bundle.back(), n);
|
|
}
|