【发布时间】:2011-06-27 15:49:30
【问题描述】:
我正在尝试计算依赖图的部分“拓扑排序”,准确地说,它实际上是一个 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;
}
【问题讨论】:
-
您可能希望通过记忆 find_partial_ordering 的返回值将最坏情况从二次减至线性...
-
您是否需要预先为图表找到一组图层,或者您可以在任务执行时逐步完成?如果您有不同的任务执行时间,创建一个算法来挑选一个满足依赖关系的元素,然后在线程空闲时运行它是很简单的。
标签: algorithm graph dependencies pseudocode topological-sort