2011-08-23 83 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