当前位置: 首页 > 知识库问答 >
问题:

在JGrapht中修剪有向无环图的更有效的方法?

呼延化
2023-03-14

我正在寻找一种更有效的方法来修剪用JGrapht构造的有向无环图(a DAG)。

DAG表示一组网络会话之间的时间关系。会话的父会话是在子会话开始之前完成的任何会话。构建DAG相对简单,但存在大量不必要的关系。为了提高效率,我希望对DAG进行修剪,以便每个子级与最小的父级数量有直接关系(或者相反,以便每个父级具有最小的直接子级数量)。

我现在使用的剪枝实现(如下所示)是基于在Streme中找到的代码。它适用于我手工构建的所有单元测试场景。然而,在真实的数据集中,它通常是相当慢的。今天我碰到一个场景,有215个顶点,但超过22,000条边。在服务器级硬件上修剪DAG大约需要8分钟的时钟时间--对于我的直接用例来说是可以忍受的,但是对于更大的场景来说太慢了。

我相信我的问题类似于我可以对这个DAG应用什么算法中描述的问题?以及在图或树中寻找冗余边的算法。也就是说,我需要为我的DAG找到传递约简或最小表示。jgrapht似乎不包含DAG的可传递约简的直接实现,只包含可传递闭包。

我正在寻找关于如何提高下面实现效率的建议,或者可能是一个指向jgrapht的可传递约简的现有实现的指针,我可以改用它。

注意:或者,如果有一个不同的用于Java的图形库,它包含一个传递约简的本机实现,我可以切换到那个库。我对jgrapht的使用仅限于一个200行的类,因此只要接口相似,将其交换出去应该不难。要维护类接口(持久化到数据库),我需要一个DAG实现,它提供一种获取给定节点的父节点和子节点的方法--类似于JGrapht的graphs.preducessorlistof()graphs.successorlistof()

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.jgrapht.DirectedGraph;
import org.jgrapht.Graphs;
import org.jgrapht.alg.DijkstraShortestPath;

public static <V, E> void prune(DirectedGraph<V, E> dag) {
   Deque<V> todo = new ArrayDeque<V>(dag.vertexSet());
   Set<V> seen = new HashSet<V>();
   while (!todo.isEmpty()) {
       V v = todo.pop();
       if (seen.contains(v)) {
           continue;
       }
       seen.add(v);
       List<V> targets = Graphs.successorListOf(dag, v);
       for (int i = 0; i < targets.size(); i++) {
           for (int j = i; j < targets.size(); j++) {
               V vi = targets.get(i);
               V vj = targets.get(j);
               List<E> path = DijkstraShortestPath.findPathBetween(dag, vi, vj);
               if (path != null && !path.isEmpty()) {
                   E edge = dag.getEdge(v, vj);
                   dag.removeEdge(edge);
               }
           }
       }
   }
}

共有1个答案

颛孙哲
2023-03-14

我担心你的算法不能正确处理图,例如有边(A,B),(B,C),(C,D)和(A,D)的图,最后一条边(A,D)没有被删除。我在类似问题传递性约简算法的答案中,在python中找到了一个正确的算法:伪代码?作者:Michael Clerx。我在这里使用jgrapht将他的python代码移植到了Java https://html" target="_blank">github.com/aequologica/dagr/blob/develop/dagr-web/src/main/Java/net/aequologica/neo/dagr/jgrapht/transitivereduction.java。

我只使用很小的图,也许这个解决方案不适用于很大的图。

 类似资料:
  • 我想在有向(无环)图中找到最长的路径。假设我知道起始节点-汇。路径应该从这一点开始。我在想我可以将边的权重设置为-1。有很多方法可以找到所有最短的路径,但你必须通过终点。有没有可能得到最短的路径(无论最终节点如何)? 假设我想为节点 nr 1(汇)找到最长路径。所以这个算法给了我1-2-3-4-5-6。

  • 输入: 生成的树: 输出: 规则: < li >输入代码总是会产生一个有向无环图 < li >每个节点都有一些wait_time值 < li >完整的图形遍历应该计算整个图形的总等待时间 < li >必须并行遍历所有独立节点(或者至少时间计算应该是这样) < li >如果两个不同节点的wait_time发生重叠,则将考虑最大值,遍历时间较短的节点将移动到下一个独立节点 < li >除了根和叶(可以

  • 假设我有以下两个树图: 我需要从第一个图中提取子图<code>b</code>并将其替换为第二个图,如下所示: JGraphT中是否有任何现有的API允许这样做?

  • 在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。 因为有向图中一个点经过两种路线到达另一个点未必形成环,因此有向无环图未必能转化成树,但任何有向树均为有向无环图。 一、简介 有向无环图是图论的重要概念,我们将首先介绍图的概念和定义,随后介绍有向图,再逐渐引至有向无环图(DAG)。值得一提的是,当DAG用于指代模型时一般指向贝叶斯网络。 一个图G

  • 我正在努力寻找一个时间复杂度为o(m log n)+o(n)的问题的解决方案。 假设有向无环图有n个节点和m个请求,每个节点最多有一个父节点。在时间=0时,图为空。请求有两种类型:添加边(u,v)或查找顶点为u的子图的根。只有在不破坏图的任何属性的情况下才应该添加边(它应该保持无循环,每个节点最多仍然应该有一条传入边)。 这样,检查添加edge是否破坏属性或返回root需要O(1)个时间。然而,更

  • 目前我正在尝试用下面的代码将当前日期修剪成日、月和年。 null 我在下面的技术中尝试了我的代码。设置:使用Python 3.5.2(x64)、Python 3.6.1(x64)的local machine和使用Python 3.6.1的Repl.it 联机试用代码,复制并粘贴行代码