【发布时间】: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