2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004 Ondra Kamenik
|
|
|
|
|
* Copyright © 2019 Dynare Team
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Dynare.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
#include "permutation.hh"
|
|
|
|
|
#include "tl_exception.hh"
|
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
/* This is easy, we simply apply the map in the fashion s∘m */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
void
|
2023-11-29 19:00:21 +01:00
|
|
|
|
Permutation::apply(const IntSequence& src, IntSequence& tar) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
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
|
2023-11-29 19:00:21 +01:00
|
|
|
|
Permutation::apply(IntSequence& tar) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
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();
|
2023-11-29 19:00:21 +01:00
|
|
|
|
while (i > 0 && permap[i - 1] == i - 1)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
i--;
|
|
|
|
|
return permap.size() - i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This calculates a map which corresponds to sorting in the following
|
2019-04-01 18:41:31 +02:00
|
|
|
|
sense: $(sorted s)∘m = s, where s is a given sequence.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
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. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
void
|
2023-11-29 19:00:21 +01:00
|
|
|
|
Permutation::computeSortingMap(const IntSequence& s)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
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++;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(j == s.size(), "Internal algorithm error in Permutation::computeSortingMap");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
flags[j] = 1;
|
|
|
|
|
permap[i] = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PermutationSet::PermutationSet()
|
|
|
|
|
{
|
2019-02-12 17:30:10 +01:00
|
|
|
|
pers.emplace_back(1);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
PermutationSet::PermutationSet(const PermutationSet& sp, int n) : order(n), size(n * sp.size)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(n != sp.order + 1, "Wrong new order in PermutationSet constructor");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sp.size; i++)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
for (int j = 0; j < order; j++)
|
|
|
|
|
pers.emplace_back(sp.pers[i], j);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-12 17:30:10 +01:00
|
|
|
|
std::vector<Permutation>
|
2023-11-29 19:00:21 +01:00
|
|
|
|
PermutationSet::getPreserving(const IntSequence& s) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(s.size() != order, "Wrong sequence length in PermutationSet::getPreserving");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-02-12 17:30:10 +01:00
|
|
|
|
std::vector<Permutation> res;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence tmp(s.size());
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
|
{
|
2019-02-12 17:30:10 +01:00
|
|
|
|
pers[i].apply(s, tmp);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (s == tmp)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
res.push_back(pers[i]);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PermutationBundle::PermutationBundle(int nmax)
|
|
|
|
|
{
|
2019-02-06 15:50:01 +01:00
|
|
|
|
nmax = std::max(nmax, 1);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
generateUpTo(nmax);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const PermutationSet&
|
2019-01-08 16:09:25 +01:00
|
|
|
|
PermutationBundle::get(int n) const
|
|
|
|
|
{
|
2019-02-12 17:30:10 +01:00
|
|
|
|
if (n > static_cast<int>(bundle.size()) || n < 1)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
TL_RAISE("Permutation set not found in PermutationSet::get");
|
2019-02-12 17:30:10 +01:00
|
|
|
|
return bundle[0];
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return bundle[n - 1];
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PermutationBundle::generateUpTo(int nmax)
|
|
|
|
|
{
|
|
|
|
|
if (bundle.size() == 0)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
bundle.emplace_back();
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
int curmax = bundle.size();
|
2023-11-29 19:00:21 +01:00
|
|
|
|
for (int n = curmax + 1; n <= nmax; n++)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
bundle.emplace_back(bundle.back(), n);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|