Как стать автором
Обновить

Комментарии 9

Удивительное дело, но в русскоязычном сегменте интернета почти нет материала, разъясняющего понятным языком соглашение Эйнштейна о суммировании

Любой нормальный учебник по ОТО или ТеорМеху =)

Более того, в свое время выходила куча «Эйнштейновских сборников» на русском. Достаточно забить в поисковик — они есть. Там эти соглашения неоднократно обсуждались.
Всегда можно использовать цепочки вложенных циклов

Это в Python то? Возьмите достаточно большие многомерные массивы и посчитайте что-нибудь на них через "цепочки вложенных циклов". Сколько чашек чая вы успеете выпить до получения результата? Если уж пишете про функции numpy, не над описать такую глупость про "цепочки вложенных циклов", ведь кто-то может действительно подумать, что с numpy-массивами в питоне надо работать через циклы, потому что привычнее и проще, а не то что эти ваши векторизованные операции над массивами вроде всяких непонятных einsum.

Спасибо, очень интересно!
Я с тензорами разбирался по книжке Борисенко и Тарапова, но там это подробно не рассмотрено.

Замечу, что у функции einsum есть параметр optimize, который отвечает за то, будут ли ваши суммы считаться эффективно или как придётся. По дефолту оптимизация выключена, поэтому при неудачном стечении обстоятельств вычисления могут получиться очень неоптимальными. В примере ниже вычисляется вектор A*A*x. Без оптимизации сначала перемножаются две матрицы n x n за O(n^3), а потом уже произойдёт умножение на вектор. С оптимизацией всё будет хорошо: произойдёт два умножения матрицы на вектор и сложность будет O(n^2).


import numpy as np
n = 1000
x = np.ones((n,))
A = np.ones((n,n))
%time _ = np.einsum("ij,jk,k->i", A,A,x)
> CPU times: user 2.51 s, sys: 3 µs, total: 2.51 s
> Wall time: 2.51 s
%time _ = np.einsum("ij,jk,k->i", A,A,x, optimize=True)
> CPU times: user 635 µs, sys: 8.01 ms, total: 8.65 ms
> Wall time: 8.55 ms

Можно ещё указывать optimize="optimal", тогда из всех вариантов вычисления суммы будет выбран оптимальный, в то время как optimize=True (алиас для optimize="greedy") означает использование жадного алгоритма для оптимизации.

Более того, optimize="optimal" почему-то умеет заставлять einsum работать с тензорами, у которых компоненты — произвольные объекты (например из sympy).
Например, код


x,y = symbols("x y")
coords = np.array([x,y])
g = np.identity(2)
print(np.einsum("ij,i,j", g, coords, coords))

выдает ошибку TypeError: invalid data type for einsum
Но если сделать


print(np.einsum("ij,i,j", g, coords, coords, optimize="optimal"))

внезапно получается правильный ответ 1.0*x**2 + 1.0*y**2.

Вообще звучит как баг.

Фиггасе. Вот это я понимаю, полиморфизм! Правда, optimize="optimal" не всегда помогает.

Жалко Эйнштейн не дожил до Python. Или хотя бы до многомерных массивов в ранних ЯП. Фиктивные индексы, индекс с запятой до стрелочки — что за дурь! Бритва Окама в помощь.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации