Phil Snyder
Phil Snyder

Reputation: 65

NetworkX - creating a deep copy of reversed graph

I'm having an issue when trying to create a deep copy of a reversed digraph in NetworkX and examining the PageRank of that copy. It doesn't appear that the issue is with PageRank, it just throws an exception when trying to calculate the PageRank of the broken reversed digraph.

First, I generate a digraph using this code, which basically just creates a bunch of nodes, randomly picks a few of them, and then draws directed edges from that node to another 50 or so randomly selected nodes. It then trims all nodes with degree 0.

def global_classroom(nodes):
    network = nx.DiGraph()
    network.add_nodes_from([User(i, "0.0.1") for i in range(nodes)])
    network_nodes = network.nodes()
    teachers = random.sample(network_nodes, nodes / 100)
    for teacher in teachers:
        for i in range(nodes / 20):
            student = network_nodes[random.randrange(nodes)]
            if teacher != student:
            network.add_edge(teacher, student)
    for node in network_nodes:
        if network.degree(node) == 0:
            network.remove_node(node)
    return network

Now, if I call this:

G = global_classroom(1000)
G.reverse(False)
print nx.pagerank(G)

Everything works perfectly fine. NetworkX is able to calculate the PageRank no problem.

But if I call this:

G = global_classroom(1000)
G_page_rank = G.reverse()
nx.pagerank(G_page_rank)

There is an exception thrown

  Traceback (most recent call last):
  File "a.py", line 62, in <module>
  rank = nx.pagerank(L_page_rank)
  File "<string>", line 2, in pagerank
  File "/Users/PSnyder/Documents/Git/infection/networkx/utils/decorators.py", line 68, in _not_implemented_for
  return f(*args,**kwargs)
  File "/Users/PSnyder/Documents/Git/infection/networkx/algorithms/link_analysis/pagerank_alg.py", line 140, in pagerank
  dangling_nodes = [n for n in W if W.out_degree(n, weight=weight) == 0.0]
  File "/Users/PSnyder/Documents/Git/infection/networkx/classes/digraph.py", line 1023, in out_degree
  return next(self.out_degree_iter(nbunch,weight))[1]
  File "/Users/PSnyder/Documents/Git/infection/networkx/classes/digraph.py", line 941, in out_degree_iter
  for n,nbrs in nodes_nbrs:
  File "/Users/PSnyder/Documents/Git/infection/networkx/classes/digraph.py", line 934, in <genexpr>
  nodes_nbrs=((n,self.succ[n]) for n in self.nbunch_iter(nbunch))
  KeyError: <__main__.User object at 0x104618050>

Where <__main__.User object at 0x104618050> is one of the many objects that make up the nodes in my digraph.

I'd like to be able to simply make a deep copy instead of needing to reverse my graph once again to revert it to its original form.

Here is the entirety of the User class which makes up my nodes:

class User(object):
    def __init__(self, name, version, teachers = [], students = []):
        self.name = name
        self.version = version
        G.add_node(self)
        self.add_teachers(teachers)
        self.add_students(students)

    def add_students(self, students):
        for student in students:
            G.add_edge(self, student)

    def add_teachers(self, teachers):
        for teacher in teachers:
            G.add_edge(teacher, self)

Upvotes: 0

Views: 890

Answers (1)

Aric
Aric

Reputation: 25289

Maybe your User object is causing an issue? You didn't include that so I can't see if this is a networkx bug or not.

This works (using integers instead of User())

import networkx as nx
import random

def global_classroom(nodes):
    network = nx.DiGraph()
    network.add_nodes_from([i for i in range(nodes)])
    network_nodes = network.nodes()
    teachers = random.sample(network_nodes, nodes / 100)
    for teacher in teachers:
        for i in range(nodes / 20):
            student = network_nodes[random.randrange(nodes)]
            if teacher != student:
                network.add_edge(teacher, student)
    for node in network_nodes:
        if network.degree(node) == 0:
            network.remove_node(node)
    return network


if __name__=='__main__':
    G = global_classroom(1000)
    G.reverse(False)
    print nx.pagerank(G).items()[0:5] # first 5

Upvotes: 1

Related Questions