1

鉴于此图:

import igraph as ig 
g=ig.Graph.Erdos_Renyi(10, 0.5, directed=True)

我们可以使用 triad_census 函数轻松找到它的三合会人口普查:

tc = g.triad_census()

如果我们打印'tc',我们会得到类似的东西:

003 : -2147483648 | 012 :  5 | 102 :  2 | 021D:  4
021U:  6 | 021C:  8 | 111D:  9 | 111U: 14
030T:  5 | 030C:  3 | 201 :  6 | 120D:  9
120U:  5 | 120C: 21 | 210 : 18 | 300 :  4

也就是说,对于每种三元组类型,我们都有在图中找到它的次数。

与“三合会普查”不同,“三合会列表”不仅会给出发现三合会的次数,还会给出每次出现的参与者节点。据我所知,这里的问题是“三合会列表算法”不一定与“三合会人口普查算法”相同,后者的计算成本较低。

我尝试查看同构,定义每个三元组,然后在图中搜索它们:

# Set up the 16 possible triads
triad_dict=dict()

#003 A,B,C, the empty graph.
triad = ig.Graph(n = 3, directed=True)
triad_dict['003'] = triad

#012 A->B, C, the graph with a single directed edge.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1)])
triad_dict['012'] = triad

#102 A<->B, C, the graph with a mutual connection between two vertices.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
                (0,2)])
triad_dict['102'] = triad

#021D A<-B->C, the out-star.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
               (0,2)])
triad_dict['021D'] = triad

#021U A->B<-C, the in-star.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(1,0),
                 (2,0)])
triad_dict['021U'] = triad 

#021C A->B->C, directed line.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
                 (1,2)])
triad_dict['021C'] = triad 

#111D A<->B<-C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
               (0,2)])
triad_dict['111D'] = triad

#111U A<->B->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
               (0,2),(2,0)])
triad_dict['111U'] = triad

#030T A->B<-C, A->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
               (2,1),
               (0,2)])
triad_dict['030T'] = triad

#030C A<-B<-C, A->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(1,0),
                 (2,1),
                 (0,2)])
triad_dict['030C'] = triad

#201 A<->B<->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),(1,0),
                 (1,2),(2,1)])
triad_dict['201'] = triad

#120D A<-B->C, A<->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
                 (0,2),
                 (1,2), (2,1)])
triad_dict['120D'] = triad

#120U A->B<-C, A<->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
                (2,1),
                (0,2), (2,0)])
triad_dict['120U'] = triad

#120C A->B->C, A<->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1),
                 (1,2),
                 (0,2), (2,0)])
triad_dict['120C'] = triad

#210 A->B<->C, A<->C.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1), 
                 (1,2), (2,1),
                 (0,2), (2,0)])
triad_dict['210'] = triad

#300 A<->B<->C, A<->C, the complete graph.
triad = ig.Graph(n = 3, directed=True)
triad.add_edges([(0,1), (1,0),
                (1,2), (2,1),
                (0,2), (2,0)])
triad_dict['300'] = triad

seq = ['300', 
       '210', 
       '120C', '120U', '120D', '201',
       '030C', '030T','111U','111D',
       '021C','021U','021D','102',
       '012',
       '003']

#Search isomorphisms for every triad
isomorphisms = dict()
for key in seq:
    isomorphisms[key] = g.get_subisomorphisms_vf2(triad_dict[key])

但是,如果我们有 A<->B<->C,它将关联到几个三元组:

A<->B<->C
A->B->C
A<->B->C
etc.

我只想考虑更完整的三元组(具有更多边的那个)并丢弃它的子三元组。我们可以清理同构字典中重复的三元组,从高阶(更多边)到低阶,例如:

#Search isomorphisms for every triad
seen = []
for key in seq:
    isos = isomorphisms[key]
    isos = [i for i in isos if i not in seen]
    isomorphisms[key] = isos 
    seen.extend(isos)

但是,这不是一个选项,因为该图表示节点之间的一组对话。如果发生了两次不同的对话:

A->B->C->D (1)
A->B->C (2)

(图是多边的)

脚本将删除 (1),因为它认为 (2) 是对应于 (1) 的子图,但不一定正确,因为在这种情况下它们代表不同的对话。

4

1 回答 1

0

您可以列出特定主题的子图同构,请参阅http://igraph.sourceforge.net/doc/python/igraph.GraphBase-class.html#get_subisomorphisms_vf2

编辑

这实际上是一个错误的答案,因为您会找到包含您正在搜索的主题的诱导子图。看评论。

不幸的是(目前)唯一的方法是从 C 中完成它并编写一个回调函数,每次找到一个主题时都会调用它。http://igraph.sourceforge.net/doc/html/ch17s03.html#igraph_motifs_randesu_callback

于 2013-11-25T14:54:25.700 回答