Выполнение внешнего добавления с numpy

Извините, если это глупый вопрос, но я только начинаю с python/numpy, и я действительно не уверен в наиболее эффективных способах решения. Я собираю демо-симулятор N-body для некоторых учеников, но пока я вычисляю силу между частицами, зацикливая позиции этих частиц, которые предсказуемо медленнее мелассы. В принципе, учитывая вектор x[i], я хотел бы вычислить:

n[i] = sum from j = 0 to n-1, j != i of (x[i]-x[j])^-2,

используя функции numpy, а не цикл. Если есть способ выполнить внешнее добавление/умножение:

m[i,j] = x[i]-x[j],
m[i,j] = x[i]*x[j],

Я мог бы использовать это для вычисления.

2 ответа

Все универсальные функции, которые принимают два входных аргумента, имеют атрибут outer:

x = np.array([1, 2, 3])
np.subtract.outer(x, x)

дает:

array([[ 0, -1, -2],
 [ 1, 0, -1],
 [ 2, 1, 0]])

и

np.multiply.outer(x, x)

приводит к:

array([[1, 2, 3],
 [2, 4, 6],
 [3, 6, 9]])


Многие из основных операторов numpy, таких как np.add, np.subtract, np.multiply и т.д., называются универсальными функциями (ufuncs), и имеют (помимо прочего) метод .outer:

import numpy as np
a = np.arange(3)
b = np.arange(5)
c = np.add.outer(a, b)
print(repr(c))
# array([[0, 1, 2, 3, 4],
# [1, 2, 3, 4, 5],
# [2, 3, 4, 5, 6]])

Еще одна очень мощная техника для такого рода вещей - broadcasting:

print(repr(a[:, None] + b[None, :]))
# array([[0, 1, 2, 3, 4],
# [1, 2, 3, 4, 5],
# [2, 3, 4, 5, 6]])

Индексирование с помощью None (или, альтернативно, с np.newaxis) вставляет новое измерение, поэтому a[:, None] имеет форму (3, 1) и b[None, :] имеет форму (1, 5). Трансляция "расширяет" результат по размерам синглтона, так что он имеет форму (3, 5).

licensed under cc by-sa 3.0 with attribution.