如何找到最短路径矩阵?
How to find the shortest path matrix?
我有一个加权邻接矩阵 m
,我需要找到最短路径矩阵。预期结果是:
library(igraph)
n = 8
m <- t(matrix(c(
0,0,0,0,0,0,0,8,
3,0,0,0,0,0,0,0,
5,0,0,5,1,0,0,0,
0,0,6,0,0,7,1,0,
0,6,2,0,0,0,0,0,
0,0,0,0,0,0,0,0,
7,4,0,0,8,0,0,3,
0,3,0,0,0,9,0,0),ncol=n))
g1 <- graph_from_adjacency_matrix(m, weighted=TRUE, mode="directed")
V(g1)$names <- letters[1:n]
plot(g1, vertex.label = V(g1)$names, edge.arrow.size=0.5)
我的尝试是:
path_name <- c()
for (i in c(1,2,6,8)){
for (path in all_simple_paths(g1, i, V(g1), mode="out")) {
path_name <- c(path_name, paste(V(g1)[path]$names, collapse=''));
}
}
path_name
[1] "ah" "ahb" "ahf" "ba" "bah" "bahf" "hb" "hba" "hf"
可以看到我只找到了四个节点的路径:1、2、5、6,名称为 a、b、f、h。如果我们以a、b、h为起始节点,我们可以为每个节点获得3条路径,而对于h则没有路径。
问题如何重构所有节点的路径?
我没有找到 Lee (wave) 算法。
您可以使用 igraph::all_shortest_paths
但是,除非我遗漏了什么,否则重建矩阵仍然很棘手。
编辑:清理了 purrr
部分
library(purrr)
library(igraph)
n = 8
m <- t(matrix(c(
0,0,0,0,0,0,0,8,
3,0,0,0,0,0,0,0,
5,0,0,5,1,0,0,0,
0,0,6,0,0,7,1,0,
0,6,2,0,0,0,0,0,
0,0,0,0,0,0,0,0,
7,4,0,0,8,0,0,3,
0,3,0,0,0,9,0,0),ncol=n))
g1 <- graph_from_adjacency_matrix(m, weighted=TRUE, mode="directed")
V(g1)$names <- letters[1:n]
v <- 1:n
mat <- matrix("",
nrow = n,
ncol = n,
dimnames = list(V(g1)$names, V(g1)$names))
map(v, ~all_shortest_paths(g1, .x, v[-.x], mode = "out")) |>
map(chuck, "res") |>
compact() |>
map_depth(~{V(g1)$names[as.vector(.x)]}, .depth = 2) |>
flatten() |>
walk(~{
mat[first(.x), last(.x)] <<- paste(.x, collapse = "")
})
mat
##> a b c d e f g h
##> a "" "ahb" "" "" "" "ahf" "" "ah"
##> b "ba" "" "" "" "" "bahf" "" "bah"
##> c "ca" "ceb" "" "cd" "ce" "cdf" "cdg" "cdgh"
##> d "dgba" "dgb" "dc" "" "dce" "df" "dg" "dgh"
##> e "eca" "eb" "ec" "ecd" "" "ecdf" "ecdg" "ecdgh"
##> f "" "" "" "" "" "" "" ""
##> g "gba" "gb" "gec" "gecd" "ge" "ghf" "" "gh"
##> h "hba" "hb" "" "" "" "hf" "" ""
您可以试试下面的代码
m <- d <- distances(g1, mode = "out")
for (i in row.names(d)) {
for (j in colnames(d)) {
if (i != j) {
if (!is.infinite(d[i, j])) {
m[i, j] <- paste0(names(shortest_paths(g1, i, j)$vpath[[1]]), collapse = "")
} else {
m[i,j] <- NA
}
} else {
m[i, j] <- ""
}
}
}
你会看到 shortest-path 矩阵 m
> m
a b c d e f g h
a "" "ahb" NA NA NA "ahf" NA "ah"
b "ba" "" NA NA NA "bahf" NA "bah"
c "ca" "ceb" "" "cd" "ce" "cdf" "cdg" "cdgh"
d "dga" "dgb" "dc" "" "dce" "df" "dg" "dgh"
e "eca" "eb" "ec" "ecd" "" "ecdf" "ecdg" "ecdgh"
f NA NA NA NA NA "" NA NA
g "ga" "gb" "gec" "gecd" "ge" "ghf" "" "gh"
h "hba" "hb" NA NA NA "hf" NA ""
我有一个加权邻接矩阵 m
,我需要找到最短路径矩阵。预期结果是:
library(igraph)
n = 8
m <- t(matrix(c(
0,0,0,0,0,0,0,8,
3,0,0,0,0,0,0,0,
5,0,0,5,1,0,0,0,
0,0,6,0,0,7,1,0,
0,6,2,0,0,0,0,0,
0,0,0,0,0,0,0,0,
7,4,0,0,8,0,0,3,
0,3,0,0,0,9,0,0),ncol=n))
g1 <- graph_from_adjacency_matrix(m, weighted=TRUE, mode="directed")
V(g1)$names <- letters[1:n]
plot(g1, vertex.label = V(g1)$names, edge.arrow.size=0.5)
我的尝试是:
path_name <- c()
for (i in c(1,2,6,8)){
for (path in all_simple_paths(g1, i, V(g1), mode="out")) {
path_name <- c(path_name, paste(V(g1)[path]$names, collapse=''));
}
}
path_name
[1] "ah" "ahb" "ahf" "ba" "bah" "bahf" "hb" "hba" "hf"
可以看到我只找到了四个节点的路径:1、2、5、6,名称为 a、b、f、h。如果我们以a、b、h为起始节点,我们可以为每个节点获得3条路径,而对于h则没有路径。
问题如何重构所有节点的路径? 我没有找到 Lee (wave) 算法。
您可以使用 igraph::all_shortest_paths
但是,除非我遗漏了什么,否则重建矩阵仍然很棘手。
编辑:清理了 purrr
部分
library(purrr)
library(igraph)
n = 8
m <- t(matrix(c(
0,0,0,0,0,0,0,8,
3,0,0,0,0,0,0,0,
5,0,0,5,1,0,0,0,
0,0,6,0,0,7,1,0,
0,6,2,0,0,0,0,0,
0,0,0,0,0,0,0,0,
7,4,0,0,8,0,0,3,
0,3,0,0,0,9,0,0),ncol=n))
g1 <- graph_from_adjacency_matrix(m, weighted=TRUE, mode="directed")
V(g1)$names <- letters[1:n]
v <- 1:n
mat <- matrix("",
nrow = n,
ncol = n,
dimnames = list(V(g1)$names, V(g1)$names))
map(v, ~all_shortest_paths(g1, .x, v[-.x], mode = "out")) |>
map(chuck, "res") |>
compact() |>
map_depth(~{V(g1)$names[as.vector(.x)]}, .depth = 2) |>
flatten() |>
walk(~{
mat[first(.x), last(.x)] <<- paste(.x, collapse = "")
})
mat
##> a b c d e f g h
##> a "" "ahb" "" "" "" "ahf" "" "ah"
##> b "ba" "" "" "" "" "bahf" "" "bah"
##> c "ca" "ceb" "" "cd" "ce" "cdf" "cdg" "cdgh"
##> d "dgba" "dgb" "dc" "" "dce" "df" "dg" "dgh"
##> e "eca" "eb" "ec" "ecd" "" "ecdf" "ecdg" "ecdgh"
##> f "" "" "" "" "" "" "" ""
##> g "gba" "gb" "gec" "gecd" "ge" "ghf" "" "gh"
##> h "hba" "hb" "" "" "" "hf" "" ""
您可以试试下面的代码
m <- d <- distances(g1, mode = "out")
for (i in row.names(d)) {
for (j in colnames(d)) {
if (i != j) {
if (!is.infinite(d[i, j])) {
m[i, j] <- paste0(names(shortest_paths(g1, i, j)$vpath[[1]]), collapse = "")
} else {
m[i,j] <- NA
}
} else {
m[i, j] <- ""
}
}
}
你会看到 shortest-path 矩阵 m
> m
a b c d e f g h
a "" "ahb" NA NA NA "ahf" NA "ah"
b "ba" "" NA NA NA "bahf" NA "bah"
c "ca" "ceb" "" "cd" "ce" "cdf" "cdg" "cdgh"
d "dga" "dgb" "dc" "" "dce" "df" "dg" "dgh"
e "eca" "eb" "ec" "ecd" "" "ecdf" "ecdg" "ecdgh"
f NA NA NA NA NA "" NA NA
g "ga" "gb" "gec" "gecd" "ge" "ghf" "" "gh"
h "hba" "hb" NA NA NA "hf" NA ""