2016-01-28 4 views
1

Добрый день, для моих исследований Я создал клеточный автомат в 2 измерениях. Программа уже запущена, но я все еще пытаюсь ее оптимизировать. Кусок кода ниже суммирует все 8 соседних ячеек центральной ячейки в 2D-массиве. После этого следующая ячейка определяется как функция суммы. Есть ли более быстрый способ, чем 2 для петель?Более эффективный способ суммирования по матрице в numpy/regular python

Прежде, чем я даже имел 4 для петель для суммирования, но это было 2 раз медленнее, чем сейчас ...

n = len(mat1) 
m = len(mat1[0]) 
mat2 = np.zeros((n,m)) 
sumN = 0 
start = time.time() 
for i in range(1,n-1): 
    for 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 and mat1[i,j] == 0: 
      mat2[i,j] = 1 
     elif str(sumN) in S and mat1[i,j] == 1: 
      mat2[i,j] = 1 
     sumN = 0 
end = time.time() 
print end - start 

Благодаря хпх, я включил пролонгировать матрицу вместо цикла по всем элементы. После этого я создал логический 2D-массив numpy, который я использую для инициализации следующего поколения.

sumN = sum(np.roll(np.roll(mat1, i, 0), j, 1) 
for i in (-1, 0, 1) for 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) and (str(int(l)) in B)) 
    or ((int(x) == 1) and (str(int(l)) in S)), mat1,sumN)).reshape(n,m)       
mat2 = np.zeros((n,m))              
mat2[b] = 1               
mat2 = mat2.reshape(n,m) 
+0

Я также использовал функцию суммы NumPy над матрицей 3х3 внутри цикла, но это было еще медленнее ... – Noveel

+1

вы можете просто использовать свертку? Например, scipy.signal.convolve2d.with форма вашего ядра? http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.signal.convolve2d.html – otterb

+0

Какова точка 'str (sumN) в B' и' str (sumN) в S' звонки? Почему вы вычисляете значение, а затем пытаетесь выяснить, находится ли строковое представление числа в 'B' или' S'? Что такое 'B' и' S'? Списки? Строки? Это поможет, поэтому я смогу дать вам ответ. – rayryeng

ответ

1

Хороший способ сделать это дано в this blog article:

nbrs_count = sum(np.roll(np.roll(mat1, i, 0), j, 1) 
       for i in (-1, 0, 1) for j in (-1, 0, 1) 
       if (i != 0 or j != 0)) 

Это работает, потому что numpy.roll(a, shift, axis) сдвигает элементы вдоль заданной оси, axis, указанное количество мест, shift с обертыванием, так каждую из 8 ячеек можно поочередно посещать, если вы перебираете строки i=-1,0,1 и столбцы j=-1,0,1, но будьте осторожны, чтобы не считать центральную ячейку.

+0

Эта уверенность ускоряет это! Спасибо, что поделился! – Noveel

0

Не уверен, что это быстрее (вы должны проверить его с помощью набора данных), но то, что вы пытаетесь сделать, похоже, близко к обработке изображений.

Изображение Scikit - довольно хороший модуль для этого, и есть очень хороший шанс быть намного быстрее, чем ваше решение, поскольку в C/Fortran реализовано множество функций.

from skimage.morphology import square 
import skimage.filters.rank as rank 
import numpy as np 

sumN=rank.sum(mat1,square(3)) # sum of each pixels in a 3 pixel-sided square 

# compare with B and S : 
n,m =np.shape(mat1) 
sumN=np.flatten(sumN) # vectorize your array to be faster 
mat1=np.flatten(sumN) 
mat2=np.zeros_like(mat1) 
for i in range(len(mat1): # only looping on 1 variable is faster 
    if str(sumN[i]) in B and mat1[i] == 0: 
     mat2[i] = 1 
    elif str(sumN[i]) in S and mat1[i] == 1: 
     mat2[i] = 1 
mat1=mat1.reshape(n,m) # go back to the previous shape 
mat2=mat2.reshape(n,m) 
Смежные вопросы