face_handles.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. //=======================================================================
  2. // Copyright (c) Aaron Windsor 2007
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //=======================================================================
  8. #ifndef __FACE_HANDLES_HPP__
  9. #define __FACE_HANDLES_HPP__
  10. #include <list>
  11. #include <boost/graph/graph_traits.hpp>
  12. #include <boost/shared_ptr.hpp>
  13. // A "face handle" is an optimization meant to serve two purposes in
  14. // the implementation of the Boyer-Myrvold planarity test: (1) it holds
  15. // the partial planar embedding of a particular vertex as it's being
  16. // constructed, and (2) it allows for efficient traversal around the
  17. // outer face of the partial embedding at that particular vertex. A face
  18. // handle is lightweight, just a shared pointer to the actual implementation,
  19. // since it is passed around/copied liberally in the algorithm. It consists
  20. // of an "anchor" (the actual vertex it's associated with) as well as a
  21. // sequence of edges. The functions first_vertex/second_vertex and
  22. // first_edge/second_edge allow fast access to the beginning and end of the
  23. // stored sequence, which allows one to traverse the outer face of the partial
  24. // planar embedding as it's being created.
  25. //
  26. // There are some policies below that define the contents of the face handles:
  27. // in the case no embedding is needed (for example, if one just wants to use
  28. // the Boyer-Myrvold algorithm as a true/false test for planarity, the
  29. // no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
  30. // either std_list (which uses as std::list) or recursive_lazy_list can be
  31. // passed as this policy. recursive_lazy_list has the best theoretical
  32. // performance (O(n) for a sequence of interleaved concatenations and reversals
  33. // of the underlying list), but I've noticed little difference between std_list
  34. // and recursive_lazy_list in my tests, even though using std_list changes
  35. // the worst-case complexity of the planarity test to O(n^2)
  36. //
  37. // Another policy is StoreOldHandlesPolicy, which specifies whether or not
  38. // to keep a record of the previous first/second vertex/edge - this is needed
  39. // if a Kuratowski subgraph needs to be isolated.
  40. namespace boost { namespace graph { namespace detail {
  41. //face handle policies
  42. //EmbeddingStorage policy
  43. struct store_embedding {};
  44. struct recursive_lazy_list : public store_embedding {};
  45. struct std_list : public store_embedding {};
  46. struct no_embedding {};
  47. //StoreOldHandlesPolicy
  48. struct store_old_handles {};
  49. struct no_old_handles {};
  50. template<typename DataType>
  51. struct lazy_list_node
  52. {
  53. typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
  54. lazy_list_node(const DataType& data) :
  55. m_reversed(false),
  56. m_data(data),
  57. m_has_data(true)
  58. {}
  59. lazy_list_node(ptr_t left_child, ptr_t right_child) :
  60. m_reversed(false),
  61. m_has_data(false),
  62. m_left_child(left_child),
  63. m_right_child(right_child)
  64. {}
  65. bool m_reversed;
  66. DataType m_data;
  67. bool m_has_data;
  68. shared_ptr<lazy_list_node> m_left_child;
  69. shared_ptr<lazy_list_node> m_right_child;
  70. };
  71. template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
  72. struct old_handles_storage;
  73. template <typename Vertex, typename Edge>
  74. struct old_handles_storage<store_old_handles, Vertex, Edge>
  75. {
  76. Vertex first_vertex;
  77. Vertex second_vertex;
  78. Edge first_edge;
  79. Edge second_edge;
  80. };
  81. template <typename Vertex, typename Edge>
  82. struct old_handles_storage<no_old_handles, Vertex, Edge>
  83. {};
  84. template <typename StoreEmbeddingPolicy, typename Edge>
  85. struct edge_list_storage;
  86. template <typename Edge>
  87. struct edge_list_storage<no_embedding, Edge>
  88. {
  89. typedef void type;
  90. void push_back(Edge) {}
  91. void push_front(Edge) {}
  92. void reverse() {}
  93. void concat_front(edge_list_storage<no_embedding,Edge>) {}
  94. void concat_back(edge_list_storage<no_embedding,Edge>) {}
  95. template <typename OutputIterator>
  96. void get_list(OutputIterator) {}
  97. };
  98. template <typename Edge>
  99. struct edge_list_storage<recursive_lazy_list, Edge>
  100. {
  101. typedef lazy_list_node<Edge> node_type;
  102. typedef shared_ptr< node_type > type;
  103. type value;
  104. void push_back(Edge e)
  105. {
  106. type new_node(new node_type(e));
  107. value = type(new node_type(value, new_node));
  108. }
  109. void push_front(Edge e)
  110. {
  111. type new_node(new node_type(e));
  112. value = type(new node_type(new_node, value));
  113. }
  114. void reverse()
  115. {
  116. value->m_reversed = !value->m_reversed;
  117. }
  118. void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
  119. {
  120. value = type(new node_type(other.value, value));
  121. }
  122. void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
  123. {
  124. value = type(new node_type(value, other.value));
  125. }
  126. template <typename OutputIterator>
  127. void get_list(OutputIterator out)
  128. {
  129. get_list_helper(out, value);
  130. }
  131. private:
  132. template <typename OutputIterator>
  133. void get_list_helper(OutputIterator o_itr,
  134. type root,
  135. bool flipped = false
  136. )
  137. {
  138. if (!root)
  139. return;
  140. if (root->m_has_data)
  141. *o_itr = root->m_data;
  142. if ((flipped && !root->m_reversed) ||
  143. (!flipped && root->m_reversed)
  144. )
  145. {
  146. get_list_helper(o_itr, root->m_right_child, true);
  147. get_list_helper(o_itr, root->m_left_child, true);
  148. }
  149. else
  150. {
  151. get_list_helper(o_itr, root->m_left_child, false);
  152. get_list_helper(o_itr, root->m_right_child, false);
  153. }
  154. }
  155. };
  156. template <typename Edge>
  157. struct edge_list_storage<std_list, Edge>
  158. {
  159. typedef std::list<Edge> type;
  160. type value;
  161. void push_back(Edge e)
  162. {
  163. value.push_back(e);
  164. }
  165. void push_front(Edge e)
  166. {
  167. value.push_front(e);
  168. }
  169. void reverse()
  170. {
  171. value.reverse();
  172. }
  173. void concat_front(edge_list_storage<std_list,Edge> other)
  174. {
  175. value.splice(value.begin(), other.value);
  176. }
  177. void concat_back(edge_list_storage<std_list, Edge> other)
  178. {
  179. value.splice(value.end(), other.value);
  180. }
  181. template <typename OutputIterator>
  182. void get_list(OutputIterator out)
  183. {
  184. std::copy(value.begin(), value.end(), out);
  185. }
  186. };
  187. template<typename Graph,
  188. typename StoreOldHandlesPolicy,
  189. typename StoreEmbeddingPolicy
  190. >
  191. struct face_handle_impl
  192. {
  193. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  194. typedef typename graph_traits<Graph>::edge_descriptor edge_t;
  195. typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
  196. edge_list_storage_t;
  197. face_handle_impl() :
  198. cached_first_vertex(graph_traits<Graph>::null_vertex()),
  199. cached_second_vertex(graph_traits<Graph>::null_vertex()),
  200. true_first_vertex(graph_traits<Graph>::null_vertex()),
  201. true_second_vertex(graph_traits<Graph>::null_vertex()),
  202. anchor(graph_traits<Graph>::null_vertex())
  203. {
  204. initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
  205. }
  206. void initialize_old_vertices_dispatch(store_old_handles)
  207. {
  208. old_handles.first_vertex = graph_traits<Graph>::null_vertex();
  209. old_handles.second_vertex = graph_traits<Graph>::null_vertex();
  210. }
  211. void initialize_old_vertices_dispatch(no_old_handles) {}
  212. vertex_t cached_first_vertex;
  213. vertex_t cached_second_vertex;
  214. vertex_t true_first_vertex;
  215. vertex_t true_second_vertex;
  216. vertex_t anchor;
  217. edge_t cached_first_edge;
  218. edge_t cached_second_edge;
  219. edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
  220. old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
  221. };
  222. template <typename Graph,
  223. typename StoreOldHandlesPolicy = store_old_handles,
  224. typename StoreEmbeddingPolicy = recursive_lazy_list
  225. >
  226. class face_handle
  227. {
  228. public:
  229. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  230. typedef typename graph_traits<Graph>::edge_descriptor edge_t;
  231. typedef face_handle_impl
  232. <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
  233. typedef face_handle
  234. <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
  235. face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
  236. pimpl(new impl_t())
  237. {
  238. pimpl->anchor = anchor;
  239. }
  240. face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
  241. pimpl(new impl_t())
  242. {
  243. vertex_t s(source(initial_edge,g));
  244. vertex_t t(target(initial_edge,g));
  245. vertex_t other_vertex = s == anchor ? t : s;
  246. pimpl->anchor = anchor;
  247. pimpl->cached_first_edge = initial_edge;
  248. pimpl->cached_second_edge = initial_edge;
  249. pimpl->cached_first_vertex = other_vertex;
  250. pimpl->cached_second_vertex = other_vertex;
  251. pimpl->true_first_vertex = other_vertex;
  252. pimpl->true_second_vertex = other_vertex;
  253. pimpl->edge_list.push_back(initial_edge);
  254. store_old_face_handles_dispatch(StoreOldHandlesPolicy());
  255. }
  256. //default copy construction, assignment okay.
  257. void push_first(edge_t e, const Graph& g)
  258. {
  259. pimpl->edge_list.push_front(e);
  260. pimpl->cached_first_vertex = pimpl->true_first_vertex =
  261. source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
  262. pimpl->cached_first_edge = e;
  263. }
  264. void push_second(edge_t e, const Graph& g)
  265. {
  266. pimpl->edge_list.push_back(e);
  267. pimpl->cached_second_vertex = pimpl->true_second_vertex =
  268. source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
  269. pimpl->cached_second_edge = e;
  270. }
  271. inline void store_old_face_handles()
  272. {
  273. store_old_face_handles_dispatch(StoreOldHandlesPolicy());
  274. }
  275. inline vertex_t first_vertex() const
  276. {
  277. return pimpl->cached_first_vertex;
  278. }
  279. inline vertex_t second_vertex() const
  280. {
  281. return pimpl->cached_second_vertex;
  282. }
  283. inline vertex_t true_first_vertex() const
  284. {
  285. return pimpl->true_first_vertex;
  286. }
  287. inline vertex_t true_second_vertex() const
  288. {
  289. return pimpl->true_second_vertex;
  290. }
  291. inline vertex_t old_first_vertex() const
  292. {
  293. return pimpl->old_handles.first_vertex;
  294. }
  295. inline vertex_t old_second_vertex() const
  296. {
  297. return pimpl->old_handles.second_vertex;
  298. }
  299. inline edge_t old_first_edge() const
  300. {
  301. return pimpl->old_handles.first_edge;
  302. }
  303. inline edge_t old_second_edge() const
  304. {
  305. return pimpl->old_handles.second_edge;
  306. }
  307. inline edge_t first_edge() const
  308. {
  309. return pimpl->cached_first_edge;
  310. }
  311. inline edge_t second_edge() const
  312. {
  313. return pimpl->cached_second_edge;
  314. }
  315. inline vertex_t get_anchor() const
  316. {
  317. return pimpl->anchor;
  318. }
  319. void glue_first_to_second
  320. (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
  321. {
  322. pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
  323. pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
  324. pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
  325. pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
  326. }
  327. void glue_second_to_first
  328. (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
  329. {
  330. pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
  331. pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
  332. pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
  333. pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
  334. }
  335. void flip()
  336. {
  337. pimpl->edge_list.reverse();
  338. std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
  339. std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
  340. std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
  341. }
  342. template <typename OutputIterator>
  343. void get_list(OutputIterator o_itr)
  344. {
  345. pimpl->edge_list.get_list(o_itr);
  346. }
  347. void reset_vertex_cache()
  348. {
  349. pimpl->cached_first_vertex = pimpl->true_first_vertex;
  350. pimpl->cached_second_vertex = pimpl->true_second_vertex;
  351. }
  352. inline void set_first_vertex(vertex_t v)
  353. {
  354. pimpl->cached_first_vertex = v;
  355. }
  356. inline void set_second_vertex(vertex_t v)
  357. {
  358. pimpl->cached_second_vertex = v;
  359. }
  360. private:
  361. void store_old_face_handles_dispatch(store_old_handles)
  362. {
  363. pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
  364. pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
  365. pimpl->old_handles.first_edge = pimpl->cached_first_edge;
  366. pimpl->old_handles.second_edge = pimpl->cached_second_edge;
  367. }
  368. void store_old_face_handles_dispatch(no_old_handles) {}
  369. boost::shared_ptr<impl_t> pimpl;
  370. };
  371. } /* namespace detail */ } /* namespace graph */ } /* namespace boost */
  372. #endif //__FACE_HANDLES_HPP__