2011-08-23 4 views
9

Я довольно новичок в Boost graph. Я пытаюсь адаптировать пример для поиска алгоритма кратчайшего пути Dijkstra, который использовал VertexList = vecS. Я изменил контейнер вершин в ListS. Я узнал, что мы должны предоставить наш собственный vertex_index для работы алгоритма, если мы используем listS.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 :: оператор [] [с Graph = boost :: adjacency_list>, boost :: property>, ValueType = boost :: detail :: error_property_not_found, Reference = boost :: detail :: error_property_not_found &, тег = boost :: vertex_index_t, boost :: adj_list_vertex_property_map :: key_type = void *] (i.std :: _ List_iterator < _Tp> :: operator * с _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, чтобы включить хранилище per-vertex для объекта 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