2011-08-23 87 views
9

我對Boost圖很新穎。我試圖修改一個例子來找到使用VertexList = vecS的Dijkstra Shortest Path算法。我將頂點容器改爲ListS。我瞭解到,如果我們使用listS,我們必須提供我們自己的vertex_index來使算法工作。Dijkstra VertexList的最短路徑= ListS在升壓圖中

int main(int, char *[]) 
{ 
    typedef float Weight; 
    typedef boost::property<boost::edge_weight_t, Weight> WeightProperty; 
    typedef boost::property<boost::vertex_name_t, std::string> NameProperty; 
    typedef boost::property<boost::vertex_index_t, int> IndexProperty; 

    typedef boost::adjacency_list < boost::listS, boost::listS, boost::directedS, 
    NameProperty, WeightProperty > Graph; 

    typedef boost::graph_traits <Graph>::vertex_descriptor Vertex; 
    typedef boost::graph_traits <Graph>::vertex_iterator Viter; 

    typedef boost::property_map < Graph, boost::vertex_index_t >::type IndexMap; 
    typedef boost::property_map < Graph, boost::vertex_name_t >::type NameMap; 

    typedef boost::iterator_property_map < Vertex*, IndexMap, Vertex, Vertex& > PredecessorMap; 
    typedef boost::iterator_property_map < Weight*, IndexMap, Weight, Weight& > DistanceMap; 

    Graph g; 


    Vertex v0 = boost::add_vertex(std::string("v0"), g); 
    Vertex v1 = boost::add_vertex(std::string("v1"), g); 
    Vertex v2 = boost::add_vertex(std::string("v2"), g); 
    Vertex v3 = boost::add_vertex(std::string("v3"), g); 

    Weight weight0 = 5; 
    Weight weight1 = 3; 
    Weight weight2 = 2; 
    Weight weight3 = 4; 

    boost::add_edge(v0, v1, weight0, g); 
    boost::add_edge(v1, v3, weight1, g); 
    boost::add_edge(v0, v2, weight2, g); 
    boost::add_edge(v2, v3, weight3, g); 


    std::vector<Vertex> predecessors(boost::num_vertices(g)); // To store parents 
    std::vector<Weight> distances(boost::num_vertices(g)); // To store distances 

    IndexMap indexMap; // = boost::get(boost::vertex_index, g); 
    NameMap name; 
    Viter i, iend; 
//Create our own vertex index. This is what I changed in the original code 
    int c = 0; 
    for (boost::tie(i, iend) = vertices(g); i != iend; ++i, ++c) { 
     indexMap[*i] = c; // **Error points to this line** 
     name[*i] = 'A' + c; 
    } 
PredecessorMap predecessorMap(&predecessors[0], indexMap); 
DistanceMap distanceMap(&distances[0], indexMap); 
boost::dijkstra_shortest_paths(g, v0, boost::distance_map(distanceMap).predecessor_map(predecessorMap)); 


    // Extract a shortest path 
    std::cout << std::endl; 
    typedef std::vector<Graph::edge_descriptor> PathType; 
    PathType path; 
    Vertex v = v3; 
    for(Vertex u = predecessorMap[v]; 
    u != v; // Keep tracking the path until we get to the source 
    v = u, u = predecessorMap[v]) // Set the current vertex to the current predecessor,  and the predecessor to one level up 
    { 
    std::pair<Graph::edge_descriptor, bool> edgePair = boost::edge(u, v, g); 
    Graph::edge_descriptor edge = edgePair.first; 
    path.push_back(edge); 
    } 

    // Write shortest path 
    std::cout << "Shortest path from v0 to v3:" << std::endl; 
    float totalDistance = 0; 
    for(PathType::reverse_iterator pathIterator = path.rbegin(); pathIterator !=  path.rend(); ++pathIterator) 
    { 
    std::cout << name[boost::source(*pathIterator, g)] << " -> " <<  name[boost::target(*pathIterator, g)] 
       << " = " << boost::get(boost::edge_weight, g, *pathIterator) <<  std::endl; 

    } 

    std::cout << std::endl; 

    std::cout << "Distance: " << distanceMap[v3] << std::endl; 

    return EXIT_SUCCESS; 
} 

我得到以下錯誤:

/spvec.cpp:62:20:錯誤:不對應的 '運營商=' 在「index.boost :: adj_list_vertex_property_map ::運算符[] [與圖= boost :: adjacency_list>,boost :: property>,ValueType = boost :: detail :: error_property_not_found,Reference = boost :: detail :: error_property_not_found &,Tag = boost :: vertex_index_t,boost :: adj_list_vertex_property_map :: key_type = void *](i.std :: _ List_iterator < _Tp> :: operator * with _Tp = void *,_Tp & = void * &)= c'

我相信我在創建自己的頂點索引時犯了一個錯誤。但無法確切地發現問題是什麼。有沒有人有什麼我做錯了一些建議..

+2

你能發佈錯誤嗎? – Dani

+0

不知道錯誤,它是乾草堆中的一根針,針甚至可能不在該代碼片段中。 –

回答

8

BGL實際上有使用dijkstra_shortest_paths使用列表/列表的例子,但它不是從HTML文檔鏈接到:http://www.boost.org/doc/libs/release/libs/graph/example/dijkstra-example-listS.cpp

錯誤消息是什麼試圖告訴你(error: no match for ‘operator=’ in ‘index.boost::adj_list_vertex_property_map...ValueType = boost::detail::error_property_not_found...)是不存在vertex_index_t屬性的每個頂點存儲,這是adj_list_vertex_property_map需要的。要解決該問題,您可以更改您的Graphtypedef以包含vertex_index_t屬性的每個頂點存儲,也可以使用「外部」屬性映射(如associative_property_map)。

dijkstra-example-listS.cpp示例使用更改圖形typedef的方法。要在代碼中使用這種方法,你可以定義:

typedef boost::adjacency_list <boost::listS, boost::listS, boost::directedS, 
    boost::property<boost::vertex_name_t, std::string, boost::property<boost::vertex_index_t, int> >, 
    boost::property<boost::edge_weight_t, Weight> > Graph; 
+0

我不想在示例中給出的圖頂點屬性內添加vertex_index_t屬性。這樣我就無法使用捆綁屬性方法。雖然上面的代碼不使用Bundled屬性,但我最終會使用它們。但正如你所建議的associative_property_map應該工作。我會嘗試。 – srkrish

6

如果有人有興趣的解決方案,創建associative_property_map如前面的答案建議解決的問題:

typedef std::map<vertex_desc, size_t>IndexMap; 
    IndexMap mapIndex; 
    boost::associative_property_map<IndexMap> propmapIndex(mapIndex); 
    //indexing the vertices 
    int i=0; 
    BGL_FORALL_VERTICES(v, g, pGraph) 
    { 
     boost::put(propmapIndex, v, i++); 
    } 

然後通過這作爲命名參數調用dijkstra_shortest_paths()調用的頂點索引映射。 PS:BGL_FORALL_VERTICES()定義在< boost/graph/iteration/iteration_macros.hpp>

+0

是否可以提供完整的代碼?前輩和距離地圖的index_map怎麼樣?你還必須把它們傳給propmapIndex?什麼是vdesc?它是矢量屬性嗎? – blakeO

+1

感謝此片段。我用它來創建一個vertex_index_map並將其傳遞給breadth_first_search函數。我發佈了一個工作示例:http://stackoverflow.com/a/43780529/779446 – opetroch