Подход № 1
Мы можем использовать np.lib.stride_tricks.as_strided
на основе scikit-image's view_as_windows
, чтобы получить раздвижные окна. Подробнее об использовании as_strided
на основе view_as_windows
.
Кроме того, он принимает аргумент step
, который идеально подходит для этой проблемы. Следовательно, реализация будет -
from skimage.util.shape import view_as_windows
def ranged_mat(n):
r = np.arange(1,n*(n-1)+2)
return view_as_windows(r,n,step=n-1)
Примеры прогонов -
In [270]: ranged_mat(2)
Out[270]:
array([[1, 2],
[2, 3]])
In [271]: ranged_mat(3)
Out[271]:
array([[1, 2, 3],
[3, 4, 5],
[5, 6, 7]])
In [272]: ranged_mat(4)
Out[272]:
array([[ 1, 2, 3, 4],
[ 4, 5, 6, 7],
[ 7, 8, 9, 10],
[10, 11, 12, 13]])
Подход № 2
Другой с outer-broadcasted-addition
-
def ranged_mat_v2(n):
r = np.arange(n)
return (n-1)*r[:,None]+r+1
Подход № 3
Мы также можем использовать numexpr
модуль , который поддерживает многоядерную обработку и, следовательно, обеспечивает более высокую эффективность при больших n's
-
import numexpr as ne
def ranged_mat_v3(n):
r = np.arange(n)
r2d = (n-1)*r[:,None]
return ne.evaluate('r2d+r+1')
Использование нарезки дает нам более эффективное использование памяти -
def ranged_mat_v4(n):
r = np.arange(n+1)
r0 = r[1:]
r1 = r[:-1,None]*(n-1)
return ne.evaluate('r0+r1')
Сроки -
In [423]: %timeit ranged_mat(10000)
273 ms ± 3.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [424]: %timeit ranged_mat_v2(10000)
316 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [425]: %timeit ranged_mat_v3(10000)
176 ms ± 85.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [426]: %timeit ranged_mat_v4(10000)
154 ms ± 82.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)