-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPermutTable.h
More file actions
118 lines (107 loc) · 3.42 KB
/
PermutTable.h
File metadata and controls
118 lines (107 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef __PERMUT_TABLE_H_CMC__
#define __PERMUT_TABLE_H_CMC__
#include <vector>
#include "ContainerUtility.h"
#include "CountSwap.h"
using namespace std;
tuple <vector<vector<int>>, vector<int>> get_permutations (const vector<int>& pos)
// <pos> is assumed to be sorted
// Return 1) all the permutations of pos. 2) the number of neighboring swaps required
// The size of pos can be 2, 3, or 4
// Did not care about the efficiency. Can be slow.
{
assert (pos.size() >=2 && pos.size() <= 4);
vector<vector<int>> re;
vector<int> swaps;
auto add_permute = [&re, &swaps] (const vector<int>& ppos)
{
if (!in_vector (re, ppos))
{
re.push_back (ppos);
int nswap = countSwaps (ppos);
swaps.push_back (nswap);
}
};
for(int p1 : pos)
{
auto tmp2 = pos;
remove_element (tmp2, p1);
for(int p2 : tmp2)
// p2 != p1
{
if (pos.size() == 2)
// Two positions
{
add_permute ({p1,p2});
}
else
{
auto tmp3 = tmp2;
remove_element (tmp3, p2);
for(int p3 : tmp3)
// p3 != p1,p2
{
if (pos.size() == 3)
// Three positions
{
add_permute ({p1,p2,p3});
}
else
// Four positions
{
auto tmp4 = tmp3;
remove_element (tmp4, p3);
for(int p4 : tmp4)
// p4 != p1,p2,p3
{
add_permute ({p1,p2,p3,p4});
}
}
}
}
}
}
return {re, swaps};
}
class PermutTable
{
public:
PermutTable () {}
// Important: The input <pos> is assumed to be sorted.
tuple <vector<vector<int>>, vector<int>> permut (const vector<int>& pos);
private:
// Key: site positions
// Value: 1) all the permutations, 2) corresponding number of swaps
map <vector<int>, tuple <vector<vector<int>>, vector<int>>> _ptable;
};
tuple <vector<vector<int>>, vector<int>> PermutTable :: permut (const vector<int>& pos)
{
// Get the representation of <pos>, which basically cares only about the numbers are different or the same
// Example: if pos=3,6,6,8, rep=0,1,1,2
// if pos=1,2,2,2, rep=0,1,1,1
// if pos=1,3,7,9, rep=0,1,2,3
vector<int> rep (pos.size(), 0);
for(int i = 1; i < pos.size(); i++)
{
if (pos.at(i) != pos.at(i-1))
rep.at(i) = rep.at(i-1) + 1;
}
// Would check keys in _ptable.
// Optimize it if necessary.
if (_ptable.count (rep) == 0)
_ptable.insert ({rep, get_permutations (rep)});
// Compute the permutations of the actual positions.
// This would be less efficient than return the representations, and then convert each of them to positions in the loop outside.
// However it is conceptually simpler, and may not be important in the whole algorithm.
// Optimize if found necessary.
auto [permut_poss, swaps] = _ptable.at (rep);
for(auto& ppos : permut_poss)
{
for(int& pi : ppos)
{
pi = pos.at(pi);
}
}
return {permut_poss, swaps};
}
#endif