dynare/dynare++/tl/cc/permutation.cc

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);
}