Bayeux  3.4.1
Core Foundation library for SuperNEMO
dependency_graph.h
Go to the documentation of this file.
1 /* Author(s): Francois Mauger <mauger@lpccaen.in2p3.fr>
3  * Creation date: 2017-06-09
4  * Last modified: 2017-06-18
5  *
6  * License:
7  *
8  * Copyright (C) 2017 Francois Mauger <mauger@lpccaen.in2p3.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  *
25  * Description:
26  *
27  * Dependency graph model.
28  * http://programmingexamples.net/wiki/Boost/BGL
29  * https://theboostcpplibraries.com/boost.graph-vertices-and-edges
30  * https://stackoverflow.com/questions/2244580/find-boost-bgl-vertex-by-a-key
31  * https://cpp.developpez.com/redaction/data/pages/users/gbdivers/boost-graph/
32  * http://matthieu-brucher.developpez.com/tutoriels/cpp/boost/graph/implementation/
33  * http://matthieu-brucher.developpez.com/tutoriels/cpp/boost/Property-Map/
34  *
35  */
36 
37 #ifndef DATATOOLS_DEPENDENCY_GRAPH_H
38 #define DATATOOLS_DEPENDENCY_GRAPH_H
39 
40 // Standard Library:
41 #include <string>
42 #include <iostream>
43 #include <set>
44 #include <memory>
45 
46 // Third party:
47 // - Boost:
48 #include <boost/config.hpp>
49 #include <boost/utility.hpp>
50 #include <boost/graph/graph_traits.hpp>
51 #include <boost/graph/adjacency_list.hpp>
52 #include <boost/graph/depth_first_search.hpp>
53 #include <boost/graph/breadth_first_search.hpp>
54 #include <boost/graph/properties.hpp>
55 #include <boost/graph/one_bit_color_map.hpp>
56 #include <boost/property_map/property_map.hpp>
57 
58 // This project:
59 #include <datatools/bit_mask.h>
60 
61 namespace datatools {
62 
65  {
66  public:
67 
69  {
70  std::string id;
71  std::string category;
73  : id("")
74  , category("") {}
75  vertex_properties_t(const std::string & id_, const std::string & category_)
76  : id(id_)
77  , category(category_) {}
78  };
79 
81  {
82  std::string topic;
84  : topic("") {}
85  edge_properties_t(const std::string & topic_)
86  : topic(topic_) {}
87  };
88 
90  {
91  std::string topic;
93  : topic("") {}
94  graph_properties_t(const std::string & topic_)
95  : topic(topic_) {}
96  };
97 
98  typedef typename boost::adjacency_list<
99  boost::vecS,
100  boost::vecS,
101  boost::bidirectionalS,
102  vertex_properties_t,
103  edge_properties_t,
104  graph_properties_t,
105  boost::listS
107  typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t;
108  typedef boost::graph_traits<graph_t>::edge_descriptor edge_t;
109  typedef boost::graph_traits<graph_t>::vertex_iterator vertex_iter_t;
110  typedef boost::graph_traits<graph_t>::edge_iterator edge_iter_t;
111  typedef boost::graph_traits<graph_t>::out_edge_iterator out_edge_iter_t;
112  typedef boost::graph_traits<graph_t>::in_edge_iterator in_edge_iter_t;
113 
116 
119 
121  bool has_vertex(const std::string & id_,
122  const std::string & category_ = "") const;
123 
125  void add_vertex(const std::string & id_,
126  const std::string & category_);
127 
129  void add_out_edge(const std::string & id_from_,
130  const std::string & id_to_,
131  const std::string & topic_);
132 
134  bool has_out_edge(const std::string & id1_,
135  const std::string & id2_,
136  const std::string & topic_ = "") const;
137 
139  void reset();
140 
143  : public boost::dfs_visitor<>
144  {
147  , _vertices(nullptr)
148  {
149  return;
150  }
151 
152  cycle_detector(std::set<vertex_t> & vertices_)
153  : _has_cycle(nullptr)
154  , _vertices(&vertices_)
155  {
156  if (_vertices->size()) _vertices->clear();
157  return;
158  }
159 
160  void back_edge(edge_t e_, const graph_t & g_)
161  {
162  // Once a cycle is detected (we pass through a back-edge), tag the cycle:
163  if (_vertices != nullptr) {
164  std::cerr << "[devel] Discovered cycle at back edge [" << e_<< "]" << std::endl;
165  _vertices->insert(boost::source(e_, g_));
166  _vertices->insert(boost::target(e_, g_));
167  }
168  if (_has_cycle != nullptr) {
169  *_has_cycle = true;
170  }
171  return;
172  }
173 
174  protected:
175 
176  bool * _has_cycle;
177  std::set<vertex_t> * _vertices = nullptr;
178 
179  };
180 
183  : public boost::dfs_visitor<>
184  {
185  public:
186 
188  : public std::exception
189  {
190  };
191 
192  typedef boost::one_bit_color_map<boost::identity_property_map> color_map_type;
193 
194  fvocf_visitor(std::set<std::string> & ids_,
195  const graph_t & g_,
196  const std::string & category_)
197  : _ids(ids_)
198  , _g(g_)
199  , _category(category_)
200  {
201  // _color_map_ptr.reset(new color_map_type(boost::num_vertices(_g)));
202  return;
203  }
204 
205  // // Vertex color is set to black
206  // void initialize_vertex(vertex_t v_, const graph_t & /*g_*/)
207  // {
208  // // boost::put(*_color_map_ptr,
209  // // v_,
210  // // boost::color_traits<boost::one_bit_color_type>::black());
211  // // std::cerr << "[devel] Initialize vertex [" << v_<< "]"<< std::endl;
212  // // if (_start == ) {
213  // // _start = v_;
214  // // }
215  // // with color " << boost::get(*_color_map_ptr, v_) << std::endl;
216  // return;
217  // }
218 
219  // // Start vertex color is set to white
220  // void start_vertex(vertex_t v_, const graph_t & /*g_*/)
221  // {
222  // // boost::put(*_color_map_ptr,
223  // // v_,
224  // // boost::color_traits<boost::one_bit_color_type>::white());
225  // // std::cerr << "[devel] Start vertex [" << v_ << "]" << std::endl;
226  // // with color " << boost::get(*_color_map_ptr, v_) << std::endl;
227  // return;
228  // }
229 
230  // void back_edge(edge_t e_, const graph_t & g_)
231  // {
232  // // std::cerr << "[devel] Back edge [" << boost::source(e_, g_) << "] -> [" << boost::target(e_, g_) << "]" << std::endl;
233  // // if (boost::source(e_, g_) == _start) {
234  // // std::cerr << "[devel] Back to start vertex: STOP!" << std::endl;
235  // // throw end_of_algo_exception();
236  // // }
237  // return;
238  // }
239 
240  // void examine_edge(edge_t e_, const graph_t & g_)
241  // {
242  // // std::cerr << "[devel] Found edge [" << boost::source(e_, g_) << "] -> [" << boost::target(e_, g_) << "]" << std::endl;
243  // return;
244  // }
245 
246  void discover_vertex(vertex_t v_, const graph_t & g_)
247  {
248  // std::cerr << "[devel] Discover vertex [" << v_<< "]" << std::endl;
249  if (_start == std::numeric_limits<vertex_t>::max()) {
250  // Record the start vertex:
251  _start = v_;
252  }
253  const vertex_properties_t & vp = g_[v_];
254  if (vp.category == _category) {
255  _ids.insert(vp.id);
256  // boost::put(*_color_map_ptr,
257  // v_,
258  // boost::color_traits<boost::one_bit_color_type>::white());
259  } else {
260 
261  }
262  return;
263  }
264 
265  void finish_vertex(vertex_t v_, const graph_t & /*g_*/)
266  {
267  // boost::put(*_color_map_ptr,
268  // v_,
269  // boost::color_traits<boost::one_bit_color_type>::black());
270  // std::cerr << "[devel] Finish vertex [" << v_<< "]" << std::endl;
271  if (v_ == _start) {
272  // std::cerr << "[devel] Back to start vertex [" << v_ << "]" << std::endl;
273  throw end_of_algo_exception();
274  }
275  return;
276  }
277 
278  protected:
279 
280  std::set<std::string> & _ids;
281  const graph_t & _g;
282  std::string _category;
283  vertex_t _start = std::numeric_limits<vertex_t>::max();
284  // std::shared_ptr<color_map_type> _color_map_ptr;
285 
286  };
287 
289  bool has_cycle() const;
290 
292  bool find_vertices_in_cycles(std::set<vertex_t> &) const;
293 
295  std::set<std::string> find_dependees_of_category_from(const std::string & depender_id_,
296  const std::string & category_) const;
297 
299  std::set<std::string> find_dependers_of_category_from(const std::string & dependee_id_,
300  const std::string & category_ = "",
301  const std::size_t depth_ = 0) const;
302 
304  void smart_print(std::ostream & out_) const;
305 
307  enum xgv_flags {
308  XGV_NONE = 0,
312  };
313 
315  void export_graphviz(std::ostream & out_, const uint32_t flags_ = 0) const;
316 
317  std::string get_vertex_id(const vertex_t) const;
318 
319  private:
320 
321  vertex_t _get_vertex_(const std::string & id_) const;
322 
324  void _find_dependers_of_category_from_(const vertex_t dependee_,
325  const std::string & category_,
326  const std::size_t depth_,
327  std::set<vertex_t> & visited_,
328  std::set<std::string> & dependers_) const;
329 
330  private:
331 
332  graph_t _g_;
333 
334  };
335 
336 } // end of namespace datatools
337 
338 #endif // DATATOOLS_DEPENDENCY_GRAPH_H
339 
340 // Local Variables: --
341 // mode: c++ --
342 // c-file-style: "gnu" --
343 // tab-width: 2 --
344 // End: --
boost::one_bit_color_map< boost::identity_property_map > color_map_type
Definition: dependency_graph.h:192
std::string topic
Topic associated to the edge.
Definition: dependency_graph.h:82
graph_properties_t()
Definition: dependency_graph.h:92
Print vertex category.
Definition: dependency_graph.h:310
graph_properties_t(const std::string &topic_)
Definition: dependency_graph.h:94
edge_properties_t()
Definition: dependency_graph.h:83
boost::graph_traits< graph_t >::out_edge_iterator out_edge_iter_t
Definition: dependency_graph.h:111
bool * _has_cycle
Definition: dependency_graph.h:176
std::string get_vertex_id(const vertex_t) const
std::string topic
Topic associated to the graph.
Definition: dependency_graph.h:91
boost::graph_traits< graph_t >::edge_iterator edge_iter_t
Definition: dependency_graph.h:110
Definition: dependency_graph.h:68
const graph_t & _g
Definition: dependency_graph.h:281
static const uint32_t bit01
Definition: bit_mask.h:28
Print edge topic.
Definition: dependency_graph.h:309
void export_graphviz(std::ostream &out_, const uint32_t flags_=0) const
Export graph to Graphviz dot format.
Print vertex index (debug)
Definition: dependency_graph.h:311
bool has_cycle() const
Check if some dependency cycle is detected.
Visitor for finding dependee vertices of given category.
Definition: dependency_graph.h:182
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, vertex_properties_t, edge_properties_t, graph_properties_t, boost::listS > graph_t
Definition: dependency_graph.h:106
Definition: dependency_graph.h:80
bool has_vertex(const std::string &id_, const std::string &category_="") const
Check it a vertex with given id and category.
std::string id
Unique name/identifier of the vertex.
Definition: dependency_graph.h:70
std::set< std::string > find_dependers_of_category_from(const std::string &dependee_id_, const std::string &category_="", const std::size_t depth_=0) const
Find all depender vertices of a given category from a starting dependee vertex.
xgv_flags
Export flags for Graphviz.
Definition: dependency_graph.h:307
void finish_vertex(vertex_t v_, const graph_t &)
Definition: dependency_graph.h:265
void back_edge(edge_t e_, const graph_t &g_)
Definition: dependency_graph.h:160
bool find_vertices_in_cycles(std::set< vertex_t > &) const
Find vertices belonging to cycles.
Visitor for cycle detection.
Definition: dependency_graph.h:142
Definition: dependency_graph.h:89
cycle_detector(bool &has_cycle)
Definition: dependency_graph.h:145
static const uint32_t bit02
Definition: bit_mask.h:29
std::set< std::string > & _ids
Definition: dependency_graph.h:280
void discover_vertex(vertex_t v_, const graph_t &g_)
Definition: dependency_graph.h:246
Dependency graph.
Definition: dependency_graph.h:64
vertex_properties_t(const std::string &id_, const std::string &category_)
Definition: dependency_graph.h:75
void add_out_edge(const std::string &id_from_, const std::string &id_to_, const std::string &topic_)
Add an out edge with given topic between to vertices.
vertex_properties_t()
Definition: dependency_graph.h:72
vertex_t _start
Definition: dependency_graph.h:283
No flags.
Definition: dependency_graph.h:308
The Bayeux/datatools library top-level namespace.
Definition: algo.h:13
boost::graph_traits< graph_t >::in_edge_iterator in_edge_iter_t
Definition: dependency_graph.h:112
cycle_detector(std::set< vertex_t > &vertices_)
Definition: dependency_graph.h:152
boost::graph_traits< graph_t >::vertex_descriptor vertex_t
Definition: dependency_graph.h:107
void smart_print(std::ostream &out_) const
Smart print.
static const uint32_t bit00
Definition: bit_mask.h:27
fvocf_visitor(std::set< std::string > &ids_, const graph_t &g_, const std::string &category_)
Definition: dependency_graph.h:194
dependency_graph()
Default constructor.
edge_properties_t(const std::string &topic_)
Definition: dependency_graph.h:85
bool has_out_edge(const std::string &id1_, const std::string &id2_, const std::string &topic_="") const
Check it an edge between two vertices exists with given topic.
void add_vertex(const std::string &id_, const std::string &category_)
Add a vertex with given id and category.
std::set< std::string > find_dependees_of_category_from(const std::string &depender_id_, const std::string &category_) const
Find all dependee vertices of a given category from a starting depender vertex.
std::string _category
Definition: dependency_graph.h:282
std::set< vertex_t > * _vertices
Definition: dependency_graph.h:177
std::string category
Category of the vertex.
Definition: dependency_graph.h:71
boost::graph_traits< graph_t >::vertex_iterator vertex_iter_t
Definition: dependency_graph.h:109
boost::graph_traits< graph_t >::edge_descriptor edge_t
Definition: dependency_graph.h:108