使用JGraphT管理从属任务的排序

时间:2017-10-19 23:54:16

标签: jgrapht

我有一个在它们之间有依赖关系的任务列表,我正在考虑如何使用JGraphT来管理任务的顺序。我会将图形设置为有向图并在处理它们时删除顶点(或者我应该屏蔽它们?)。如果我一次只执行一个任务,我可以使用TopologicalOrderIterator,但我希望将任务并行化。我可以获得TopologicalOrderIterator并检查Graphs.vertexHasPredecessors,直到我找到尽可能多的执行次数,但理想情况下会有Graphs.getVerticesWithNoPredecessors之类的内容。我看到Netflix提供了一个实用程序来获取叶子顶点,所以我可以反转图形并使用它,但它可能不值得。谁能指出我更好的方式?谢谢!

1 个答案:

答案 0 :(得分:0)

拓扑订单可能不一定是你想要的。这是一个例子,为什么不呢。给定以下任务的拓扑排序:[1,2,3,4]和弧(1,3)(2,3)。也就是说,任务1需要在任务3之前完成,类似于24。我们还假设任务1需要很长时间才能完成。因此,我们可以开始并行处理任务12,但在3完成之前无法启动1。即使任务2完成,我们也无法启动任务4,因为任务3是我们排序中的下一个任务,此任务被1阻止。

这是你能做的。创建一个数组dep[],跟踪每个任务的未实现依赖项的数量。因此,dep[i]==0表示已完成任务i的所有依赖项,这意味着我们现在可以执行任务i。如果dep[i]>0,我们还无法执行任务i。让我们假设有一个任务j需要在任务i之前执行。一旦我们完成任务j,我们就可以减少任务i的未实现依赖项的数量,即:dep[i]=dep[i]-1。同样,如果dep[i]==0,我们现在可以处理任务i了。 简而言之,伪代码中的算法看起来像这样:

  1. 初始化dep[]数组。
  2. 开始使用i
  3. 并行处理所有任务dep[i]==0
  4. 如果任务i完成,则对依赖于dep[j]的所有任务j递减i。如果任务jdep[j]==0,请开始处理。
  5. 您当然可以使用定向图来建模依赖关系。每次完成任务时,您都可以简单地遍历传出的邻居(在jgrapht中使用successorsOf(顶点)函数)。 DAG也可以简单地用于检查可行性:如果图形包含一个循环,那么您的依赖项就会出现问题。但是,如果您不需要这种重型机械,我只需创建一个二维数组,其中每个任务i存储依赖于i的任务。

    结果算法在O(n + m)时间内运行,其中n是任务数,m是弧数(依赖性)。所以这非常有效。