在未知大小的加权有向图上,如何从最短到最长迭代两个顶点之间的所有可能的非循环路径?
On a weighted directed graph of unknown size, how can one iterate over all possible acyclic paths between two vertices from shortest to longest?
我们可以假设所有边的权重都是正的,并且您可以在 O(1) 时间内枚举从顶点向外延伸的边,同样地,向内延伸的边。
例如,您可以执行 Dijkstra 遍历(或 A*,具有可接受的启发式算法)并标记每个顶点与起点的距离,直到找到结束顶点,然后在这些标记描述可能的情况时反向递归这些标记最优路径上的前辈。也就是说,对于每一个可能的前驱,如果标记距离之间的差异等于连接它们的边的权重,则可以确定它是否在贪婪最优路径上找到。
在查看可能的前辈时,传入边的成本加上到每个顶点的最佳距离之间的差值等于将此边包含在解决方案中所导致的最优性损失(最佳路径上的边为零) .所以也许问题变成了:如何最好地扩展它以产生 所有 可能的路径按最优性递减排序? 是否有一种干净的方法来执行对这种元图的最佳优先遍历?
这似乎是寻找有用解决方案的正确方向。也许需要记住的一件有用的事情是,如果到目前为止您探索的路径部分可能是至少 x 次优的解决方案的一部分,则只需要检查循环沿着最后 x 访问的距离完成(x 的任何次优路径不可能包含长于 x[=29 的循环=]).
有没有更有效的方法?
作为奖励问题,是否也可以在具有负边权重的图(已知大小)上执行此操作?如果引入负循环,是否会变得更加困难? (请记住,由于我们只寻找非循环路径,这并不一定意味着最优解会消失。)
对于 N 个节点的完整图,其大小为 (N-2)!从节点 A 到节点 B 的可能非循环路径。想一想......这应该是一个巨大的数字,如果你只需要 K(足够大,但数量合理)路径,你最好在评论中提到 K-shortest_path。
如果您可以管理足够的内存来容纳所有可能的方式,那么有一个显而易见的解决方案 - 生成所有可能的方式并按权重对它们进行排序。如果没有,您将不得不将答案转储到磁盘然后收集它们。
您可以使用修改后的 BFS 枚举所有可能的方式 - "visited" 数组被传递给递归调用而不是全局布尔数组。当您访问目的地时,将其添加到全局解决方案地图(键 - 权重,值 - 具有此权重的路径列表)。
如果您无法承受将所有路径都保存在内存中,您可以将它们转储到临时文件中。对此的天真的解决方案:打开名称为 0 的文件 - 最多填充 10 位数字 - 或者任何适合你需要的 - 重量,并为路径添加一行。收集完所有路径后,按照合适的顺序读取文件,形成最终结果。
注意 如果可以,最好不要 open/append/close 文件。例如,当路径总数超过某个限制时,您可以在地图中收集路径并仅转储最长列表。
归功于 n.m。:关于 K-shortest-path routing 的维基百科文章描述了各种现代方法,包括用于泛化 Dijkstra 的伪代码,以及指向 2011 年关于 K* 的论文的链接,该论文也利用了启发式。
我们可以假设所有边的权重都是正的,并且您可以在 O(1) 时间内枚举从顶点向外延伸的边,同样地,向内延伸的边。
例如,您可以执行 Dijkstra 遍历(或 A*,具有可接受的启发式算法)并标记每个顶点与起点的距离,直到找到结束顶点,然后在这些标记描述可能的情况时反向递归这些标记最优路径上的前辈。也就是说,对于每一个可能的前驱,如果标记距离之间的差异等于连接它们的边的权重,则可以确定它是否在贪婪最优路径上找到。
在查看可能的前辈时,传入边的成本加上到每个顶点的最佳距离之间的差值等于将此边包含在解决方案中所导致的最优性损失(最佳路径上的边为零) .所以也许问题变成了:如何最好地扩展它以产生 所有 可能的路径按最优性递减排序? 是否有一种干净的方法来执行对这种元图的最佳优先遍历?
这似乎是寻找有用解决方案的正确方向。也许需要记住的一件有用的事情是,如果到目前为止您探索的路径部分可能是至少 x 次优的解决方案的一部分,则只需要检查循环沿着最后 x 访问的距离完成(x 的任何次优路径不可能包含长于 x[=29 的循环=]).
有没有更有效的方法?
作为奖励问题,是否也可以在具有负边权重的图(已知大小)上执行此操作?如果引入负循环,是否会变得更加困难? (请记住,由于我们只寻找非循环路径,这并不一定意味着最优解会消失。)
对于 N 个节点的完整图,其大小为 (N-2)!从节点 A 到节点 B 的可能非循环路径。想一想......这应该是一个巨大的数字,如果你只需要 K(足够大,但数量合理)路径,你最好在评论中提到 K-shortest_path。
如果您可以管理足够的内存来容纳所有可能的方式,那么有一个显而易见的解决方案 - 生成所有可能的方式并按权重对它们进行排序。如果没有,您将不得不将答案转储到磁盘然后收集它们。
您可以使用修改后的 BFS 枚举所有可能的方式 - "visited" 数组被传递给递归调用而不是全局布尔数组。当您访问目的地时,将其添加到全局解决方案地图(键 - 权重,值 - 具有此权重的路径列表)。
如果您无法承受将所有路径都保存在内存中,您可以将它们转储到临时文件中。对此的天真的解决方案:打开名称为 0 的文件 - 最多填充 10 位数字 - 或者任何适合你需要的 - 重量,并为路径添加一行。收集完所有路径后,按照合适的顺序读取文件,形成最终结果。
注意 如果可以,最好不要 open/append/close 文件。例如,当路径总数超过某个限制时,您可以在地图中收集路径并仅转储最长列表。
归功于 n.m。:关于 K-shortest-path routing 的维基百科文章描述了各种现代方法,包括用于泛化 Dijkstra 的伪代码,以及指向 2011 年关于 K* 的论文的链接,该论文也利用了启发式。