找到两个顶点(节点)之间的所有路径

时间:2011-10-28 15:36:13

标签: r graph

我是R编程的新手,我参与使用R表示图形。 我想问一下如何实现一个代码,该代码可以根据邻接矩阵找到两个顶点或节点之间的所有路径。我已经在其他编程语言中看到了很多实现,但是大多数都使用(BFS)中的队列来使它们工作。例如,这是我的图表的边缘列表。

          [,1] [,2]
    [1,]    0    1
    [2,]    1    2
    [3,]    1    3
    [4,]    1    4
    [5,]    2    5
    [6,]    2    6
    [7,]    5    7
    [8,]    5    8
    [9,]    6    9
   [10,]    6   10
   [11,]    8   11
   [12,]   10   12
   [13,]   11   13
   [14,]   11   14
   [15,]   11   15
   [16,]   12   16
   [17,]   12   17
   [18,]   12   18
   [19,]   13   19
   [20,]   16   20
   [21,]   19   21
   [22,]   19   22
   [23,]   20   22
   [24,]   20   23    

如果我想要节点0和节点22之间的所有路径,它们应该是两条路径:

   [[1]]
    [1]  0  1  2  6 10 12 16 20 22

   [[2]]
    [1]  0  1  2  5  8 11 13 19 22

谢谢

5 个答案:

答案 0 :(得分:4)

我使用以下代码来创建一个矩阵(顶点x顶点),其中包含每两个顶点之间所有路径的数量

library(igraph)
setwd("C:/Workspace")
graph <- read.graph("graph.txt", format="edgelist")
direct <- get.adjacency(graph)
indirect <- direct
max <- vcount(graph)-1
for(i in 0:max)
 for(j in 0:max)
  indirect[i,j] <- length(get.all.shortest.paths(graph, from=i, to=j, mode="out"))

我建议将igraph库用于此目的。

library(igraph)

我已将您的边缘列表放入名为“graph.txt”的文件中,我将其放入“C:\ workspace”中。然后我使用以下代码在R:

中读入该文件
setwd("C:/Workspace")
graph <- read.graph("graph.txt", format="edgelist")

您可能希望绘制图表以确保一切正常(但是,此步骤可以放弃):

plot(graph, layout=layout.fruchterman.reingold.grid)

我创建了一个邻接矩阵来查看顶点之间的所有直接链接:

direct <- get.adjacency(graph)

然后我创建一个名为“间接”的虚拟矩阵,它是相邻矩阵的副本。我只需要这个矩阵以后用间接值填充它:

indirect <- direct

最后,我遍历整个图,找到每两个顶点之间所有间接连接的数量。我将这个数字放入我之前创建的间接矩阵中(另外我创建了一个将所有值放在对角线零上的子句)。模式“out”确保仅计算传出路径。这也可以设置为“in”或“total”:

max <- vcount(graph)-1
for(i in 0:max)
 for(j in 0:max)
   indirect[i,j] <- length(get.all.shortest.paths(graph, from=i, to=j, mode="out"))

答案 1 :(得分:2)

假设您有一个简单的directed acyclic graph(DAG),以下方法可用于计算:

(A^n)_ij为您提供节点ni之间j长度的路径数。因此,您需要计算A + A^2 + ... + A^n + ...以获取任意两个节点之间的路径总数。您必须使用DAG,因为这样可以保证足够大的nA^n = 0。然后结果可写为A . (I - A)^(-1),其中I是单位矩阵。


编辑:

我真的不知道R所以我只能给你一些伪代码或解释。

首先,让我们找到可从节点i 到达的节点集。让我们定义向量v以仅包含零,除了在它包含1的i位置。对于您将拥有的第一个节点

v = (1,0,0, ..., 0)

现在让v_(n+1) = sign(v_n + A . v_n),其中sign()函数的目的是将非零元素替换为1并保留零。执行此迭代直到达到固定点,然后您将拥有向量v,其中非零元素位于与节点i可到达的节点对应的位置。

如果不是向量v而是以身份矩阵(与A大小相同)开始,那么您将一次性获得每个其他节点的可达节点。

现在您拥有任何起始节点的可达节点集。类似地,您可以获取任何目标节点可以到达的节点列表(只需反转有向边,即转置A

接下来,让我们遍历图表并找到您需要的所有路径

这个递归函数应该这样做(伪代码):

traverse( path-so-far, target ):
    let S = the last element of path-so-far
    if S == target:
        output path-so-far
        return
    let N = the set of nodes reachable from S in one step
    remove all nodes from N from which the target is not reachable
    for each K in N:
       traverse( append(path-so-far, K), target )

path-so-far是已访问过的节点列表; target是目标节点。

对于给定的一对起始节点和目标节点,只需执行traverse( {start}, target )

请注意,我们删除目标无法访问的所有节点的步骤仅用于加速遍历,并且不要输入“盲目小巷”

答案 2 :(得分:0)

您希望很好地阅读图形模型任务视图:

http://ftp.heanet.ie/mirrors/cran.r-project.org/web/views/gR.html

虽然我不知道你在做什么是统计意义上的图形建模,但是这个任务视图概述了图处理和算法的包。

我已经将igraph用于各种图形事物。

答案 3 :(得分:0)

只需进行深度优先搜索而不检查所访问的节点 - 这可以为您提供特定长度的两个点之间的路径数

void dfs(int start, int hops)
{
  if(hops == k && start == t)
    {
      path++;
      return;
    }
  else if(hops >= k)
    return;
  for(int w = 1; w <= n; w++)
    if(routes[start][w])
      dfs(w, hops + 1);
}

主要是打电话

dfs(start_node, length);

如果有多条连接两个点的路径,并且每个路径被认为不同,怎么办?

答案 4 :(得分:0)

检查以下igraph功能:

http://igraph.org/r/doc/all_simple_paths.html

它列出了来自一个来源的所有简单路径。

描述 此函数列表是从一个源顶点到另一个顶点或顶点的简单路径。如果访问的顶点不会被访问多次,则路径很简单。

用法 all_simple_paths(graph,from,to = V(graph),mode = c(&#34; out&#34;,&#34; in&#34;,&#34; all&#34;,   &#34;总&#34))

参数

图表
输入图。


源顶点。


顶点的目标顶点。默认为所有顶点。

模式
字符常量,给出是否应为有向图计算到达或来自给定顶点的最短路径。如果超出那么从顶点开始的最短路径,如果在那时将被考虑。如果全部是默认值,那么将使用相应的无向图,即。没有定向路径被搜索。对于无向图,该参数将被忽略。

详细

请注意,图形的两个顶点之间可能存在指数级的路径,如果图形是格子状的,则使用此函数时可能会耗尽内存。

此函数当前忽略多个循环边。