Update.
[pytorch.git] / eingather.py
1 #!/usr/bin/env python
2
3 # Any copyright is dedicated to the Public Domain.
4 # https://creativecommons.org/publicdomain/zero/1.0/
5
6 # Written by Francois Fleuret <francois@fleuret.org>
7
8 import re, torch
9
10 #####################
11
12
13 def eingather(op, src, index):
14     s_src, s_dst = re.search("^([^ ]*) *-> *(.*)", op).groups()
15     s_index = re.search("\(([^)]*)\)", s_src).group(1)
16     s_src = re.sub("\([^)]*\)", "_", s_src)
17
18     shape = tuple(src.size(s_src.index(v)) for v in s_dst)
19
20     idx = []
21
22     for i in range(index.dim()):
23         v = s_index[i]
24         j = s_dst.index(v)
25         a = (
26             torch.arange(index.size(i))
27             .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
28             .expand(shape)
29         )
30         idx.append(a)
31
32     index = index[idx]
33
34     idx = []
35
36     for i in range(src.dim()):
37         v = s_src[i]
38         if v == "_":
39             idx.append(index)
40         else:
41             j = s_dst.index(v)
42             a = (
43                 torch.arange(src.size(i))
44                 .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
45                 .expand(shape)
46             )
47             idx.append(a)
48
49     return src[idx]
50
51
52 #######################
53
54 src = torch.rand(3, 5, 7, 11)
55 index = torch.randint(src.size(2), (src.size(3), src.size(1), src.size(3)))
56
57 # I want result[a,c,e]=src[c,a,index[e,a,e],e]
58
59 result = eingather("ca(eae)e -> ace", src, index)
60
61 # Check
62
63 error = 0
64
65 for a in range(result.size(0)):
66     for c in range(result.size(1)):
67         for e in range(result.size(2)):
68             error += (result[a, c, e] - src[c, a, index[e, a, e], e]).abs()
69
70 print(error.item())