Re: Conversion to graph adjacency list

[email protected]
Newsgroups gmane.comp.python.scientific.user
Message-ID <[email protected]>
Thanks Robert for your hepfull response, now I better understand how csr conversion works.

I'm benchmarking some graph libraries. My edges-to-csr conversion was hand-written in Python, so very slow! Now, with your code, execution time is 7 times faster!

Here is the code, perhaps we can optimize more:


# =============================================
from time import clock
from sys import stderr, stdin

from scipy.sparse.csgraph import minimum_spanning_tree
from scipy.sparse import csr_matrix
import numpy as np


# ------------ Scipy Code ---------------------------

def wedges2adj(edges, n):
    
    G=[[]for _ in range(n)]
    for a, b, w in edges:
        G[a].append((b,w))
        G[b].append((a,w))
    return G

def wedges2scr(edges, n):
    G=wedges2adj(edges, n)
    indptr=[0] 
    cnt=0
     
    for line in G:
        cnt+=len(line)
        indptr.append(cnt)
    data=[]
    indices=[]
    for i in range(n):
        for (j,w) in G[i]:
            data.append(w)
            indices.append(j)
            
    return [data, indptr, indices]

def csr2wedges(Mcsr, shape):
    n, p=shape
    k=0
    edges=[]
    data, cumul, cols  = Mcsr.data,Mcsr.indptr, Mcsr.indices  
    for i in range(n):
        for j in range(cumul[i+1]-cumul[i]):
            edges.append((i, cols[k], data[k]))
            k+=1
    return edges

def kruskal_scipy(edges, n):
    data, indptr, indices=wedges2scr(edges, n)
    csr=csr_matrix((data, indices, indptr), shape=(n, n))     
    tree=minimum_spanning_tree(csr)
    edges=csr2wedges(tree, (n,n))
    return int(sum((round(w)) for (a,b,w) in edges))

# °°°°°°°°°°°°°°°°°°°°°°°



def wedges2scr_FAST(wedges, n):
    row_ind, col_ind, costs = np.transpose(wedges)
    return csr_matrix((costs, (row_ind, col_ind)),
    shape=(n,n))

def kruskal_scipy_FAST(wedges, n):    
    csr=wedges2scr_FAST(wedges, n)
    tree=minimum_spanning_tree(csr).tocoo()
    return int(round(sum(w for (i,j,w) in zip(tree.row, tree.col, tree.data))))


# ------------ Benchmark ---------------------------

def go(solver, L):
    global duration

    N=len(L)
    k=1
    solution=[]
    while k<N:
        edges=[]
        n=L[k]
        k+=1
            
        for a in range(n):
            d=L[k]
            k+=1
            for j in range(d):
                b=L[k]
                k+=1
                w=L[k]
                k+=1
                if a<b:
                    edges.append([a,b-1,w])
        if solver==kruskal_scipy:
            data, indptr, indices=wedges2scr(edges, n)
                
            start=clock()
            csr=csr_matrix((data, indices, indptr), shape=(n, n))             
            tree=minimum_spanning_tree(csr)
            edges=csr2wedges(tree, (n,n)) 
            sol=solver(edges, n)
            duration+=clock()-start              
            solution.append(sol)             
        else:
          
            start=clock()
            sol=solver(edges, n)
            duration+=clock()-start
            solution.append(sol)
    return solution

# data
L=list(int(z) for z in stdin.read().split() if z.isdigit())
output=[]
solvers=[kruskal_scipy, kruskal_scipy_FAST]
for solver in solvers:
    duration=0
    costs=go(solver, L)
    output.append(costs)
    print("%-20s : %.3f" %(solver.__name__, duration), file=stderr)

if all(output[i]== output[0] for i in range(len(solvers))):
    print("NO error detected", file=stderr)
else:
    print("ERROR detected", file=stderr)

# =============================================


Link to data file (100 graphs with at most 30000 vertices each):

https://drive.google.com/file/d/1BKxRAzJ9jeowbrFPyLZ23EomKn1eqohs/view?usp=sharing

The above code is faster than Networkit library code and little slower than Graph-Tool library. 

I have two observations:

1. Python code is only 2 times slower
2. Pure C-code is about 9 times faster

In each case, even SciPy cf. _min_spanning_tree.pyx, algorithm is the same: kruskal with Union-find.




_______________________________________________
SciPy-User mailing list
[email protected]
https://mail.python.org/mailman/listinfo/scipy-user
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.