【问题标题】:Boost Graph Library turn restrictions or turn penaltiesBoost Graph Library 转弯限制或转弯惩罚
【发布时间】:2017-04-27 10:33:37
【问题描述】:

我正在寻找一种方法,在我的 Boost Graph Library 应用程序中使用有向图来包含转弯限制和/或转弯惩罚。例如,我需要限制掉头(如果这是最好的方法,这可能是一个非常高的惩罚)。

我在 Boost Graph 中找不到明确的机制来添加此类惩罚/限制,处理转弯限制的最佳方法是什么?

到目前为止,我看到的唯一解决方案是用“内部边缘”为每个可能的顶点转弯扩展图形,省略“内部边缘”来限制转弯。这对我来说似乎很暴力,有没有更好的方法?

示例图:

假设有两个源 A 和 E,并且到每个顶点的最短路径是使用 Dijkstra 计算的(参见下面的代码示例)。

两个最短路径树是( printShortestPath() 的输出):

Shortest path from A to all vertices: 
distances and parents:
distance(A) = 0, parent(A) = A
distance(B) = 100, parent(B) = A
distance(C) = 200, parent(C) = B
distance(D) = 200, parent(D) = B
distance(E) = 1.79769e+308, parent(E) = E
-------------
Shortest path from E to all vertices: 
distances and parents:
distance(A) = 1.79769e+308, parent(A) = A
distance(B) = 100, parent(B) = E
distance(C) = 200, parent(C) = B
distance(D) = 200, parent(D) = B
distance(E) = 0, parent(E) = E

在 Boost::Graph 中禁止这种转向(e1 到 e4)的优雅方法是什么?

一个简单的解决方案是扩展图表,使其具有表示转弯运动的附加边(禁止的成本很高),但我希望有一种更优雅的方式。

代码:

#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <QString>
#include <vector>

using namespace boost;

struct GraphNode
{
    GraphNode() {}
    GraphNode(const QString& name_):name(name_) {}
    QString name;
};

struct GraphLink
{
    GraphLink() {}
    GraphLink(const QString& name_, double length_, double travelTime_):name(name_),length(length_), travelTime(travelTime_) {}
    QString name;
    double length; // in meters
    double travelTime; // in seconds
};

typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, GraphNode, GraphLink> NetworkGraph;
typedef graph_traits < NetworkGraph >::vertex_descriptor vertex_descriptor;
typedef std::vector<decltype (GraphLink::length)> distancesT;

void printShortestPath (const NetworkGraph& map, distancesT distances,std::vector<vertex_descriptor> p )
{
    std::cout << "distances and parents:" << std::endl;
    graph_traits < NetworkGraph >::vertex_iterator vi, vend;
    for (auto vs=vertices(map); vs.first!=vs.second;++vs.first)
    {
        auto currEdge=map[*vs.first];
        auto parent=p[*vs.first];
        QString parentName=map[parent].name;
              QString name =currEdge.name;
              std::cout << "distance(" << name.toStdString() << ") = " << distances[*vs.first] << ", ";
              std::cout << "parent(" << name.toStdString() << ") = " << parentName.toStdString() << std::
                endl;
    }

}


