astar_search_test.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //
  2. //=======================================================================
  3. // Copyright (c) 2004 Kristopher Beevers
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //=======================================================================
  9. //
  10. #include <boost/graph/astar_search.hpp>
  11. #include <boost/graph/adjacency_list.hpp>
  12. #include <boost/graph/random.hpp>
  13. #include <boost/random.hpp>
  14. #include <utility>
  15. #include <vector>
  16. #include <list>
  17. #include <iostream>
  18. #include <math.h> // for sqrt
  19. #include <time.h>
  20. using namespace boost;
  21. using namespace std;
  22. // auxiliary types
  23. struct location
  24. {
  25. float y, x; // lat, long
  26. };
  27. struct my_float {float v; explicit my_float(float v = float()): v(v) {}};
  28. typedef my_float cost;
  29. ostream& operator<<(ostream& o, my_float f) {return o << f.v;}
  30. my_float operator+(my_float a, my_float b) {return my_float(a.v + b.v);}
  31. bool operator==(my_float a, my_float b) {return a.v == b.v;}
  32. bool operator<(my_float a, my_float b) {return a.v < b.v;}
  33. template <class Name, class LocMap>
  34. class city_writer {
  35. public:
  36. city_writer(Name n, LocMap l, float _minx, float _maxx,
  37. float _miny, float _maxy,
  38. unsigned int _ptx, unsigned int _pty)
  39. : name(n), loc(l), minx(_minx), maxx(_maxx), miny(_miny),
  40. maxy(_maxy), ptx(_ptx), pty(_pty) {}
  41. template <class Vertex>
  42. void operator()(ostream& out, const Vertex& v) const {
  43. float px = 1 - (loc[v].x - minx) / (maxx - minx);
  44. float py = (loc[v].y - miny) / (maxy - miny);
  45. out << "[label=\"" << name[v] << "\", pos=\""
  46. << static_cast<unsigned int>(ptx * px) << ","
  47. << static_cast<unsigned int>(pty * py)
  48. << "\", fontsize=\"11\"]";
  49. }
  50. private:
  51. Name name;
  52. LocMap loc;
  53. float minx, maxx, miny, maxy;
  54. unsigned int ptx, pty;
  55. };
  56. template <class WeightMap>
  57. class time_writer {
  58. public:
  59. time_writer(WeightMap w) : wm(w) {}
  60. template <class Edge>
  61. void operator()(ostream &out, const Edge& e) const {
  62. out << "[label=\"" << wm[e] << "\", fontsize=\"11\"]";
  63. }
  64. private:
  65. WeightMap wm;
  66. };
  67. // euclidean distance heuristic
  68. template <class Graph, class CostType, class LocMap>
  69. class distance_heuristic : public astar_heuristic<Graph, CostType>
  70. {
  71. public:
  72. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  73. distance_heuristic(LocMap l, Vertex goal)
  74. : m_location(l), m_goal(goal) {}
  75. CostType operator()(Vertex u)
  76. {
  77. float dx = m_location[m_goal].x - m_location[u].x;
  78. float dy = m_location[m_goal].y - m_location[u].y;
  79. return CostType(::sqrt(dx * dx + dy * dy));
  80. }
  81. private:
  82. LocMap m_location;
  83. Vertex m_goal;
  84. };
  85. struct found_goal {}; // exception for termination
  86. // visitor that terminates when we find the goal
  87. template <class Vertex>
  88. class astar_goal_visitor : public boost::default_astar_visitor
  89. {
  90. public:
  91. astar_goal_visitor(Vertex goal) : m_goal(goal) {}
  92. template <class Graph>
  93. void examine_vertex(Vertex u, Graph&) {
  94. if(u == m_goal)
  95. throw found_goal();
  96. }
  97. private:
  98. Vertex m_goal;
  99. };
  100. int main(int, char **)
  101. {
  102. // specify some types
  103. typedef adjacency_list<listS, vecS, undirectedS, no_property,
  104. property<edge_weight_t, cost> > mygraph_t;
  105. typedef property_map<mygraph_t, edge_weight_t>::type WeightMap;
  106. typedef mygraph_t::vertex_descriptor vertex;
  107. typedef mygraph_t::edge_descriptor edge_descriptor;
  108. typedef std::pair<int, int> edge;
  109. // specify data
  110. enum nodes {
  111. Troy, LakePlacid, Plattsburgh, Massena, Watertown, Utica,
  112. Syracuse, Rochester, Buffalo, Ithaca, Binghamton, Woodstock,
  113. NewYork, N
  114. };
  115. const char *name[] = {
  116. "Troy", "Lake Placid", "Plattsburgh", "Massena",
  117. "Watertown", "Utica", "Syracuse", "Rochester", "Buffalo",
  118. "Ithaca", "Binghamton", "Woodstock", "New York"
  119. };
  120. location locations[] = { // lat/long
  121. {42.73, 73.68}, {44.28, 73.99}, {44.70, 73.46},
  122. {44.93, 74.89}, {43.97, 75.91}, {43.10, 75.23},
  123. {43.04, 76.14}, {43.17, 77.61}, {42.89, 78.86},
  124. {42.44, 76.50}, {42.10, 75.91}, {42.04, 74.11},
  125. {40.67, 73.94}
  126. };
  127. edge edge_array[] = {
  128. edge(Troy,Utica), edge(Troy,LakePlacid),
  129. edge(Troy,Plattsburgh), edge(LakePlacid,Plattsburgh),
  130. edge(Plattsburgh,Massena), edge(LakePlacid,Massena),
  131. edge(Massena,Watertown), edge(Watertown,Utica),
  132. edge(Watertown,Syracuse), edge(Utica,Syracuse),
  133. edge(Syracuse,Rochester), edge(Rochester,Buffalo),
  134. edge(Syracuse,Ithaca), edge(Ithaca,Binghamton),
  135. edge(Ithaca,Rochester), edge(Binghamton,Troy),
  136. edge(Binghamton,Woodstock), edge(Binghamton,NewYork),
  137. edge(Syracuse,Binghamton), edge(Woodstock,Troy),
  138. edge(Woodstock,NewYork)
  139. };
  140. unsigned int num_edges = sizeof(edge_array) / sizeof(edge);
  141. cost weights[] = { // estimated travel time (mins)
  142. my_float(96), my_float(134), my_float(143), my_float(65), my_float(115), my_float(133), my_float(117), my_float(116), my_float(74), my_float(56),
  143. my_float(84), my_float(73), my_float(69), my_float(70), my_float(116), my_float(147), my_float(173), my_float(183), my_float(74), my_float(71), my_float(124)
  144. };
  145. // create graph
  146. mygraph_t g(N);
  147. WeightMap weightmap = get(edge_weight, g);
  148. for(std::size_t j = 0; j < num_edges; ++j) {
  149. edge_descriptor e; bool inserted;
  150. boost::tie(e, inserted) = add_edge(edge_array[j].first,
  151. edge_array[j].second, g);
  152. weightmap[e] = weights[j];
  153. }
  154. // pick random start/goal
  155. boost::minstd_rand gen(time(0));
  156. vertex start = gen() % num_vertices(g);
  157. vertex goal = gen() % num_vertices(g);
  158. cout << "Start vertex: " << name[start] << endl;
  159. cout << "Goal vertex: " << name[goal] << endl;
  160. vector<mygraph_t::vertex_descriptor> p(num_vertices(g));
  161. vector<cost> d(num_vertices(g));
  162. boost::property_map<mygraph_t, boost::vertex_index_t>::const_type
  163. idx = get(boost::vertex_index, g);
  164. try {
  165. // call astar named parameter interface
  166. astar_search
  167. (g, start,
  168. distance_heuristic<mygraph_t, cost, location*>
  169. (locations, goal),
  170. predecessor_map(make_iterator_property_map(p.begin(), idx)).
  171. distance_map(make_iterator_property_map(d.begin(), idx)).
  172. visitor(astar_goal_visitor<vertex>(goal)).distance_inf(my_float((std::numeric_limits<float>::max)())));
  173. } catch(found_goal fg) { // found a path to the goal
  174. list<vertex> shortest_path;
  175. for(vertex v = goal;; v = p[v]) {
  176. shortest_path.push_front(v);
  177. if(p[v] == v)
  178. break;
  179. }
  180. cout << "Shortest path from " << name[start] << " to "
  181. << name[goal] << ": ";
  182. list<vertex>::iterator spi = shortest_path.begin();
  183. cout << name[start];
  184. for(++spi; spi != shortest_path.end(); ++spi)
  185. cout << " -> " << name[*spi];
  186. cout << endl << "Total travel time: " << d[goal] << endl;
  187. return 0;
  188. }
  189. cout << "Didn't find a path from " << name[start] << "to"
  190. << name[goal] << "!" << endl;
  191. return 0;
  192. }