2017-09-23 65 views
1

我是BGL的新手,嘗試使用BGL設置簡單的最短路徑查找程序,其中無向圖被定義爲具有自定義EdgeProperty和VertexProperty的鄰接列表。我得到編譯時錯誤,我認爲我的模板和Boost技能不足。 代碼如下:Boost圖庫使用捆綁屬性

#include <boost/graph/adjacency_list.hpp> 
#include <boost/graph/directed_graph.hpp> 
#include <boost/graph/graph_traits.hpp> 
#include <boost/graph/dijkstra_shortest_paths.hpp> 
#include<iostream> 
#include <map> 

using namespace std; 
using namespace boost; 
enum Node_type 
{ 
    STAIR, 
    LEVEL, 
    LIFT, 
    OTHER, 
    UNKNOWN 
}; 

class VertexProperty 
{ 
public: 
    VertexProperty(){ id=-1; type=Node_type::UNKNOWN, level_id=254, stair_id=254;} 
    std::string toString() 
    { 
    std::string str; 
    str = "id "+to_string(id)+" type "+to_string(type)+" level "+to_string(level_id)+" stair_id "+to_string(stair_id); 
    return str; 
    } 

    int getVertexID() {return id;} 
    int id; 
    Node_type type; 
    int level_id; 
    int stair_id; 
}; 

class EdgeProperty 
{ 
public: 
    EdgeProperty(){id=-1, weight=0;} 
    EdgeProperty(int i, double wt){ id=i; weight=wt; } 
    double getWeigth(){ return weight;} 
    int getID() {return id;} 
    std::string toString() 
    { 
    std::string str; 
    str = "id "+to_string(id)+" weight="+to_string(weight); 
    return str; 
    } 

    int id; 
    double weight; 
}; 

typedef boost::property<boost::edge_weight_t, double> EdgeWeigthProperty; 
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,VertexProperty, EdgeProperty> UndirectedGraph; 
typedef boost::graph_traits<UndirectedGraph>::edge_iterator edge_iterator; 
typedef boost::graph_traits<UndirectedGraph>::vertex_iterator vertex_iterator; 
typedef boost::directed_graph <boost::no_property, EdgeWeigthProperty> DirectedGraph; 
typedef boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 
typedef boost::graph_traits<UndirectedGraph>::edge_descriptor edge_descriptor; 

class A 
{ 
public: 
    A(); 
    void undirected_graph_creation(); 
    void directed_graph_creation(); 
    void showEdges(); 
    void showVertices(); 
    void run_dijkastra(); 
    UndirectedGraph g; 
    DirectedGraph dg; 
    map<int, vertex_descriptor> map_id_vertex_desc; 
    map<int, edge_descriptor> map_id_edge_desc; 
    map<int, Node_type> map_node_id_type; 
}; 

A::A() 

    { 

    } 

    void A::undirected_graph_creation() 
    { 

    UndirectedGraph::vertex_descriptor v0= boost::add_vertex(g); 
    map_id_vertex_desc.emplace(0,v0); 
    g[v0].id=0; 
    g[v0].type=Node_type::LEVEL; 
    UndirectedGraph::vertex_descriptor v1= boost::add_vertex(g); 
    g[v1].id=1; 
    g[v1].type=Node_type::STAIR; 
    map_id_vertex_desc.emplace(1,v1); 
    UndirectedGraph::vertex_descriptor v2= boost::add_vertex(g); 
    map_id_vertex_desc.emplace(2,v2); 
    g[v2].id=2; 
    g[v2].type=Node_type::STAIR; 
    UndirectedGraph::vertex_descriptor v3= boost::add_vertex(g); 
    map_id_vertex_desc.emplace(3,v3); 
    g[v3].id=3; 
    g[v3].type=Node_type::STAIR; 
    /*EdgeWeigthProperty w8(8); 
    EdgeWeigthProperty w18(18); 
    EdgeWeigthProperty w20(20); 
    EdgeWeigthProperty w2(2); 
    EdgeWeigthProperty w7(7);*/ 
    EdgeProperty w8(1,8); 
    EdgeProperty w18(2,18); 
    EdgeProperty w20(3,20); 
    EdgeProperty w2(4,2); 
    EdgeProperty w7(5,7); 

    boost::add_edge(v0,v1,w8,g); 
    boost::add_edge(v0,v3,w18,g); 
    boost::add_edge(v1,v2,w20,g); 
    boost::add_edge(v2,v3,w2,g); 
    boost::add_edge(v1,v3,w7,g); 
} 

void A::showEdges() 
{ 
    std::pair<edge_iterator,edge_iterator> ei=edges(g); 
    std::cout<<" number of edges "<<num_edges(g)<<endl; 
    std::cout<<" Edge list "; 
    for(edge_iterator it= ei.first; it!=ei.second; ++it) 
    cout<<*it<<" "<<g[*it].toString()<<endl; 
} 

