-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmultidimensional_box.py
More file actions
90 lines (72 loc) · 2.74 KB
/
Copy pathmultidimensional_box.py
File metadata and controls
90 lines (72 loc) · 2.74 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
from typing import List, Iterable
from general import three_dimensional_plot
def multidimensional_box_product(*streams: Iterable) -> List:
n = len(streams)
def recursive_product(i_stream) -> List:
for element in streams[i_stream]:
if i_stream == n - 1:
# On final dimension, yield each element
yield [element]
else:
# On other dimension, yield each element followed by each
# possible combination of elements in the remaining dimensions
for remaining_elements in recursive_product(i_stream + 1):
yield [element] + remaining_elements
yield from recursive_product(0)
def multidimensional_box_pairing(lengths: List[int], indexes: List[int]) -> int:
# Should probably assert that all indexes are less than corresponding lengths
n = len(lengths)
index = 0
dimension_product = 1
# Compute indexes from last to first because that is the order the product is grown
for dimension in reversed(range(n)):
index += indexes[dimension] * dimension_product
dimension_product *= lengths[dimension]
return index
def multidimensional_box_unpairing(lengths: List[int], index: int) -> List[int]:
# Should probably assert that index is less than the product of lengths
n = len(lengths)
indexes = [0] * n # Preallocate list
dimension_product = 1
# Compute indexes from last to first because that is the order the product is grown
for dimension in reversed(range(n)):
indexes[dimension] = index // dimension_product % lengths[dimension]
dimension_product *= lengths[dimension]
return indexes
def multidimensional_box_plot():
points = [
[0, 0, 0],
[0, 0, 1],
[0, 0, 2],
[0, 1, 0],
[0, 1, 1],
[0, 1, 2],
[1, 0, 0],
[1, 0, 1],
[1, 0, 2],
[1, 1, 0],
[1, 1, 1],
[1, 1, 2],
]
arrows = [
[0, 0, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 2],
[0, 0, 2, 0, 1, 0],
[0, 1, 0, 0, 1, 1],
[0, 1, 1, 0, 1, 2],
[1, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 0, 2],
[1, 0, 2, 1, 1, 0],
[1, 1, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 2],
]
return three_dimensional_plot(points, arrows)
if __name__ == '__main__':
lengths = [2, 3, 4]
for i, (x, y, z) in enumerate(multidimensional_box_product(*[list(range(length)) for length in lengths])):
paired = multidimensional_box_pairing(lengths, [x, y, z])
unpaired = multidimensional_box_unpairing(lengths, i)
print(f'{i} == {paired}, {[x, y, z]} == {unpaired}')
assert i == paired
assert [x, y, z] == unpaired
multidimensional_box_plot().show()