提升图表库限制或转罚点

时间:2017-04-27 10:33:38

标签: c++ boost boost-graph

我正在寻找一种方法,使用有向图在我的Boost图库应用程序中包含转弯限制和/或处罚。我需要限制例如U形转弯(如果这是最好的方式,可能会受到很高的惩罚)。

我无法在Boost Graph中找到一个明确的机制来添加这样的惩罚/限制,那么处理转弯限制的最佳方法是什么?

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

示例图: enter image description here

假设有两个源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;
}

1 个答案:

答案 0 :(得分:0)

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

![enter image description here

在上图中,顶点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;
}