加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 程序设计 > 正文

用于计算依赖图的部分排序的算法

发布时间:2020-05-29 11:41:10 所属栏目:程序设计 来源:互联网
导读:我试图计算依赖图的部分“拓扑排序”,这实际上是一个DAG(定向非循环图),它是精确的;以便并行执行没有冲突的依赖关系的任务. 我想出了这个简单的算法,因为我在Google上发现的并不那么有用(我只会发现自己并行运行的算法来计算正常的拓扑排序). visit(node){ ma

我试图计算依赖图的部分“拓扑排序”,这实际上是一个DAG(定向非循环图),它是精确的;以便并行执行没有冲突的依赖关系的任务.

我想出了这个简单的算法,因为我在Google上发现的并不那么有用(我只会发现自己并行运行的算法来计算正常的拓扑排序).

visit(node)
{
    maxdist = 0;
    foreach (e : in_edge(node))
    {
        maxdist = max(maxdist,1 + visit(source(e)))
    }
    distance[node] = maxdist;
    return distance[node];
}

make_partial_ordering(node)
{
    set all node distances to +infinite;
    num_levels = visit(node,0);
    return sort(nodes,by increasing distance) where distances < +infinite;
}

(请注意,这只是伪代码,肯定会有一些可能的小优化)

对于正确性,似乎很明显:对于叶子(= =没有进一步依赖的节点),最大距离到叶始终为0(正确,因为循环由于0边缘而被跳过).
对于连接到节点n1,…,nk的任何节点,最大距离到叶是1 max {distance [n1],..,distance [nk]}.

我写下了算法之后,我找到了这篇文章:http://msdn.microsoft.com/en-us/magazine/dd569760.aspx
但是老实说,他们为什么要做所有的列表复制等等,这似乎真的没有效率?

无论如何,我想知道我的算法是否正确,如果是这样的话,我可以读取一些关于它的东西.

更新:我在我的程序中实现了这个算法,似乎对我测试的一切都很有用.
代码如下:

typedef boost::graph_traits<my_graph> my_graph_traits;
  typedef my_graph_traits::vertices_size_type vertices_size_type;
  typedef my_graph_traits::vertex_descriptor vertex;
  typedef my_graph_traits::edge_descriptor edge;

  vertices_size_type find_partial_ordering(vertex v,std::map<vertices_size_type,std::set<vertex> >& distance_map)
  {
      vertices_size_type d = 0;

      BOOST_FOREACH(edge e,in_edges(v))
      {
          d = std::max(d,1 + find_partial_ordering(source(e),distance_map));
      }

      distance_map[d].insert(v);

      return d;
  }
你的算法(C)是有效的,但它具有非常糟糕的最坏情况时间复杂度.它计算节点上的find_partial_ordering与该节点一样多的路径.在树的情况下,路径的数量为1,但是在一般的有向无环图中,路径的数量可以是指数的.

您可以通过memoizing的find_partial_ordering结果修复此问题,并在您已经计算了特定节点的值时返回而不进行递归.然而,这仍然给你一个堆栈破坏的递归解决方案.

这不符合你的需要吗?

编辑:啊,我明白,你想知道深度边界在哪里,这样你可以在给定的深度平行一切.您仍然可以使用维基百科的算法(因此避免递归).

首先,使用维基百科上的算法进行拓扑排序.现在通过以拓扑顺序访问节点来计算深度:

depths : array 1..n
for i in 1..n
    depths[i] = 0
    for j in children of i
        depths[i] = max(depths[i],depths[j] + 1)
return depths

请注意,上面没有递归,只是一个简单的O(| V | | E |)算法.这与维基百科的算法具有相同的复杂性.

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读