【问题标题】:Boost BGL Dijkstra Shortest PathsBoost BGL Dijkstra 最短路径
【发布时间】:2015-05-19 01:23:37
【问题描述】:

我不熟悉 boost 库并尝试学习。我已经使用 boost 图形库来调用 dijstra 的最短路径函数来在地图中查找到目的地的路径。顶点是交叉点,边是街道段。

我正在以最短时间找到最短路径。为此,我将边缘权重定义为时间,时间 = st 段长度 * 它的速度/限制。这确实给了我最短的路径(按时间)。 但是,我还要考虑一个回合,并在每个回合的总时间上增加 15 秒。我如何检测转弯是给定两个街段(边缘),如果第二个 st 名称不等于第一个 st 名称,则它是一个转弯。

基本上,我想动态分配权重(不仅仅是像我在这里所做的那样在开始时设置它们)。当程序在搜索过程中访问边缘时,我希望它在这个阶段检查父母(或这里的前辈)。我如何在可以做到这一点的参数中传递一个函数或某些东西?

vector<unsigned>  OurGraph::find_awesome_path(unsigned start, unsigned finish)
{

    // start and finish are intersection IDs,
    // Get the corresponding Vertices in the graph. 
    Vertex start_node = vertex_map[start]; 
    Vertex dest_node = vertex_map[finish];   

    std::vector<Vertex> predecessors(boost::num_vertices(my_graph)); // To store parents
    std::vector<float> distances(boost::num_vertices(my_graph)); // To store dijkstra distances

    IndexMap indexMap = boost::get(boost::vertex_index, my_graph);
    PredecessorMap predecessorMap(&predecessors[0], indexMap);
    DistanceMap distanceMap(&distances[0], indexMap);

    boost::dijkstra_shortest_paths(my_graph, start_node, boost::distance_map(distanceMap).predecessor_map(predecessorMap));
vector<Edge> path;

    path = get_edge_path(dest_node, predecessorMap);    // Extracts edges from edge descriptors in predecessor map
                                                    // and piles them in a vector of Edge. 
    return segment_list_from_edges(path);           // Convert edges to street segment IDs and return.
}

其中 my_graph 是一个类型 GraphGraph , Vertex, Edge, IndexMap, PredecessorMapDistanceMap 是类型定义如下:

typedef boost::property<boost::edge_weight_t, float> WeightProperty;
typedef boost::property<boost::vertex_name_t, unsigned> IntersectionProperty;  
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS,
  IntersectionProperty, WeightProperty > Graph;
typedef boost::graph_traits < Graph >::vertex_descriptor Vertex;
typedef boost::graph_traits < Graph >::edge_descriptor Edge;
typedef boost::property_map < Graph, boost::vertex_index_t >::type IndexMap;
typedef boost::iterator_property_map < Vertex*, IndexMap, Vertex, Vertex& > PredecessorMap;
typedef boost::iterator_property_map < float*, IndexMap, float, float& > DistanceMap;

【问题讨论】:

  • 您可能无法直接使用 Dijkstra 的算法,因为它假定沿某些边缘行驶所产生的额外成本与您如何开始顶点。您可以通过在同一条街道上的每对非相邻顶点 u 和 v 之间添加额外的边,然后将 每条 边的成本增加 15 秒(新边将包括15s 只需花费一次)。最后,无论你得到什么解决方案,都需要 15 秒的时间。注意:如果所有 n 个顶点都属于同一条道路,这可能是 O(n^2) 个额外的边!
  • 我不太明白这个建议。在我有限的理解中,我做了以下事情(每次分别):(1)向短路顶点添加额外的边,这将是一个转弯。 (2) 在同一条街道上的顶点上添加额外的边。 (3) 赋予不同的权重值而不是0.25 ....包括大小常数、当前或下一段的长度、当前或下一段的时间。 ....它们要么返回非法路径(包括这些额外的边缘),要么没有区别,要么返回更糟糕的路径。
  • (2) 最接近正确。对于任意一对顶点 u 和 v 在同一条道路上,但不是彼此相邻,您需要添加一条边:这条边的目的是让 Dijkstra 选择对应的一系列来自原始图的边,而只支付 25 秒的转弯成本一次。所以例如如果您在同一条道路上有 5 个顶点 a、b、c、d、e,您将添加边 ac、bd、ce、ad、be、ae,每个边的成本等于它们“跨越”的边的总和+25(例如,be 的成本为 cost(bc)+cost(cd)+cost(de)+25)。所有原始边缘的成本也增加了 25。
  • 如果 Dijkstra 在其解决方案中包含这些额外边之一,这意味着它“跨越”的原始边的底层集合(例如,添加的边 be 跨越原始边 bc、cd 和 de ) 是最短路径的一部分。
  • 在新版本的图中,每条边需要额外花费 25s。这个想法是原始图中的每个 turnless subpath 对应于新图中的一条边,额外的 25s 是该子路径开始时所需的转弯的费用。 (从最终解决方案中减去 25,因为您不需要在开始时转弯。)虽然可以在新图中创建类似 ac->ce 的路径,即使它不离开也会收取额外的 25s同样的道路,Dijkstra 永远不会这样做,因为我们确保已经有更便宜的单边路径 ae。

标签: c++ algorithm boost graph


【解决方案1】:

您可以这样做的一种方法是使用微分图。在这种情况下,微分图中的每个顶点都将等同于当前图中的一条边。例如,一个顶点会封装一个转弯。然后,您可以将转弯权重添加到涉及街道名称更改(或用于确定转弯的任何机制)的边缘。

【讨论】:

    猜你喜欢
    • 2015-09-17
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    相关资源
    最近更新 更多