簡體   English   中英

修剪雜散節點的大圖

[英]Pruning large graphs of stray nodes

我有一個圖表,包含大約35,000個以純文本表示的節點:

node1 -> node35000
node29420 -> node35000
node2334 -> node4116
...

我想通過刪除不屬於鏈的節點至少三個長來修剪它。 所以,如果我只有

1 -> 2;
2 -> 3;
3 -> 4;
0 -> 4;

我想保留1,2,3和4(因為1 -> 2 -> 3 -> 4是四個節點長)但丟棄0,即刪除0 -> 4

有沒有想過這樣做的好方法? 我嘗試了Perl和shell函數的組合,但我認為我需要一個更好的方法。 除非有工具可以做到這一點? 數據采用graphviz格式,但我沒有看到該套件中的任何工具與手頭的任務相關。

哦,如果有一種簡單的方法可以做這樣的事情,我會接受建議 - 它不一定是我建議的任務。 我只是想找到一種方法來消除大塊周圍的大部分噪音(這種情況很少見,而且大部分只是一些相交的鏈條)。

作為graphviz工具一部分的工具gvpr允許將規則應用於圖形並輸出修改后的圖形。

從描述:

它將輸入圖復制到其輸出,可能轉換其結構和屬性,創建新圖,...

看起來您想要刪除所有具有0的indegree並且僅具有outdegree為0的鏈接節點(后繼者)的節點。

這是我的gvpr腳本版本nostraynodes.gv

BEGIN {node_t n; int candidates[]; int keepers[];}
E{
  if (tail.indegree == 0 && head.outdegree == 0)
  {
    candidates[tail] = 1;
    candidates[head] = 1;
  }
  else if (tail.indegree == 0)
  {
    keepers[tail] = 1;
  }
  else if (head.outdegree == 0)
  {
    keepers[head] = 1;
  }
}

END_G {
  for (candidates[n]){
    if (n in keepers == 0)
    {
       delete(NULL, n);
    }
  }
}

這是腳本的作用:

  1. 遍歷所有邊一個時間和填充兩個列表:

    • 候選人 - 可能必須刪除的節點列表,以及
    • keepers - 節點列表,可能最終出現在候選者中但不應被刪除。

    那么什么被添加到哪個列表?

    • 任何兩個節點彼此連接,其中尾節點沒有任何進入邊緣,並且頭節點沒有任何輸出邊緣,形成僅2個節點的鏈,因此是要刪除的候選節點; 也就是說,除非相同的節點是長於2個節點的另一個鏈的一部分:
    • 沒有任何入射邊緣但連接到自身具有輸出邊緣的頭節點的尾節點是保持器 ;
    • 沒有任何輸出邊緣但連接到尾節點的頭節點也是一個保持器 ,該節點本身具有輸入邊緣。
  2. 刪除所有不在飼養員中的 候選人

此解決方案不是通用的,僅適用於問題中所述的問題,即僅保留鏈長度至少為3個節點。 它也不會刪除短循環(兩個節點相互連接)。

您可以使用以下行調用它:

gvpr -c -f .\nostraynodes.gv .\graph.dot

使用示例圖表的輸出是:

digraph g {
    1 -> 2;
    2 -> 3;
    3 -> 4;
}

請注意,這是我的第一個gvpr腳本 - 可能有更好的方法來編寫它,我不知道它如何處理35000個節點,但我相信這不應該是一個大問題。


另請參見Graphviz / Dot - 如何用獨特的顏色標記樹中的所有葉子? 有關圖變換的簡單示例。

Gephi是一個出色的開源GUI工具,用於可視化和操作圖形,你可能會在那里找到某種類型的過濾器......也許一個度過濾器會這樣做:它會刪除只有的節點有一個優勢。 您還可以過濾度數,度數,可以計算PageRank等。它還有一些非常好的尺寸/標簽/顏色選項,並且易於放大/縮小。

假設任何給定節點可以具有任意多個前驅或后繼節點,則節點的度數和出度與解決問題無關。

以下是針對路徑長度為3的標准的N個節點和E邊緣的所有圖的簡單O(N + E)算法。 該算法可以在Perl或C中輕松實現。該方法基於定義和斷言:將“制造節點”定義為具有父節點和子節點(前導節點和后繼節點節點)的任何節點。 將保留的每個節點都是一個節點,或者是一個節點的父節點或子節點。

  1. 將狀態數組S [Nmax]初始化為全零。 Nmax是最大節點數。 如果一開始就不知道Nmax,請讀取所有數據並找出它。

  2. 讀入給定的邊緣列表。 每個輸入項指定從節點p到節點q的有向邊(p,q)。 對於讀入的每個(p,q)項:將S [p]設置為S [p] | 1表示p具有子節點,並將S [q]設置為S [q] | 2表示q有父母。 (在此步驟之后,每個節點n都有S [n] == 3.)

  3. 再次閱讀邊緣列表。 對於讀入的每個(p,q)項:If(S [p] == 3)或(S [q] == 3)輸出邊(p,q)。

要將此方法擴展到3以外的路徑長度K,請將邊列表保留在內存中,使用父鏈和子鏈的長度維護Sp []和Sc [],並執行K / 2次額外通過。 可能在時間O(N + K * E)做。 該問題沒有指定圖是否是DAG(有向無環圖),但給出的示例是DAG。 對於K> 3,它可能會有所不同。

更新1這里是K> 3算法的更精確的陳述,其中H [i] .p和H [i] .q是邊緣#i的端點,並且pc [j],cc [j]是前身的長度和關於節點j的后繼鏈。 另外,設E =邊緣數; N =節點數; 和K =保持邊緣所需的最小鏈長。

  1. 將E edge數據條目讀入H []數組。 將所有pc [j],cc [j]條目設置為0。

  2. 對於i = 1到E,設置cc [H [i] .p] = 1並且pc [H [i] .q] = 1。

  3. 對於j = 1至K + 1,{i = 1至E,{令p = H [i] .p且q = H [i] .q。 設定cc [p] = max(cc [p],1 + cc [q])和pc [q] = max(pc [q],1 + pc [p])。 }}

  4. 對於i = 1到E,{令p = H [i] .p並且q = H [i] .q。 輸出邊沿(p,q)如果pc [p] + cc [p] +1> = K且pc [q] + cc [q] +1> = K.}

如果圖形不是DAG並且包含短循環路徑,則此方法可能會出錯。 例如,如果圖形邊緣包括(1,2)和(2,1)並且沒有其他節點鏈接到節點1或2,則不應輸出這些邊緣; 但是我們最終得到了那些節點的cc []和pc []的K + 2,所以無論如何它們都得到輸出。

暫無
暫無

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

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