OSSIA
Open Scenario System for Interactive Application
breadth_first_search.hpp
1 #pragma once
2 #include <boost/graph/adjacency_list.hpp>
3 #include <boost/graph/breadth_first_search.hpp>
4 
5 namespace boost
6 {
7 template <typename IndexMap = identity_property_map>
8 struct two_bit_color_map_fast
9 {
10  std::size_t n;
11  IndexMap index;
12  mutable std::vector<unsigned char> data;
13 
14  BOOST_STATIC_CONSTANT(int, bits_per_char = std::numeric_limits<unsigned char>::digits);
15  BOOST_STATIC_CONSTANT(int, elements_per_char = bits_per_char / 2);
16  typedef typename property_traits<IndexMap>::key_type key_type;
17  typedef two_bit_color_type value_type;
18  typedef void reference;
19  typedef read_write_property_map_tag category;
20 
21  explicit two_bit_color_map_fast(std::size_t n, const IndexMap& index = IndexMap())
22  : n(n)
23  , index(index)
24  , data((n + elements_per_char - 1) / elements_per_char)
25  {
26  // Fill to white
27  std::fill(data.begin(), data.end(), 0);
28  }
29 
30  void resize(std::size_t n)
31  {
32  this->n = n;
33  data.resize((n + elements_per_char - 1) / elements_per_char);
34  std::fill(data.begin(), data.end(), 0);
35  }
36 };
37 
38 template <typename IndexMap>
39 inline two_bit_color_type
40 get(const two_bit_color_map_fast<IndexMap>& pm,
41  typename property_traits<IndexMap>::key_type key)
42 {
43  BOOST_STATIC_CONSTANT(
44  int, elements_per_char = two_bit_color_map_fast<IndexMap>::elements_per_char);
45  typename property_traits<IndexMap>::value_type i = get(pm.index, key);
46  BOOST_ASSERT((std::size_t)i < pm.n);
47 
48  std::size_t byte_num = i / elements_per_char;
49  std::size_t bit_position = ((i % elements_per_char) * 2);
50 
51  return two_bit_color_type((pm.data[byte_num] >> bit_position) & 3);
52 }
53 
54 template <typename IndexMap>
55 inline void
56 put(const two_bit_color_map_fast<IndexMap>& pm,
57  typename property_traits<IndexMap>::key_type key, two_bit_color_type value)
58 {
59  BOOST_STATIC_CONSTANT(
60  int, elements_per_char = two_bit_color_map_fast<IndexMap>::elements_per_char);
61  typename property_traits<IndexMap>::value_type i = get(pm.index, key);
62  BOOST_ASSERT((std::size_t)i < pm.n);
63  BOOST_ASSERT(value >= 0 && value < 4);
64 
65  std::size_t byte_num = i / elements_per_char;
66  std::size_t bit_position = ((i % elements_per_char) * 2);
67 
68  pm.data[byte_num]
69  = (unsigned char)((pm.data[byte_num] & ~(3 << bit_position)) | (value << bit_position));
70 }
71 
72 template <typename IndexMap>
73 inline two_bit_color_map_fast<IndexMap>
74 make_two_bit_color_map_fast(std::size_t n, const IndexMap& index_map)
75 {
76  return two_bit_color_map_fast<IndexMap>(n, index_map);
77 }
78 
79 } // end namespace boost
80 
81 namespace ossia::bfs
82 {
83 template <
84  class IncidenceGraph, class Vertex, class Buffer, class BFSVisitor, class ColorMap>
85 void breadth_first_visit_simple(
86  const IncidenceGraph& g, Vertex source, Buffer& Q, BFSVisitor& vis, ColorMap& color)
87 {
88  using namespace boost;
89  using GTraits = graph_traits<IncidenceGraph>;
90  typename GTraits::out_edge_iterator ei, ei_end;
91 
92  BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<IncidenceGraph>));
93 
94  put(color, source, two_bit_gray);
95  vis.discover_vertex(source, g);
96  Q.push_back(source);
97 
98  while(!Q.empty())
99  {
100  Vertex u = Q.front();
101  Q.pop_front();
102  for(std::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
103  {
104  Vertex v = target(*ei, g);
105  auto v_color = get(color, v);
106  if(v_color == two_bit_white)
107  {
108  put(color, v, two_bit_gray);
109  if(vis.discover_vertex(v, g))
110  return;
111  Q.push_back(v);
112  }
113  }
114  put(color, source, two_bit_black);
115  }
116 }
117 
118 template <class VertexListGraph, class Visitor, class Queue, class ColorMap>
119 void breadth_first_search_simple(
120  const VertexListGraph& g,
121  typename boost::graph_traits<VertexListGraph>::vertex_descriptor s, Visitor& vis,
122  Queue& Q, ColorMap& color)
123 {
124  using namespace boost;
125  // auto color = make_two_bit_color_map_fast(boost::num_vertices(g),
126  // choose_const_pmap(get_param(vis, vertex_index), g, vertex_index));
127  // make_two_bit_color_map_fast(boost::num_vertices(g), vertex_index);
128  typename boost::graph_traits<VertexListGraph>::vertex_iterator i, i_end;
129  for(boost::tie(i, i_end) = vertices(g); i != i_end; ++i)
130  put(color, *i, two_bit_white);
131 
132  breadth_first_visit_simple(g, s, Q, vis, color);
133 }
134 }