Algorithm 大型散乱节点图的剪枝

Algorithm 大型散乱节点图的剪枝,algorithm,language-agnostic,graph-theory,graphviz,Algorithm,Language Agnostic,Graph Theory,Graphviz,我有一个由35000个节点组成的图,用纯文本表示: 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函数的组合

我有一个由35000个节点组成的图,用纯文本表示:

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格式的,但我在该套件中没有看到任何与手头任务相关的工具

哦,如果有一个简单的方法来做这样的事情,我愿意接受建议——它不需要完全是我建议的任务。我只是在寻找一种方法来消除大团块周围的大部分噪音(这是很少见的,而且大部分只是几个相交的链)。

是一个优秀的开源GUI工具,用于可视化和操作图形,您可能会在其中找到某种过滤器来处理这类事情。。。也许度过滤器可以做到:它可以删除只有一条边的节点。您还可以过滤入度、出度、计算PageRank等。它还具有一些非常好的大小/标签/颜色选项,并且易于放大/缩小。

作为的一部分,该工具允许将规则应用于图形并输出修改后的图形

根据描述:

它将输入图形复制到输出,可能会转换它们的 结构和属性,创建新图形

看起来您希望删除indegree为0且仅有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);
    }
  }
}
以下是脚本的作用:

  • 将所有边循环一次并填充两个列表:

    • 候选节点-可能必须删除的节点列表,以及
    • 保留者-可能最终成为候选节点但不应删除的节点列表
    那么,在哪个列表中添加了什么

    • 任何两个相互连接的节点,其中尾部节点没有任何传入边,头部节点没有任何传出边,形成只有2个节点的链,因此是要删除的候选节点;也就是说,除非相同节点是长度超过2个节点的其他链的一部分:
    • 没有任何传入边但连接到自身具有传出边的头部节点的尾部节点是保持器;及
    • 头部节点没有任何传出边,但连接到尾部节点(其本身具有传入边),也是保持器
  • 删除不在列表中的所有候选人
  • 此解决方案不是通用的,仅适用于问题中所述的问题,即仅保持链至少3个节点长。它也不会删除短循环(两个节点相互连接)

    您可以使用以下行调用此命令:

    gvpr -c -f .\nostraynodes.gv .\graph.dot
    
    使用示例图的输出为:

    digraph g {
        1 -> 2;
        2 -> 3;
        3 -> 4;
    }
    
    请注意,这是我的第一个
    gvpr
    脚本-可能有更好的编写方法,我不确定它如何处理35000个节点,尽管我相信这不会有什么大不了的



    另请参见图转换的一个简单示例。

    假设任何给定节点都可以有任意多个前辈或后辈,则节点的入度和出度与解决问题无关

    下面是一个简单的O(N+E)算法,用于所有N个节点和E个边的图,在路径长度为3的条件下。该算法可以在Perl或C中轻松实现。该方法基于定义和断言:将“生成节点”定义为具有父节点和子节点(前置节点和后继节点)的任何节点。将保留的每个节点都是生成节点,或者是生成节点的父节点或子节点

  • 将状态数组S[Nmax]初始化为全零。Nmax是最大节点数。如果一开始不知道Nmax,请读取所有数据并找出它

  • 读入给定的边列表。每个输入项指定从节点p到节点q的有向边(p,q)。对于读入的每个(p,q)项:将S[p]设置为S[p]| 1表示p有一个子项,将S[q]设置为S[q]| 2表示q有一个父项。(在此步骤之后,每个生成的节点n都有S[n]==3。)

  • 再次阅读边列表。对于读入的每个(p,q)项:如果(S[p]==3)或(S[q]==3)输出边(p,q)

  • 要将此方法扩展到路径长度K而不是3,请将边列表保留在内存中,使用父链和子链的长度维护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=保持边缘所需的最小链长度

  • 将E边缘数据条目读入H[]数组。将所有pc[j]、cc[j]条目设置为0

  • 对于i=1到E,设置cc[H[i].p]=1和pc[H[i].q]=1

  • 对于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])}为

  • 对于i=1到E,{设p=H[i].p和q=H[i].q.当pc[p]+cc[p]+1>=K和pc[q]+cc[q]+1>=K时的输出边(p,q)}

  • 如果图形不是DAG并且包含短循环路径,则此方法可能会出错。例如,如果图形边包括(1,2)和(2,1),并且没有其他节点链接到节点1或2,则这些边都不应输出;但是我们