Xped
Loading...
Searching...
No Matches
Permutations.hpp
Go to the documentation of this file.
1#ifndef XPED_PERMUTATIONS_HPP_
2#define XPED_PERMUTATIONS_HPP_
3
4#include <algorithm>
5#include <array>
6#include <cassert>
7#include <complex>
8#include <fstream>
9#include <iostream>
10#include <numeric>
11#include <set>
12#include <vector>
13
14#include <boost/algorithm/string.hpp>
15
16namespace Xped::util {
17
18struct Permutation;
19
21{
23 Transposition(const std::size_t source_in, const std::size_t target_in)
24 : source(source_in)
25 , target(target_in){};
26 Transposition(const std::array<std::size_t, 2> data)
27 : source(data[0])
28 , target(data[1]){};
29 std::string print() const
30 {
31 std::stringstream ss;
32 ss << source << " <===> " << target;
33 return ss.str();
34 }
35 std::size_t source = 0;
36 std::size_t target = 0;
37};
38
40{
41 typedef std::vector<std::size_t> Cycle;
42
44
45 template <typename Container>
46 Permutation(const Container& in)
47 {
48 pi.resize(in.size());
49 std::copy(in.begin(), in.end(), pi.begin());
50 initialize();
51 }
52
53 Permutation(const std::string filename)
54 {
55 std::ifstream stream(filename, std::ios::in);
56 std::string line;
57 if(stream.is_open()) {
58 while(std::getline(stream, line)) {
59 std::vector<std::string> results;
60
61 boost::split(results, line, [](char c) { return c == '\t'; });
62 if(results[0].find("#") != std::string::npos) { continue; } // skip lines with a hashtag
63 int source = stoi(results[0]);
64 int target = stoi(results[1]);
65 assert(source >= 0 and "Invalid permutation data in file.");
66 assert(target >= 0 and "Invalid permutation data in file.");
67 if(source >= pi.size()) { pi.resize(source + 1); }
68 pi[source] = target;
69 }
70 stream.close();
71 }
72 N = pi.size();
73
74 // consistency check
75 std::set<std::size_t> bijectivePermutation;
76 for(std::size_t i = 0; i < N; i++) {
77 assert(pi[i] < N and "Invalid permutation data in file.");
78 auto it = bijectivePermutation.find(pi[i]);
79 if(it == bijectivePermutation.end()) {
80 bijectivePermutation.insert(pi[i]);
81 } else {
82 assert(false and "Invalid permutation data in file.");
83 }
84 }
85 initialize();
86 };
87
89 {
90 N = pi.size();
91 pi_inv.resize(N);
92 for(std::size_t i = 0; i < N; i++) { pi_inv[pi[i]] = i; }
93
94 std::vector<bool> visited(N, false);
95 while(!std::all_of(visited.cbegin(), visited.cend(), [](bool b) { return b; })) {
96 auto start_it = std::find(visited.cbegin(), visited.cend(), false);
97 std::size_t start = std::distance(visited.cbegin(), start_it);
98
99 visited[pi_inv[start]] = true;
100
101 Cycle cycle;
102 cycle.push_back(start);
103 auto tmp = start;
104 for(std::size_t i = 0; i < N; i++) {
105 auto next_power = pi[tmp];
106 if(next_power == start) {
107 continue;
108 } else {
109 cycle.push_back(next_power);
110 visited[pi_inv[next_power]] = true;
111 tmp = next_power;
112 }
113 }
114 cycles.push_back(cycle);
115 }
116 }
117
118 friend std::size_t hash_value(const Permutation& p)
119 {
120 std::size_t seed = 0;
121 boost::hash_combine(seed, p.pi);
122 return seed;
123 }
124
125 bool operator==(const Permutation& other) const { return pi == other.pi; }
126
127 static Permutation Identity(std::size_t N)
128 {
129 std::vector<std::size_t> id(N);
130 std::iota(id.begin(), id.end(), 0ul);
131 return Permutation(id);
132 }
133
134 static std::vector<Permutation> all(std::size_t N)
135 {
136 std::vector<std::size_t> data(N);
137 std::iota(data.begin(), data.end(), 0ul);
138 std::vector<Permutation> out;
139 do {
140 Permutation p(data);
141 out.push_back(p);
142 } while(std::next_permutation(data.begin(), data.end()));
143 return out;
144 }
145
146 std::string print() const
147 {
148 std::stringstream ss;
149 for(const auto& c : cycles) {
150 ss << "(";
151 for(std::size_t i = 0; i < c.size(); i++) {
152 if((i < c.size() - 1)) {
153 ss << c[i] << ",";
154 } else {
155 ss << c[i];
156 }
157 }
158 ss << ")";
159 }
160 ss << std::endl;
161 size_t count = 0;
162 for(const auto& elem : pi) {
163 ss << count << " ==> " << elem << std::endl;
164 count++;
165 }
166 return ss.str();
167 };
168
169 std::vector<Transposition> transpositions() const
170 {
171 std::vector<Transposition> out;
172 for(const auto& c : cycles) {
173 for(std::size_t i = 0; i < c.size() - 1; i++) {
174 Transposition t(c[0], c[c.size() - 1 - i]);
175 out.push_back(t);
176 }
177 }
178 return out;
179 };
180
181 std::vector<std::vector<Transposition>> independentTranspositions() const
182 {
183 std::vector<std::vector<Transposition>> out(cycles.size());
184 std::size_t count = 0;
185 for(const auto& c : cycles) {
186 for(std::size_t i = 0; i < c.size() - 1; i++) {
187 Transposition t(c[0], c[c.size() - 1 - i]);
188 out[count].push_back(t);
189 }
190 count++;
191 }
192 return out;
193 };
194
195 std::vector<std::size_t> decompose() const
196 {
197 std::vector<bool> visited(N, false);
198 std::vector<std::size_t> a(N);
199 std::iota(a.begin(), a.end(), 0ul);
200
201 std::vector<std::size_t> out;
202 if(a == pi) { return out; } // early return if it is the identity permutation
203
204 for(std::size_t i = 0; i < N; i++) {
205 auto index = std::distance(a.begin(), std::find(a.begin(), a.end(), pi[i]));
206 // std::cout << "i=" << i << ", pi[i]=" << pi[i] << ", index=" << index << ", a="; for (const auto& o:a) {std::cout << o << " ";}
207 // std::cout << std::endl;
208 if(index == 0) { continue; }
209 if(i == 0) {
210 for(std::size_t j = index - 1; j < index; --j) {
211 // std::cout << "j=" << j << std::endl;
212 std::swap(a[j], a[j + 1]);
213 out.push_back(j);
214 }
215 } else {
216 for(std::size_t j = index - 1; j >= i; --j) {
217 // std::cout << "j=" << j << std::endl;
218 std::swap(a[j], a[j + 1]);
219 out.push_back(j);
220 }
221 }
222 }
223 assert(a == pi and "Error when determining the swaps of a permutation.");
224 return out;
225 }
226
227 std::size_t parity()
228 {
229 std::size_t out = 0;
230 for(const auto& c : cycles) { out += (c.size() - 1) % 2; }
231 return out % 2;
232 }
233
234 template <typename Container>
235 void apply(Container& c) const
236 {
237 if(c.size() == 1) { return; }
238 Container tmp(c);
239 for(std::size_t i = 0; i < c.size(); i++) { tmp[i] = c[pi[i]]; }
240 c = tmp;
241 }
242
244 {
245 Permutation out(pi_inv);
246 return out;
247 }
248
249 template <typename IndexType>
250 std::vector<IndexType> pi_as_index() const
251 {
252 std::vector<IndexType> out(N);
253 std::copy(pi.begin(), pi.end(), out.begin());
254 return out;
255 }
256
257 std::size_t N;
258 std::vector<std::size_t> pi;
259 std::vector<std::size_t> pi_inv;
260 std::vector<Cycle> cycles;
261};
262
263} // namespace Xped::util
264#endif
Definition: FusionTree.hpp:15
Definition: Permutations.hpp:40
std::size_t N
Definition: Permutations.hpp:257
Permutation(const Container &in)
Definition: Permutations.hpp:46
Permutation()
Definition: Permutations.hpp:43
std::vector< std::size_t > decompose() const
Definition: Permutations.hpp:195
std::vector< std::vector< Transposition > > independentTranspositions() const
Definition: Permutations.hpp:181
static std::vector< Permutation > all(std::size_t N)
Definition: Permutations.hpp:134
std::vector< IndexType > pi_as_index() const
Definition: Permutations.hpp:250
std::size_t parity()
Definition: Permutations.hpp:227
std::vector< std::size_t > pi_inv
Definition: Permutations.hpp:259
std::vector< Transposition > transpositions() const
Definition: Permutations.hpp:169
static Permutation Identity(std::size_t N)
Definition: Permutations.hpp:127
std::string print() const
Definition: Permutations.hpp:146
void initialize()
Definition: Permutations.hpp:88
Permutation inverse() const
Definition: Permutations.hpp:243
bool operator==(const Permutation &other) const
Definition: Permutations.hpp:125
std::vector< std::size_t > Cycle
Definition: Permutations.hpp:41
Permutation(const std::string filename)
Definition: Permutations.hpp:53
void apply(Container &c) const
Definition: Permutations.hpp:235
friend std::size_t hash_value(const Permutation &p)
Definition: Permutations.hpp:118
std::vector< std::size_t > pi
Definition: Permutations.hpp:258
std::vector< Cycle > cycles
Definition: Permutations.hpp:260
Definition: Permutations.hpp:21
Transposition(const std::size_t source_in, const std::size_t target_in)
Definition: Permutations.hpp:23
std::size_t target
Definition: Permutations.hpp:36
Transposition()
Definition: Permutations.hpp:22
Transposition(const std::array< std::size_t, 2 > data)
Definition: Permutations.hpp:26
std::string print() const
Definition: Permutations.hpp:29
std::size_t source
Definition: Permutations.hpp:35