Советую прочитать нотация Эйнштейна в Википедии .
Вот краткий ответ на ваш вопрос:
np.einsum('aabb->ab', A)
означает:
res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
res[a, b] = A[a, a, b, b]
return res
Краткое объяснение:
aabb
означает индексы и их равенство (см. A[a, a, b, b]
);
->ab
означает, что форма (max_a, max_b)
, и вам не нужно, чтобы два имели сумму по этим двум индексам. (если бы они были c
также, то вы должны суммировать все по c
, поскольку оно не представлено после ->
)
Другие ваши примеры:
np.einsum('abab->ab', A)
# Same as (by logic, not by actual code)
res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
res[a, b] = A[a, b, a, b]
return res
np.einsum('abba->ab', A)
# Same as (by logic, not by actual code)
res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
res[a, b] = A[a, b, b, a]
return res
np.einsum('abcb->abc', A)
# Same as (by logic, not by actual code)
res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
for c in range(max_c):
res[a, b, c] = A[a, b, c, b]
return res
np.einsum('abbc->abc', A)
# Same as (by logic, not by actual code)
res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
for c in range(max_c):
res[a, b, c] = A[a, b, b, c]
return res
Некоторый код, чтобы проверить, что это действительно так:
import numpy as np
max_a = 2
max_b = 3
max_c = 5
shape_1 = (max_a, max_b, max_c, max_b)
A = np.arange(1, np.prod(shape_1) + 1).reshape(shape_1)
print(A)
print()
print(np.einsum('abcb->abc', A))
print()
res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
for b in range(max_b):
for c in range(max_c):
res[a, b, c] = A[a, b, c, b]
print(res)
print()