2013-11-22 50 views
1

模擬傳播這裏是低效的Python代碼我有:numpy的:如何在晶格

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) 

基本上從基體的中心傳播的真實狀態。由於我在Python中編碼循環和傳播規則,所以這當然非常慢。

我的問題是,我怎樣才能使用Numpy索引來儘可能快地做到這一點?

+1

我運行了你的代碼,它以[0,0]爲True且其餘全部爲假的矩陣結束。當然,這不是你想要的? –

+0

@JohnZwinck基於'從矩陣的中心傳播真實狀態'我想它應該是'矩陣[50,50] =真'而不是'矩陣[0,0] =真' – alko

+0

@JohnZwinck at-alko你是對的。 – dsign

回答

1

我可以想到一種方法,但它與您的原始代碼不同。也就是說,可以在每個步驟數組(k循環)中過濾一個數值,將每個值傳播到它的neiboughours,即將擲骰子擲4倍數,然後評估下一步數組。每個操作都可以使用一個numpy一行(對矩陣使用where,reshape,+*),所以不會出現內循環。

不同之處在於我們沒有考慮價值,在一個步驟中傳播,一次評估所有變更。事實上,它會減慢速度,並且我認爲,在滿足所有矩陣所需的步驟方面,傳播速度是顯而易見的。

如果這種方法沒問題,我可以拿出一些代碼。

+0

嗨!感謝您的回答。我想我可以從那裏拿走......事實上,現在我認爲它「不考慮(步進傳播)值」是解決我的問題的正確方法.... – dsign

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,這應該足夠快。

+0

我在找numpy索引的方式尋找更多的東西......恐怕在這種情況下,Queue不會有太大幫助,因爲在numpy實現後面有一些C代碼來完成這項工作...... Anyway , 感謝您的關注。 – dsign