2016-04-16 6 views
0

Ich möchte die Kante in der ursprünglichen Matrix schneiden und frage mich, gibt es einen schnelleren Weg. Da ich die selectEdge-Funktion oft mit den gleichen Positionen und Positionen ausführen muss, was bedeutet, dass sich der Index für viele Graphen nicht ändert? Ist es möglich, eine Mapping-Matrix zu erstellen, die für alle geeignet ist?Beschleunigen Sie erhalten Kantenmatrix nach Index mit numpy Array

vielen Dank

def selectEdge(positions, positions_u, originalMat, selectedMat): 
    """ select Edge by neighbors of all points 
    many to many 
    m positions 
    n positions 
    would have m*n edges 
    update selectedMat 
    """ 
    for ele in positions: 
     for ele_u in positions_u:    
      selectedMat[ele][ele_u] += originalMat[ele][ele_u] 
      selectedMat[ele_u][ele] += originalMat[ele_u][ele] 
    return selectedMat 

ich nur die obere Dreiecksmatrix müssen, weil sie symmetrisch

def test_selectEdge(self): 
     positions, positions_u = np.array([0,1,5,7]), np.array([2,3,4,6]) 
     originalMat, selectedMat = np.array([[1.0]*8]*8), np.array([[0.0]*8]*8) 
     selectedMat = selectEdge(positions, positions_u, originalMat, selectedMat) 
     print 'position, positions_u' 
     print positions, positions_u 
     print 'originalMat', originalMat 
     print 'selectedMat', selectedMat 

hier ist mein Test

position, positions_u 
[0 1 5 7] [2 3 4 6] 
originalMat 
[[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1.]] 
selectedMat 
[[ 0. 0. 1. 1. 1. 0. 1. 0.] 
[ 0. 0. 1. 1. 1. 0. 1. 0.] 
[ 1. 1. 0. 0. 0. 1. 0. 1.] 
[ 1. 1. 0. 0. 0. 1. 0. 1.] 
[ 1. 1. 0. 0. 0. 1. 0. 1.] 
[ 0. 0. 1. 1. 1. 0. 1. 0.] 
[ 1. 1. 0. 0. 0. 1. 0. 1.] 
[ 0. 0. 1. 1. 1. 0. 1. 0.]] 

führt, es wäre sogar noch langsamer sein für letzteres zum Auswählen von Nachbarkanten

def selectNeighborEdges(originalMat, selectedMat, relation): 
    """ select Edge by neighbors of all points 
    one to many 
    Args: 
     relation: dict, {node1:[node i, node j,...], node2:[node i, node j, ...]} 

    update selectedMat 
    """ 
    for key in relation: 
     selectedMat = selectEdge([key], relation[key], originalMat, selectedMat) 
    return selectedMat 

Antwort

3

Sie können die Doppel for-loop beseitigen "advanced integer indexing" unter Verwendung:

X, Y = positions[:,None], positions_u[None,:] 
selectedMat[X, Y] += originalMat[X, Y] 
selectedMat[Y, X] += originalMat[Y, X] 

Zum Beispiel

import numpy as np 

def selectEdge(positions, positions_u, originalMat, selectedMat): 
    for ele in positions: 
     for ele_u in positions_u: 
      selectedMat[ele][ele_u] += originalMat[ele][ele_u] 
      selectedMat[ele_u][ele] += originalMat[ele_u][ele] 
    return selectedMat 

def alt_selectEdge(positions, positions_u, originalMat, selectedMat): 
    X, Y = positions[:,None], positions_u[None,:] 
    selectedMat[X, Y] += originalMat[X, Y] 
    selectedMat[Y, X] += originalMat[Y, X] 
    return selectedMat 


N, M = 100, 50 
positions = np.random.choice(np.arange(N), M, replace=False) 
positions_u = np.random.choice(np.arange(N), M, replace=False) 
originalMat = np.random.random((N, N)) 
selectedMat = np.zeros_like(originalMat) 

Prüfen Sie zunächst, dass selectEdge und alt_selectEdge das gleiche Ergebnis zurück:

expected = selectEdge(positions, positions_u, originalMat, selectedMat) 
result = alt_selectEdge(positions, positions_u, originalMat, selectedMat) 
assert np.allclose(expected, result) 

ist hier ein timeit Benchmark (mit IPython):

In [89]: %timeit selectEdge(positions, positions_u, originalMat, selectedMat) 
100 loops, best of 3: 4.44 ms per loop 

In [90]: %timeit alt_selectEdge(positions, positions_u, originalMat, selectedMat) 
10000 loops, best of 3: 104 µs per loop 
Verwandte Themen