我试图计算一个依赖图的部分“拓扑排序”,它实际上是一个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的返回值来将最坏情况从二次方减少到线性...... – 2011-02-16 14:56:30
您是否需要预先为图找到一组图层,或者您是否可以增量方式任务执行?如果您的任务执行时间不尽相同,那么创建一个算法来挑选其依赖关系已满足的元素很简单,然后在线程空闲时运行该算法。 – 2011-02-19 03:26:34