Sorry if this is a silly question but I am just getting started with python/numpy and I'm really not sure of the most efficient ways to go about things. I'm putting together a demo N-body simulator for some students, but for now, I am computing the force between particles by looping over the positions of those particles which is predictably as slow as molasses. Basically, given a vector x[i]
, I would like to compute:
n[i] = sum from j = 0 to n-1, j != i of (x[i]-x[j])^-2,
using numpy functions rather than looping. If there is a way to perform outer addition/multiplication:
m[i,j] = x[i]-x[j], m[i,j] = x[i]*x[j],
I could use that to do the computation.
To create you own ufunc, you have to define a function, like you do with normal functions in Python, then you add it to your NumPy ufunc library with the frompyfunc() method. The frompyfunc() method takes the following arguments: function - the name of the function. inputs - the number of input arguments (arrays).
All universal functions that take two input arguments have an attribute outer
:
x = np.array([1, 2, 3]) np.subtract.outer(x, x)
gives:
array([[ 0, -1, -2], [ 1, 0, -1], [ 2, 1, 0]])
and
np.multiply.outer(x, x)
results in:
array([[1, 2, 3], [2, 4, 6], [3, 6, 9]])
Many of numpy's basic operators such as np.add
, np.subtract
, np.multiply
etc. are known as universal functions (ufuncs), and have (amongst other things) an .outer
method:
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]])
Another very powerful technique for doing this sort of thing is broadcasting:
print(repr(a[:, None] + b[None, :])) # array([[0, 1, 2, 3, 4], # [1, 2, 3, 4, 5], # [2, 3, 4, 5, 6]])
Indexing with None
(or alternatively, with np.newaxis
) inserts a new dimension, so a[:, None]
has shape (3, 1)
and b[None, :]
has shape (1, 5)
. Broadcasting "expands" the result along the singleton dimensions, so that it has shape (3, 5)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With