BALL  1.4.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
graphAlgorithms.h
Go to the documentation of this file.
1 #ifndef BALL_DATATYPE_GRAPH_GRAPHALGORITHMS_H
2 #define BALL_DATATYPE_GRAPH_GRAPHALGORITHMS_H
3 
4 #ifndef BALL_COMMON_GLOBAL_H
5 # include <BALL/COMMON/global.h>
6 #endif
7 
8 #ifndef BALL_COMMON_EXCEPTION_H
9 # include <BALL/COMMON/exception.h>
10 #endif
11 
12 #ifndef BALL_DATATYPE_STRING_H
13 # include <BALL/DATATYPE/string.h>
14 #endif
15 
16 #include <boost/graph/properties.hpp>
17 #include <boost/graph/graph_traits.hpp>
18 #include <boost/graph/adjacency_list.hpp>
19 #include <boost/graph/tree_traits.hpp>
20 #include <boost/graph/iteration_macros.hpp>
21 #include <boost/graph/copy.hpp>
22 #include <boost/shared_ptr.hpp>
23 
24 #include <iostream>
25 
26 namespace boost
27 {
30 
33 
34  BOOST_INSTALL_PROPERTY(vertex, atom_ptr);
35  BOOST_INSTALL_PROPERTY(vertex, orig_ptr);
36 
37  BOOST_INSTALL_PROPERTY(edge, bond_ptr);
38  BOOST_INSTALL_PROPERTY(edge, orig_ptr);
39 }
40 
41 namespace BALL
42 {
43  namespace GRAPH
44  {
45  template <class UndirectedGraph> class UndoEliminateOperation;
46 
54  {
55  public:
56  IllegalStateException(const char* file, int line, String message);
57  };
58 
64  {
65  public:
66  UnconnectedGraphException(const char * file, int line);
67  UnconnectedGraphException(const char * file, int line, BALL::String computation);
68  };
69 
73  template <class Graph>
75  {
76  public:
77  typedef typename boost::graph_traits<Graph>::vertex_descriptor VertexType;
78  typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIterator;
79  typedef typename boost::graph_traits<Graph>::adjacency_iterator NeighbourIterator;
80  typedef typename boost::graph_traits<Graph>::edge_descriptor EdgeType;
81 
82  // this defines an editable version of the graph, i.e., a graph with list-based storage types
83  // that has property maps on the edges and vertices pointing to edges and vertices of an instance
84  // of the original graph type
85  typedef boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS,
86  boost::property<boost::vertex_orig_ptr_t, VertexType,
87  boost::property<boost::vertex_index_t, int> >,
88  boost::property<boost::edge_orig_ptr_t, EdgeType> > EditableGraph;
89 
90  };
91 
92  template <typename Graph1, typename Graph2>
94  {
95  EditableEdgeCopier(const Graph1& /*g1*/, Graph2& g2)
96  : edge_orig_map(get(boost::edge_orig_ptr, g2))
97  {}
98 
99  template <typename Edge1, typename Edge2>
100  void operator()(const Edge1& e1, Edge2& e2) const
101  {
102  put(edge_orig_map, e2, e1);
103  }
104 
105  mutable typename boost::property_map<Graph2, boost::edge_orig_ptr_t>::type edge_orig_map;
106  };
107 
108  template <typename Graph1, typename Graph2>
110  makeEditableEdgeCopier(const Graph1& g1, Graph2& g2)
111  {
112  return EditableEdgeCopier<Graph1,Graph2>(g1, g2);
113  }
114 
115  template <typename Graph1, typename Graph2>
117  {
118  EditableVertexCopier(const Graph1& g1_, Graph2& g2_)
119  : vertex_orig_map(get(boost::vertex_orig_ptr, g2_)),
120  g1(g1_),
121  g2(g2_)
122  {}
123 
124  template <typename Vertex1, typename Vertex2>
125  void operator()(const Vertex1& v1, Vertex2& v2) const
126  {
127  boost::put(vertex_orig_map, v2, v1);
128  boost::put(boost::vertex_index, g2, v2, boost::get(boost::vertex_index, g1, v1));
129  }
130 
131  mutable typename boost::property_map<Graph2, boost::vertex_orig_ptr_t>::type vertex_orig_map;
132  Graph1 const& g1;
133  Graph2& g2;
134  };
135 
136  template <typename Graph1, typename Graph2>
138  makeEditableVertexCopier(const Graph1& g1, Graph2& g2)
139  {
141  }
142 
148  template <class UndirectedGraph>
149  void eliminateVertex(typename GraphTraits<UndirectedGraph>::VertexType& vertex, UndirectedGraph& graph)
150  {
151  typename GraphTraits<UndirectedGraph>::NeighbourIterator ai, bi, ai_end;
152 
153  for (tie(ai, ai_end) = adjacent_vertices(vertex, graph); ai != ai_end; ++ai)
154  {
155  bi = ai; ++bi;
156  for (; bi != ai_end; ++bi)
157  if (*bi != *ai && !boost::edge(*ai, *bi, graph).second)
158  boost::add_edge(*ai, *bi, graph);
159  }
160 
161  boost::clear_vertex(vertex, graph);
162  boost::remove_vertex(vertex, graph);
163  }
164 
173  template <class UndirectedGraph>
175  UndirectedGraph& graph)
176  {
177  typename GraphTraits<UndirectedGraph>::NeighbourIterator ai, bi, ai_end;
178  UndoEliminateOperation<UndirectedGraph> result(graph, vertex);
179 
180  for (tie(ai, ai_end) = adjacent_vertices(vertex, graph); ai != ai_end; ++ai)
181  {
182  result.getNeighbours().push_back(boost::get(boost::vertex_index, graph, *ai));
183 
184  typedef typename boost::property_traits<typename boost::property_map<UndirectedGraph, boost::edge_all_t>::type>::value_type EdgeProperties;
185 
186  result.getEdgeProperties().push_back(boost::get(boost::edge_all_t(), graph, boost::edge(vertex, *ai, graph).first));
187 
188  bi = ai; ++bi;
189  for (; bi != ai_end; ++bi)
190  {
191  if (!boost::edge(*ai, *bi, graph).second)
192  {
193  boost::add_edge(*ai, *bi, graph);
194  result.getEdges().push_back(std::make_pair(boost::get(boost::vertex_index, graph, *ai),
195  boost::get(boost::vertex_index, graph, *bi)));
196  }
197  }
198  }
199 
200  boost::clear_vertex(vertex, graph);
201  boost::remove_vertex(vertex, graph);
202 
203  return result;
204  }
205 
215  template <class UndirectedGraph>
216  class UndoEliminateOperation
217  {
218  public:
219  typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor VertexType;
220  typedef typename boost::graph_traits<UndirectedGraph>::edge_descriptor EdgeType;
221  typedef typename boost::graph_traits<UndirectedGraph>::adjacency_iterator NeighbourIterator;
222 
223  typedef typename boost::property_traits<typename boost::property_map<UndirectedGraph,
224  boost::vertex_all_t>::type>::value_type VertexProperties;
225  typedef typename boost::property_traits<typename boost::property_map<UndirectedGraph,
226  boost::edge_all_t>::type>::value_type EdgeProperties;
227 
231  UndoEliminateOperation(UndirectedGraph& graph, VertexType const& a);
232 
237 
243  VertexType undo();
244 
245  std::vector<std::pair<int, int> >& getEdges() { return edges_; }
246  std::vector<EdgeProperties>& getEdgeProperties() { return edge_properties_; }
247  std::vector<int>& getNeighbours() { return neighbours_; }
248 
249  protected:
250  UndirectedGraph* graph;
253  std::vector<std::pair<int, int> > edges_;
254  std::vector<EdgeProperties> edge_properties_;
255  std::vector<int> neighbours_;
256  bool applied;
257  };
258 
259  template <class UndirectedGraph>
261  : graph(&ugraph),
262  vertex(a),
263  edges_(),
264  neighbours_(),
265  applied(true)
266  {
267  vertex_properties_ = boost::get(boost::vertex_all_t(), ugraph, a);
268  }
269 
270  template <class UndirectedGraph>
273  {
274  return vertex;
275  }
276 
277  template <class UndirectedGraph>
279  {
280  if (!applied)
281  {
282  throw IllegalStateException(__FILE__, __LINE__, "Can't undo an elimination twice");
283  }
284 
285  applied = false;
286 
287  VertexType v = boost::add_vertex(vertex_properties_, *graph);
288 
289  std::map<int, VertexType> index_to_vertex;
290  BGL_FORALL_VERTICES_T(v, *graph, UndirectedGraph)
291  {
292  index_to_vertex[boost::get(boost::vertex_index, *graph, v)] = v;
293  }
294 
295  for (Position i=0; i<neighbours_.size(); ++i)
296  {
297  boost::add_edge(v, index_to_vertex[neighbours_[i]], edge_properties_[i], *graph);
298  }
299 
300  for (Position i=0; i<edges_.size(); ++i)
301  {
302  boost::remove_edge(index_to_vertex[edges_[i].first], index_to_vertex[edges_[i].second], *graph);
303  }
304 
305  return v;
306  }
307 
308  template <class UndirectedGraph>
309  void deepCopy(const UndirectedGraph& src, UndirectedGraph& target)
310  {
311  typedef std::map<typename boost::graph_traits<UndirectedGraph>::vertex_descriptor,int> VertexIndexMap;
312  typedef boost::associative_property_map<VertexIndexMap> VertexIndexPropertyMap;
313 
314  VertexIndexMap vertex_map;
315  VertexIndexPropertyMap vertex_property_map(vertex_map);
316 
317  typename boost::graph_traits<UndirectedGraph>::vertices_size_type count = 0;
318 
319  typename boost::graph_traits<UndirectedGraph>::vertex_iterator vi, vend;
320  for (boost::tie(vi, vend) = boost::vertices(src); vi != vend; ++vi)
321  vertex_map[*vi] = count++;
322 
323  boost::copy_graph(src, target, vertex_index_map(vertex_property_map));
324  }
325 
326  template <class Tree, class From, class To, class Functor>
328  {
329  public:
330  typedef typename Tree::children_iterator ChildrenIterator;
331 
332  typedef typename std::vector<To>::iterator ArgumentIterator;
333 
334  PostOrderFolding(Tree& tree, Functor& f)
335  : return_stack_(boost::shared_ptr<std::vector<To> >(new std::vector<To>())),
336  tree_(&tree),
337  f_(&f)
338  {
339  boost::traverse_tree(root(*tree_), *tree_, *this);
340  }
341 
343  {
344  return *return_stack_->begin();
345  }
346 
347  template <class Node>
348  void preorder(Node, Tree&)
349  {
350  }
351 
352  template <class Node>
353  void inorder(Node, Tree&)
354  {
355  }
356 
357  template <class Node>
358  void postorder(Node n, Tree& t)
359  {
360  ChildrenIterator c_i, c_end;
361  boost::tie(c_i, c_end) = children(n, t);
362 
363  bool is_leaf = (c_i == c_end);
364 
365  ArgumentIterator begin_arg = return_stack_->end();
366  ArgumentIterator end_arg = return_stack_->end();
367 
368  if (!is_leaf)
369  {
370  for (; c_i != c_end; ++c_i)
371  {
372  --begin_arg;
373  }
374  }
375 
376  To value = (*f_)(n, begin_arg, end_arg);
377 
378  if (begin_arg != end_arg)
379  {
380  return_stack_->erase(begin_arg, end_arg);
381  }
382 
383  return_stack_->push_back(value);
384  }
385 
386  protected:
387  boost::shared_ptr<std::vector<To> > return_stack_;
388 
389  Tree* tree_;
390  Functor* f_;
391  };
392 
393  }
394 }
395 
396 #endif // BALL_DATATYPE_GRAPH_GRAPHALGORITHMS_H
397 
398