-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpermutation.py
More file actions
83 lines (65 loc) · 3.28 KB
/
permutation.py
File metadata and controls
83 lines (65 loc) · 3.28 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
# ==============================================================================
# file: permutation.py
# description: Permutation implementation used in the protocol.
# ==============================================================================
from random import shuffle, getstate, setstate, seed
class IsolatedPermutation:
"""Permutation class allows to permute a list and to invert the permutation of a permuted list.
This implementation has been designed to be controlled by a seed, useful to applied the same permutation
over several algorithms.
"""
@staticmethod
def new(nb_items: int, perm_seed: int, turn: int):
"""Creates and returns an initialized permutation adapted to permute a list of a given size.
Args:
nb_items: Number of items in the list to permute or to invert.
perm_seed: Permutation seed used to initialize the random state.
turn: Integer used to create the same permutation at a given time step.
"""
permutation = IsolatedPermutation(nb_items, perm_seed)
permutation.reset(turn)
return permutation
def __init__(self, nb_items, perm_seed: int):
self.nb_items = nb_items
self.perm_seed = perm_seed
def reset(self, turn: int):
"""Resets the permutation for a given time step."""
permuted_index = [i for i in range(self.nb_items)]
save_state = getstate()
seed(self.perm_seed + turn)
shuffle(permuted_index)
setstate(save_state)
self.__permutation = {index: perm for index, perm in enumerate(permuted_index)}
self.__inverse = {perm: index for index, perm in enumerate(permuted_index)}
def permute(self, values):
"""Returns the permuted list given in parameter.
Args:
values: List to be permuted.
"""
if len(values) != self.nb_items:
raise Exception("Cannot permutate list with a size different from {}".format(self.nb_items))
permuted_values = [None for _ in range(self.nb_items)]
for real_index, permuted_index in self.__permutation.items():
permuted_values[permuted_index] = values[real_index]
return permuted_values
def invert_permutation(self, permuted_values):
"""Returns the permuted list where each item has been replaced to his original position.
Args:
permuted_values: Permuted list to be inverted.
"""
if len(permuted_values) != self.nb_items:
raise Exception("Cannot permutate list with a size different from {}".format(self.nb_items))
values = [None for _ in range(self.nb_items)]
for real_index, permuted_index in self.__permutation.items():
values[real_index] = permuted_values[permuted_index]
return values
def invert_permuted_index(self, permuted_index):
"""Returns the original position of the given permuted index.
Args:
permuted_index: Permuted index.
"""
return self.__inverse[permuted_index]
def __str__(self):
return str(
"Permutation({} -> {}), Inverse({} -> {})".format(self.__permutation.keys(), self.__permutation.values(),
self.__inverse.keys(), self.__inverse.values()))