簡體   English   中英

查找兩個頂點(節點)之間的所有路徑

[英]Find all paths between two vertices (nodes)

我是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

謝謝

我使用以下代碼創建了一個矩陣 (頂點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"))

假設您有一個簡單的有向無環圖 (DAG),以下方法將適用於計數:

(A^n)_ij給出節點ij之間長度為n的路徑數。 因此,您需要計算A + A^2 + ... + A^n + ...以獲取任意兩個節點之間的路徑總數。 使用DAG至關重要,因為這保證了對於足夠大的nA^n = 0 然后結果可以寫成A . (I - A)^(-1) 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並保持零為0。執行此迭代直到到達固定點,然后您將在與從節點i可達的節點相對應的位置處具有一個帶有非零元素的向量v

如果不是從向量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 )

請注意,我們刪除所有目標無法到達的節點的步驟只是為了加快遍歷速度,並且不要輸入“盲巷”

只需進行深度優先搜索,而無需檢查訪問的節點-這可以為您提供特定長度的兩點之間的路徑數

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);

如果有多個路徑連接兩個點,並且每個路徑都被認為是不同的,該怎么辦?

檢查以下igraph功能:

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

它列出了來自一個來源的所有簡單路徑。

說明此函數列表是從一個源頂點到另一個頂點或多個頂點的簡單路徑。 如果路徑訪問的頂點不被多次訪問,則該路徑很簡單。

用法all_simple_paths(graph,from,to = V(graph),mode = c(“ out”,“ in”,“ all”,“ total”))

爭論

圖形
輸入圖。


源頂點。


頂點的目標頂點。 默認為所有頂點。

模式
字符常數,給出是否應該為有向圖計算到給定頂點的最短路徑。 如果離開,則考慮從頂點到頂點的最短路徑。 如果全部為默認值,則將使用相應的無向圖,即。 搜索未定向的路徑。 對於無向圖,將忽略此參數。

細節

請注意,圖形的兩個頂點之間可能有成倍的路徑,並且如果您的圖形是格子狀的,則使用此函數時可能會用光內存。

該函數當前忽略了多個和循環邊。

您希望對圖形模型任務視圖有很好的了解:

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

盡管我不認為您正在做的是統計意義上的圖形建模,但是此任務視圖概述了用於圖形處理和算法的程序包。

我已經將igraph用於各種圖形事物。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM