Add permutation groups & implement converting cyclic & dihedral groups into permutations
This commit is contained in:
parent
1f57c76036
commit
ce829f7356
3 changed files with 183 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/group/permutation.hpp>
|
||||
#include <psemek/util/range.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -55,6 +56,14 @@ namespace psemek::group
|
|||
return repr_;
|
||||
}
|
||||
|
||||
group::permutation<N, Repr> permutation() const
|
||||
{
|
||||
typename group::permutation<N, Repr>::repr_type repr;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
repr[i] = (i + repr_) % N;
|
||||
return group::permutation<N, Repr>::from_repr(repr);
|
||||
}
|
||||
|
||||
struct value_iterator
|
||||
{
|
||||
using difference_type = Repr;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/group/cyclic.hpp>
|
||||
#include <psemek/group/permutation.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
|
@ -87,6 +88,25 @@ namespace psemek::group
|
|||
return repr_ >= N;
|
||||
}
|
||||
|
||||
group::permutation<N, Repr> permutation() const
|
||||
{
|
||||
if (repr_ < N)
|
||||
{
|
||||
typename group::permutation<N, Repr>::repr_type repr;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
repr[i] = (i + repr_) % N;
|
||||
return group::permutation<N, Repr>::from_repr(repr);
|
||||
}
|
||||
else
|
||||
{
|
||||
typename group::permutation<N, Repr>::repr_type repr;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
repr[i] = (N - i) % N;
|
||||
|
||||
return rotation(repr_ % N).permutation() * group::permutation<N, Repr>::from_repr(repr);
|
||||
}
|
||||
}
|
||||
|
||||
struct value_iterator
|
||||
{
|
||||
using difference_type = Repr;
|
||||
|
|
|
|||
154
libs/group/include/psemek/group/permutation.hpp
Normal file
154
libs/group/include/psemek/group/permutation.hpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/util/range.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace psemek::group
|
||||
{
|
||||
|
||||
template <std::size_t N, typename Repr = std::size_t>
|
||||
struct permutation
|
||||
{
|
||||
static_assert(std::is_integral_v<Repr> && std::is_unsigned_v<Repr>);
|
||||
static_assert(std::numeric_limits<Repr>::max() > N);
|
||||
|
||||
using repr_type = std::array<Repr, N>;
|
||||
|
||||
static constexpr std::size_t size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
permutation() = default;
|
||||
|
||||
static permutation identity()
|
||||
{
|
||||
return permutation{};
|
||||
}
|
||||
|
||||
static permutation from_repr(repr_type const & value)
|
||||
{
|
||||
return permutation{value};
|
||||
}
|
||||
|
||||
repr_type const & value() const
|
||||
{
|
||||
return repr_;
|
||||
}
|
||||
|
||||
repr_type operator() (repr_type const & value) const
|
||||
{
|
||||
repr_type result;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
result[repr_[i]] = value[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
struct value_iterator
|
||||
{
|
||||
using difference_type = Repr;
|
||||
using value_type = permutation<N, Repr>;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
repr_type repr;
|
||||
bool end;
|
||||
|
||||
permutation<N, Repr> operator *() const
|
||||
{
|
||||
return permutation<N, Repr>{repr};
|
||||
}
|
||||
|
||||
value_iterator & operator++()
|
||||
{
|
||||
end = std::next_permutation(repr.begin(), repr.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator == (value_iterator const & it1, value_iterator const & it2)
|
||||
{
|
||||
return it1.repr == it2.repr && it1.end == it2.end;
|
||||
}
|
||||
};
|
||||
|
||||
static auto values()
|
||||
{
|
||||
repr_type repr;
|
||||
std::iota(repr.begin(), repr.end(), Repr{0});
|
||||
return util::range{value_iterator{repr, false}, value_iterator{repr, true}};
|
||||
}
|
||||
|
||||
private:
|
||||
repr_type repr_{0};
|
||||
|
||||
explicit permutation(repr_type const & repr)
|
||||
: repr_(repr)
|
||||
{}
|
||||
};
|
||||
|
||||
template <std::size_t N, typename Repr>
|
||||
bool operator == (permutation<N, Repr> const & g1, permutation<N, Repr> const & g2)
|
||||
{
|
||||
return g1.value() == g2.value();
|
||||
}
|
||||
|
||||
template <std::size_t N, typename Repr>
|
||||
auto operator <=> (permutation<N, Repr> const & g1, permutation<N, Repr> const & g2)
|
||||
{
|
||||
return g1.value() <=> g2.value();
|
||||
}
|
||||
|
||||
template <std::size_t N, typename Repr>
|
||||
permutation<N, Repr> operator * (permutation<N, Repr> const & g1, permutation<N, Repr> const & g2)
|
||||
{
|
||||
typename permutation<N, Repr>::repr_type repr;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
repr[i] = g1.value()[g2.value()[i]];
|
||||
return permutation<N, Repr>::from_repr(repr);
|
||||
}
|
||||
|
||||
template <std::size_t N, typename Repr>
|
||||
permutation<N, Repr> inverse(permutation<N, Repr> const & g)
|
||||
{
|
||||
typename permutation<N, Repr>::repr_type repr;
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
repr[g.value()[i]] = i;
|
||||
return permutation<N, Repr>::from_repr(repr);
|
||||
}
|
||||
|
||||
template <typename OStream, std::size_t N, typename Repr>
|
||||
OStream & operator << (OStream & os, permutation<N, Repr> const & g)
|
||||
{
|
||||
os << 'S' << N << '(';
|
||||
for (Repr i = 0; i < N; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
os << ", ";
|
||||
os << g.value()[i];
|
||||
}
|
||||
os << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename OStream, std::size_t N, typename Repr>
|
||||
void write(OStream & out, permutation<N, Repr> const & g)
|
||||
{
|
||||
write(out, g.value());
|
||||
}
|
||||
|
||||
template <typename IStream, std::size_t N, typename Repr>
|
||||
void read(IStream & in, permutation<N, Repr> & g)
|
||||
{
|
||||
typename permutation<N, Repr>::repr_type value;
|
||||
read(in, value);
|
||||
g = permutation<N, Repr>::from_repr(value);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue