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
|
|
|
|
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
// Permutations.
|
|
|
|
|
|
|
|
|
|
/* The permutation class is useful when describing a permutation of
|
|
|
|
|
indices in permuted symmetry tensor. This tensor comes to existence,
|
|
|
|
|
for instance, as a result of the following tensor multiplication:
|
2019-04-01 18:41:31 +02:00
|
|
|
|
|
|
|
|
|
[g_y³]_γ₁γ₂γ₃ [g_yu]^γ₁_α₁β₃ [g_yu]^γ₂_α₂β₁ [g_u]^γ₃_β₂
|
|
|
|
|
|
|
|
|
|
If this operation is done by a Kronecker product of unfolded tensors, the
|
|
|
|
|
resulting tensor has permuted indices. So, in this case the permutation is
|
|
|
|
|
implied by the equivalence: { {0,4}, {1,3}, {2} }. This results in a
|
|
|
|
|
permutation which maps indices (0,1,2,3,4)↦(0,2,4,3,1).
|
|
|
|
|
|
|
|
|
|
The other application of Permutation class is to permute indices with the
|
|
|
|
|
same permutation as done during sorting.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
Here we only define an abstraction for the permutation defined by an
|
2019-04-01 18:41:31 +02:00
|
|
|
|
equivalence. Its basic operation is to apply the permutation to the integer
|
|
|
|
|
sequence. The application is right (or inner), in sense that it works on
|
|
|
|
|
indices of the sequence not items of the sequence. More formally s∘m ≠ m∘s.
|
|
|
|
|
In here, the application of the permutation defined by map m is s∘m.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
Also, we need PermutationSet class which contains all permutations
|
|
|
|
|
of an n-element set, and a bundle of permutations PermutationBundle
|
|
|
|
|
which contains all permutation sets up to a given number.
|
2019-12-20 14:36:20 +01:00
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
#ifndef PERMUTATION_H
|
|
|
|
|
#define PERMUTATION_H
|
|
|
|
|
|
|
|
|
|
#include "int_sequence.hh"
|
|
|
|
|
#include "equivalence.hh"
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
/* The permutation object will have a map, which defines mapping of indices
|
|
|
|
|
(0,1,…,n-1)↦(m₀,m₁,…, mₙ₋₁). The map is the sequence (m₀,m₁,…, mₙ₋₁). When
|
|
|
|
|
the permutation with the map m is applied on sequence s, it permutes its
|
|
|
|
|
indices: s∘id↦s∘m.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
So we have one constructor from equivalence, then a method apply(),
|
|
|
|
|
and finally a method tailIdentity() which returns a number of trailing
|
2019-01-08 16:09:25 +01:00
|
|
|
|
indices which yield identity. Also we have a constructor calculating
|
|
|
|
|
map, which corresponds to permutation in sort. This is, we want
|
2019-04-01 18:41:31 +02:00
|
|
|
|
(sorted s)∘m = s.
|
2019-12-20 14:36:20 +01:00
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class Permutation
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
IntSequence permap;
|
|
|
|
|
public:
|
2019-02-27 19:07:01 +01:00
|
|
|
|
explicit Permutation(int len)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
: permap(len)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
permap[i] = i;
|
|
|
|
|
}
|
2019-02-27 19:07:01 +01:00
|
|
|
|
explicit Permutation(const Equivalence &e)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
: permap(e.getN())
|
|
|
|
|
{
|
|
|
|
|
e.trace(permap);
|
|
|
|
|
}
|
|
|
|
|
Permutation(const Equivalence &e, const Permutation &per)
|
|
|
|
|
: permap(e.getN())
|
|
|
|
|
{
|
|
|
|
|
e.trace(permap, per);
|
|
|
|
|
}
|
2019-02-27 19:07:01 +01:00
|
|
|
|
explicit Permutation(const IntSequence &s)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
: permap(s.size())
|
|
|
|
|
{
|
|
|
|
|
computeSortingMap(s);
|
|
|
|
|
};
|
|
|
|
|
Permutation(const Permutation &p1, const Permutation &p2)
|
|
|
|
|
: permap(p2.permap)
|
|
|
|
|
{
|
|
|
|
|
p1.apply(permap);
|
|
|
|
|
}
|
|
|
|
|
Permutation(const Permutation &p, int i)
|
2019-02-27 14:34:28 +01:00
|
|
|
|
: permap(p.permap.insert(p.size(), i))
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
bool
|
|
|
|
|
operator==(const Permutation &p)
|
|
|
|
|
{
|
|
|
|
|
return permap == p.permap;
|
|
|
|
|
}
|
|
|
|
|
int
|
|
|
|
|
size() const
|
|
|
|
|
{
|
|
|
|
|
return permap.size();
|
|
|
|
|
}
|
|
|
|
|
void
|
|
|
|
|
print() const
|
|
|
|
|
{
|
|
|
|
|
permap.print();
|
|
|
|
|
}
|
|
|
|
|
void apply(const IntSequence &src, IntSequence &tar) const;
|
|
|
|
|
void apply(IntSequence &tar) const;
|
|
|
|
|
void inverse();
|
|
|
|
|
int tailIdentity() const;
|
|
|
|
|
const IntSequence &
|
|
|
|
|
getMap() const
|
|
|
|
|
{
|
|
|
|
|
return permap;
|
|
|
|
|
}
|
|
|
|
|
IntSequence &
|
|
|
|
|
getMap()
|
|
|
|
|
{
|
|
|
|
|
return permap;
|
|
|
|
|
}
|
|
|
|
|
protected:
|
|
|
|
|
void computeSortingMap(const IntSequence &s);
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-01 18:41:31 +02:00
|
|
|
|
/* The PermutationSet maintains an array of of all permutations. The default
|
|
|
|
|
constructor constructs one element permutation set of one element sets. The
|
|
|
|
|
second constructor constructs a new permutation set over n from all
|
|
|
|
|
permutations over n-1. The parameter n needs not to be provided, but it
|
|
|
|
|
serves to distinguish the constructor from copy constructor.
|
|
|
|
|
|
|
|
|
|
The method getPreserving() returns a factor subgroup of permutations, which
|
|
|
|
|
are invariants with respect to the given sequence. This are all permutations
|
|
|
|
|
p yielding p∘s = s, where s is the given sequence. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class PermutationSet
|
|
|
|
|
{
|
2019-01-09 15:58:45 +01:00
|
|
|
|
int order{1};
|
|
|
|
|
int size{1};
|
2019-02-12 17:30:10 +01:00
|
|
|
|
std::vector<Permutation> pers;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
|
|
|
|
PermutationSet();
|
|
|
|
|
PermutationSet(const PermutationSet &ps, int n);
|
|
|
|
|
int
|
|
|
|
|
getNum() const
|
|
|
|
|
{
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
const Permutation &
|
|
|
|
|
get(int i) const
|
|
|
|
|
{
|
2019-02-12 17:30:10 +01:00
|
|
|
|
return pers[i];
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2019-02-12 17:30:10 +01:00
|
|
|
|
std::vector<Permutation> getPreserving(const IntSequence &s) const;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* The permutation bundle encapsulates all permutations sets up to some
|
|
|
|
|
given dimension. */
|
|
|
|
|
|
|
|
|
|
class PermutationBundle
|
|
|
|
|
{
|
2019-02-12 17:30:10 +01:00
|
|
|
|
std::vector<PermutationSet> bundle;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
|
|
|
|
PermutationBundle(int nmax);
|
2019-02-21 18:46:53 +01:00
|
|
|
|
const PermutationSet &get(int n) const;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
void generateUpTo(int nmax);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|