4

I'm working on a graph with multiple edges between the same nodes (edges are having different values). In order to model this graph I need to use MultiGraph instead of normal Graph. Unfortunately, it's not possible to run PageRank algo on it.

Any workarounds known ?

NetworkXNotImplemented: not implemented for multigraph type

grechut
  • 2,897
  • 1
  • 19
  • 18
  • Why not use a DiGraph which does support PageRank? Do you need to use a MultiGraph? – EdChum Feb 17 '15 at 11:54
  • Yes, because we can have multiple edges between the same nodes (with different weight of an edge) – grechut Feb 17 '15 at 12:36
  • It's not a particulary complex algorithm: http://networkx.github.io/documentation/networkx-1.9/_modules/networkx/algorithms/link_analysis/pagerank_alg.html#pagerank Perhaps you can modify it for what you want. – Joel Feb 17 '15 at 12:52
  • You can use [pagerank_numpy](https://networkx.github.io/documentation/latest/reference/generated/networkx.algorithms.link_analysis.pagerank_alg.pagerank_numpy.html#networkx.algorithms.link_analysis.pagerank_alg.pagerank_numpy) or [pagerank_scipy](https://networkx.github.io/documentation/latest/reference/generated/networkx.algorithms.link_analysis.pagerank_alg.pagerank_scipy.html#networkx.algorithms.link_analysis.pagerank_alg.pagerank_scipy). Both work with MultiGraph. – Roque Apr 10 '15 at 15:57

2 Answers2

9

You could create make a graph without parallel edges and then run pagerank. Here is an example of summing edge weights of parallel edges to make a simple graph:

import networkx as nx
G = nx.MultiGraph()
G.add_edge(1,2,weight=7)
G.add_edge(1,2,weight=10)
G.add_edge(2,3,weight=9)

# make new graph with sum of weights on each edge
H = nx.Graph()
for u,v,d in G.edges(data=True):
    w = d['weight']
    if H.has_edge(u,v):
        H[u][v]['weight'] += w
    else:
        H.add_edge(u,v,weight=w)

print H.edges(data=True)
#[(1, 2, {'weight': 17}), (2, 3, {'weight': 9})]
print nx.pagerank(H)
#{1: 0.32037465332634, 2: 0.4864858243244209, 3: 0.1931395223492388}
Aric
  • 24,511
  • 5
  • 78
  • 77
0

You can still compose a Digraph by combining the edges while adding their weights.

# combining edges using defaultdict
# input-- combined list of all edges
# ouput-- list of edges with summed weights for duplicate edges
from collections import defaultdict  
def combine_edges(combined_edge_list):    
    ddict = defaultdict(list)

    for edge in combined_edge_list:
        n1,n2,w = edge
        ddict[(n1,n2)].append(w)
    
    for k in ddict.keys():
        ddict[k] = sum(ddict[k])
    
    edges = list(zip( ddict.keys(), ddict.values() ) )    

    return [(n1,n2,w) for (n1,n2),w in edges]   
kosmos
  • 359
  • 5
  • 13