我有一个15M(百万)DAG(有向无环图 - 实际上是指向超立方体)的集合,我想从中删除同构。这个的常见算法是什么?每个图都相当小,一个维数为N的混合立方体,其中N为3到6(现在),得到64个节点的图形,每个N = 6个案例。
使用networkx和python,我实现了这个,适用于像300k(千)这样的小集合就好(几天后运行)。
def isIsomorphicDuplicate(hcL, hc):
"""checks if hc is an isomorphism of any of the hc's in hcL
Returns True if hcL contains an isomorphism of hc
Returns False if it is not found"""
#for each cube in hcL, check if hc could be isomorphic
#if it could be isomorphic, then check if it is
#if it is isomorphic, then return True
#if all comparisons have been made already, then it is not an isomorphism and return False
for saved_hc in hcL:
if nx.faster_could_be_isomorphic(saved_hc, hc):
if nx.fast_could_be_isomorphic(saved_hc, hc):
if nx.is_isomorphic(saved_hc, hc):
return True
return False
更好的方法是将每个图形转换为规范排序,对集合进行排序,然后删除重复项。这绕过了检查二进制is_isomophic()测试中的每个15M图,我相信上面的实现类似O(N!N)(不考虑同构时间)而干净转换为规范排序和排序应该采取O(N)用于转换+ O(log(N)N)用于搜索+ O(N)用于删除重复项。 O(N!N)>>为O(log(N)N)
我在Canonical图形标注上发现了这篇论文,但它用数学方程式非常简洁地描述,没有伪代码:“McKay的Canonical Graph Labeling Algorithm” - http://www.math.unl.edu/~aradcliffe1/Papers/Canonical.pdf
tldr:我有一个不可思议的大量图表来检查二进制同构检查。我相信这样做的常用方法是通过规范排序。是否存在任何打包算法或直接发布以实现算法(即具有伪代码)?
答案 0 :(得分:18)
以下是 McKay的Canonical Graph Labeling Algorithm 的细分,正如Hartke和Radcliffe [link to paper]的论文所示。
我首先应该指出这里有一个开源实现:nauty and Traces source code。
好的,让我们这样做!不幸的是,这个算法在图论中很重要,所以我们需要一些术语。首先,我将首先定义 isomorphic 和自动。
<强>同构:强>
如果它们是相同的,则两个图是同构的,除了顶点标记不同。以下两个图是同构的。
自守:
如果它们完全相同,则两个图是自动的,包括顶点标记。以下两个图是自守的。这似乎微不足道,但由于技术原因,这一点很重要。
图表哈希:
这一切的核心思想是有一种方法将图形散列为字符串,然后对于给定的图形,您计算与其同构的所有图形的哈希字符串。按字母顺序(技术上按字典顺序)最大的同构哈希字符串称为&#34; Canonical Hash&#34;,生成它的图形称为&#34; Canonical Isomorph&#34;或&#34; Canonical标记&#34 ;.
有了这个,要检查是否有两个图是同构的,你只需要检查它们的规范的同形体(或规范的标记)是否相等(即彼此的自动形态)。哇行话!不幸的是,没有术语,这更令人困惑: - (
我们要使用的哈希函数对于图G称为i(G):通过查看G中的每对顶点(按顶点标签的顺序)构建二进制字符串并放置&#34; 1& #34;如果这两个顶点之间有一条边,则a&#34; 0&#34;如果不。这样,i(G)中的第j位表示图中没有该边的存在。
麦凯的标准图标记算法
问题在于,对于n个顶点上的图形,有基于你如何标记顶点的O(n!)个可能的同构哈希字符串,如果我们必须多次计算相同的字符串,那么还有很多(即自动形态) )。一般来说,我们必须计算每个isomorph哈希字符串,以便找到最大的一个,没有神奇的排序。 McKay的算法是一种搜索算法,可以通过从搜索树中修剪所有自动变形来更快地找到这个规范的isomoprh,迫使规范isomoprh中的顶点按递增程度顺序进行标记,以及一些其他减少我们必须哈希的同形数。
(1)第4节:McKay的第一步是根据程度对顶点进行排序,从而修剪大部分isomoprhs进行搜索,但不保证是唯一的排序,因为可能有更多比给定度数的一个顶点。例如,下图有6个顶点; verts {1,2,3}有1度,verts {4,5}有2度,vert {6}有3度。根据顶点度的部分排序是{1,2,3 | 4 ,5 | 6}
(2)第5节:对顶点没有区分的顶点施加人工对称性;基本上我们采用一个具有相同度数的顶点组,然后依次选择一个在总排序中的第一个(图2中的纸张),所以在上面的例子中,节点{1,2 ,3 | 4,5 | 6}会生孩子{{ 1 | 2,3 | 4,5 | 6},{ 2 | 1,3 | 4, 5 | 6}},{ 3 | 1,2 | 4,5 | 6}}}扩展群组{1,2,3}以及子群{{1,2,3 |} 4 | 5 | 6},{1,2,3 | 5 | 4 | 6}}扩展群组{4,5}。这种拆分可以一直到叶节点完成,这些叶节点是像{1 | 2 | 3 | 4 | 5 | 6}这样的总排序,它描述了G的完全同构。这允许我们通过顶点进行部分排序程度从(1),{1,2,3 | 4,5 | 6},并建立一个树列出规范同构的所有候选人 - 这已经是一个少于n的方法!因为,例如,顶点6将永远不会出现。请注意,McKay以深度优先的方式评估孩子,从最小的群体开始,这导致更深但更窄的树,这对于下一步中的在线修剪更好。另请注意,每个总排序叶节点可能出现在多个子树中,修剪进来的地方!
(3)Sect。 6:在搜索树时,查找自同构并使用它来修剪树。这里的数学有点高于我,但我认为这个想法是,如果你发现树中的两个节点是彼此的自同构,那么你可以安全地修剪它们的一个子树,因为你知道它们都会产生相同的叶子节点
我只给出了McKay的高级描述,这篇论文在数学中有了更深入的内容,构建实现需要理解这个数学。希望我已经给你足够的上下文,要么回去重新阅读论文,要么阅读实现的源代码。
答案 1 :(得分:4)
这是一个有趣的问题,我没有答案! 这是我的两分钱:
按15M
你的意思是1500万无向图吗?每个人有多大?任何已知的属性(树,planar
,k-trees
)?
您是否尝试过提前检测误报来减少检查次数?有些东西包括计算和比较顶点,边缘度和度数序列等数字?除了测试给定的两个图是否是同构的其他启发式方法。另外,请检查nauty。它可能是您检查它们的方式(并生成规范排序)。
答案 2 :(得分:3)
这确实是一个有趣的问题。
我会从邻接矩阵角度接近它。两个同构图将具有邻接矩阵,其中行/列的顺序不同。所以我的想法是为每个图形计算几个矩阵属性,这些属性对行/列交换是不变的,在我的头顶上:
numVerts, min, max, sum/mean, trace (probably not useful if there are no reflexive edges), norm, rank, min/max/mean column/row sums, min/max/mean column/row norm
并且所有属性上的任何一对同构图都是相同的。
你可以创建一个哈希函数,它接收一个图形并吐出一个像
这样的哈希字符串string hashstr = str(numVerts)+str(min)+str(max)+str(sum)+...
然后按散列字符串对所有图形进行排序,你只需要对那些散列相同的图形进行完全同构检查。
鉴于您在36个节点上有1500万个图形,我假设您正在处理加权图形,对于未加权的无向图形,这种技术的效果会降低。
答案 3 :(得分:2)
如果你的所有图形都是超立方体(就像你说的那样),那么这是微不足道的:所有具有相同尺寸的超立方体都是同构的,具有不同尺寸的超立方体不是。因此,在线性时间内浏览您的集合,并根据节点数量(对于超立方体:不同维度&lt; =&gt;不同数量的节点)将每个图表放入存储桶中,并使用它完成。
答案 4 :(得分:1)
既然你提到可以检查测试较小的约300k图形组的异形,我会尝试将15M图形分成~300k节点的组并在每组上运行同构测试
说:每个图Gi:= VixEi(Vertices x Edges)
(1)创建图表桶,使第n个桶仅包含| V | = n
的图形(2)对于在(1)中创建的每个桶,创建子桶,使得第(n,m)个子桶只包含图形,使得| V | = n和| E | = m
(3)如果组仍然太大,则按照度数对每个图中的节点进行排序(意味着连接到节点的边的nr),从中创建一个向量并通过该向量分布图
(3)的例子:
假设4个节点V = {v1,v2,v3,v4}。设d(v)为v度,其中d(v1)= 3,d(v2)= 1,d(v3)= 5,d(v4)= 4,然后找< := transitive hull ( { (v2,v1), (v1,v4), (v4,v3) } )
并创建一个依赖于的向量离开的程度和顺序
(1,3,4,5)=(d(v2),d(v1),d(v4),d(v3))= d({v2,v1,v4,v3})= d( ≤)
现在您已将15M图表划分为每个存储桶具有以下特征的存储桶:
如果你期望找不到太多的同构,我认为它足够精细
到目前为止成本:O(n)+ O(n)+ O(n * log(n))
(4)现在,您可以假设每个桶内的成员可能是同性的。您可以在存储桶上运行同构检查,只需要将当前测试的图表与您在此存储桶中找到的所有代表进行比较。假设不应该太多,所以我认为这很便宜。
在第4步,您也可以愉快地将计算分配到多个计算节点,这应该真正加快流程
答案 5 :(得分:0)
也许你可以只使用McKay的实现?现在可以在这里找到:http://pallini.di.uniroma1.it/
您可以将15M图表转换为nauty使用的压缩graph6
格式(或sparse6
),然后运行nauty工具labelg
以生成规范标签(同样在{{ 1}}格式)。
例如 - 从一组随机图中删除同构图:
graph6