是否有一個相當於在Perl中解除引用的Python?


0 Answers

Question

我目前正在將一個代碼庫移植到Python中,我最初是用Perl實現的。 當我在整個數據集上運行時,以下一小段代碼佔用了大量運行時間的90%。

    def equate():
        for i in range(row):
            for j in range(row):
                 if adj_matrix[i][j] != adj_matrix[mapping[i]][mapping[j]]:
                 return False
        return True

其中equate是另一種方法中的閉包,row是一個整數,adj_matrix是一個表示一個矩陣的列表,mapping是一個表示一個向量的列表。

等效的Perl代碼如下所示:

sub equate
{
    for ( 0..$row)
    {
        my ($smrow, $omrow) = ($$adj_matrix[$_], $$adj_matrix[$$mapping[$_]]); #DEREF LINE
        for (0..$row)
        {
            return 0 if $$smrow[$_] != $$omrow[$$mapping[$_]];
        }
    }
    return 1;
 }

這被封裝在子外部子程序中,所以我不必將變量傳遞給子程序。

簡而言之,Perl版本要快得多,我的測試表明這是由於“DEREF LINE”中的解引用。 我已經嘗試了我相信在Python中的等價物:

    def equate():
        for i in range(row):
            row1 = adj_matrix[i]
            row2 = adj_matrix[mapping[i]]
            for j in range(row):
                 if row1[j] != row2[mapping[j]]:
                 return False
        return True

但這是一個微不足道的改進。 此外,我嘗試使用NumPy矩陣來表示adj_matrix,但這也是一個小的改進,可能是因為adj_matrix通常是一個小矩陣,所以NumPy的開銷要大得多,而且我也沒有做任何矩陣數學運算。

我歡迎任何改善Python equate方法的運行時間的建議,以及為什麼我的“改進的”Python equate方法沒有equate的解釋。 雖然我認為自己是一名稱職的Perl程序員,但我是一名Python新手。

額外細節:

我使用的Python 3.4,雖然類似的行為被觀察到,當我最初在2.7中實現它。 自從我工作的實驗室使用3.4以來,我改用了3.4。

至於載體的內容,請允許我提供一些背景知識,以下細節是有意義的。 這是識別兩個化合物(a和b)之間的子圖同構的算法的一部分,這兩個化合物分別由圖A和B表示,其中每個原子是一個節點,並且每個原子都是一個邊。 上面的代碼適用於A = B的簡化情況,所以我正在尋找化合物(對稱平面)的對稱變換,並且原子數量中的A的大小為N.每個原子被分配一個唯一的索引,從零。

映射是維度為1xN的一維向量,映射中的每個元素都是一個整數。 mapping[i] = j ,表示具有索引i的原子(將被稱為原子i或一般原子'索引')當前被映射到原子j。 沒有映射表示為j = -1。

Adj_matrix是維度為NxN的二維矩陣,其中每個元素adj_matrix [i] [j] = k是一個自然數,表示化合物A中原子i和j之間的邊的存在和順序。如果k = 0,則不存在這樣的邊緣(在i和j之間沒有鍵),否則k> 0,並且k表示原子i和j之間的鍵的順序。

當A!= B時,有兩個不同的adj_matrices equate比較,原子中a和b的大小是Na和Nb。 Na不必等於Nb,但是Na = <Nb。 我只提到這一點,因為對於在一般情況下無效的特例,優化是可能的,但任何建議都會有幫助。




Related