Я думаю, что вы можете сделать оба с einsum
first_term = np.einsum('km, ijklm -> i', s, (pp[..., None, None] - pp[:, None, None, ...])**2 )
second_term = np.einsum('k, ijk -> i', np.linalg.norm(s, axis = 1), (pp - p)**2 )
Теперь есть проблема: тензор ijklm
в first_term
станет огромным, если nb
и nc
получат большой. Вам, вероятно, следует распределить его так, чтобы вы получили 3 меньших тензора:
first_term = np.einsum('km, ijk, ijk -> i', s, pp, pp) +\
np.einsum('km, ilm, ilm -> i', s, pp, pp) -\
2 * np.einsum('km, ijk, ilm -> i', s, pp, pp)
. Это использует тот факт, что (a-b)**2 = a**2 + b**2 - 2ab
позволяет разбить задачу на три части, каждая из которых может быть выполнена за один шаг. с точечным произведением