在 Python 中使用 networkx 识别子图

Recognizing subgraphs with networkx in Python

我有一个 3x3 的正方形格子,其中每个节点都与其垂直的邻居相连。由于它是一个重复格子,因此一侧的外部节点连接到另一侧的外部节点。例如,在 this diagram 中,节点 '0, 0' 连接到 '0, 2' 和 '2, 0'(以及 '0, 1' 和 '1, 0')。

我想使用 NetworkX 识别 horizontal subgraphs(例如“0, 0”、“1, 0”、“2, 0”)。这是我的代码:

import networkx as nx
import networkx.algorithms.isomorphism as iso
import matplotlib.pyplot as plt
import numpy as np


wrap = True #If True, outer nodes are connected to nodes on opposite end
size = 3
pos = {}

big_graph = nx.Graph()    
#Create nodes
for i in xrange(size):
    for j in xrange(size):
        current_node = '{}, {}'.format(i, j)
        big_graph.add_node(current_node, i = i, j = j)
        pos[current_node] = np.array([i, j])

#Create edges
for i in xrange(size):
    for j in xrange(size):
        current_node = '{}, {}'.format(i, j)
        #Add edge to connect node above
        if i != 0:
            big_graph.add_edge(current_node, '{}, {}'.format(i-1, j), direction = 'hor')
        elif wrap:
            big_graph.add_edge(current_node, '{}, {}'.format(size-1, j), direction = 'hor')

        #Add edge to connect node below
        if i != (size-1):
            big_graph.add_edge(current_node, '{}, {}'.format(i+1, j), direction = 'hor')
        elif wrap:
            big_graph.add_edge(current_node, '{}, {}'.format(0, j), direction = 'hor')

        #Add edge to connect node above
        if j != 0:
            big_graph.add_edge(current_node, '{}, {}'.format(i, j-1), direction = 'vert')
        elif wrap:
            big_graph.add_edge(current_node, '{}, {}'.format(i, size-1), direction = 'vert')

        #Add edge to connect node below
        if j != (size-1):
            big_graph.add_edge(current_node, '{}, {}'.format(i, j+1), direction = 'vert')
        elif wrap:
            big_graph.add_edge(current_node, '{}, {}'.format(i, 0), direction = 'vert')

#Print Node information
print 'Nodes:'
print 'n    Node   i  j'
for i, node in enumerate(sorted(big_graph.nodes_iter())):
    print '{:2d}   {}   {}  {}'.format(i, node, nx.get_node_attributes(big_graph, 'i')[node], nx.get_node_attributes(big_graph, 'j')[node])
print '-'*10

#Print Edge information
print 'Edges:'
print 'n    Nodes                  Direction'
for i, edge in enumerate(sorted(big_graph.edges_iter())):
    print '{:2d}   {}       {}'.format(i, edge, nx.get_edge_attributes(big_graph, 'direction')[edge])
print '-'*10


#Subgraph to recognize
small_graph = nx.Graph()
small_graph.add_nodes_from(['A', 'B', 'C'])
small_graph.add_edge('A', 'B', direction = 'hor')
small_graph.add_edge('B', 'C', direction = 'hor')


#Print edge information
print 'Small graph edges'
for i, edge in enumerate(sorted(small_graph.edges_iter())):
    print '{} {}  {}'.format(i, edge, nx.get_edge_attributes(small_graph, 'direction')[edge])
    #print '{}'.format(edge, nx.get_edge_attributes(small_graph))
print '-'*10

#Find subgraphs
GM = iso.GraphMatcher(big_graph, small_graph, edge_match=iso.categorical_edge_match('direction', ''))
subgraph_list = []
print 'Subgraphs found'
for i, subgraph in enumerate(GM.subgraph_isomorphisms_iter()):
    print '{}\t{}'.format(i, subgraph)
    subgraph_list.append(subgraph)
print 'Number of subgraphs: {}'.format(len(subgraph_list))


#Draw the graph
pos=nx.spring_layout(big_graph, pos = pos)
nx.draw(big_graph, pos = pos, node_size = 700)
nx.draw_networkx_labels(big_graph, pos = pos)
plt.show()

当 wrap 设置为 False 时,它​​会给出我期望的答案:

Subgraphs found
0   {'0, 0': 'A', '1, 0': 'B', '2, 0': 'C'}
1   {'0, 1': 'A', '1, 1': 'B', '2, 1': 'C'}
2   {'1, 2': 'B', '0, 2': 'A', '2, 2': 'C'}
3   {'1, 2': 'B', '0, 2': 'C', '2, 2': 'A'}
4   {'0, 0': 'C', '1, 0': 'B', '2, 0': 'A'}
5   {'0, 1': 'C', '1, 1': 'B', '2, 1': 'A'}
Number of subgraphs: 6

但是,当 wrap = True 时,它​​找不到任何子图。

Subgraphs found
Number of subgraphs: 0

有谁知道为什么会这样?

我的解释是,当您使用 wrap=True 时它找不到子图,因为缺少开始和结束节点 - 它们未指定。也就是说,当你包裹格子时,它的行为有点像一个球体,当你在它的表面上行走时,没有物理起点或终点。

我的建议是像您所说的那样更改 size,或者尽可能坚持使用 wrap=False