Matlab 邻接矩阵中的循环检测
设Matlab 邻接矩阵中的循环检测,matlab,graph,matrix,graph-algorithm,Matlab,Graph,Matrix,Graph Algorithm,设A为图G=(V,E)的邻接矩阵A(i,j)=1如果节点i和j与边连接,则A(i,j)=0 我的目标是了解G是否是非循环的。循环的定义方式如下: i和j连接:A(i,j)=1 j和k连接:A(j,k)=1 k和i连接:A(k,i)=1 我实施了一个解决方案,该解决方案在矩阵中导航如下: 从边缘开始(i,j) 选择从j引出的边集O,即j第A 以DFS方式导航O 如果此导航生成的路径之一指向节点i,则检测到一个循环 显然,这个解决方案非常慢,因为我必须计算矩阵中的所有路径。如果A非常大,则所
A
为图G=(V,E)
的邻接矩阵A(i,j)=1
如果节点i
和j
与边连接,则A(i,j)=0
我的目标是了解G
是否是非循环的。循环的定义方式如下:
和i
连接:j
A(i,j)=1
和j
连接:k
A(j,k)=1
和k
连接:i
A(k,i)=1
- 从边缘开始
(i,j)
- 选择从
引出的边集j
,即O
第j
A
- 以DFS方式导航
O
- 如果此导航生成的路径之一指向节点
,则检测到一个循环i
A
非常大,则所需的开销非常大。我想知道是否有一种方法可以导航邻接矩阵,以便在不使用DFS等昂贵算法的情况下找到循环
我想在MATLAB中实现我的解决方案
提前感谢,
Eleanore.如果A是有向或无向图G的邻接矩阵,那么矩阵
A^n
(即,A的n个副本的矩阵乘积)具有以下特性:第i行和第j列中的条目给出了长度为n的从顶点i到顶点j的(有向或无向)行走次数
例如,如果对于某个整数n,矩阵A^n至少包含一个非零对角项,则该图具有大小为n的循环
检查矩阵非零对角元素最简单的方法是计算矩阵trace(A)=sum(diag(A))
(在我们的例子中,矩阵幂的元素总是非负的)
Matlab解决方案可以如下所示:
for n=2:size(A,1)
if trace(A^n) ~= 0
fprintf('Graph contain cycle of size %d', n)
break;
end
end
这种方法使用DFS,但非常有效,因为我们不会在后续DFS中重复节点 高层方法: 将所有节点的值初始化为
-1
从每个未探测的节点执行DFS,将该节点的值设置为从0
开始的自动递增值
对于这些DFS,使用previous node's value+i/n^k
更新每个节点的值,其中该节点是前一个节点的i
子节点,k
是探索的深度,跳过已探索的节点(检查更大的值除外)
因此,n=10
的示例如下:
0.1 0.11 0.111
j - k - p
0 / \ 0.12
i \ 0.2 l
m
1 1.1
q - o
...
您还可以对每个节点使用i/分支因子+1
,以减少数字的有效位数,但这需要额外的计算来确定
所以在上面我们做了一个来自i
的DFS,它有两个孩子j
和m
m
没有孩子,j
有两个孩子。。。。然后我们完成了i
,并从下一个未探测的节点q
启动了另一个DFS
每当你遇到一个更大的值,你就知道一个循环发生了
复杂性:
您最多检查一次每个节点,并且在每个节点上执行n次检查,因此复杂性是O(n^2)
,这与查看矩阵中的每个条目一次相同(这是您做得最好的)
注意:
我还要注意的是,除非是一个非常密集的图,否则a可能比邻接矩阵快。根据对的观察,你需要计算a^n,一种稍微有效的方法是
n = size(A,1);
An = A;
for ii = 2:n
An = An * A; % do not re-compute A^n from skratch
if trace(An) ~= 0
fprintf(1, 'got cycles\n');
end
end
这也是我发现的问题。我想,解释如下:
当我们谈论循环时,隐含的意思是有向循环。当你考虑有向图时,你的邻接矩阵有不同的含义;这确实是一个长度为2的有向循环。所以,$A^n$的解实际上是针对有向图的。对于无向图,我猜想一个解决方案是只考虑矩阵的上三角版本(其余填充零)并重复该过程。让我知道这是否是正确答案。我在回答这个问题时遇到了这个问题。对于未来的读者,我觉得我需要指出(正如其他人已经指出的那样)丹尼尔·阿索茨基的答案是错误的,并提供一种替代方法。Danil所指的定理是,A^k的(i,j)项计算长度k从i到j的行走次数,这里的关键是允许行走重复顶点。因此,即使a^k的对角线条目为正,条目正在计数的每次行走都可能包含重复的顶点,因此不会计为循环 反例:根据Danil的答案,长度为4的路径将包含一个4-循环(更不用说答案将暗示p=NP,因为它将解决Hamilton循环问题) 无论如何,这里有另一种方法。一个图是非循环的当且仅当它是一个森林,即它有c个分量和n-c边,其中n是顶点的数目。幸运的是,有一种方法可以使用L来计算组件的数量,它是通过将-a的(i,i)项替换为a的第i行中的项之和(即标记为i的顶点的度数)来获得的。然后我们知道G的分量数是n秩(L)(即0的重数作为L的特征值) 因此G有一个循环当且仅当边的数目至少为n-(n秩(L))+1。另一方面,通过握手引理,边的数目正好是迹(L)的一半。因此: G是非循环的当且仅当0.5*trace(L)=秩(L)。等价地,G有一个循环,如果