在一个私人开源项目中,我遇到了以下问题:
有各种各样的任务要执行。其中一些任务将具有
我在寻找一个简单的算法,如何利用这些信息构建一个有向图,然后可以用于周期检测,并以一个允许尊重所有这些条件的顺序执行所有任务。
问:什么是构建这样一个图的有效、好的方法?
谢谢你的帮助。
注意:很明显,我们需要在图中增加两个节点:一个开始节点和一个结束节点。让我们把它们命名为开始和结束。显然,没有依赖关系的节点必须以START这样的构造结束-
您可以从任何顺序开始,然后遍历该顺序,交换任何不有序的元素。您可以重复这个过程,直到没有更多的任务是不有序的。
我会使用一个哈希表(或简单的数组)进行快速查找,以确定任务是否无序。
伪代码:
class Task:
id: int # serial id of task, ie 1..n
not_before: array[int] # ids of tasks this task cannot precede
not_after: array[int] # ids of tasks this task cannot come after
tasks: array[Task] = ... # tasks in order of ids
order: array[int] = [1,2,...,n] # task ids in initial order
positions: array[int] = ... # positions[i] is the index of task i in order array
def swap_tasks(i, j):
swap(order[positions[i]], order[positions[j]])
swap(positions[i], positions[j])
repeat:
made_swap = False
for i in 0..n: # loop over task ids
for j in tasks[i].not_before:
if positions[i] < positions[j]:
swap_tasks(i, j)
made_swap = True
for j in tasks[i].not_after:
if positions[i] > positions[j]:
swap_tasks(i, j)
made_swap = True
if made_swap == False:
break
对于n
任务和O(k)
每个任务的约束,这应该在O(n²log(k))
中运行,因为一个任务最多可以移动n次(因为它不能返回到上一个被交换的任务的位置)。
我想过按顺序处理任务并插入
not_after
任务,然后是任务
,然后是not_before
任务,然后插入(或移动(如果它们已经出现)后续任务以满足约束,但这似乎并没有什么帮助,因为not_before
和not_after
任务可能彼此不按顺序,所以我们仍然需要大量的交换。
需求中有一个“杀手”特性,阻止了简单的解决方案。约束的方向不是一个而是两个:
在现实世界中,我面临的这些依赖关系甚至更加复杂,但这并不重要:所有这些都可以分解为刚刚描述的模拟情况。
现在算法:
步骤1:将每个任务的所有这些约束编译为每个任务的一组单向依赖项。这样就可以很容易地处理单向依赖关系。首先构建一个图,然后执行循环检测,然后执行拓扑排序(感谢术语Dimitry)的第一个想法可以完全放弃。因此,每个项目最终都有一组依赖项:
在这样做的同时,我们甚至可以对这些依赖项进行健全性检查。如果约束规范中存在错误,我们可以在这一步中轻松检测到。
第2步:现在我们有一个非常简单的问题,因为只有单向依赖关系。这些可以被视为先决条件:只有满足所有先决条件,才能执行任务。现在我们可以进行如下操作:
pack all tasks into a list named /notYetProcessed/ create empty list /result/ while there are still tasks to process in /notYetProcessed/ do: create empty list /remaining/ for all tasks /t/ in /notYetProcessed/ do: if all dependencies are met for /t/ then do: add /t/ to /result/ else do: add /t/ to /remaining/ if /length(notYetProcessed)/ matches /length(remaining)/ then do: terminate with error /notYetProcessed/ = /remaining/
外部while条件终止后,结果
将包含一个要处理的任务列表,其顺序遵循开头定义的所有约束。
如果上述算法终止时出现错误,这意味着:*此循环中无法处理任何任务*这意味着:无法解析某些依赖关系*这意味着:存在一个任务依赖循环,该循环恰好涉及剩余的任务
步骤3:现在一个接一个地处理存储在结果
中的所有任务,一个接一个地处理,你就没事了。
正如您所见,这可以在不构建数据的特殊图形表示的情况下完成。拓扑排序是通过接受第一个解决方案(“所有可能的排序顺序的第一个变体”)来“直接”对数据执行的,我们可以得到第一个解决方案。
可能有一些更有效的算法来解决这个问题(在执行第一个依赖项编译之后),我可能不知道。如果是这样,我很乐意了解他们!
问题内容: 可以运行以了解模块任务的依赖性。有没有办法找到 buildscript依赖 的 传递依赖 ? 示例: 直接取决于: 可以在MVNRepository上看到。但是,这些工件有其自己的依赖性。有没有找到方法而无需手动遍历整个依赖树的方法? 为了澄清起见,我正在谈论的类路径由以下方式定义: 问题答案: 您可以使用以下命令: Udacity提供了很棒的Android Gradle 教程,但是您
我有一个自定义gradle任务的问题:我想复制我的android jar库,然后将其重命名为“clean build”,这是我如何定义它的: 问题是,在gradle日志结果中,'clean'是在'build'任务之后完成的,因此库永远不会复制到目标文件夹: 我也尝试过在“depends on:[]”中更改任务的顺序,但这并没有改变任何东西...有人知道我错在哪里吗?提前致谢
问题内容: 我有一个独立的Java应用程序,我想将其打包为:myapp.jar。并将所有相关的jar文件复制到“备用文件夹”。理想情况下,我想让Maven更新META- INF文件,以将所有类路径依赖项jar条目添加到其中。 例如,如果我的项目引用了commons.jar,并且当我使用此插件构建程序集时,它将所有.class文件和程序包从commons.jar复制到myappjar- with-d
我有以下结构: api和web项目都使用插件,但其他项目只有插件。 我想在根项目中为heroku定义一个任务,即: 对所有拥有它的子项目执行干净任务 对所有拥有它的子项目执行战争任务 在所有拥有它的子项目上执行构建任务 我看到了这个答案:按顺序调用子项目和其他任务但失败的Gradle批处理任务。已尝试以下配置 并获取此错误: (api有war插件,如果我取消对task stage的注释,我可以运行
我试图通过这个Gradle插件https://github.com/theboegl/gradle-launch4j使用http://launch4j.sourceforge.net/。 当我执行时,我会得到以下输出。 这是我的年级版本信息。 这是我的构建脚本。
我试图用Maven做一个小程序。我使用的是来自我大学教授的模板,我想使用log4j进行日志记录。当我在eclipse中运行该程序时,它工作得很好。然而,当我用“MVN install”创建jar并尝试用cmd运行程序时,我得到的是一个NoClassDefFoundError 我在这里还发现了这一点:NoClassDefFoundError在Maven依赖上,我尝试使用maven-shade-plu