...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
// Named parameter interface template <typename VertexListGraph, typename AStarHeuristic, typename P, typename T, typename R> void astar_search (VertexListGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, const bgl_named_params<P, T, R>& params); // Non-named parameter interface template <typename VertexListGraph, typename AStarHeuristic, typename AStarVisitor, typename PredecessorMap, typename CostMap, typename DistanceMap, typename WeightMap, typename VertexIndexMap, typename ColorMap, typename CompareFunction, typename CombineFunction, typename CostInf, typename CostZero> inline void astar_search (VertexListGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, AStarVisitor vis, PredecessorMap predecessor, CostMap cost, DistanceMap distance, WeightMap weight, VertexIndexMap index_map, ColorMap color, CompareFunction compare, CombineFunction combine, CostInf inf, CostZero zero);
This algorithm implements a heuristic search on a weighted, directed or undirected graph for the case where all edge weights are non-negative.
The A* algorithm is a heuristic graph search algorithm: an A* search is "guided" by a heuristic function. A heuristic function h(v) is one which estimates the cost from a non-goal state (v) in the graph to some goal state, g. Intuitively, A* follows paths (through the graph) to the goal that are estimated by the heuristic function to be the best paths. Unlike best-first search, A* takes into account the known cost from the start of the search to v; the paths A* takes are guided by a function f(v) = g(v) + h(v), where h(v) is the heuristic function, and g(v) (sometimes denoted c(s, v)) is the known cost from the start to v. Clearly, the efficiency of A* is highly dependent on the heuristic function with which it is used.
The A* algorithm is very similar to Dijkstra's Shortest Paths algorithm. This implementation finds all the shortest paths from the start vertex to every other vertex by creating a search tree, examining vertices according to their remaining cost to some goal, as estimated by a heuristic function. Most commonly, A* is used to find some specific goal vertex or vertices in a graph, after which the search is terminated.
A* is particularly useful for searching implicit graphs. Implicit graphs are graphs that are not completely known at the beginning of the search. Upon visiting a vertex, its neighbors are "generated" and added to the search. Implicit graphs are particularly useful for searching large state spaces -- in gameplaying scenarios (e.g. chess), for example -- in which it may not be possible to store the entire graph. Implicit searches can be performed with this implementation of A* by creating special visitors that generate neighbors of newly-expanded vertices.
This implementation of A* is based on an OPEN/CLOSED list formulation of the algorithm. Vertices on the OPEN list have been ``discovered'' by the algorithm, but not ``expanded'' (we have not discovered their adjacent vertices). Vertices on the CLOSED list have been completely examined by our search (we have expanded them and added their children to the OPEN list). Vertices that are on neither list have not been encountered in any context so far in our search. A major advantage of this formulation of the A* algorithm over other approaches is that it avoids ``cycles'' in the state space; the search will not become trapped by loops in the graph. The OPEN/CLOSED lists are implemented using BGL's vertex coloring mechanisms. Vertices in OPEN are colored gray, vertices in CLOSED are colored black, and undiscovered vertices are colored white.
The criteria for expanding a vertex on the OPEN list is that it has the lowest f(v) = g(v) + h(v) value of all vertices on OPEN. Cost information about vertices is stored in a property map.
The following is the pseudocode for the A* heuristic search algorithm. In the pseudocode, h is the heuristic function, w is the edge weight, d is the distance of a vertex from s, and Q is a priority queue, sorted by f, the estimated cost to the goal of the path through a vertex. p is a predecessor map. The visitor event points for the algorithm are indicated by the labels on the right.
A*(G, s, h) for each vertex u in V d[u] := f[u] := infinity color[u] := WHITE p[u] := u end for color[s] := GRAY d[s] := 0 f[s] := h(s) INSERT(Q, s) while (Q != Ø) u := EXTRACT-MIN(Q) for each vertex v in Adj[u] if (w(u,v) + d[u] < d[v]) d[v] := w(u,v) + d[u] f[v] := d[v] + h(v) p[v] := u if (color[v] = WHITE) color[v] := GRAY INSERT(Q, v) else if (color[v] = BLACK) color[v] := GRAY INSERT(Q, v) end if else ... end for color[u] := BLACK end while |
initialize vertex u discover vertex s examine vertex u examine edge (u,v) edge (u,v) relaxed discover vertex v reopen vertex v edge (u,v) not relaxed finish vertex u |
The graph object on which the algorithm will be applied. The type VertexListGraph must be a model of the Vertex List Graph concept.IN: vertex_descriptor s
The start vertex for the search. All distances will be calculated from this vertex, and the shortest paths tree (recorded in the predecessor map) will be rooted at this vertex.IN: AStarHeuristic h
The heuristic function that guides the search. The type AStarHeuristic must be a model of the AStarHeuristic concept.
The weight or ``length'' of each edge in the graph. The weights must all be non-negative; the algorithm will throw a negative_edge exception if one of the edges is negative. The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight map. The value type for this map must be the same as the value type of the distance map.IN: vertex_index_map(VertexIndexMap i_map)
Default: get(edge\_weight, g)
This maps each vertex to an integer in the range [0, num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.OUT: predecessor_map(PredecessorMap p_map)
Default: get(vertex_index, g). Note: if you use this default, make sure your graph has an internal vertex_index property. For example, adjacenty_list with VertexList=listS does not have an internal vertex_index property.
The predecessor map records the edges in the minimum spanning tree. Upon completion of the algorithm, the edges (p[u],u) for all u in V are in the minimum spanning tree. If p[u] = u then u is either the start vertex or a vertex that is not reachable from the start. The PredecessorMap type must be a Read/Write Property Map with key and vertex types the same as the vertex descriptor type of the graph.UTIL/OUT: distance_map(DistanceMap d_map)
Default: dummy_property_map
The shortest path weight from the start vertex s to each vertex in the graph g is recorded in this property map. The shortest path weight is the sum of the edge weights along the shortest path. The type DistanceMap must be a model of Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. The value type of the distance map is the element type of a Monoid formed with the combine function object and the zero object for the identity element. Also the distance value type must have a StrictWeakOrdering provided by the compare function object.UTIL/OUT: rank_map(CostMap c_map)
Default: iterator_property_map created from a std::vector with the same value type as the WeightMap, and of size num_vertices(g), and using the i_map for the index map.
The f-value for each vertex. The f-value is defined as the sum of the cost to get to a vertex from the start vertex, and the estimated cost (as returned by the heuristic function h) from the vertex to a goal. The type CostMap must be a model of Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. The value type of the distance map is the element type of a Monoid formed with the combine function object and the zero object for the identity element. Also the distance value type must have a StrictWeakOrdering provided by the compare function object. The value type for this map must be the same as the value type for the distance map.UTIL/OUT: color_map(ColorMap c_map)
Default: iterator_property_map created from a std::vector with the same value type as the WeightMap, and of size num_vertices(g), and using the i_map for the index map.
This is used during the execution of the algorithm to mark the vertices, indicating whether they are on the OPEN or CLOSED lists. The vertices start out white and become gray when they are inserted into the OPEN list. They then turn black when they are examined and placed on the CLOSED list. At the end of the algorithm, vertices reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.IN: distance_compare(CompareFunction cmp)
Default: iterator_property_map created from a std::vector of value type default_color_type, with size num_vertices(g), and using the i_map for the index map.
This function is use to compare distances to determine which vertex is closer to the start vertex, and to compare f-values to determine which vertex on the OPEN list to examine next. The CompareFunction type must be a model of Binary Predicate and have argument types that match the value type of the DistanceMap property map.IN: distance_combine(CombineFunction cmb)
Default: std::less<D> with D = typename property_traits<DistanceMap>::value_type.
This function is used to combine distances to compute the distance of a path, and to combine distance and heuristic values to compute the f-value of a vertex. The CombineFunction type must be a model of Binary Function. Both argument types of the binary function must match the value type of the DistanceMap property map (which is the same as that of the WeightMap and CostMap property maps). The result type must be the same type as the distance value type.IN: distance_inf(D inf)
Default: std::plus<D> with D = typename property_traits<DistanceMap>::value_type.
The inf object must be the greatest value of any D object. That is, compare(d, inf) == true for any d != inf. The type D is the value type of the DistanceMap.IN: distance_zero(D zero)
Default: std::numeric_limits<D>::max()
The zero value must be the identity element for the Monoid formed by the distance values and the combine function object. The type D is the value type of the DistanceMap.OUT: visitor(AStarVisitor v)
Default: D() with D = typename property_traits<DistanceMap>::value_type.
Use this to specify actions that you would like to happen during certain event points within the algorithm. The type AStarVisitor must be a model of the AStarVisitor concept. The visitor object is passed by value [1].
Default: astar_visitor<null_visitor>
The time complexity is O((E + V) log V).
See example/astar-cities.cpp for an example of using A* search.
Copyright © 2004 | Kristopher Beevers, Rensselaer Polytechnic Institute (beevek@cs.rpi.edu) |