2017-04-27 78 views
0

我正在尋找一種方法來在我的Boost圖庫應用程序中使用有向圖來包含轉彎限制和/或轉向處罰。我需要限制例如U形轉彎(如果這是最好的方式,這可能是非常高的罰分)。Boost Graph Library轉向限制或轉向處罰

我在Boost Graph中找不到明確的機制來添加這樣的懲罰/限制,那麼處理轉彎限制的最佳方法是什麼?

我到目前爲止看到的唯一解決方案是擴大圖形的'內部邊緣',用於頂點中的每個可能的轉彎,忽略限制轉彎的'內部邊緣'。這對我來說似乎非常蠻橫,有沒有更好的辦法?

實施例圖: enter image description here

假設有兩個源A和E,以及使用迪傑斯特拉(見下面的代碼示例)被計算爲每個頂點的最短路徑。

兩個最短路徑樹(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 

什麼是優雅的方式在升壓禁止這個轉折點(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; 
} 

回答

0

由於沒有答案即將到來的是,我將發佈一個默認回答,我希望在有人可以提高。

![enter image description here

在上面的曲線圖中,頂點B已被取代的頂點B1 ... B4

對於允許轉動運動,「內部」邊緣已被添加,和用於禁止運動他們已被省略。在對所有移動進行懲罰的情況下,這將通過nrIncoming * nrOutgoing邊爲每個節點擴展圖。從A到d

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 

現在最短路徑是經由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; 
}