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

134 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// Copyright 2004, Ondra Kamenik
#include "permutation.hh"
#include "tl_exception.hh"
/* This is easy, we simply apply the map in the fashion s∘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: $(sorted s)∘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);
}