如何查找不会导致循环依赖的子包

时间:2012-03-02 12:51:39

标签: algorithm graph dependencies

我们有一条规则禁止包之间的循环依赖。

我们还有一个相当庞大的软件包,需要进行一些拆分。

问题是:如何识别类的/所有/最大子集,可以从包中提取到新包中,而不会产生循环依赖。

是否有一个众所周知的算法?

变量很棒,其中on可以定义算法可以忽略的最大依赖项数。

显然,子集应该与包不同,也不应该是空的。 如果是最大子集,则应小于原始包的一半。

3 个答案:

答案 0 :(得分:3)

基本上,您的类,对象或您拥有的内容存储在表示adjacency matrix(有或没有循环)的矩阵(称为directed graph)中。请参见下图和相应的邻接矩阵。

enter image description here

由此,我们可以计算可达性矩阵,该矩阵描述了一个节点可以从当前节点传播到哪个节点。对于此图,可达性矩阵是

enter image description here

您需要一种算法来重新排列矩阵的行和列,以便所有非零元素都在主对角线下方。可以按照它们出现在矩阵中的顺序执行这个为真的对象索引序列,并且将满足每个对象的所有必要依赖性。如果已知图形是非循环的,则可以通过topological sorting来实现。

当有向图中出现循环时,您将无法找到这种情况的排序。

输入Design/Dependency Structure Matrix(DSM)。可以实现所谓的分区算法以将对象划分为级别。对于每个级别,对象可以按任意顺序执行,并且不依赖于一个或另一个。对于上图,节点3,4和5不相互依赖,可以按任何顺序执行。

分区算法已在(Warfield 1973)中开发,它能够检测和隔离DSM中的循环。这类似于拓扑排序算法,但使用可达性矩阵来检测和隔离循环。

简要算法:

  
      
  1. 创建新的分区级别
  2.   
  3. 计算可达性,前提设定R(s)和A(s)
  4.   
  5. 对于DSM中的每个元素,计算集合乘积R(s)A(s)
  6.   
  7. 如果R(s)A(s)= R(s),则将元素s添加到当前级别
  8.   
  9. 从列表中删除元素s,并从所有其他元素的可达性和先行集中删除所有引用。
  10.   
  11. 如果项目列表不为空,则从1开始重复。
  12.   

先行集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。只需提取物品,直到遇到一个循环。