这是我的低效Python代码:
import numpy as np
import random
matrix = np.empty( (100,100), dtype=bool )
matrix[:,:] = False
matrix[50,50] = True
def propagate(matrix, i, j):
for (di,dj) in [ (1,0), (0,1), (-1,0), (0,-1) ]:
(ni,nj) = (i+di, j+dj)
if matrix[ni,nj] and flip_coin_is_face():
matrix[i,j] = True
def flip_coin_is_face():
return random.uniform(0,1) < 0.5
for k in xrange(1000):
for i in xrange(1,99):
for j in xrange(1,99):
propagate(matrix, i, j)
基本上从矩阵的中心传播True状态。由于我在Python中编写循环和传播规则,因此这当然非常慢。
我的问题是,如何使用Numpy索引尽可能快地进行此操作?
答案 0 :(得分:1)
我对numpy不太好,但要通过矩阵“传播”,你可以使用像广度优先搜索这样的东西。如果您之前没有使用它,它看起来像这样:
import Queue
def neighbors(i, j, mat_shape):
rows = mat_shape[0]
cols = mat_shape[1]
offsets = [(-1, 0), (1, 0), (0, 1), (0, -1)]
neighbors = []
for off in offsets:
r = off[0]+i
c = off[1]+j
if 0 <= r and r <= rows and 0 <= c and c <= cols:
neighbors.append((r,c))
return neighbors
def propagate(matrix, i, j):
# 'parents' is used in two ways. first, it tells us where we've already been
# second, it tells us w
parents = np.empty(matrix.shape)
parents[:,:] = None
# first-in-first-out queue. initially it just has the start point
Q = Queue.Queue()
# do the first step manually; start propagation with neighbors
matrix[i,j] = True
for n in neighbors(i,j,matrix.shape):
Q.put(n)
parents[n[0],n[1]] = (i,j)
# initialization done. on to the propagation
while not Q.empty():
current = Q.get() # get's front element and removes it
parent = parents[current[0], current[1]]
matrix[current[0], current[1]] = matrix[parent[0], parent[1]] and flip_coin_is_face()
# propagate to neighbors, in order
for next in neighbors(current[0], current[1], matrix.shape):
# only propagate there if we haven't already
if parents[next[0], next[1]] is None:
parents[next[0], next[1]] = current
Q.put(next)
return matrix
你可能会更聪明并且提前切断传播(因为一旦它到达False
,它将永远不会再次获得True
。但对于100x100,这应该足够快。
答案 1 :(得分:1)
我可以想到一种方法,但它与原始代码不同。也就是说,您可以在每个步骤数组中过滤掉一个(k
循环),将每个值传播到它的neiboughours,即滚动骰子4次,然后评估下一步数组。每个操作都可以使用numpy one liner(使用where
,reshape
,+
和*
作为矩阵),因此不会有内部循环。
实际上,差异在于我们没有考虑在一个步骤中传播的值,一次评估所有更改。事实上,它将减慢,并且我认为,根据完成所有矩阵所需的步骤,传播速度会明显减慢。
如果这种方法没问题,我可以提出一些代码。