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有一个循环,如果