检测邻接矩阵中的循环

时间:2013-05-08 08:40:13

标签: matlab graph matrix graph-algorithm

A成为图G = (V,E)的邻接矩阵。 A(i,j) = 1如果节点ij与边缘连接,则为A(i,j) = 0

我的目标是了解G是否是非循环的。循环的定义如下:

  • ij已关联:A(i,j) = 1
  • jk已关联:A(j,k) = 1
  • ki已关联:A(k,i) = 1

我已经实现了一个解决方案,可以按如下方式导航矩阵:

  • 从边缘(i,j)
  • 开始
  • 选择从O传出的边{1}},即第jj
  • 中的所有1
  • 以DFS方式导航A
  • 如果从此导航生成的其中一条路径指向节点O,则会检测到一个周期

显然这个解决方案非常慢,因为我必须评估矩阵中的所有路径。如果i非常大,则所需的开销非常大。我想知道是否有一种导航邻接矩阵的方法,以便在不使用昂贵算法(如DFS)的情况下找到周期。

我想在MATLAB中实现我的解决方案。

提前致谢,

Eleanore。

8 个答案:

答案 0 :(得分:11)

在回答math.stackexchange这个问题时,我遇到了这个问题。对于未来的读者,我觉得我需要指出(正如其他人已经知道的那样)Danil Asotsky的答案是不正确的,并提供了另一种方法。 Danil所指的定理是A ^ k的(i,j)条目计算长度为k的的数量,从i到j在G中。这里的关键是a walk 允许重复顶点。因此,即使A ^ k的对角线条目是正的,每个步行条目的计数可能包含重复的顶点,因此不会计为循环。

反例:根据Danil的答案,长度为4的路径将包含一个4周期(更不用说答案意味着P = NP,因为它可以解决汉密尔顿循环问题)。

无论如何,这是另一种方法。当且仅当它是森林时,图是非循环的,即它具有c个分量和正好是n-c个边,其中n是顶点的数量。幸运的是,有一种方法可以使用Laplacian matrix L来计算组件的数量,这是通过将-A的(i,i)条目替换为A的第i行中的条目总和来获得的(即,标记为i)的顶点度。然后,已知G的分量数是n-rank(L)(即,作为L的特征值的0的多重性)。

因此,当且仅当边数为至少n-(n-rank(L))+ 1时,G才有一个周期。另一方面,通过握手引理,边数正好是迹线(L)的一半。所以:

  当且仅当0.5 * trace(L)= rank(L)时,G是非环状的。等效地,当且仅当0.5 * trace(L)> = rank(L)+1时,G具有周期。

答案 1 :(得分:7)

根据对Danil的观察,您需要计算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 :(得分:5)

如果A是有向或无向图G的邻接矩阵,则矩阵A^n(即,n个n个副本的矩阵乘积)具有以下属性:第i行和第j列中的条目给出从顶点i到顶点j的长度为n的(有向或无向)行程的数量。

E.g。如果对于某个整数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

答案 3 :(得分:1)

这种方法使用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/branching factor+1来减少数字的有效数字,但这需要额外的计算才能确定。

所以上面我们从i做了一个DFS,它有2个孩子jmm没有孩子,j有2个孩子,......然后我们完成i并从下一个未开发的节点q开始另一个DFS。

每当遇到更大的值时,您就知道发生了一个循环。

<强>复杂度:

您最多检查一个节点一次,并且在每个节点进行n次检查,因此复杂度为O(n^2),这与查看矩阵中的每个条目一次(您不能做多少)比...好。

注意:

我还要注意,adjacency list可能比邻接矩阵更快,除非它是一个非常密集的图形。

答案 4 :(得分:0)

这也是我发现的问题。我想,解释如下:
当我们谈论周期时,隐含地意味着有向周期。当您考虑有向图时,您拥有的邻接矩阵具有不同的含义;它实际上是长度为2的有向循环。因此,$ A ^ n $的解决方案实际上是针对有向图。对于无向图,我想一个修复就是只考虑矩阵的上三角形(其余的填充零)并重复该过程。如果这是正确答案,请告诉我。

答案 5 :(得分:0)

关于矩阵方法的更多想法...引用的例子是断开连接图的邻接矩阵(节点1和2连接,节点3和4连接,但两对都没有连接到另一对) 。当您计算A ^ 2时,答案(如上所述)是单位矩阵。但是,由于Trace(A ^ 2)= 4,这表明每个长度为2的循环有两个(这是正确的)。在正确识别这些循环并从矩阵中移除之前,不允许计算A ^ 3。这是一个需要几个步骤的参与过程,并且由R.L.Norman很好地详细说明,&#34;定向图的周期位置的矩阵方法,&#34; AIChE J,11-3(1965)pp.450-452。请注意:作者不清楚这种方法是否能保证找到所有循环,UNIQUE循环和/或ELEMENTARY循环。我的经验表明,它绝对不能确定唯一的循环。

答案 6 :(得分:0)

如果有图G由其邻接矩阵M表示,那么如果在其中存在周期,则M&#39; =(I-M)将是单数。 I:M的相同阶数的单位矩阵

答案 7 :(得分:0)

我无法直接添加评论,但 Casteels (@casteels) 的此评论不正确:

<块引用>

@Pushpendre 我的观点是,如果丹尼尔的答案对有向图是正确的,那么它对无向图也是正确的,但事实并非如此。我之前评论中的反例没有你写的邻接>矩阵;我说用>每个方向的有向边替换每个边。这给出了与无向情况相同的邻接矩阵。 > 你确定你不会把循环和封闭步行混淆吗? – Casteels 4 月 24 日 >'15 9:20

只要有向图有两个顶点,两个方向都有弧,那么它就有一个长度为 2 的圈,以及它的邻接矩阵的平方(在上面提出的“构造”中,它确实等于底层无向图的对角线系数),将具有非零对角系数(非空无向图的每个邻接矩阵的平方也是如此,因为边立即给出一个(非基本的)长度为 2 的步行顶点到自身)。所以在这种情况下,丹尼尔的回答基本上正确地检测到了一个循环。上面的推理是不正确的。

丹尼尔的答案对于有向图确实是正确的。在有向图中,一条弧不能双向遍历,因此每个封闭的有向行走都必须包含一个有向环,这将在有向图的原始邻接矩阵的某个幂的对角线上创建一个非零系数。所以可以不断地计算矩阵的幂,从 1 到顶点数,只要对角线系数不为零就停止。