More efficient way of suming over a matrix in numpy/regular python -
good day, studies created cellular automato in 2 dimension. program running still try optimize it. piece of code bellow sums 8 neighbor cells of central cell in 2d array. after next cell gets defined function of sum. there faster way 2 for-loops?
before had 4 loops summation, 2 time slower it's now...
n = len(mat1) m = len(mat1[0]) mat2 = np.zeros((n,m)) sumn = 0 start = time.time() in range(1,n-1): j in range(1,m-1): sumn = mat1[i-1,j-1] + mat1[i-1,j] + mat1[i-1,j+1] + mat1[i,j-1] +mat1[i,j+1] + mat1[i+1,j] + mat1[i+1,j+1]+ mat1[i+1,j-1] if str(sumn) in b , mat1[i,j] == 0: mat2[i,j] = 1 elif str(sumn) in s , mat1[i,j] == 1: mat2[i,j] = 1 sumn = 0 end = time.time() print end - start
thanks xnx, included roll on matrix instead of looping on elements. after created boolean 2d numpy array use initialize next generation.
sumn = sum(np.roll(np.roll(mat1, i, 0), j, 1) in (-1, 0, 1) j in (-1, 0, 1) if (i != 0 or j != 0)).flatten() mat1 = mat1.flatten() b = np.array(map(lambda x,l: ((int(x) == 0) , (str(int(l)) in b)) or ((int(x) == 1) , (str(int(l)) in s)), mat1,sumn)).reshape(n,m) mat2 = np.zeros((n,m)) mat2[b] = 1 mat2 = mat2.reshape(n,m)
a nice way given in this blog article:
nbrs_count = sum(np.roll(np.roll(mat1, i, 0), j, 1) in (-1, 0, 1) j in (-1, 0, 1) if (i != 0 or j != 0))
it works because numpy.roll(a, shift, axis)
shifts elements along given axis, axis
, specified number of places, shift
wrapping, each of 8 cells can visited in turn if iterate on rows i=-1,0,1
, columns j=-1,0,1
take care not count centre cell itself.
Comments
Post a Comment