问题 算法解析基于版本范围的依赖


我在依赖算法上有一个问题,依赖类似于maven依赖,除了它是基于严格的版本范围。

例如:

component A, version 1 depends on: component B, version 1~3; and component C, version 2~3
component D, version 1 depends on: component B, version 2~4; and component C, version 1~2

现在,我想在安装组件A,版本1和组件D,版本1时获得依赖关系。因为它们都依赖于组件B,C所以我需要一个正确的算法来获得正确的B和C版本

此外,我可能需要升级组件A和D.例如,现在我有以下新版本:

component A, version 2 depends on: component B, version 3~5; and component C, version 4~5
component A, version 3 depends on: component B, version 6~7; and component C, version 4~5
component D, version 2 depends on: component B, version 3~4; and component C, version 3~4

现在我需要一个算法来获取正确的A和D版本,我可以升级到它们的所有依赖项。这里的一个问题是组件A,版本3和组件D,版本2具有组件B的依赖冲突

是否存在解决此类问题的算法?或类似(更容易)的问题。你有什么建议吗?

因为不应该有很多数据,所以不要考虑性能。

提前致谢!


2486
2018-04-09 08:08


起源

对于一个简单的解决方案,您可以使用拓扑排序吗?您可以从构建图表开始,其中每个节点都是{node id,version no}。之后进行拓扑排序以获得依赖顺序。 - trequartista
谢谢,但在我的情况下,依赖只需要解析一个组件版本,所以如果构建一个图,对于具有相同节点id的节点,输出列表必须只输出一个节点;对于某些节点,它们的版本可能会发生冲突,因此这样的节点可能永远不会出现在输出列表中。如何解决这个问题呢? - Xilang
不是我的意思,每个节点都有节点ID和版本ID。即。 {Component A,version 1}和{Component A,version 2}是不同的节点。例如: - trequartista
例如:“组件A,版本1取决于:组件B,版本1~3;”将转换为{Component A version1}和{component B version 1},{Component A version1}和{component B version 2},{Component A version1}和{component B version 3}之间的边缘。因此,您可以通过这种方式构建有向图并解决您可以进行拓扑排序(或变体)的依赖关系,从而为您提供{component Id和version no}作为父级 - trequartista
我知道你关于如何构建图形的想法,但我不知道在构建图形之后如何进行拓扑排序。这不是一个常规的拓扑排序。 - Xilang


答案:


通过3SAT的以下减少,这个问题是NP难的。给定3CNF公式,对于每个变量,有一个具有两个版本的组件,并且对于每个子句,存在具有三个版本的组件。我们想安装一个版本的“超级”组件,它依赖于所有子句组件,但对版本并不挑剔。对于每个子句,子句组件1依赖于在子句中出现的第一个变量,如果文字是正数则需要版本1,如果是负数则需要0。条款组件2取决于第二个变量等。当且仅当公式可满足时,我们才能安装超级组件。

鉴于这种减少,将你的问题表述为有意义 约束满足。每个组件都是一个变量,其可能的值是该组件的版本,如果没有安装该组件,则为“未安装”是一个选项。对于具有依赖于组件B的版本的版本的每个组件A,存在涉及A和B的变量的约束,从而将版本的选择限制为其域的产品的特定子集。对于第一个示例中的A和B,这是{(1,1),(1,2),(1,3)},因为版本1取决于B版本1~3。如果A的版本2也可用,则该约束将是{(1,1),(1,2),(1,3),(2,3),(2,4),(2,5) }。如果我们不必安装A或B,那么{(none,none),(none,1),(none,2),(none,3),(none,4),(none,5), (1,1),(1,2),(1,3),(2,3),(2,4),(2,5)}。

由于您的实例很小,您可能需要完整的回溯搜索,可能需要约束传播。约束传播的常用算法是 AC-3,根据已消除的内容,强制执行弧一致性,即从考虑中删除所有明显不起作用的版本。例如,给定约束{(1,1),(1,2),(1,3)},我们可以消除B = none,因为没有出现。现在B的选择受到限制,我们可以推断B的依赖关系C等。当没有更多的简化要做时,我们必须猜测;一种策略是选择剩下最少版本的组件并递归尝试所有这些(回溯)。


11
2018-05-02 11:37





这是一个变种 可满足性问题。 osgi也必须处理这个问题。所以你可以查看osgi规范和/或实现,看看他们是如何解决它的。


1
2018-04-09 09:43