1
votes

I'm currently trying to build a block model using the python package networkx. I found that the function networkx.quotient_graph can be used for this job:

g_block = nx.quotient_graph(G=g, partition=node_list, relabel=True)

In the next step, I want to export the generated block graph "g_block" to a file to import it afterwards in a visualization tool that supports for example graphml-files.

nx.write_graphml(g_block, 'test_block.graphml')

However, this leads to the error:

{KeyError}class 'networkx.classes.graphviews.SubDiGraph'

Can someone help?

1

1 Answers

0
votes

Currently networkx (version 2.2) doesn't support nested graphs in a way you can easily export and visualize. Consider using graphviz for handling your nested graph and export it to a dot format.

For working with a networkx version of the graph, you can transform the pygraphviz to a networkx graph and vise versa by keeping a 'graph' property for nodes (which is semantically a subgraph), similarly to the result of quotient_graph.

Here is an example of transforming a small networkx graph to pygraphviz with subgraphs, and exporting it as a dot file:

import networkx as nx
import pygraphviz as pgv

G = nx.erdos_renyi_graph(6, 0.5, directed=False)
node_list = [set([0, 1, 2, 3]), set([4, 5])]
pgv_G = pgv.AGraph(directed=True)
pgv_G.add_edges_from(G.edges())
for i, sub_graph in enumerate(node_list):
    pgv_G.add_subgraph(sub_graph, name=str(i))

print(pgv_G)
pgv_G.write("test_pgv.dot")

Note that netwrokx also allows writing and reading 'dot' format (see example), however since there is no built-in support for nested graphs it's not too helpful for this purpose.


The reason you can't write the quotient_graph is twofold:

  1. In a quotient_graph each node has a 'graph' property, which is a SubDiGraph (or a SubGraph, if the original graph is undirected). A SubDiGraph is a ReadOnlyGraph which means it is not possible to write it using the standard networkx.readwrite utils.
  2. Even if we convert the SubDiGraph to a DiGraph, not every graph file format allows to encode a 'graph' property. For example, graphml format supports primitive properties such as booleans, integers etc. Read more here.

One solution that works is to solve the first issue by overriding the 'graph' property with a DiGraph copy of the original SubDiGraph. The second issue can be simply solved by using another file format (e.g., pickle format can work). Read about all supported formats here.

Following is a working example:

g_block = nx.quotient_graph(G=G, partition=node_list, relabel=True)

def subdigraph_to_digraph(subdigraph):
    G = nx.DiGraph()
    G.add_nodes_from(subdigraph.nodes())
    G.add_edges_from(subdigraph.edges())
    return G

for node in g_block:
    g_block.nodes[node]['graph'] = subdigraph_to_digraph(g_block.nodes[node]['graph'])

nx.write_gpickle(g_block, "test_block.pickle")

This allows to write and load the nested graph for using with netwrokx, however for the purpose of using the exported file in a visualization tool this is not too helpful.