我是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
谢谢
答案 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
为您提供节点n
和i
之间j
长度的路径数。因此,您需要计算A + A^2 + ... + A^n + ...
以获取任意两个节点之间的路径总数。您必须使用DAG,因为这样可以保证足够大的n
,A^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))
参数
图表
输入图。
这
源顶点。
要
顶点的目标顶点。默认为所有顶点。
模式
字符常量,给出是否应为有向图计算到达或来自给定顶点的最短路径。如果超出那么从顶点开始的最短路径,如果在那时将被考虑。如果全部是默认值,那么将使用相应的无向图,即。没有定向路径被搜索。对于无向图,该参数将被忽略。
详细
请注意,图形的两个顶点之间可能存在指数级的路径,如果图形是格子状的,则使用此函数时可能会耗尽内存。
此函数当前忽略多个循环边。