【问题标题】:Detecting cycles in an adjacency matrix检测邻接矩阵中的循环
【发布时间】:2013-05-02 10:00:49
【问题描述】:

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)
  • 选择从j出边的集合O,即jA行中的所有1
  • 以 DFS 方式导航 O
  • 如果从此导航生成的路径之一通向节点i,则检测到循环

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

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

提前致谢,

埃莉诺。

【问题讨论】:

    标签: matlab graph matrix graph-algorithm


    【解决方案1】:

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

    反例:根据丹尼尔的回答,长度为 4 的路径将包含一个 4 循环(更不用说答案会暗示 P=NP,因为它会解决汉密尔顿循环问题)。

    无论如何,这是另一种方法。一个图是无环的当且仅当它是一个森林,即它有 c 个分量并且恰好有 n-c 个边,其中 n 是顶点的数量。幸运的是,有一种方法可以使用Laplacian matrixL 来计算分量的数量,它是通过将 -A 的 (i,i) 条目替换为 A 的第 i 行中条目的总和(即程度顶点标记为 i)。则可知G的分量数为n-rank(L)(即0作为L的特征值的重数)。

    所以 G 有一个循环当且仅当边数至少为 n-(n-rank(L))+1。另一方面,根据握手引理,边数正好是 trace(L) 的一半。所以:

    G 是非循环的当且仅当 0.5*trace(L)=rank(L)。等效地,当且仅当 0.5*trace(L) >= rank(L)+1 时,G 有一个循环。

    【讨论】:

    • Asotsky 的答案仅在有向图的情况下是正确的。
    • Casteels 声明 a graph is acyclic iff it has exactly n-c edges 仅适用于无向图。 G is acyclic if and only if the number of edges is at least n-(n-rank(L))+1 的说法显然是错误的(at least 应该是at most
    • @Pushpendre 最初的问题是关于无向图的。但是回想起来,尚不清楚 OP 是否只是在寻找任何长度的三角形或循环。她使用的循环定义似乎暗示她想要三角形,但所提出的算法使它看起来她正在寻找任何长度的循环。无论如何,即使对于有向图,阿索茨基的回答也是不正确的,因为任何无向图都可以通过用两条有向边替换每条边来制成有向图,一条在任一方向。所以我的反例仍然有效。但是,是的,那句话有错别字,谢谢。
    • 让我们使用您使用的“反例”。 A path of length 4 would contain a 4-cycle according to Danil's answer 4 次方路径的有向图中的邻接矩阵将是 {{0, 1, 0, 0},{0, 0, 1,0}, {0, 0, 0, 1}, {0, 0, 0,0}}^4 任何人都可以通过粘贴 wolfram alpha 来确认它没有对角线条目。您是对的,可以通过将一条边替换为两条边将无向图转换为有向图,但是这样做会自动为图添加循环,因此这种构造是无用的。
    • @Pushpendre 我的意思是,如果 Daniel 的答案对于有向图是正确的,那么对于无向图也是正确的,但事实并非如此。我之前评论中的反例没有您写下的邻接矩阵;我说用每个方向上的有向边替换每个边。这给出了与无向情况相同的邻接矩阵。你确定你没有把循环和封闭步行混淆吗?
    【解决方案2】:

    基于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
    

    【讨论】:

    • 相当简单,但效率不高。 n个矩阵乘法就不少了。
    • 请注意,丹尼尔的回答是错误的,至少对于无向图而言;这种方法效率更高,但仍然得出相同的错误结果(例如,考虑无向图的 A^2 的对角线是每个节点的度数,不需要为零就不会出现循环) .有关正确方法,请参阅 Casteels 答案。
    【解决方案3】:

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

    例如如果对于某个整数 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
    

    【讨论】:

    【解决方案4】:

    这种方法使用 DFS,但是非常有效,因为我们不会在后续的 DFS 中重复节点。

    高级方法:

    将所有节点的值初始化为-1

    从每个未探索的节点执行 DFS,将该节点的值设置为从 0 开始的自动递增值。

    对于这些 DFS,使用 previous node's value + i/n^k 更新每个节点的值,其中该节点是前一个节点的 ith 子节点,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,它有两个孩子jmm 没有孩子,j 有 2 个孩子,...。然后我们完成了 i 并从下一个未探索的节点 q 开始了另一个 DFS。

    只要遇到更大的值,就知道发生了循环。

    复杂性:

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

    注意:

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

    【讨论】:

      【解决方案5】:

      这也是我发现的问题。我想,解释如下:
      当我们谈论循环时,我们隐含地指的是定向循环。当您考虑有向图时,您所拥有的邻接矩阵具有不同的含义;它确实是一个长度为 2 的有向循环。因此,$A^n$ 的解决方案实际上是针对有向图的。对于无向图,我想解决方法是只考虑矩阵的上三角版本(其余部分用零填充)并重复该过程。让我知道这是否是正确的答案。

      【讨论】:

        【解决方案6】:

        如果有向图 G 由其邻接矩阵 M 表示,则如果其中存在循环,则 M'=(I - M ) 将是奇异的。 I : M 的同阶单位矩阵

        【讨论】:

        • 这是错误的:设 G 为有向图,邻接矩阵 M= {{0,1,0,0},{0,0,1,1},{1,0,0 ,1},{1,0,0,0}}。这有定向循环,但 I-M 是非奇异的 (det(I-M)=-2)
        【解决方案7】:

        关于矩阵方法的更多想法...引用的示例是断开连接图的邻接矩阵(节点 1 和 2 连接,节点 3 和 4 连接,但没有一对连接到另一对)。当您计算 A^2 时,答案(如上所述)是单位矩阵。但是,由于 Trace(A^2) = 4,这表明有 2 个循环,每个循环长度为 2(这是正确的)。在正确识别并从矩阵中删除这些循环之前,不允许计算 A^3。这是一个涉及多个步骤的过程,R.L. Norman 很好地详细说明了这一过程,“A Matrix Method for Location of Cycles of a Directed Graph”,AIChE J, 11-3 (1965) pp. 450-452。请注意:作者不清楚这种方法是否能保证找到所有循环、唯一循环和/或基本循环。我的经验表明,它绝对不能只识别独特的周期。

        【讨论】:

          【解决方案8】:

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

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

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

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

          【讨论】:

          • 请修改报价单。将> 放在该行的开头。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-03
          • 1970-01-01
          • 2016-04-06
          • 1970-01-01
          相关资源
          最近更新 更多