我们有一条规则禁止包之间的循环依赖。
我们还有一个相当庞大的软件包,需要进行一些拆分。
问题是:如何识别类的/所有/最大子集,可以从包中提取到新包中,而不会产生循环依赖。
是否有一个众所周知的算法?
变量很棒,其中on可以定义算法可以忽略的最大依赖项数。
显然,子集应该与包不同,也不应该是空的。 如果是最大子集,则应小于原始包的一半。
答案 0 :(得分:3)
基本上,您的类,对象或您拥有的内容存储在表示adjacency matrix(有或没有循环)的矩阵(称为directed graph)中。请参见下图和相应的邻接矩阵。
由此,我们可以计算可达性矩阵,该矩阵描述了一个节点可以从当前节点传播到哪个节点。对于此图,可达性矩阵是
您需要一种算法来重新排列矩阵的行和列,以便所有非零元素都在主对角线下方。可以按照它们出现在矩阵中的顺序执行这个为真的对象索引序列,并且将满足每个对象的所有必要依赖性。如果已知图形是非循环的,则可以通过topological sorting来实现。
当有向图中出现循环时,您将无法找到这种情况的排序。
输入Design/Dependency Structure Matrix(DSM)。可以实现所谓的分区算法以将对象划分为级别。对于每个级别,对象可以按任意顺序执行,并且不依赖于一个或另一个。对于上图,节点3,4和5不相互依赖,可以按任何顺序执行。
分区算法已在(Warfield 1973)中开发,它能够检测和隔离DSM中的循环。这类似于拓扑排序算法,但使用可达性矩阵来检测和隔离循环。
简要算法:
- 创建新的分区级别
- 计算可达性,前提设定R(s)和A(s)
- 对于DSM中的每个元素,计算集合乘积R(s)A(s)
- 如果R(s)A(s)= R(s),则将元素
s
添加到当前级别- 从列表中删除元素
s
,并从所有其他元素的可达性和先行集中删除所有引用。- 如果项目列表不为空,则从1开始重复。
醇>
先行集A(s)是列s
中非零元素的行索引集,而可达性集R(s)是非零元素的列索引集。 s
。
最后,一些伪代码(在VB.NET中,不能少):
CalculateInitialAntecedentSets()
CalculateInitialReachabilitySets()
While UnlabelledItems > 0
Sequence.AddNewPartitionLevel()
For Each s In ReachabilityMatrix
If NoDependencies(s) and AlreadyConsidered(s) Then
AddToLevel(CurrentLevel, s)
End If
Next
RemoveDependencies(ReachabilitySets, Sequence.Level(CurrentLevel))
RemoveDependencies(AntecedentSets, Sequence.Level(CurrentLevel))
UpdateConsideredList(Sequence.Level(CurrentLevel))
Unlabelled = Unlabelled - Sequence.Level(CurrentLevel).Count
CurrentLevel = CurrentLevel + 1
End While
(几年前这是我硕士论文的主题)
Warfield,John N。(1973),“系统建模中的二元矩阵”,IEEE系统,人与控制论SMC-3(5),441-449。
答案 1 :(得分:1)
只是一个想法:
构建一个有向图,其中您的类是节点,依赖项是边。检测所有strongly connected components。计算它们的重量(=节点数/类数)。现在你有balanced partition problem - 将一组组件权重划分为两个子集,它们的总和之间的差异最小。
答案 2 :(得分:0)
您正在寻找的算法是topological sorting。只需提取物品,直到遇到一个循环。