HavoqGT
breadth_first_search.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Lawrence Livermore National Security, LLC.
3  * Produced at the Lawrence Livermore National Laboratory.
4  * Written by Roger Pearce <rpearce@llnl.gov>.
5  * LLNL-CODE-644630.
6  * All rights reserved.
7  *
8  * This file is part of HavoqGT, Version 0.1.
9  * For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
10  *
11  * Please also read this link – Our Notice and GNU Lesser General Public License.
12  * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
13  *
14  * This program is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License (as published by the Free
16  * Software Foundation) version 2.1 dated February 1999.
17  *
18  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
20  * PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
28  *
29  * Our Preamble Notice
30  *
31  * A. This notice is required to be provided under our contract with the
32  * U.S. Department of Energy (DOE). This work was produced at the Lawrence
33  * Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
34  *
35  * B. Neither the United States Government nor Lawrence Livermore National
36  * Security, LLC nor any of their employees, makes any warranty, express or
37  * implied, or assumes any liability or responsibility for the accuracy,
38  * completeness, or usefulness of any information, apparatus, product, or process
39  * disclosed, or represents that its use would not infringe privately-owned rights.
40  *
41  * C. Also, reference herein to any specific commercial products, process, or
42  * services by trade name, trademark, manufacturer or otherwise does not
43  * necessarily constitute or imply its endorsement, recommendation, or favoring by
44  * the United States Government or Lawrence Livermore National Security, LLC. The
45  * views and opinions of authors expressed herein do not necessarily state or
46  * reflect those of the United States Government or Lawrence Livermore National
47  * Security, LLC, and shall not be used for advertising or product endorsement
48  * purposes.
49  *
50  */
51 
52 #ifndef HAVOQGT_MPI_BREADTH_FIRST_SEARCH_HPP_INCLUDED
53 #define HAVOQGT_MPI_BREADTH_FIRST_SEARCH_HPP_INCLUDED
54 
55 
57 #include <boost/container/deque.hpp>
58 
59 namespace havoqgt { namespace mpi {
60 
61 
62 template <typename Visitor>
64 {
65 
66 protected:
67  std::priority_queue< Visitor, std::deque<Visitor>,
68  std::greater<Visitor> > m_data;
69 public:
71 
72  bool push(Visitor const & task)
73  {
74  m_data.push(task);
75  return true;
76  }
77 
78  void pop()
79  {
80  m_data.pop();
81  }
82 
83  Visitor const & top() //const
84  {
85  return m_data.top();
86  }
87 
88  size_t size() const
89  {
90  return m_data.size();;
91  }
92 
93  bool empty() const
94  {
95  return m_data.empty();
96  }
97 
98  void clear()
99  {
100  m_data.clear();
101  }
102 };
103 
104 template <typename Visitor>
106 {
107 public:
108  typedef uint32_t level_number_type;
109  typedef typename boost::container::deque<Visitor>::size_type size_type;
110 
111 protected:
112  std::vector<boost::container::deque<Visitor> > m_vec_bfs_level_stack;
113  level_number_type m_cur_min_level;
114  size_type m_size;
115 public:
116  bfs_queue() : m_vec_bfs_level_stack(20), m_cur_min_level(std::numeric_limits<level_number_type>::max()), m_size(0) { }
117 
118  bool push(Visitor const & task)
119  {
120  while(task.level() >= m_vec_bfs_level_stack.size()) {
121  m_vec_bfs_level_stack.push_back(boost::container::deque<Visitor>());
122  }
123  m_vec_bfs_level_stack[task.level()].push_back(task);
124  ++m_size;
125  m_cur_min_level = std::min(m_cur_min_level, (uint32_t)task.level());
126  return true;
127  }
128 
129  void pop()
130  {
131  m_vec_bfs_level_stack[m_cur_min_level].pop_back();
132  --m_size;
133  if(m_vec_bfs_level_stack[m_cur_min_level].empty()) {
134  //if now empty, find next level;
135  for(;m_cur_min_level < m_vec_bfs_level_stack.size(); ++m_cur_min_level) {
136  if(!m_vec_bfs_level_stack[m_cur_min_level].empty()) break;
137  }
138  }
139  }
140 
141  Visitor const & top() //const
142  {
143  return m_vec_bfs_level_stack[m_cur_min_level].back();
144  }
145 
146  size_type size() const
147  {
148  return m_size;
149  }
150 
151  bool empty() const
152  {
153  return (m_size == 0);
154  }
155 
156  void clear()
157  {
158  for(typename std::vector<boost::container::deque<Visitor> >::iterator itr = m_vec_bfs_level_stack.begin();
159  itr != m_vec_bfs_level_stack.end(); ++itr) {
160  itr->clear();
161  }
162  m_size = 0;
163  m_cur_min_level = std::numeric_limits<level_number_type>::max();
164  }
165 };
166 
167 
168 
169 template<typename Graph, typename LevelData, typename ParentData>
170 class bfs_visitor {
171 public:
172  typedef typename Graph::vertex_locator vertex_locator;
173  bfs_visitor(): m_level(std::numeric_limits<uint64_t>::max()) { }
174  bfs_visitor(vertex_locator _vertex, uint64_t _level, vertex_locator _parent)
175  : vertex(_vertex)
176  , m_parent(_parent)
177  , m_level(_level) { }
178 
179  bfs_visitor(vertex_locator _vertex)
180  : vertex(_vertex)
181  , m_parent(_vertex)
182  , m_level(0) { }
183 
184 
185  bool pre_visit() const {
186  bool do_visit = (*level_data())[vertex] > level();
187  if(do_visit) {
188  (*level_data())[vertex] = level();
189  }
190  return do_visit;
191  }
192 
193  template<typename VisitorQueueHandle>
194  bool visit(Graph& g, VisitorQueueHandle vis_queue) const {
195  if(level() <= (*level_data())[vertex]) {
196  (*level_data())[vertex] = level();
197  (*parent_data())[vertex] = parent();
198 
199  typedef typename Graph::edge_iterator eitr_type;
200  for(eitr_type eitr = g.edges_begin(vertex); eitr != g.edges_end(vertex); ++eitr) {
201  vertex_locator neighbor = eitr.target();
202  //std::cout << "Visiting neighbor: " << g.locator_to_label(neighbor) << std::endl;
203  bfs_visitor new_visitor(neighbor, level() + 1,
204  vertex);
205  vis_queue->queue_visitor(new_visitor);
206  }
207  return true;
208  }
209  return false;
210  }
211 
212  uint64_t level() const { return m_level; }
213  vertex_locator parent() const { return m_parent; }
214 
215  friend inline bool operator>(const bfs_visitor& v1, const bfs_visitor& v2) {
216  //return v1.level() > v2.level();
217  if(v1.level() > v2.level())
218  {
219  return true;
220  } else if(v1.level() < v2.level())
221  {
222  return false;
223  }
224  return !(v1.vertex < v2.vertex);
225  }
226 
227  // friend inline bool operator<(const bfs_visitor& v1, const bfs_visitor& v2) {
228  // return v1.level() < v2.level();
229  // }
230 
231  static void set_level_data(LevelData* _data) { level_data() = _data; }
232 
233  static LevelData*& level_data() {
234  static LevelData* data;
235  return data;
236  }
237 
238  static void set_parent_data(ParentData* _data) { parent_data() = _data; }
239  static ParentData*& parent_data() {
240  static ParentData* data;
241  return data;
242  }
243  vertex_locator vertex;
244  //uint64_t m_parent : 40;
245  vertex_locator m_parent;
246  uint64_t m_level : 8;
247 } __attribute__ ((packed));
248 
249 
250 template <typename TGraph, typename LevelData, typename ParentData>
251 void breadth_first_search(TGraph* g,
252  LevelData& level_data,
253  ParentData& parent_data,
254  typename TGraph::vertex_locator s) {
255 
256  typedef bfs_visitor<TGraph, LevelData, ParentData> visitor_type;
257  visitor_type::set_level_data(&level_data);
258  visitor_type::set_parent_data(&parent_data);
260 
261  visitor_queue_type vq(g);
262  vq.init_visitor_traversal(s);
263 }
264 
265 
266 
267 }} //end namespace havoqgt::mpi
268 
269 
270 
271 
272 #endif //HAVOQGT_MPI_BREADTH_FIRST_SEARCH_HPP_INCLUDED
static void set_parent_data(ParentData *_data)
static void set_level_data(LevelData *_data)
static LevelData *& level_data()
friend bool operator>(const bfs_visitor &v1, const bfs_visitor &v2)
static ParentData *& parent_data()
std::vector< boost::container::deque< Visitor > > m_vec_bfs_level_stack
Graph::vertex_locator vertex_locator
bfs_visitor(vertex_locator _vertex)
bool push(Visitor const &task)
bfs_visitor(vertex_locator _vertex, uint64_t _level, vertex_locator _parent)
bool visit(Graph &g, VisitorQueueHandle vis_queue) const
std::priority_queue< Visitor, std::deque< Visitor >, std::greater< Visitor > > m_data
vertex_locator parent() const
void breadth_first_search(TGraph *g, LevelData &level_data, ParentData &parent_data, typename TGraph::vertex_locator s)
boost::container::deque< Visitor >::size_type size_type