I am quite new to Boost graph. I am trying to adapt an example for finding Dijkstra Shortest Path algorithm which used VertexList = vecS. I changed the vertex container to ListS. I learned that we have to provide our own vertex_index for the algorithm to work if we use 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;
}
I get the following error:
/spvec.cpp:62:20: error: no match for ‘operator=’ in ‘index.boost::adj_list_vertex_property_map::operator[] [with Graph = 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’
I am sure I made a mistake in creating my own vertex index. But couldn´t find out exactly what´s the issue. Does anyone have some suggestions on what I am doing wrong..
Dijkstra itself has no problem with 0 weight, per definition of the algorithm. It only gets problematic with negative weights. Since in every round Dijkstra will settle a node. If you later find a negative weighted edge, this could lead to a shorter path to that settled node.
Dijkstra's algorithm solves the shortest-path problem for any weighted, directed graph with non-negative weights. It can handle graphs consisting of cycles, but negative weights will cause this algorithm to produce incorrect results.
Look at all nodes directly adjacent to the starting node. The values carried by the edges connecting the start and these adjacent nodes are the shortest distances to each respective node.
BGL actually has an example of using dijkstra_shortest_paths
with listS/listS, but it's not linked to from the HTML documentation: http://www.boost.org/doc/libs/release/libs/graph/example/dijkstra-example-listS.cpp
What the error message is trying to tell you (error: no match for ‘operator=’ in ‘index.boost::adj_list_vertex_property_map...ValueType = boost::detail::error_property_not_found...
) is that there is no per-vertex storage for the vertex_index_t
property, which is what adj_list_vertex_property_map
needs. To fix the problem you can either change your Graph
typedef
to include per-vertex storage for the vertex_index_t
property or use an "external" property map such as associative_property_map
.
The dijkstra-example-listS.cpp
example uses the approach of changing the graph typedef
. To use this approach in your code, you could define:
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;
If somebody is interested in the solution, Creating an associative_property_map as suggested in the previous answer solved the issue:
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++);
}
Then pass this Vertex index map to the dijkstra_shortest_paths() call as a named parameter. PS: BGL_FORALL_VERTICES() is defined in < boost/graph/iteration/iteration_macros.hpp >
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With