int main(int, char *[])
{
    //Create the vertices

    NetworkGraph map;
    NetworkGraph::vertex_descriptor vertexA = add_vertex(map);
    map[vertexA].name ="A";
    NetworkGraph::vertex_descriptor vertexB = add_vertex(map);
    map[vertexB].name ="B";
    NetworkGraph::vertex_descriptor vertexC = add_vertex(map);
    map[vertexC].name ="C";
    NetworkGraph::vertex_descriptor vertexD = add_vertex(map);
    map[vertexD].name ="D";
    NetworkGraph::vertex_descriptor vertexE = add_vertex(map);
    map[vertexE].name ="E";

    // Create the edges

    NetworkGraph::edge_descriptor e1 = add_edge(vertexA,vertexB,map).first;
    map[e1].name ="e1";
    map[e1].length =100.0;

    NetworkGraph::edge_descriptor e2 = add_edge(vertexB,vertexC,map).first;
    map[e2].name ="e2";
    map[e2].length =100.0;

    NetworkGraph::edge_descriptor e3 = add_edge(vertexC,vertexD,map).first;
    map[e3].name ="e3";
    map[e3].length =100.0;

    NetworkGraph::edge_descriptor e4 = add_edge(vertexB,vertexD,map).first;
    map[e4].name ="e4";
    map[e4].length =100.0;

    NetworkGraph::edge_descriptor e5 = add_edge(vertexE,vertexB,map).first;
    map[e5].name ="e5";
    map[e5].length =100.0;

    distancesT distances (num_vertices(map)); // distances
    std::vector<vertex_descriptor> p (num_vertices(map)); // parents

    //calculate shortest paths from vertex A using Dijkstra, based on GraphLink::length as edge cost
    dijkstra_shortest_paths (map,
                             vertexA,
                             weight_map (get(&GraphLink::length, map))
                                .distance_map (make_iterator_property_map(distances.begin(), get(vertex_index, map)))
                                .predecessor_map (make_iterator_property_map(p.begin(), get(vertex_index, map))) );

    std::cout << "Shortest path from A to all vertices: " << std::endl;
    printShortestPath (map, distances, p);

    //calculate shortest paths from vertex E using Dijkstra, based on GraphLink::length as edge cost
    dijkstra_shortest_paths (map,
                             vertexE,
                             weight_map (get(&GraphLink::length, map))
                                .distance_map (make_iterator_property_map(distances.begin(), get(vertex_index, map)))
                                .predecessor_map (make_iterator_property_map(p.begin(), get(vertex_index, map))) );

    std::cout << "-------------" << std::endl;
    std::cout << "Shortest path from E to all vertices: " << std::endl;
    printShortestPath (map, distances, p);
    return EXIT_SUCCESS;
}