void A::showVertices() 
{ 
    std::pair<vertex_iterator, vertex_iterator> vi= boost::vertices(g); 
    std::cout<<" Number of vertices are "<<endl; 
    for(vertex_iterator i = vi.first; i!=vi.second; ++i) 
    { 
    cout<<*i<<" id="<<g[*i].toString()<<" type="<<g[*i].type<<endl; 
    } 

} 
void A::run_dijkastra() 
{ 
    std::vector<vertex_descriptor> predecessors(boost::num_vertices(g)); 
    std::vector<EdgeProperty> distances(boost::num_vertices(g)); 
    std::pair<vertex_iterator,vertex_iterator> vi=boost::vertices(g); 
    vertex_descriptor first_vertex_descriptor = *(vi.first); 
    vertex_descriptor start_vertex = boost::vertex(0,g); 

// boost::dijkstra_shortest_paths(g, first_vertex_descriptor, 
    //        boost::weight_map(get(&EdgeProperty::weight,g)) 
    //        .distance_map(boost::make_iterator_property_map(distances.begin(), get(boost::vertex_index, g)))        ); 

dijkstra_shortest_paths(g, first_vertex_descriptor, 
         predecessor_map(make_iterator_property_map(predecessors.begin(), get(vertex_index,g))).distance_map(make_iterator_property_map(distances.begin(), get(boost::vertex_index,g))).weight_map(get(&EdgeProperty::weight,g)); 
/* 
std::cout << "distances and parents:" << std::endl; 
graph_traits <UndirectedGraph>::vertex_iterator vi1, vend1; 
for (boost::tie(vi1, vend1) = vertices(g); vi1 != vend1; ++vi1) { 
    std::cout << "distance(" << g[*vi1].id << ") = " << distances[*vi1].toString() << ", "; 
    std::cout << "parent(" << g[*vi1].id << ") = " << g[predecessors[*vi1]].id << std:: 
    endl; 
}*/ 
} 

void A::directed_graph_creation() 
{ 
//todo 

} 
int main() 
{ 
    A a_graph; 
    a_graph.undirected_graph_creation(); 
    a_graph.showEdges(); 
    a_graph.showVertices();; 
    a_graph.run_dijkastra(); 
    return 0; 
} 

錯誤是從雙到EdgeProperty正是未知的轉換。看起來我在調用dijkstra_shortest_paths函數的語法上有錯誤。

我還想用函數替換EdgeProperty的數據成員。

我的其他查詢是關於通過頂點描述符維護節點的索引。目前,我正在使用VertexProperty :: id做一個字典來維護VertexProperty類型的對象。 Do Boost在內部維護我可以使用的任何字典。

我使用在Ubuntu 16.04 gcc5.4版本的編譯器謝謝

尼廷

+0

你需要'distances'是一個'的std ::矢量'。 – llonesmiz

+0

太多的問題,太多的代碼(所有的評論與它有什麼關係?) – sehe

回答

0

@llonesmiz是正確的標記。這裏是代碼和現場演示的一般清理。

我還使用make_transform_value_property_map來使用getWeight()並使所有數據成員保密。

注意嫌疑std::map實例是不是真的有用了,現在你使用捆綁的性質(?)。在任何情況下,你可能會下降一些代碼,如果你不需要他們的任何更多:Shorter Demo

注意你可能不知道print_graphEven Shorter,略有刪節輸出

Live On Coliru

#include <boost/graph/adjacency_list.hpp> 
#include <boost/graph/dijkstra_shortest_paths.hpp> 
#include <boost/property_map/transform_value_property_map.hpp> 
#include <iostream> 
#include <map> 

enum class Node_type { STAIR, LEVEL, LIFT, OTHER, UNKNOWN }; 

static std::ostream& operator<<(std::ostream& os, Node_type type) { 
    switch(type) { 
     case Node_type::STAIR: return os << "STAIR"; 
     case Node_type::LEVEL: return os << "LEVEL"; 
     case Node_type::LIFT: return os << "LIFT"; 
     case Node_type::OTHER: return os << "OTHER"; 
     default: 
     case Node_type::UNKNOWN: return os << "UNKNOWN"; 
    } 
} 

class VertexProperty { 
    public: 
    VertexProperty(int id = -1, Node_type type = Node_type::UNKNOWN, int level_id=254, int stair_id=254) 
     : id(id), type(type), level_id(level_id), stair_id(stair_id) { } 

    std::string toString() const { 
     std::ostringstream oss; 
     oss << *this; 
     return oss.str(); 
    } 

    int getVertexID() { return id; } 

    private: 
    friend std::ostream& operator<<(std::ostream& os, VertexProperty const& v) { 
     return os << "id " << v.id << " type " << v.type << " level " << v.level_id << " stair_id " << v.stair_id; 
    } 

    int id; 
    Node_type type; 
    int level_id; 
    int stair_id; 
}; 

class EdgeProperty { 
    public: 
    EdgeProperty(int i = -1, double wt = 0) : id(i), weight(wt) { 
     id = i; 
     weight = wt; 
    } 
    double getWeight() { return weight; } 
    int getID() { return id; } 

    std::string toString() const { 
     std::ostringstream oss; 
     oss << *this; 
     return oss.str(); 
    } 

    private: 
    friend std::ostream& operator<<(std::ostream& os, EdgeProperty const& e) { 
     return os << "id " << e.id << " weight=" << std::fixed << e.weight; 
    } 

    int id; 
    double weight; 
}; 

class A { 
    public: 
    void undirected_graph_creation(); 
    void showEdges(); 
    void showVertices(); 
    void runDijstra(); 

    private: 
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexProperty, EdgeProperty> UndirectedGraph; 
    UndirectedGraph g; 

    using edge_iterator  = UndirectedGraph::edge_iterator; 
    using vertex_iterator = UndirectedGraph::vertex_iterator; 
    using vertex_descriptor = UndirectedGraph::vertex_descriptor; 
    using edge_descriptor = UndirectedGraph::edge_descriptor; 

    std::map<int, vertex_descriptor> map_id_vertex_desc; 
    std::map<int, edge_descriptor> map_id_edge_desc; 
    std::map<int, Node_type>   map_node_id_type; 
}; 

void A::undirected_graph_creation() { 

    auto add_vertex = [this](int id, Node_type type) { 
     // TODO: these maps are probably not required anymore 
     map_node_id_type[id] = type; 
     vertex_descriptor vd = boost::add_vertex(VertexProperty{id, type}, g); 
     return map_id_vertex_desc[id] = vd; 
    }; 

    auto v0 = add_vertex(0, Node_type::LEVEL); 
    auto v1 = add_vertex(1, Node_type::STAIR); 
    auto v2 = add_vertex(2, Node_type::STAIR); 
    auto v3 = add_vertex(3, Node_type::STAIR); 

    auto add_edge = [this](vertex_descriptor u, vertex_descriptor v, EdgeProperty prop) { 
     auto ins = boost::add_edge(u, v, prop, g); 

     if (ins.second) 
      map_id_edge_desc[prop.getID()] = ins.first; 

     return ins.first; 
    }; 

    add_edge(v0, v1, {1, 8}); 
    add_edge(v0, v3, {2, 18}); 
    add_edge(v1, v2, {3, 20}); 
    add_edge(v2, v3, {4, 2}); 
    add_edge(v1, v3, {5, 7}); 
} 

void A::showEdges() { 
    for (auto e : boost::make_iterator_range(boost::edges(g))) 
     std::cout << "Edge " << e << " " << g[e] << "\n"; 
} 

void A::showVertices() { 
    for (auto v : boost::make_iterator_range(boost::vertices(g))) 
     std::cout << "Vertex " << v << " " << g[v] << "\n"; 
} 

void A::runDijstra() { 
    std::vector<vertex_descriptor> predecessors(num_vertices(g)); 
    std::vector<double>   distances(num_vertices(g)); 
    vertex_descriptor start = *(vertices(g).first); 

    auto v_index = get(boost::vertex_index, g); 
    auto weight = boost::make_transform_value_property_map(std::mem_fn(&EdgeProperty::getWeight), get(boost::edge_bundle, g)); 

    dijkstra_shortest_paths(
     g, start, 
     predecessor_map(make_iterator_property_map(predecessors.begin(), v_index)) 
      .distance_map(make_iterator_property_map(distances.begin(), v_index)) 
      .weight_map(weight)); 

    std::cout << "distances and parents:\n"; 
    for (auto v : boost::make_iterator_range(boost::vertices(g))) { 
     auto id = g[v].getVertexID(); 
     std::cout << "distance(" << id << ") = " << distances[v] << ", "; 
     std::cout << "parent(" << id << ") = " << g[predecessors[v]] << "\n"; 
    } 
} 

int main() { 
    A a; 
    a.undirected_graph_creation(); 
    a.showEdges(); 
    a.showVertices(); 

    a.runDijstra(); 
} 

打印:

Edge (0,1) id 1 weight=8.000000 
Edge (0,3) id 2 weight=18.000000 
Edge (1,2) id 3 weight=20.000000 
Edge (2,3) id 4 weight=2.000000 
Edge (1,3) id 5 weight=7.000000 
Vertex 0 id 0 type LEVEL level 254 stair_id 254 
Vertex 1 id 1 type STAIR level 254 stair_id 254 
Vertex 2 id 2 type STAIR level 254 stair_id 254 
Vertex 3 id 3 type STAIR level 254 stair_id 254 
distances and parents: 
distance(0) = 0.000000, parent(0) = id 0 type LEVEL level 254 stair_id 254 
distance(1) = 8.000000, parent(1) = id 0 type LEVEL level 254 stair_id 254 
distance(2) = 17.000000, parent(2) = id 3 type STAIR level 254 stair_id 254 
distance(3) = 15.000000, parent(3) = id 1 type STAIR level 254 stair_id 254