Chris@16
|
1 //=======================================================================
|
Chris@16
|
2 // Copyright 2001 University of Notre Dame.
|
Chris@16
|
3 // Authors: Jeremy G. Siek and Lie-Quan Lee
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //=======================================================================
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_SUBGRAPH_HPP
|
Chris@16
|
11 #define BOOST_SUBGRAPH_HPP
|
Chris@16
|
12
|
Chris@16
|
13 // UNDER CONSTRUCTION
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/config.hpp>
|
Chris@16
|
16 #include <list>
|
Chris@16
|
17 #include <vector>
|
Chris@16
|
18 #include <map>
|
Chris@16
|
19 #include <boost/assert.hpp>
|
Chris@16
|
20 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
21 #include <boost/graph/graph_mutability_traits.hpp>
|
Chris@16
|
22 #include <boost/graph/properties.hpp>
|
Chris@16
|
23 #include <boost/iterator/indirect_iterator.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/static_assert.hpp>
|
Chris@16
|
26 #include <boost/assert.hpp>
|
Chris@16
|
27 #include <boost/type_traits.hpp>
|
Chris@16
|
28 #include <boost/mpl/if.hpp>
|
Chris@16
|
29 #include <boost/mpl/or.hpp>
|
Chris@16
|
30
|
Chris@16
|
31 namespace boost {
|
Chris@16
|
32
|
Chris@16
|
33 struct subgraph_tag { };
|
Chris@16
|
34
|
Chris@16
|
35 /** @name Property Lookup
|
Chris@16
|
36 * The local_property and global_property functions are used to create
|
Chris@16
|
37 * structures that determine the lookup strategy for properties in subgraphs.
|
Chris@16
|
38 * Note that the nested kind member is used to help interoperate with actual
|
Chris@16
|
39 * Property types.
|
Chris@16
|
40 */
|
Chris@16
|
41 //@{
|
Chris@16
|
42 template <typename T>
|
Chris@16
|
43 struct local_property
|
Chris@16
|
44 {
|
Chris@16
|
45 typedef T kind;
|
Chris@16
|
46 local_property(T x) : value(x) { }
|
Chris@16
|
47 T value;
|
Chris@16
|
48 };
|
Chris@16
|
49
|
Chris@16
|
50 template <typename T>
|
Chris@16
|
51 inline local_property<T> local(T x)
|
Chris@16
|
52 { return local_property<T>(x); }
|
Chris@16
|
53
|
Chris@16
|
54 template <typename T>
|
Chris@16
|
55 struct global_property
|
Chris@16
|
56 {
|
Chris@16
|
57 typedef T kind;
|
Chris@16
|
58 global_property(T x) : value(x) { }
|
Chris@16
|
59 T value;
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@16
|
62 template <typename T>
|
Chris@16
|
63 inline global_property<T> global(T x)
|
Chris@16
|
64 { return global_property<T>(x); }
|
Chris@16
|
65 //@}
|
Chris@16
|
66
|
Chris@16
|
67 // Invariants of an induced subgraph:
|
Chris@16
|
68 // - If vertex u is in subgraph g, then u must be in g.parent().
|
Chris@16
|
69 // - If edge e is in subgraph g, then e must be in g.parent().
|
Chris@16
|
70 // - If edge e=(u,v) is in the root graph, then edge e
|
Chris@16
|
71 // is also in any subgraph that contains both vertex u and v.
|
Chris@16
|
72
|
Chris@16
|
73 // The Graph template parameter must have a vertex_index and edge_index
|
Chris@16
|
74 // internal property. It is assumed that the vertex indices are assigned
|
Chris@16
|
75 // automatically by the graph during a call to add_vertex(). It is not
|
Chris@16
|
76 // assumed that the edge vertices are assigned automatically, they are
|
Chris@16
|
77 // explicitly assigned here.
|
Chris@16
|
78
|
Chris@16
|
79 template <typename Graph>
|
Chris@16
|
80 class subgraph {
|
Chris@16
|
81 typedef graph_traits<Graph> Traits;
|
Chris@16
|
82 typedef std::list<subgraph<Graph>*> ChildrenList;
|
Chris@16
|
83 public:
|
Chris@16
|
84 // Graph requirements
|
Chris@16
|
85 typedef typename Traits::vertex_descriptor vertex_descriptor;
|
Chris@16
|
86 typedef typename Traits::edge_descriptor edge_descriptor;
|
Chris@16
|
87 typedef typename Traits::directed_category directed_category;
|
Chris@16
|
88 typedef typename Traits::edge_parallel_category edge_parallel_category;
|
Chris@16
|
89 typedef typename Traits::traversal_category traversal_category;
|
Chris@16
|
90
|
Chris@16
|
91 // IncidenceGraph requirements
|
Chris@16
|
92 typedef typename Traits::out_edge_iterator out_edge_iterator;
|
Chris@16
|
93 typedef typename Traits::degree_size_type degree_size_type;
|
Chris@16
|
94
|
Chris@16
|
95 // AdjacencyGraph requirements
|
Chris@16
|
96 typedef typename Traits::adjacency_iterator adjacency_iterator;
|
Chris@16
|
97
|
Chris@16
|
98 // VertexListGraph requirements
|
Chris@16
|
99 typedef typename Traits::vertex_iterator vertex_iterator;
|
Chris@16
|
100 typedef typename Traits::vertices_size_type vertices_size_type;
|
Chris@16
|
101
|
Chris@16
|
102 // EdgeListGraph requirements
|
Chris@16
|
103 typedef typename Traits::edge_iterator edge_iterator;
|
Chris@16
|
104 typedef typename Traits::edges_size_type edges_size_type;
|
Chris@16
|
105
|
Chris@16
|
106 typedef typename Traits::in_edge_iterator in_edge_iterator;
|
Chris@16
|
107
|
Chris@16
|
108 typedef typename edge_property_type<Graph>::type edge_property_type;
|
Chris@16
|
109 typedef typename vertex_property_type<Graph>::type vertex_property_type;
|
Chris@16
|
110 typedef subgraph_tag graph_tag;
|
Chris@16
|
111 typedef Graph graph_type;
|
Chris@16
|
112 typedef typename graph_property_type<Graph>::type graph_property_type;
|
Chris@16
|
113
|
Chris@16
|
114 // Create the main graph, the root of the subgraph tree
|
Chris@16
|
115 subgraph()
|
Chris@16
|
116 : m_parent(0), m_edge_counter(0)
|
Chris@16
|
117 { }
|
Chris@16
|
118
|
Chris@16
|
119 subgraph(const graph_property_type& p)
|
Chris@16
|
120 : m_graph(p), m_parent(0), m_edge_counter(0)
|
Chris@16
|
121 { }
|
Chris@16
|
122
|
Chris@16
|
123 subgraph(vertices_size_type n, const graph_property_type& p = graph_property_type())
|
Chris@16
|
124 : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
|
Chris@16
|
125 {
|
Chris@16
|
126 typename Graph::vertex_iterator v, v_end;
|
Chris@16
|
127 vertices_size_type i = 0;
|
Chris@16
|
128 for(boost::tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
|
Chris@16
|
129 m_global_vertex[i++] = *v;
|
Chris@16
|
130 }
|
Chris@16
|
131
|
Chris@16
|
132 // copy constructor
|
Chris@16
|
133 subgraph(const subgraph& x)
|
Chris@16
|
134 : m_parent(x.m_parent), m_edge_counter(x.m_edge_counter)
|
Chris@16
|
135 , m_global_vertex(x.m_global_vertex), m_global_edge(x.m_global_edge)
|
Chris@16
|
136 {
|
Chris@16
|
137 if(x.is_root())
|
Chris@16
|
138 {
|
Chris@16
|
139 m_graph = x.m_graph;
|
Chris@16
|
140 }
|
Chris@16
|
141 // Do a deep copy (recursive).
|
Chris@16
|
142 // Only the root graph is copied, the subgraphs contain
|
Chris@16
|
143 // only references to the global vertices they own.
|
Chris@16
|
144 typename subgraph<Graph>::children_iterator i,i_end;
|
Chris@16
|
145 boost::tie(i,i_end) = x.children();
|
Chris@16
|
146 for(; i != i_end; ++i)
|
Chris@16
|
147 {
|
Chris@16
|
148 subgraph<Graph> child = this->create_subgraph();
|
Chris@16
|
149 child = *i;
|
Chris@16
|
150 vertex_iterator vi,vi_end;
|
Chris@16
|
151 boost::tie(vi,vi_end) = vertices(*i);
|
Chris@16
|
152 for (;vi!=vi_end;++vi)
|
Chris@16
|
153 {
|
Chris@16
|
154 add_vertex(*vi,child);
|
Chris@16
|
155 }
|
Chris@16
|
156 }
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@16
|
159
|
Chris@16
|
160 ~subgraph() {
|
Chris@16
|
161 for(typename ChildrenList::iterator i = m_children.begin();
|
Chris@16
|
162 i != m_children.end(); ++i)
|
Chris@16
|
163 {
|
Chris@16
|
164 delete *i;
|
Chris@16
|
165 }
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 // Return a null vertex descriptor for the graph.
|
Chris@16
|
169 static vertex_descriptor null_vertex()
|
Chris@16
|
170 { return Traits::null_vertex(); }
|
Chris@16
|
171
|
Chris@16
|
172
|
Chris@16
|
173 // Create a subgraph
|
Chris@16
|
174 subgraph<Graph>& create_subgraph() {
|
Chris@16
|
175 m_children.push_back(new subgraph<Graph>());
|
Chris@16
|
176 m_children.back()->m_parent = this;
|
Chris@16
|
177 return *m_children.back();
|
Chris@16
|
178 }
|
Chris@16
|
179
|
Chris@16
|
180 // Create a subgraph with the specified vertex set.
|
Chris@16
|
181 template <typename VertexIterator>
|
Chris@16
|
182 subgraph<Graph>& create_subgraph(VertexIterator first, VertexIterator last) {
|
Chris@16
|
183 m_children.push_back(new subgraph<Graph>());
|
Chris@16
|
184 m_children.back()->m_parent = this;
|
Chris@16
|
185 for(; first != last; ++first) {
|
Chris@16
|
186 add_vertex(*first, *m_children.back());
|
Chris@16
|
187 }
|
Chris@16
|
188 return *m_children.back();
|
Chris@16
|
189 }
|
Chris@16
|
190
|
Chris@16
|
191 // local <-> global descriptor conversion functions
|
Chris@16
|
192 vertex_descriptor local_to_global(vertex_descriptor u_local) const
|
Chris@16
|
193 { return is_root() ? u_local : m_global_vertex[u_local]; }
|
Chris@16
|
194
|
Chris@16
|
195 vertex_descriptor global_to_local(vertex_descriptor u_global) const {
|
Chris@16
|
196 vertex_descriptor u_local; bool in_subgraph;
|
Chris@16
|
197 if (is_root()) return u_global;
|
Chris@16
|
198 boost::tie(u_local, in_subgraph) = this->find_vertex(u_global);
|
Chris@16
|
199 BOOST_ASSERT(in_subgraph == true);
|
Chris@16
|
200 return u_local;
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 edge_descriptor local_to_global(edge_descriptor e_local) const
|
Chris@16
|
204 { return is_root() ? e_local : m_global_edge[get(get(edge_index, m_graph), e_local)]; }
|
Chris@16
|
205
|
Chris@16
|
206 edge_descriptor global_to_local(edge_descriptor e_global) const
|
Chris@16
|
207 { return is_root() ? e_global : (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; }
|
Chris@16
|
208
|
Chris@16
|
209 // Is vertex u (of the root graph) contained in this subgraph?
|
Chris@16
|
210 // If so, return the matching local vertex.
|
Chris@16
|
211 std::pair<vertex_descriptor, bool>
|
Chris@16
|
212 find_vertex(vertex_descriptor u_global) const {
|
Chris@16
|
213 if (is_root()) return std::make_pair(u_global, true);
|
Chris@16
|
214 typename LocalVertexMap::const_iterator i = m_local_vertex.find(u_global);
|
Chris@16
|
215 bool valid = i != m_local_vertex.end();
|
Chris@16
|
216 return std::make_pair((valid ? (*i).second : null_vertex()), valid);
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 // Is edge e (of the root graph) contained in this subgraph?
|
Chris@16
|
220 // If so, return the matching local edge.
|
Chris@16
|
221 std::pair<edge_descriptor, bool>
|
Chris@16
|
222 find_edge(edge_descriptor e_global) const {
|
Chris@16
|
223 if (is_root()) return std::make_pair(e_global, true);
|
Chris@16
|
224 typename LocalEdgeMap::const_iterator i =
|
Chris@16
|
225 m_local_edge.find(get(get(edge_index, root().m_graph), e_global));
|
Chris@16
|
226 bool valid = i != m_local_edge.end();
|
Chris@16
|
227 return std::make_pair((valid ? (*i).second : edge_descriptor()), valid);
|
Chris@16
|
228 }
|
Chris@16
|
229
|
Chris@16
|
230 // Return the parent graph.
|
Chris@16
|
231 subgraph& parent() { return *m_parent; }
|
Chris@16
|
232 const subgraph& parent() const { return *m_parent; }
|
Chris@16
|
233
|
Chris@16
|
234 // Return true if this is the root subgraph
|
Chris@16
|
235 bool is_root() const { return m_parent == 0; }
|
Chris@16
|
236
|
Chris@16
|
237 // Return the root graph of the subgraph tree.
|
Chris@16
|
238 subgraph& root()
|
Chris@16
|
239 { return is_root() ? *this : m_parent->root(); }
|
Chris@16
|
240
|
Chris@16
|
241 const subgraph& root() const
|
Chris@16
|
242 { return is_root() ? *this : m_parent->root(); }
|
Chris@16
|
243
|
Chris@16
|
244 // Return the children subgraphs of this graph/subgraph.
|
Chris@16
|
245 // Use a list of pointers because the VC++ std::list doesn't like
|
Chris@16
|
246 // storing incomplete type.
|
Chris@16
|
247 typedef indirect_iterator<
|
Chris@16
|
248 typename ChildrenList::const_iterator
|
Chris@16
|
249 , subgraph<Graph>
|
Chris@16
|
250 , std::bidirectional_iterator_tag
|
Chris@16
|
251 >
|
Chris@16
|
252 children_iterator;
|
Chris@16
|
253
|
Chris@16
|
254 typedef indirect_iterator<
|
Chris@16
|
255 typename ChildrenList::const_iterator
|
Chris@16
|
256 , subgraph<Graph> const
|
Chris@16
|
257 , std::bidirectional_iterator_tag
|
Chris@16
|
258 >
|
Chris@16
|
259 const_children_iterator;
|
Chris@16
|
260
|
Chris@16
|
261 std::pair<const_children_iterator, const_children_iterator> children() const {
|
Chris@16
|
262 return std::make_pair(const_children_iterator(m_children.begin()),
|
Chris@16
|
263 const_children_iterator(m_children.end()));
|
Chris@16
|
264 }
|
Chris@16
|
265
|
Chris@16
|
266 std::pair<children_iterator, children_iterator> children() {
|
Chris@16
|
267 return std::make_pair(children_iterator(m_children.begin()),
|
Chris@16
|
268 children_iterator(m_children.end()));
|
Chris@16
|
269 }
|
Chris@16
|
270
|
Chris@16
|
271 std::size_t num_children() const { return m_children.size(); }
|
Chris@16
|
272
|
Chris@16
|
273 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
Chris@16
|
274 // Defualt property access delegates the lookup to global properties.
|
Chris@16
|
275 template <typename Descriptor>
|
Chris@16
|
276 typename graph::detail::bundled_result<Graph, Descriptor>::type&
|
Chris@16
|
277 operator[](Descriptor x)
|
Chris@16
|
278 { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; }
|
Chris@16
|
279
|
Chris@16
|
280 template <typename Descriptor>
|
Chris@16
|
281 typename graph::detail::bundled_result<Graph, Descriptor>::type const&
|
Chris@16
|
282 operator[](Descriptor x) const
|
Chris@16
|
283 { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; }
|
Chris@16
|
284
|
Chris@16
|
285 // Local property access returns the local property of the given descripor.
|
Chris@16
|
286 template <typename Descriptor>
|
Chris@16
|
287 typename graph::detail::bundled_result<Graph, Descriptor>::type&
|
Chris@16
|
288 operator[](local_property<Descriptor> x)
|
Chris@16
|
289 { return m_graph[x.value]; }
|
Chris@16
|
290
|
Chris@16
|
291 template <typename Descriptor>
|
Chris@16
|
292 typename graph::detail::bundled_result<Graph, Descriptor>::type const&
|
Chris@16
|
293 operator[](local_property<Descriptor> x) const
|
Chris@16
|
294 { return m_graph[x.value]; }
|
Chris@16
|
295
|
Chris@16
|
296 // Global property access returns the global property associated with the
|
Chris@16
|
297 // given descriptor. This is an alias for the default bundled property
|
Chris@16
|
298 // access operations.
|
Chris@16
|
299 template <typename Descriptor>
|
Chris@16
|
300 typename graph::detail::bundled_result<Graph, Descriptor>::type&
|
Chris@16
|
301 operator[](global_property<Descriptor> x)
|
Chris@16
|
302 { return (*this)[x.value]; }
|
Chris@16
|
303
|
Chris@16
|
304 template <typename Descriptor>
|
Chris@16
|
305 typename graph::detail::bundled_result<Graph, Descriptor>::type const&
|
Chris@16
|
306 operator[](global_property<Descriptor> x) const
|
Chris@16
|
307 { return (*this)[x.value]; }
|
Chris@16
|
308
|
Chris@16
|
309 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
Chris@16
|
310
|
Chris@16
|
311 // private:
|
Chris@16
|
312 typedef typename property_map<Graph, edge_index_t>::type EdgeIndexMap;
|
Chris@16
|
313 typedef typename property_traits<EdgeIndexMap>::value_type edge_index_type;
|
Chris@16
|
314 BOOST_STATIC_ASSERT((!is_same<edge_index_type,
|
Chris@16
|
315 boost::detail::error_property_not_found>::value));
|
Chris@16
|
316
|
Chris@16
|
317 private:
|
Chris@16
|
318 typedef std::vector<vertex_descriptor> GlobalVertexList;
|
Chris@16
|
319 typedef std::vector<edge_descriptor> GlobalEdgeList;
|
Chris@16
|
320 typedef std::map<vertex_descriptor, vertex_descriptor> LocalVertexMap;
|
Chris@16
|
321 typedef std::map<edge_index_type, edge_descriptor> LocalEdgeMap;
|
Chris@16
|
322 // TODO: Should the LocalVertexMap be: map<index_type, descriptor>?
|
Chris@16
|
323 // TODO: Can we relax the indexing requirement if both descriptors are
|
Chris@16
|
324 // LessThanComparable?
|
Chris@16
|
325 // TODO: Should we really be using unorderd_map for improved lookup times?
|
Chris@16
|
326
|
Chris@16
|
327 public: // Probably shouldn't be public....
|
Chris@16
|
328 Graph m_graph;
|
Chris@16
|
329 subgraph<Graph>* m_parent;
|
Chris@16
|
330 edge_index_type m_edge_counter; // for generating unique edge indices
|
Chris@16
|
331 ChildrenList m_children;
|
Chris@16
|
332 GlobalVertexList m_global_vertex; // local -> global
|
Chris@16
|
333 LocalVertexMap m_local_vertex; // global -> local
|
Chris@16
|
334 GlobalEdgeList m_global_edge; // local -> global
|
Chris@16
|
335 LocalEdgeMap m_local_edge; // global -> local
|
Chris@16
|
336
|
Chris@16
|
337 edge_descriptor local_add_edge(vertex_descriptor u_local,
|
Chris@16
|
338 vertex_descriptor v_local,
|
Chris@16
|
339 edge_descriptor e_global)
|
Chris@16
|
340 {
|
Chris@16
|
341 edge_descriptor e_local;
|
Chris@16
|
342 bool inserted;
|
Chris@16
|
343 boost::tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
|
Chris@16
|
344 put(edge_index, m_graph, e_local, m_edge_counter++);
|
Chris@16
|
345 m_global_edge.push_back(e_global);
|
Chris@16
|
346 m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
|
Chris@16
|
347 return e_local;
|
Chris@16
|
348 }
|
Chris@16
|
349 };
|
Chris@16
|
350
|
Chris@16
|
351 template <typename Graph>
|
Chris@16
|
352 struct vertex_bundle_type<subgraph<Graph> >
|
Chris@16
|
353 : vertex_bundle_type<Graph>
|
Chris@16
|
354 { };
|
Chris@16
|
355
|
Chris@16
|
356 template<typename Graph>
|
Chris@16
|
357 struct edge_bundle_type<subgraph<Graph> >
|
Chris@16
|
358 : edge_bundle_type<Graph>
|
Chris@16
|
359 { };
|
Chris@16
|
360
|
Chris@16
|
361 template<typename Graph>
|
Chris@16
|
362 struct graph_bundle_type<subgraph<Graph> >
|
Chris@16
|
363 : graph_bundle_type<Graph>
|
Chris@16
|
364 { };
|
Chris@16
|
365
|
Chris@16
|
366 //===========================================================================
|
Chris@16
|
367 // Functions special to the Subgraph Class
|
Chris@16
|
368
|
Chris@16
|
369 template <typename G>
|
Chris@16
|
370 typename subgraph<G>::vertex_descriptor
|
Chris@16
|
371 add_vertex(typename subgraph<G>::vertex_descriptor u_global,
|
Chris@16
|
372 subgraph<G>& g)
|
Chris@16
|
373 {
|
Chris@16
|
374 BOOST_ASSERT(!g.is_root());
|
Chris@16
|
375 typename subgraph<G>::vertex_descriptor u_local, v_global;
|
Chris@16
|
376 typename subgraph<G>::edge_descriptor e_global;
|
Chris@16
|
377
|
Chris@16
|
378 u_local = add_vertex(g.m_graph);
|
Chris@16
|
379 g.m_global_vertex.push_back(u_global);
|
Chris@16
|
380 g.m_local_vertex[u_global] = u_local;
|
Chris@16
|
381
|
Chris@16
|
382 subgraph<G>& r = g.root();
|
Chris@16
|
383
|
Chris@16
|
384 // remember edge global and local maps
|
Chris@16
|
385 {
|
Chris@16
|
386 typename subgraph<G>::out_edge_iterator ei, ei_end;
|
Chris@16
|
387 for (boost::tie(ei, ei_end) = out_edges(u_global, r);
|
Chris@16
|
388 ei != ei_end; ++ei) {
|
Chris@16
|
389 e_global = *ei;
|
Chris@16
|
390 v_global = target(e_global, r);
|
Chris@16
|
391 if (g.find_vertex(v_global).second == true)
|
Chris@16
|
392 g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
|
Chris@16
|
393 }
|
Chris@16
|
394 }
|
Chris@16
|
395 if (is_directed(g)) { // not necessary for undirected graph
|
Chris@16
|
396 typename subgraph<G>::vertex_iterator vi, vi_end;
|
Chris@16
|
397 typename subgraph<G>::out_edge_iterator ei, ei_end;
|
Chris@16
|
398 for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
|
Chris@16
|
399 v_global = *vi;
|
Chris@16
|
400 if (v_global == u_global)
|
Chris@16
|
401 continue; // don't insert self loops twice!
|
Chris@16
|
402 if (!g.find_vertex(v_global).second)
|
Chris@16
|
403 continue; // not a subgraph vertex => try next one
|
Chris@16
|
404 for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
|
Chris@16
|
405 e_global = *ei;
|
Chris@16
|
406 if(target(e_global, r) == u_global) {
|
Chris@16
|
407 g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
|
Chris@16
|
408 }
|
Chris@16
|
409 }
|
Chris@16
|
410 }
|
Chris@16
|
411 }
|
Chris@16
|
412
|
Chris@16
|
413 return u_local;
|
Chris@16
|
414 }
|
Chris@16
|
415
|
Chris@16
|
416 // NOTE: Descriptors are local unless otherwise noted.
|
Chris@16
|
417
|
Chris@16
|
418 //===========================================================================
|
Chris@16
|
419 // Functions required by the IncidenceGraph concept
|
Chris@16
|
420
|
Chris@16
|
421 template <typename G>
|
Chris@16
|
422 std::pair<typename graph_traits<G>::out_edge_iterator,
|
Chris@16
|
423 typename graph_traits<G>::out_edge_iterator>
|
Chris@16
|
424 out_edges(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
425 { return out_edges(v, g.m_graph); }
|
Chris@16
|
426
|
Chris@16
|
427 template <typename G>
|
Chris@16
|
428 typename graph_traits<G>::degree_size_type
|
Chris@16
|
429 out_degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
430 { return out_degree(v, g.m_graph); }
|
Chris@16
|
431
|
Chris@16
|
432 template <typename G>
|
Chris@16
|
433 typename graph_traits<G>::vertex_descriptor
|
Chris@16
|
434 source(typename graph_traits<G>::edge_descriptor e, const subgraph<G>& g)
|
Chris@16
|
435 { return source(e, g.m_graph); }
|
Chris@16
|
436
|
Chris@16
|
437 template <typename G>
|
Chris@16
|
438 typename graph_traits<G>::vertex_descriptor
|
Chris@16
|
439 target(typename graph_traits<G>::edge_descriptor e, const subgraph<G>& g)
|
Chris@16
|
440 { return target(e, g.m_graph); }
|
Chris@16
|
441
|
Chris@16
|
442 //===========================================================================
|
Chris@16
|
443 // Functions required by the BidirectionalGraph concept
|
Chris@16
|
444
|
Chris@16
|
445 template <typename G>
|
Chris@16
|
446 std::pair<typename graph_traits<G>::in_edge_iterator,
|
Chris@16
|
447 typename graph_traits<G>::in_edge_iterator>
|
Chris@16
|
448 in_edges(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
449 { return in_edges(v, g.m_graph); }
|
Chris@16
|
450
|
Chris@16
|
451 template <typename G>
|
Chris@16
|
452 typename graph_traits<G>::degree_size_type
|
Chris@16
|
453 in_degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
454 { return in_degree(v, g.m_graph); }
|
Chris@16
|
455
|
Chris@16
|
456 template <typename G>
|
Chris@16
|
457 typename graph_traits<G>::degree_size_type
|
Chris@16
|
458 degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
459 { return degree(v, g.m_graph); }
|
Chris@16
|
460
|
Chris@16
|
461 //===========================================================================
|
Chris@16
|
462 // Functions required by the AdjacencyGraph concept
|
Chris@16
|
463
|
Chris@16
|
464 template <typename G>
|
Chris@16
|
465 std::pair<typename subgraph<G>::adjacency_iterator,
|
Chris@16
|
466 typename subgraph<G>::adjacency_iterator>
|
Chris@16
|
467 adjacent_vertices(typename subgraph<G>::vertex_descriptor v, const subgraph<G>& g)
|
Chris@16
|
468 { return adjacent_vertices(v, g.m_graph); }
|
Chris@16
|
469
|
Chris@16
|
470 //===========================================================================
|
Chris@16
|
471 // Functions required by the VertexListGraph concept
|
Chris@16
|
472
|
Chris@16
|
473 template <typename G>
|
Chris@16
|
474 std::pair<typename subgraph<G>::vertex_iterator,
|
Chris@16
|
475 typename subgraph<G>::vertex_iterator>
|
Chris@16
|
476 vertices(const subgraph<G>& g)
|
Chris@16
|
477 { return vertices(g.m_graph); }
|
Chris@16
|
478
|
Chris@16
|
479 template <typename G>
|
Chris@16
|
480 typename subgraph<G>::vertices_size_type
|
Chris@16
|
481 num_vertices(const subgraph<G>& g)
|
Chris@16
|
482 { return num_vertices(g.m_graph); }
|
Chris@16
|
483
|
Chris@16
|
484 //===========================================================================
|
Chris@16
|
485 // Functions required by the EdgeListGraph concept
|
Chris@16
|
486
|
Chris@16
|
487 template <typename G>
|
Chris@16
|
488 std::pair<typename subgraph<G>::edge_iterator,
|
Chris@16
|
489 typename subgraph<G>::edge_iterator>
|
Chris@16
|
490 edges(const subgraph<G>& g)
|
Chris@16
|
491 { return edges(g.m_graph); }
|
Chris@16
|
492
|
Chris@16
|
493 template <typename G>
|
Chris@16
|
494 typename subgraph<G>::edges_size_type
|
Chris@16
|
495 num_edges(const subgraph<G>& g)
|
Chris@16
|
496 { return num_edges(g.m_graph); }
|
Chris@16
|
497
|
Chris@16
|
498 //===========================================================================
|
Chris@16
|
499 // Functions required by the AdjacencyMatrix concept
|
Chris@16
|
500
|
Chris@16
|
501 template <typename G>
|
Chris@16
|
502 std::pair<typename subgraph<G>::edge_descriptor, bool>
|
Chris@16
|
503 edge(typename subgraph<G>::vertex_descriptor u,
|
Chris@16
|
504 typename subgraph<G>::vertex_descriptor v,
|
Chris@16
|
505 const subgraph<G>& g)
|
Chris@16
|
506 { return edge(u, v, g.m_graph); }
|
Chris@16
|
507
|
Chris@16
|
508 //===========================================================================
|
Chris@16
|
509 // Functions required by the MutableGraph concept
|
Chris@16
|
510
|
Chris@16
|
511 namespace detail {
|
Chris@16
|
512
|
Chris@16
|
513 template <typename Vertex, typename Edge, typename Graph>
|
Chris@16
|
514 void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
|
Chris@16
|
515 subgraph<Graph>& g);
|
Chris@16
|
516
|
Chris@16
|
517 template <typename Vertex, typename Edge, typename Children, typename G>
|
Chris@16
|
518 void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
|
Chris@16
|
519 Children& c, subgraph<G>* orig)
|
Chris@16
|
520 {
|
Chris@16
|
521 for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
|
Chris@16
|
522 if ((*i)->find_vertex(u_global).second &&
|
Chris@16
|
523 (*i)->find_vertex(v_global).second)
|
Chris@16
|
524 {
|
Chris@16
|
525 add_edge_recur_down(u_global, v_global, e_global, **i, orig);
|
Chris@16
|
526 }
|
Chris@16
|
527 }
|
Chris@16
|
528 }
|
Chris@16
|
529
|
Chris@16
|
530 template <typename Vertex, typename Edge, typename Graph>
|
Chris@16
|
531 void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
|
Chris@16
|
532 subgraph<Graph>& g, subgraph<Graph>* orig)
|
Chris@16
|
533 {
|
Chris@16
|
534 if(&g != orig ) {
|
Chris@16
|
535 // add local edge only if u_global and v_global are in subgraph g
|
Chris@16
|
536 Vertex u_local, v_local;
|
Chris@16
|
537 bool u_in_subgraph, v_in_subgraph;
|
Chris@16
|
538 boost::tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
|
Chris@16
|
539 boost::tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
|
Chris@16
|
540 if(u_in_subgraph && v_in_subgraph) {
|
Chris@16
|
541 g.local_add_edge(u_local, v_local, e_global);
|
Chris@16
|
542 }
|
Chris@16
|
543 }
|
Chris@16
|
544 children_add_edge(u_global, v_global, e_global, g.m_children, orig);
|
Chris@16
|
545 }
|
Chris@16
|
546
|
Chris@16
|
547 template <typename Vertex, typename Graph>
|
Chris@16
|
548 std::pair<typename subgraph<Graph>::edge_descriptor, bool>
|
Chris@16
|
549 add_edge_recur_up(Vertex u_global, Vertex v_global,
|
Chris@16
|
550 const typename Graph::edge_property_type& ep,
|
Chris@16
|
551 subgraph<Graph>& g, subgraph<Graph>* orig)
|
Chris@16
|
552 {
|
Chris@16
|
553 if(g.is_root()) {
|
Chris@16
|
554 typename subgraph<Graph>::edge_descriptor e_global;
|
Chris@16
|
555 bool inserted;
|
Chris@16
|
556 boost::tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph);
|
Chris@16
|
557 put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
|
Chris@16
|
558 g.m_global_edge.push_back(e_global);
|
Chris@16
|
559 children_add_edge(u_global, v_global, e_global, g.m_children, orig);
|
Chris@16
|
560 return std::make_pair(e_global, inserted);
|
Chris@16
|
561 } else {
|
Chris@16
|
562 return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
|
Chris@16
|
563 }
|
Chris@16
|
564 }
|
Chris@16
|
565
|
Chris@16
|
566 } // namespace detail
|
Chris@16
|
567
|
Chris@16
|
568 // Add an edge to the subgraph g, specified by the local vertex descriptors u
|
Chris@16
|
569 // and v. In addition, the edge will be added to any (all) other subgraphs that
|
Chris@16
|
570 // contain vertex descriptors u and v.
|
Chris@16
|
571
|
Chris@16
|
572 template <typename G>
|
Chris@16
|
573 std::pair<typename subgraph<G>::edge_descriptor, bool>
|
Chris@16
|
574 add_edge(typename subgraph<G>::vertex_descriptor u,
|
Chris@16
|
575 typename subgraph<G>::vertex_descriptor v,
|
Chris@16
|
576 const typename G::edge_property_type& ep,
|
Chris@16
|
577 subgraph<G>& g)
|
Chris@16
|
578 {
|
Chris@16
|
579 if (g.is_root()) {
|
Chris@16
|
580 // u and v are really global
|
Chris@16
|
581 return detail::add_edge_recur_up(u, v, ep, g, &g);
|
Chris@16
|
582 } else {
|
Chris@16
|
583 typename subgraph<G>::edge_descriptor e_local, e_global;
|
Chris@16
|
584 bool inserted;
|
Chris@16
|
585 boost::tie(e_global, inserted) =
|
Chris@16
|
586 detail::add_edge_recur_up(g.local_to_global(u),
|
Chris@16
|
587 g.local_to_global(v),
|
Chris@16
|
588 ep, g, &g);
|
Chris@16
|
589 e_local = g.local_add_edge(u, v, e_global);
|
Chris@16
|
590 return std::make_pair(e_local, inserted);
|
Chris@16
|
591 }
|
Chris@16
|
592 }
|
Chris@16
|
593
|
Chris@16
|
594 template <typename G>
|
Chris@16
|
595 std::pair<typename subgraph<G>::edge_descriptor, bool>
|
Chris@16
|
596 add_edge(typename subgraph<G>::vertex_descriptor u,
|
Chris@16
|
597 typename subgraph<G>::vertex_descriptor v,
|
Chris@16
|
598 subgraph<G>& g)
|
Chris@16
|
599 { return add_edge(u, v, typename G::edge_property_type(), g); }
|
Chris@16
|
600
|
Chris@16
|
601 namespace detail {
|
Chris@16
|
602 //-------------------------------------------------------------------------
|
Chris@16
|
603 // implementation of remove_edge(u,v,g)
|
Chris@16
|
604 template <typename Vertex, typename Graph>
|
Chris@16
|
605 void remove_edge_recur_down(Vertex u_global, Vertex v_global,
|
Chris@16
|
606 subgraph<Graph>& g);
|
Chris@16
|
607
|
Chris@16
|
608 template <typename Vertex, typename Children>
|
Chris@16
|
609 void children_remove_edge(Vertex u_global, Vertex v_global,
|
Chris@16
|
610 Children& c)
|
Chris@16
|
611 {
|
Chris@16
|
612 for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
|
Chris@16
|
613 if((*i)->find_vertex(u_global).second &&
|
Chris@16
|
614 (*i)->find_vertex(v_global).second)
|
Chris@16
|
615 {
|
Chris@16
|
616 remove_edge_recur_down(u_global, v_global, **i);
|
Chris@16
|
617 }
|
Chris@16
|
618 }
|
Chris@16
|
619 }
|
Chris@16
|
620
|
Chris@16
|
621 template <typename Vertex, typename Graph>
|
Chris@16
|
622 void remove_edge_recur_down(Vertex u_global, Vertex v_global,
|
Chris@16
|
623 subgraph<Graph>& g)
|
Chris@16
|
624 {
|
Chris@16
|
625 Vertex u_local, v_local;
|
Chris@16
|
626 u_local = g.m_local_vertex[u_global];
|
Chris@16
|
627 v_local = g.m_local_vertex[v_global];
|
Chris@16
|
628 remove_edge(u_local, v_local, g.m_graph);
|
Chris@16
|
629 children_remove_edge(u_global, v_global, g.m_children);
|
Chris@16
|
630 }
|
Chris@16
|
631
|
Chris@16
|
632 template <typename Vertex, typename Graph>
|
Chris@16
|
633 void remove_edge_recur_up(Vertex u_global, Vertex v_global,
|
Chris@16
|
634 subgraph<Graph>& g)
|
Chris@16
|
635 {
|
Chris@16
|
636 if(g.is_root()) {
|
Chris@16
|
637 remove_edge(u_global, v_global, g.m_graph);
|
Chris@16
|
638 children_remove_edge(u_global, v_global, g.m_children);
|
Chris@16
|
639 } else {
|
Chris@16
|
640 remove_edge_recur_up(u_global, v_global, *g.m_parent);
|
Chris@16
|
641 }
|
Chris@16
|
642 }
|
Chris@16
|
643
|
Chris@16
|
644 //-------------------------------------------------------------------------
|
Chris@16
|
645 // implementation of remove_edge(e,g)
|
Chris@16
|
646
|
Chris@16
|
647 template <typename G, typename Edge, typename Children>
|
Chris@16
|
648 void children_remove_edge(Edge e_global, Children& c)
|
Chris@16
|
649 {
|
Chris@16
|
650 for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
|
Chris@16
|
651 std::pair<typename subgraph<G>::edge_descriptor, bool> found =
|
Chris@16
|
652 (*i)->find_edge(e_global);
|
Chris@16
|
653 if (!found.second) {
|
Chris@16
|
654 continue;
|
Chris@16
|
655 }
|
Chris@16
|
656 children_remove_edge<G>(e_global, (*i)->m_children);
|
Chris@16
|
657 remove_edge(found.first, (*i)->m_graph);
|
Chris@16
|
658 }
|
Chris@16
|
659 }
|
Chris@16
|
660
|
Chris@16
|
661 } // namespace detail
|
Chris@16
|
662
|
Chris@16
|
663 template <typename G>
|
Chris@16
|
664 void
|
Chris@16
|
665 remove_edge(typename subgraph<G>::vertex_descriptor u,
|
Chris@16
|
666 typename subgraph<G>::vertex_descriptor v,
|
Chris@16
|
667 subgraph<G>& g)
|
Chris@16
|
668 {
|
Chris@16
|
669 if(g.is_root()) {
|
Chris@16
|
670 detail::remove_edge_recur_up(u, v, g);
|
Chris@16
|
671 } else {
|
Chris@16
|
672 detail::remove_edge_recur_up(g.local_to_global(u),
|
Chris@16
|
673 g.local_to_global(v), g);
|
Chris@16
|
674 }
|
Chris@16
|
675 }
|
Chris@16
|
676
|
Chris@16
|
677 template <typename G>
|
Chris@16
|
678 void
|
Chris@16
|
679 remove_edge(typename subgraph<G>::edge_descriptor e, subgraph<G>& g)
|
Chris@16
|
680 {
|
Chris@16
|
681 typename subgraph<G>::edge_descriptor e_global = g.local_to_global(e);
|
Chris@16
|
682 #ifndef NDEBUG
|
Chris@16
|
683 std::pair<typename subgraph<G>::edge_descriptor, bool> fe = g.find_edge(e_global);
|
Chris@16
|
684 BOOST_ASSERT(fe.second && fe.first == e);
|
Chris@16
|
685 #endif //NDEBUG
|
Chris@16
|
686 subgraph<G> &root = g.root(); // chase to root
|
Chris@16
|
687 detail::children_remove_edge<G>(e_global, root.m_children);
|
Chris@16
|
688 remove_edge(e_global, root.m_graph); // kick edge from root
|
Chris@16
|
689 }
|
Chris@16
|
690
|
Chris@16
|
691 // This is slow, but there may not be a good way to do it safely otherwise
|
Chris@16
|
692 template <typename Predicate, typename G>
|
Chris@16
|
693 void
|
Chris@16
|
694 remove_edge_if(Predicate p, subgraph<G>& g) {
|
Chris@16
|
695 while (true) {
|
Chris@16
|
696 bool any_removed = false;
|
Chris@16
|
697 typedef typename subgraph<G>::edge_iterator ei_type;
|
Chris@16
|
698 for (std::pair<ei_type, ei_type> ep = edges(g);
|
Chris@16
|
699 ep.first != ep.second; ++ep.first) {
|
Chris@16
|
700 if (p(*ep.first)) {
|
Chris@16
|
701 any_removed = true;
|
Chris@16
|
702 remove_edge(*ep.first, g);
|
Chris@16
|
703 break; /* Since iterators may be invalidated */
|
Chris@16
|
704 }
|
Chris@16
|
705 }
|
Chris@16
|
706 if (!any_removed) break;
|
Chris@16
|
707 }
|
Chris@16
|
708 }
|
Chris@16
|
709
|
Chris@16
|
710 template <typename G>
|
Chris@16
|
711 void
|
Chris@16
|
712 clear_vertex(typename subgraph<G>::vertex_descriptor v, subgraph<G>& g) {
|
Chris@16
|
713 while (true) {
|
Chris@16
|
714 typedef typename subgraph<G>::out_edge_iterator oei_type;
|
Chris@16
|
715 std::pair<oei_type, oei_type> p = out_edges(v, g);
|
Chris@16
|
716 if (p.first == p.second) break;
|
Chris@16
|
717 remove_edge(*p.first, g);
|
Chris@16
|
718 }
|
Chris@16
|
719 }
|
Chris@16
|
720
|
Chris@16
|
721 namespace detail {
|
Chris@16
|
722 template <typename G>
|
Chris@16
|
723 typename subgraph<G>::vertex_descriptor
|
Chris@16
|
724 add_vertex_recur_up(subgraph<G>& g)
|
Chris@16
|
725 {
|
Chris@16
|
726 typename subgraph<G>::vertex_descriptor u_local, u_global;
|
Chris@16
|
727 if (g.is_root()) {
|
Chris@16
|
728 u_global = add_vertex(g.m_graph);
|
Chris@16
|
729 g.m_global_vertex.push_back(u_global);
|
Chris@16
|
730 } else {
|
Chris@16
|
731 u_global = add_vertex_recur_up(*g.m_parent);
|
Chris@16
|
732 u_local = add_vertex(g.m_graph);
|
Chris@16
|
733 g.m_global_vertex.push_back(u_global);
|
Chris@16
|
734 g.m_local_vertex[u_global] = u_local;
|
Chris@16
|
735 }
|
Chris@16
|
736 return u_global;
|
Chris@16
|
737 }
|
Chris@16
|
738 } // namespace detail
|
Chris@16
|
739
|
Chris@16
|
740 template <typename G>
|
Chris@16
|
741 typename subgraph<G>::vertex_descriptor
|
Chris@16
|
742 add_vertex(subgraph<G>& g)
|
Chris@16
|
743 {
|
Chris@16
|
744 typename subgraph<G>::vertex_descriptor u_local, u_global;
|
Chris@16
|
745 if(g.is_root()) {
|
Chris@16
|
746 u_global = add_vertex(g.m_graph);
|
Chris@16
|
747 g.m_global_vertex.push_back(u_global);
|
Chris@16
|
748 u_local = u_global;
|
Chris@16
|
749 } else {
|
Chris@16
|
750 u_global = detail::add_vertex_recur_up(g.parent());
|
Chris@16
|
751 u_local = add_vertex(g.m_graph);
|
Chris@16
|
752 g.m_global_vertex.push_back(u_global);
|
Chris@16
|
753 g.m_local_vertex[u_global] = u_local;
|
Chris@16
|
754 }
|
Chris@16
|
755 return u_local;
|
Chris@16
|
756 }
|
Chris@16
|
757
|
Chris@16
|
758
|
Chris@16
|
759 #if 0
|
Chris@16
|
760 // TODO: Under Construction
|
Chris@16
|
761 template <typename G>
|
Chris@16
|
762 void remove_vertex(typename subgraph<G>::vertex_descriptor u, subgraph<G>& g)
|
Chris@16
|
763 { BOOST_ASSERT(false); }
|
Chris@16
|
764 #endif
|
Chris@16
|
765
|
Chris@16
|
766 //===========================================================================
|
Chris@16
|
767 // Functions required by the PropertyGraph concept
|
Chris@16
|
768
|
Chris@16
|
769 /**
|
Chris@16
|
770 * The global property map returns the global properties associated with local
|
Chris@16
|
771 * descriptors.
|
Chris@16
|
772 */
|
Chris@16
|
773 template <typename GraphPtr, typename PropertyMap, typename Tag>
|
Chris@16
|
774 class subgraph_global_property_map
|
Chris@16
|
775 : public put_get_helper<
|
Chris@16
|
776 typename property_traits<PropertyMap>::reference,
|
Chris@16
|
777 subgraph_global_property_map<GraphPtr, PropertyMap, Tag>
|
Chris@16
|
778 >
|
Chris@16
|
779 {
|
Chris@16
|
780 typedef property_traits<PropertyMap> Traits;
|
Chris@16
|
781 public:
|
Chris@16
|
782 typedef typename mpl::if_<is_const<typename remove_pointer<GraphPtr>::type>,
|
Chris@16
|
783 readable_property_map_tag,
|
Chris@16
|
784 typename Traits::category>::type
|
Chris@16
|
785 category;
|
Chris@16
|
786 typedef typename Traits::value_type value_type;
|
Chris@16
|
787 typedef typename Traits::key_type key_type;
|
Chris@16
|
788 typedef typename Traits::reference reference;
|
Chris@16
|
789
|
Chris@16
|
790 subgraph_global_property_map()
|
Chris@16
|
791 { }
|
Chris@16
|
792
|
Chris@16
|
793 subgraph_global_property_map(GraphPtr g, Tag tag)
|
Chris@16
|
794 : m_g(g), m_tag(tag)
|
Chris@16
|
795 { }
|
Chris@16
|
796
|
Chris@16
|
797 reference operator[](key_type e) const {
|
Chris@16
|
798 PropertyMap pmap = get(m_tag, m_g->root().m_graph);
|
Chris@16
|
799 return m_g->is_root()
|
Chris@16
|
800 ? pmap[e]
|
Chris@16
|
801 : pmap[m_g->local_to_global(e)];
|
Chris@16
|
802 }
|
Chris@16
|
803
|
Chris@16
|
804 GraphPtr m_g;
|
Chris@16
|
805 Tag m_tag;
|
Chris@16
|
806 };
|
Chris@16
|
807
|
Chris@16
|
808 /**
|
Chris@16
|
809 * The local property map returns the local property associated with the local
|
Chris@16
|
810 * descriptors.
|
Chris@16
|
811 */
|
Chris@16
|
812 template <typename GraphPtr, typename PropertyMap, typename Tag>
|
Chris@16
|
813 class subgraph_local_property_map
|
Chris@16
|
814 : public put_get_helper<
|
Chris@16
|
815 typename property_traits<PropertyMap>::reference,
|
Chris@16
|
816 subgraph_local_property_map<GraphPtr, PropertyMap, Tag>
|
Chris@16
|
817 >
|
Chris@16
|
818 {
|
Chris@16
|
819 typedef property_traits<PropertyMap> Traits;
|
Chris@16
|
820 public:
|
Chris@16
|
821 typedef typename mpl::if_<is_const<typename remove_pointer<GraphPtr>::type>,
|
Chris@16
|
822 readable_property_map_tag,
|
Chris@16
|
823 typename Traits::category>::type
|
Chris@16
|
824 category;
|
Chris@16
|
825 typedef typename Traits::value_type value_type;
|
Chris@16
|
826 typedef typename Traits::key_type key_type;
|
Chris@16
|
827 typedef typename Traits::reference reference;
|
Chris@16
|
828
|
Chris@16
|
829 typedef Tag tag;
|
Chris@16
|
830 typedef PropertyMap pmap;
|
Chris@16
|
831
|
Chris@16
|
832 subgraph_local_property_map()
|
Chris@16
|
833 { }
|
Chris@16
|
834
|
Chris@16
|
835 subgraph_local_property_map(GraphPtr g, Tag tag)
|
Chris@16
|
836 : m_g(g), m_tag(tag)
|
Chris@16
|
837 { }
|
Chris@16
|
838
|
Chris@16
|
839 reference operator[](key_type e) const {
|
Chris@16
|
840 // Get property map on the underlying graph.
|
Chris@16
|
841 PropertyMap pmap = get(m_tag, m_g->m_graph);
|
Chris@16
|
842 return pmap[e];
|
Chris@16
|
843 }
|
Chris@16
|
844
|
Chris@16
|
845 GraphPtr m_g;
|
Chris@16
|
846 Tag m_tag;
|
Chris@16
|
847 };
|
Chris@16
|
848
|
Chris@16
|
849 namespace detail {
|
Chris@16
|
850 // Extract the actual tags from local or global property maps so we don't
|
Chris@16
|
851 // try to find non-properties.
|
Chris@16
|
852 template <typename P> struct extract_lg_tag { typedef P type; };
|
Chris@16
|
853 template <typename P> struct extract_lg_tag< local_property<P> > {
|
Chris@16
|
854 typedef P type;
|
Chris@16
|
855 };
|
Chris@16
|
856 template <typename P> struct extract_lg_tag< global_property<P> > {
|
Chris@16
|
857 typedef P type;
|
Chris@16
|
858 };
|
Chris@16
|
859
|
Chris@16
|
860 // NOTE: Mysterious Property template parameter unused in both metafunction
|
Chris@16
|
861 // classes.
|
Chris@16
|
862 struct subgraph_global_pmap {
|
Chris@16
|
863 template <class Tag, class SubGraph, class Property>
|
Chris@16
|
864 struct bind_ {
|
Chris@16
|
865 typedef typename SubGraph::graph_type Graph;
|
Chris@16
|
866 typedef SubGraph* SubGraphPtr;
|
Chris@16
|
867 typedef const SubGraph* const_SubGraphPtr;
|
Chris@16
|
868 typedef typename extract_lg_tag<Tag>::type TagType;
|
Chris@16
|
869 typedef typename property_map<Graph, TagType>::type PMap;
|
Chris@16
|
870 typedef typename property_map<Graph, TagType>::const_type const_PMap;
|
Chris@16
|
871 public:
|
Chris@16
|
872 typedef subgraph_global_property_map<SubGraphPtr, PMap, TagType> type;
|
Chris@16
|
873 typedef subgraph_global_property_map<const_SubGraphPtr, const_PMap, TagType>
|
Chris@16
|
874 const_type;
|
Chris@16
|
875 };
|
Chris@16
|
876 };
|
Chris@16
|
877
|
Chris@16
|
878 struct subgraph_local_pmap {
|
Chris@16
|
879 template <class Tag, class SubGraph, class Property>
|
Chris@16
|
880 struct bind_ {
|
Chris@16
|
881 typedef typename SubGraph::graph_type Graph;
|
Chris@16
|
882 typedef SubGraph* SubGraphPtr;
|
Chris@16
|
883 typedef const SubGraph* const_SubGraphPtr;
|
Chris@16
|
884 typedef typename extract_lg_tag<Tag>::type TagType;
|
Chris@16
|
885 typedef typename property_map<Graph, TagType>::type PMap;
|
Chris@16
|
886 typedef typename property_map<Graph, TagType>::const_type const_PMap;
|
Chris@16
|
887 public:
|
Chris@16
|
888 typedef subgraph_local_property_map<SubGraphPtr, PMap, TagType> type;
|
Chris@16
|
889 typedef subgraph_local_property_map<const_SubGraphPtr, const_PMap, TagType>
|
Chris@16
|
890 const_type;
|
Chris@16
|
891 };
|
Chris@16
|
892 };
|
Chris@16
|
893
|
Chris@16
|
894 // These metafunctions select the corresponding metafunctions above, and
|
Chris@16
|
895 // are used by the choose_pmap metafunction below to specialize the choice
|
Chris@16
|
896 // of local/global property map. By default, we defer to the global
|
Chris@16
|
897 // property.
|
Chris@16
|
898 template <class Tag>
|
Chris@16
|
899 struct subgraph_choose_pmap_helper {
|
Chris@16
|
900 typedef subgraph_global_pmap type;
|
Chris@16
|
901 };
|
Chris@16
|
902 template <class Tag>
|
Chris@16
|
903 struct subgraph_choose_pmap_helper< local_property<Tag> > {
|
Chris@16
|
904 typedef subgraph_local_pmap type;
|
Chris@16
|
905 };
|
Chris@16
|
906 template <class Tag>
|
Chris@16
|
907 struct subgraph_choose_pmap_helper< global_property<Tag> > {
|
Chris@16
|
908 typedef subgraph_global_pmap type;
|
Chris@16
|
909 };
|
Chris@16
|
910
|
Chris@16
|
911 // As above, unless we're requesting vertex_index_t. Then it's always a
|
Chris@16
|
912 // local property map. This enables the correct translation of descriptors
|
Chris@16
|
913 // between local and global layers.
|
Chris@16
|
914 template <>
|
Chris@16
|
915 struct subgraph_choose_pmap_helper<vertex_index_t> {
|
Chris@16
|
916 typedef subgraph_local_pmap type;
|
Chris@16
|
917 };
|
Chris@16
|
918 template <>
|
Chris@16
|
919 struct subgraph_choose_pmap_helper< local_property<vertex_index_t> > {
|
Chris@16
|
920 typedef subgraph_local_pmap type;
|
Chris@16
|
921 };
|
Chris@16
|
922 template <>
|
Chris@16
|
923 struct subgraph_choose_pmap_helper< global_property<vertex_index_t> > {
|
Chris@16
|
924 typedef subgraph_local_pmap type;
|
Chris@16
|
925 };
|
Chris@16
|
926
|
Chris@16
|
927 // Determine the kind of property. If SameType<Tag, vertex_index_t>, then
|
Chris@16
|
928 // the property lookup is always local. Otherwise, the lookup is global.
|
Chris@16
|
929 // NOTE: Property parameter is basically unused.
|
Chris@16
|
930 template <class Tag, class Graph, class Property>
|
Chris@16
|
931 struct subgraph_choose_pmap {
|
Chris@16
|
932 typedef typename subgraph_choose_pmap_helper<Tag>::type Helper;
|
Chris@16
|
933 typedef typename Helper::template bind_<Tag, Graph, Property> Bind;
|
Chris@16
|
934 typedef typename Bind::type type;
|
Chris@16
|
935 typedef typename Bind::const_type const_type;
|
Chris@16
|
936 };
|
Chris@16
|
937
|
Chris@16
|
938 // Used by the vertex/edge property selectors to determine the kind(s) of
|
Chris@16
|
939 // property maps used by the property_map type generator.
|
Chris@16
|
940 struct subgraph_property_generator {
|
Chris@16
|
941 template <class SubGraph, class Property, class Tag>
|
Chris@16
|
942 struct bind_ {
|
Chris@16
|
943 typedef subgraph_choose_pmap<Tag, SubGraph, Property> Choice;
|
Chris@16
|
944 typedef typename Choice::type type;
|
Chris@16
|
945 typedef typename Choice::const_type const_type;
|
Chris@16
|
946 };
|
Chris@16
|
947 };
|
Chris@16
|
948
|
Chris@16
|
949 } // namespace detail
|
Chris@16
|
950
|
Chris@16
|
951 template <>
|
Chris@16
|
952 struct vertex_property_selector<subgraph_tag> {
|
Chris@16
|
953 typedef detail::subgraph_property_generator type;
|
Chris@16
|
954 };
|
Chris@16
|
955
|
Chris@16
|
956 template <>
|
Chris@16
|
957 struct edge_property_selector<subgraph_tag> {
|
Chris@16
|
958 typedef detail::subgraph_property_generator type;
|
Chris@16
|
959 };
|
Chris@16
|
960
|
Chris@16
|
961 // ==================================================
|
Chris@16
|
962 // get(p, g), get(p, g, k), and put(p, g, k, v)
|
Chris@16
|
963 // ==================================================
|
Chris@16
|
964 template <typename G, typename Property>
|
Chris@16
|
965 typename property_map<subgraph<G>, Property>::type
|
Chris@16
|
966 get(Property p, subgraph<G>& g) {
|
Chris@16
|
967 typedef typename property_map< subgraph<G>, Property>::type PMap;
|
Chris@16
|
968 return PMap(&g, p);
|
Chris@16
|
969 }
|
Chris@16
|
970
|
Chris@16
|
971 template <typename G, typename Property>
|
Chris@16
|
972 typename property_map<subgraph<G>, Property>::const_type
|
Chris@16
|
973 get(Property p, const subgraph<G>& g) {
|
Chris@16
|
974 typedef typename property_map< subgraph<G>, Property>::const_type PMap;
|
Chris@16
|
975 return PMap(&g, p);
|
Chris@16
|
976 }
|
Chris@16
|
977
|
Chris@16
|
978 template <typename G, typename Property, typename Key>
|
Chris@16
|
979 typename property_traits<
|
Chris@16
|
980 typename property_map<subgraph<G>, Property>::const_type
|
Chris@16
|
981 >::value_type
|
Chris@16
|
982 get(Property p, const subgraph<G>& g, const Key& k) {
|
Chris@16
|
983 typedef typename property_map< subgraph<G>, Property>::const_type PMap;
|
Chris@16
|
984 PMap pmap(&g, p);
|
Chris@16
|
985 return pmap[k];
|
Chris@16
|
986 }
|
Chris@16
|
987
|
Chris@16
|
988 template <typename G, typename Property, typename Key, typename Value>
|
Chris@16
|
989 void put(Property p, subgraph<G>& g, const Key& k, const Value& val) {
|
Chris@16
|
990 typedef typename property_map< subgraph<G>, Property>::type PMap;
|
Chris@16
|
991 PMap pmap(&g, p);
|
Chris@16
|
992 pmap[k] = val;
|
Chris@16
|
993 }
|
Chris@16
|
994
|
Chris@16
|
995 // ==================================================
|
Chris@16
|
996 // get(global(p), g)
|
Chris@16
|
997 // NOTE: get(global(p), g, k) and put(global(p), g, k, v) not supported
|
Chris@16
|
998 // ==================================================
|
Chris@16
|
999 template <typename G, typename Property>
|
Chris@16
|
1000 typename property_map<subgraph<G>, global_property<Property> >::type
|
Chris@16
|
1001 get(global_property<Property> p, subgraph<G>& g) {
|
Chris@16
|
1002 typedef typename property_map<
|
Chris@16
|
1003 subgraph<G>, global_property<Property>
|
Chris@16
|
1004 >::type Map;
|
Chris@16
|
1005 return Map(&g, p.value);
|
Chris@16
|
1006 }
|
Chris@16
|
1007
|
Chris@16
|
1008 template <typename G, typename Property>
|
Chris@16
|
1009 typename property_map<subgraph<G>, global_property<Property> >::const_type
|
Chris@16
|
1010 get(global_property<Property> p, const subgraph<G>& g) {
|
Chris@16
|
1011 typedef typename property_map<
|
Chris@16
|
1012 subgraph<G>, global_property<Property>
|
Chris@16
|
1013 >::const_type Map;
|
Chris@16
|
1014 return Map(&g, p.value);
|
Chris@16
|
1015 }
|
Chris@16
|
1016
|
Chris@16
|
1017 // ==================================================
|
Chris@16
|
1018 // get(local(p), g)
|
Chris@16
|
1019 // NOTE: get(local(p), g, k) and put(local(p), g, k, v) not supported
|
Chris@16
|
1020 // ==================================================
|
Chris@16
|
1021 template <typename G, typename Property>
|
Chris@16
|
1022 typename property_map<subgraph<G>, local_property<Property> >::type
|
Chris@16
|
1023 get(local_property<Property> p, subgraph<G>& g) {
|
Chris@16
|
1024 typedef typename property_map<
|
Chris@16
|
1025 subgraph<G>, local_property<Property>
|
Chris@16
|
1026 >::type Map;
|
Chris@16
|
1027 return Map(&g, p.value);
|
Chris@16
|
1028 }
|
Chris@16
|
1029
|
Chris@16
|
1030 template <typename G, typename Property>
|
Chris@16
|
1031 typename property_map<subgraph<G>, local_property<Property> >::const_type
|
Chris@16
|
1032 get(local_property<Property> p, const subgraph<G>& g) {
|
Chris@16
|
1033 typedef typename property_map<
|
Chris@16
|
1034 subgraph<G>, local_property<Property>
|
Chris@16
|
1035 >::const_type Map;
|
Chris@16
|
1036 return Map(&g, p.value);
|
Chris@16
|
1037 }
|
Chris@16
|
1038
|
Chris@16
|
1039 template <typename G, typename Tag>
|
Chris@16
|
1040 inline typename graph_property<G, Tag>::type&
|
Chris@16
|
1041 get_property(subgraph<G>& g, Tag tag) {
|
Chris@16
|
1042 return get_property(g.m_graph, tag);
|
Chris@16
|
1043 }
|
Chris@16
|
1044
|
Chris@16
|
1045 template <typename G, typename Tag>
|
Chris@16
|
1046 inline const typename graph_property<G, Tag>::type&
|
Chris@16
|
1047 get_property(const subgraph<G>& g, Tag tag) {
|
Chris@16
|
1048 return get_property(g.m_graph, tag);
|
Chris@16
|
1049 }
|
Chris@16
|
1050
|
Chris@16
|
1051 //===========================================================================
|
Chris@16
|
1052 // Miscellaneous Functions
|
Chris@16
|
1053
|
Chris@16
|
1054 template <typename G>
|
Chris@16
|
1055 typename subgraph<G>::vertex_descriptor
|
Chris@16
|
1056 vertex(typename subgraph<G>::vertices_size_type n, const subgraph<G>& g)
|
Chris@16
|
1057 { return vertex(n, g.m_graph); }
|
Chris@16
|
1058
|
Chris@16
|
1059 //===========================================================================
|
Chris@16
|
1060 // Mutability Traits
|
Chris@16
|
1061 // Just pull the mutability traits form the underlying graph. Note that this
|
Chris@16
|
1062 // will probably fail (badly) for labeled graphs.
|
Chris@16
|
1063 template <typename G>
|
Chris@16
|
1064 struct graph_mutability_traits< subgraph<G> > {
|
Chris@16
|
1065 typedef typename graph_mutability_traits<G>::category category;
|
Chris@16
|
1066 };
|
Chris@16
|
1067
|
Chris@16
|
1068 } // namespace boost
|
Chris@16
|
1069
|
Chris@16
|
1070 #endif // BOOST_SUBGRAPH_HPP
|