【问题讨论】:

    标签: c++ boost boost-graph


    【解决方案1】:

    由于还没有答案,我将发布一个默认答案,希望有人可以改进。

    在上图中,顶点 B 已替换为顶点 B1...B4

    对于允许的转动运动,已添加“内部”边缘,而对于不允许的运动,它们已被省略。在对所有运动进行转弯惩罚的情况下,这会将图形扩展为每个节点的 nrIncoming*nrOutgoing 边。

    Resulting shortest paths from source A resp. E:
    
    Shortest path from A to all vertices: 
    distances and parents:
    distance(A) = 0, parent(A) = A
    distance(B1) = 100, parent(B1) = A
    distance(B2) = 1.79769e+308, parent(B2) = B2
    distance(B3) = 100, parent(B3) = B1
    distance(B4) = 1.79769e+308, parent(B4) = B4
    distance(C) = 200, parent(C) = B3
    distance(D) = 300, parent(D) = C
    distance(E) = 1.79769e+308, parent(E) = E
    -------------
    Shortest path from E to all vertices: 
    distances and parents:
    distance(A) = 1.79769e+308, parent(A) = A
    distance(B1) = 1.79769e+308, parent(B1) = B1
    distance(B2) = 100, parent(B2) = E
    distance(B3) = 100, parent(B3) = B2
    distance(B4) = 100, parent(B4) = B2
    distance(C) = 200, parent(C) = B3
    distance(D) = 200, parent(D) = B4
    distance(E) = 0, parent(E) = E
    

    现在从 A 到 D 的最短路径是通过 e1-> e1e2 -> e2 -> e3,费用为 300。

    代码:

    #include <boost/config.hpp>
    #include <iostream>
    #include <boost/graph/graph_traits.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/dijkstra_shortest_paths.hpp>
    #include <QString>
    #include <vector>
    
    using namespace boost;
    
    struct GraphNode
    {
        GraphNode() {}
        GraphNode(const QString& name_):name(name_) {}
        QString name;
    };
    
    struct GraphLink
    {
        GraphLink() {}
        GraphLink(const QString& name_, double length_, double travelTime_):name(name_),length(length_), travelTime(travelTime_) {}
        QString name;
        double length; // in meters
        double travelTime; // in seconds
    };
    
    typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, GraphNode, GraphLink> NetworkGraph;
    typedef graph_traits < NetworkGraph >::vertex_descriptor vertex_descriptor;
    typedef std::vector<decltype (GraphLink::length)> distancesT;
    
    void printShortestPath (const NetworkGraph& map, distancesT distances,std::vector<vertex_descriptor> p )
    {
        std::cout << "distances and parents:" << std::endl;
        graph_traits < NetworkGraph >::vertex_iterator vi, vend;
        for (auto vs=vertices(map); vs.first!=vs.second;++vs.first)
        {
            auto currEdge=map[*vs.first];
            auto parent=p[*vs.first];
            QString parentName=map[parent].name;
                  QString name =currEdge.name;
                  std::cout << "distance(" << name.toStdString() << ") = " << distances[*vs.first] << ", ";
                  std::cout << "parent(" << name.toStdString() << ") = " << parentName.toStdString() << std::
                    endl;
        }
    
    }
    
    
    int main(int, char *[])
    {
        //Create the vertices
    
        NetworkGraph map;
        NetworkGraph::vertex_descriptor vertexA = add_vertex(map);
        map[vertexA].name ="A";
        //NetworkGraph::vertex_descriptor vertexB = add_vertex(map);
        //map[vertexB].name ="B";
        // Instead of vertex B we will create vertex B1...B4
        NetworkGraph::vertex_descriptor vertexB1 = add_vertex(map);
        map[vertexB1].name ="B1";
        NetworkGraph::vertex_descriptor vertexB2 = add_vertex(map);
        map[vertexB2].name ="B2";
        NetworkGraph::vertex_descriptor vertexB3 = add_vertex(map);
        map[vertexB3].name ="B3";
        NetworkGraph::vertex_descriptor vertexB4 = add_vertex(map);
        map[vertexB4].name ="B4";
    
        NetworkGraph::vertex_descriptor vertexC = add_vertex(map);
        map[vertexC].name ="C";
        NetworkGraph::vertex_descriptor vertexD = add_vertex(map);
        map[vertexD].name ="D";
        NetworkGraph::vertex_descriptor vertexE = add_vertex(map);
        map[vertexE].name ="E";
    
        // Create the edges
    
        NetworkGraph::edge_descriptor e1 = add_edge(vertexA,vertexB1,map).first;
        map[e1].name ="e1";
        map[e1].length =100.0;
    
        NetworkGraph::edge_descriptor e2 = add_edge(vertexB3,vertexC,map).first;
        map[e2].name ="e2";
        map[e2].length =100.0;
    
        NetworkGraph::edge_descriptor e3 = add_edge(vertexC,vertexD,map).first;
        map[e3].name ="e3";
        map[e3].length =100.0;
    
        NetworkGraph::edge_descriptor e4 = add_edge(vertexB4,vertexD,map).first;
        map[e4].name ="e4";
        map[e4].length =100.0;
    
        NetworkGraph::edge_descriptor e5 = add_edge(vertexE,vertexB2,map).first;
        map[e5].name ="e5";
        map[e5].length =100.0;
    
        // add internal edges with 0.0 length
        NetworkGraph::edge_descriptor e1e2 = add_edge(vertexB1,vertexB3,map).first;
        map[e1e2].name ="e1-e2";
        map[e1e2].length =0.0;
    
        NetworkGraph::edge_descriptor e5e4 = add_edge(vertexB2,vertexB4,map).first;
        map[e5e4].name ="e5-e4";
        map[e5e4].length =0.0;
    
        NetworkGraph::edge_descriptor e5e2 = add_edge(vertexB2,vertexB3,map).first;
        map[e5e2].name ="e5-e2";
        map[e5e2].length =0.0;
    
        distancesT distances (num_vertices(map)); // distances
        std::vector<vertex_descriptor> p (num_vertices(map)); // parents
    
        //calculate shortest paths from vertex A using Dijkstra, based on GraphLink::length as edge cost
        dijkstra_shortest_paths (map,
                                 vertexA,
                                 weight_map (get(&GraphLink::length, map))
                                    .distance_map (make_iterator_property_map(distances.begin(), get(vertex_index, map)))
                                    .predecessor_map (make_iterator_property_map(p.begin(), get(vertex_index, map))) );
    
        std::cout << "Shortest path from A to all vertices: " << std::endl;
        printShortestPath (map, distances, p);
    
        //calculate shortest paths from vertex E using Dijkstra, based on GraphLink::length as edge cost
        dijkstra_shortest_paths (map,
                                 vertexE,
                                 weight_map (get(&GraphLink::length, map))
                                    .distance_map (make_iterator_property_map(distances.begin(), get(vertex_index, map)))
                                    .predecessor_map (make_iterator_property_map(p.begin(), get(vertex_index, map))) );
    
        std::cout << "-------------" << std::endl;
        std::cout << "Shortest path from E to all vertices: " << std::endl;
        printShortestPath (map, distances, p);
        return EXIT_SUCCESS;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-28
      • 2022-01-15
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多