我正在寻找一种方法,使用有向图在我的Boost图库应用程序中包含转弯限制和/或处罚。我需要限制例如U形转弯(如果这是最好的方式,可能会受到很高的惩罚)。
我无法在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;
}
答案 0 :(得分:0)
由于还没有即将发布的答案,我会发布一个默认答案,我希望有人可以改进。
在上图中,顶点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 - &gt; e2 - &gt; 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;
}