realizando la adición externa con numpy

Lo siento si esta es una pregunta tonta, pero acabo de comenzar con python / numpy y realmente no estoy seguro de cuál es la forma más eficiente de abordar las cosas. Estoy armando un simulador de N-body para algunos estudiantes, pero por ahora, estoy calculando la fuerza entre las partículas haciendo un bucle sobre las posiciones de esas partículas, lo cual es predeciblemente tan lento como la melaza. Básicamente, dado un vector x[i] , me gustaría calcular:

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

utilizando funciones numpy en lugar de bucles. Si hay una manera de realizar la sum / multiplicación externa:

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

Podría usar eso para hacer el cálculo.

Todas las funciones universales que toman dos argumentos de entrada tienen un atributo outer :

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

da:

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

y

 np.multiply.outer(x, x) 

resultados en:

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

Muchos de los operadores básicos de np.add , como np.add , np.add , np.subtract , etc. se conocen como funciones universales (ufuncs) y tienen (entre otras cosas) un método .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]]) 

Otra técnica muy poderosa para hacer este tipo de cosas es la transmisión :

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

La indización con None (o alternativamente, con np.newaxis ) inserta una nueva dimensión, por lo que a[:, None] tiene forma (3, 1) y b[None, :] np.newaxis b[None, :] tiene forma (1, 5) . La difusión “expande” el resultado a lo largo de las dimensiones singleton, para que tenga forma (3, 5) .