/Src/Dependencies/Boost/boost/graph/metric_tsp_approx.hpp

http://hadesmem.googlecode.com/ · C++ Header · 314 lines · 218 code · 50 blank · 46 comment · 9 complexity · 20e25880554f0831f6e63016d44a064e MD5 · raw file

  1. //=======================================================================
  2. // Copyright 2008
  3. // Author: Matyas W Egyhazy
  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. #ifndef BOOST_GRAPH_METRIC_TSP_APPROX_HPP
  10. #define BOOST_GRAPH_METRIC_TSP_APPROX_HPP
  11. // metric_tsp_approx
  12. // Generates an approximate tour solution for the traveling salesperson
  13. // problem in polynomial time. The current algorithm guarantees a tour with a
  14. // length at most as long as 2x optimal solution. The graph should have
  15. // 'natural' (metric) weights such that the triangle inequality is maintained.
  16. // Graphs must be fully interconnected.
  17. // TODO:
  18. // There are a couple of improvements that could be made.
  19. // 1) Change implementation to lower uppper bound Christofides heuristic
  20. // 2) Implement a less restrictive TSP heuristic (one that does not rely on
  21. // triangle inequality).
  22. // 3) Determine if the algorithm can be implemented without creating a new
  23. // graph.
  24. #include <vector>
  25. #include <boost/shared_ptr.hpp>
  26. #include <boost/concept_check.hpp>
  27. #include <boost/graph/graph_traits.hpp>
  28. #include <boost/graph/graph_as_tree.hpp>
  29. #include <boost/graph/adjacency_list.hpp>
  30. #include <boost/graph/prim_minimum_spanning_tree.hpp>
  31. #include <boost/graph/lookup_edge.hpp>
  32. #include <boost/throw_exception.hpp>
  33. namespace boost
  34. {
  35. // Define a concept for the concept-checking library.
  36. template <typename Visitor, typename Graph>
  37. struct TSPVertexVisitorConcept
  38. {
  39. private:
  40. Visitor vis_;
  41. public:
  42. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  43. BOOST_CONCEPT_USAGE(TSPVertexVisitorConcept)
  44. {
  45. Visitor vis(vis_); // require copy construction
  46. Graph g(1);
  47. Vertex v(*vertices(g).first);
  48. vis_.visit_vertex(v, g); // require visit_vertex
  49. }
  50. };
  51. // Tree visitor that keeps track of a preorder traversal of a tree
  52. // TODO: Consider migrating this to the graph_as_tree header.
  53. // TODO: Parameterize the underlying stores o it doesn't have to be a vector.
  54. template<typename Node, typename Tree> class PreorderTraverser
  55. {
  56. private:
  57. std::vector<Node>& path_;
  58. public:
  59. typedef typename std::vector<Node>::const_iterator const_iterator;
  60. PreorderTraverser(std::vector<Node>& p) : path_(p) {}
  61. void preorder(Node n, const Tree&)
  62. { path_.push_back(n); }
  63. void inorder(Node, const Tree&) const {}
  64. void postorder(Node, const Tree&) const {}
  65. const_iterator begin() const { return path_.begin(); }
  66. const_iterator end() const { return path_.end(); }
  67. };
  68. // Forward declarations
  69. template <typename> class tsp_tour_visitor;
  70. template <typename, typename, typename, typename> class tsp_tour_len_visitor;
  71. template<typename VertexListGraph, typename OutputIterator>
  72. void metric_tsp_approx_tour(VertexListGraph& g, OutputIterator o)
  73. {
  74. metric_tsp_approx_from_vertex(g, *vertices(g).first,
  75. get(edge_weight, g), get(vertex_index, g),
  76. tsp_tour_visitor<OutputIterator>(o));
  77. }
  78. template<typename VertexListGraph, typename WeightMap, typename OutputIterator>
  79. void metric_tsp_approx_tour(VertexListGraph& g, WeightMap w, OutputIterator o)
  80. {
  81. metric_tsp_approx_from_vertex(g, *vertices(g).first,
  82. w, tsp_tour_visitor<OutputIterator>(o));
  83. }
  84. template<typename VertexListGraph, typename OutputIterator>
  85. void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
  86. typename graph_traits<VertexListGraph>::vertex_descriptor start,
  87. OutputIterator o)
  88. {
  89. metric_tsp_approx_from_vertex(g, start, get(edge_weight, g),
  90. get(vertex_index, g), tsp_tour_visitor<OutputIterator>(o));
  91. }
  92. template<typename VertexListGraph, typename WeightMap,
  93. typename OutputIterator>
  94. void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
  95. typename graph_traits<VertexListGraph>::vertex_descriptor start,
  96. WeightMap w, OutputIterator o)
  97. {
  98. metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g),
  99. tsp_tour_visitor<OutputIterator>(o));
  100. }
  101. template<typename VertexListGraph, typename TSPVertexVisitor>
  102. void metric_tsp_approx(VertexListGraph& g, TSPVertexVisitor vis)
  103. {
  104. metric_tsp_approx_from_vertex(g, *vertices(g).first,
  105. get(edge_weight, g), get(vertex_index, g), vis);
  106. }
  107. template<typename VertexListGraph, typename Weightmap,
  108. typename VertexIndexMap, typename TSPVertexVisitor>
  109. void metric_tsp_approx(VertexListGraph& g, Weightmap w,
  110. TSPVertexVisitor vis)
  111. {
  112. metric_tsp_approx_from_vertex(g, *vertices(g).first, w,
  113. get(vertex_index, g), vis);
  114. }
  115. template<typename VertexListGraph, typename WeightMap,
  116. typename VertexIndexMap, typename TSPVertexVisitor>
  117. void metric_tsp_approx(VertexListGraph& g, WeightMap w, VertexIndexMap id,
  118. TSPVertexVisitor vis)
  119. {
  120. metric_tsp_approx_from_vertex(g, *vertices(g).first, w, id, vis);
  121. }
  122. template<typename VertexListGraph, typename WeightMap,
  123. typename TSPVertexVisitor>
  124. void metric_tsp_approx_from_vertex(VertexListGraph& g,
  125. typename graph_traits<VertexListGraph>::vertex_descriptor start,
  126. WeightMap w, TSPVertexVisitor vis)
  127. {
  128. metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), vis);
  129. }
  130. template <
  131. typename VertexListGraph,
  132. typename WeightMap,
  133. typename VertexIndexMap,
  134. typename TSPVertexVisitor>
  135. void metric_tsp_approx_from_vertex(const VertexListGraph& g,
  136. typename graph_traits<VertexListGraph>::vertex_descriptor start,
  137. WeightMap weightmap,
  138. VertexIndexMap indexmap,
  139. TSPVertexVisitor vis)
  140. {
  141. using namespace boost;
  142. using namespace std;
  143. BOOST_CONCEPT_ASSERT((VertexListGraphConcept<VertexListGraph>));
  144. BOOST_CONCEPT_ASSERT((TSPVertexVisitorConcept<TSPVertexVisitor, VertexListGraph>));
  145. // Types related to the input graph (GVertex is a template parameter).
  146. typedef typename graph_traits<VertexListGraph>::vertex_descriptor GVertex;
  147. typedef typename graph_traits<VertexListGraph>::vertex_iterator GVItr;
  148. // We build a custom graph in this algorithm.
  149. typedef adjacency_list <vecS, vecS, directedS, no_property, no_property > MSTImpl;
  150. typedef graph_traits<MSTImpl>::edge_descriptor Edge;
  151. typedef graph_traits<MSTImpl>::vertex_descriptor Vertex;
  152. typedef graph_traits<MSTImpl>::vertex_iterator VItr;
  153. // And then re-cast it as a tree.
  154. typedef iterator_property_map<vector<Vertex>::iterator, property_map<MSTImpl, vertex_index_t>::type> ParentMap;
  155. typedef graph_as_tree<MSTImpl, ParentMap> Tree;
  156. typedef tree_traits<Tree>::node_descriptor Node;
  157. // A predecessor map.
  158. typedef vector<GVertex> PredMap;
  159. typedef iterator_property_map<typename PredMap::iterator, VertexIndexMap> PredPMap;
  160. PredMap preds(num_vertices(g));
  161. PredPMap pred_pmap(preds.begin(), indexmap);
  162. // Compute a spanning tree over the in put g.
  163. prim_minimum_spanning_tree(g, pred_pmap,
  164. root_vertex(start)
  165. .vertex_index_map(indexmap)
  166. .weight_map(weightmap));
  167. // Build a MST using the predecessor map from prim mst
  168. MSTImpl mst(num_vertices(g));
  169. std::size_t cnt = 0;
  170. pair<VItr, VItr> mst_verts(vertices(mst));
  171. for(typename PredMap::iterator vi(preds.begin()); vi != preds.end(); ++vi, ++cnt)
  172. {
  173. if(indexmap[*vi] != cnt) {
  174. add_edge(*next(mst_verts.first, indexmap[*vi]),
  175. *next(mst_verts.first, cnt), mst);
  176. }
  177. }
  178. // Build a tree abstraction over the MST.
  179. vector<Vertex> parent(num_vertices(mst));
  180. Tree t(mst, *vertices(mst).first,
  181. make_iterator_property_map(parent.begin(),
  182. get(vertex_index, mst)));
  183. // Create tour using a preorder traversal of the mst
  184. vector<Node> tour;
  185. PreorderTraverser<Node, Tree> tvis(tour);
  186. traverse_tree(0, t, tvis);
  187. pair<GVItr, GVItr> g_verts(vertices(g));
  188. for(PreorderTraverser<Node, Tree>::const_iterator curr(tvis.begin());
  189. curr != tvis.end(); ++curr)
  190. {
  191. // TODO: This is will be O(n^2) if vertex storage of g != vecS.
  192. GVertex v = *next(g_verts.first, get(vertex_index, mst)[*curr]);
  193. vis.visit_vertex(v, g);
  194. }
  195. // Connect back to the start of the tour
  196. vis.visit_vertex(*g_verts.first, g);
  197. }
  198. // Default tsp tour visitor that puts the tour in an OutputIterator
  199. template <typename OutItr>
  200. class tsp_tour_visitor
  201. {
  202. OutItr itr_;
  203. public:
  204. tsp_tour_visitor(OutItr itr)
  205. : itr_(itr)
  206. { }
  207. template <typename Vertex, typename Graph>
  208. void visit_vertex(Vertex v, const Graph&)
  209. {
  210. BOOST_CONCEPT_ASSERT((OutputIterator<OutItr, Vertex>));
  211. *itr_++ = v;
  212. }
  213. };
  214. // Tsp tour visitor that adds the total tour length.
  215. template<typename Graph, typename WeightMap, typename OutIter, typename Length>
  216. class tsp_tour_len_visitor
  217. {
  218. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  219. BOOST_CONCEPT_ASSERT((OutputIterator<OutIter, Vertex>));
  220. OutIter iter_;
  221. Length& tourlen_;
  222. WeightMap& wmap_;
  223. Vertex previous_;
  224. // Helper function for getting the null vertex.
  225. Vertex null()
  226. { return graph_traits<Graph>::null_vertex(); }
  227. public:
  228. tsp_tour_len_visitor(Graph const&, OutIter iter, Length& l, WeightMap map)
  229. : iter_(iter), tourlen_(l), wmap_(map), previous_(null())
  230. { }
  231. void visit_vertex(Vertex v, const Graph& g)
  232. {
  233. typedef typename graph_traits<Graph>::edge_descriptor Edge;
  234. // If it is not the start, then there is a
  235. // previous vertex
  236. if(previous_ != null())
  237. {
  238. // NOTE: For non-adjacency matrix graphs g, this bit of code
  239. // will be linear in the degree of previous_ or v. A better
  240. // solution would be to visit edges of the graph, but that
  241. // would require revisiting the core algorithm.
  242. Edge e;
  243. bool found;
  244. boost::tie(e, found) = lookup_edge(previous_, v, g);
  245. if(!found) {
  246. BOOST_THROW_EXCEPTION(not_complete());
  247. }
  248. tourlen_ += wmap_[e];
  249. }
  250. previous_ = v;
  251. *iter_++ = v;
  252. }
  253. };
  254. // Object generator(s)
  255. template <typename OutIter>
  256. inline tsp_tour_visitor<OutIter>
  257. make_tsp_tour_visitor(OutIter iter)
  258. { return tsp_tour_visitor<OutIter>(iter); }
  259. template <typename Graph, typename WeightMap, typename OutIter, typename Length>
  260. inline tsp_tour_len_visitor<Graph, WeightMap, OutIter, Length>
  261. make_tsp_tour_len_visitor(Graph const& g, OutIter iter, Length& l, WeightMap map)
  262. { return tsp_tour_len_visitor<Graph, WeightMap, OutIter, Length>(g, iter, l, map); }
  263. } //boost
  264. #endif // BOOST_GRAPH_METRIC_TSP_APPROX_HPP