1 | #include <boost/property_map.hpp>
|
---|
2 | #include <boost/graph/properties.hpp>
|
---|
3 | #include <boost/graph/adjacency_iterator.hpp>
|
---|
4 | #include <vector>
|
---|
5 |
|
---|
6 | /// A skeleton user defined graph not using any of the builtin Boost Graph Library graph types.
|
---|
7 | namespace MyGraph {
|
---|
8 |
|
---|
9 | class Graph;
|
---|
10 | class Vertex;
|
---|
11 | class Edge;
|
---|
12 |
|
---|
13 | typedef Vertex* VertexDesc;
|
---|
14 | typedef Edge* EdgeDesc;
|
---|
15 | typedef std::vector<EdgeDesc>::iterator EdgeIterator;
|
---|
16 | typedef std::vector<VertexDesc>::iterator VertexIterator;
|
---|
17 |
|
---|
18 | class Vertex {
|
---|
19 | public:
|
---|
20 | unsigned int index();
|
---|
21 | std::pair<EdgeIterator, EdgeIterator> outEdges() const;
|
---|
22 | std::pair<EdgeIterator, EdgeIterator> inEdges() const;
|
---|
23 | unsigned int outEdgeCount() const;
|
---|
24 | unsigned int inEdgeCount() const;
|
---|
25 | EdgeIterator outEdgeBegin() const;
|
---|
26 | EdgeIterator outEdgeEnd() const;
|
---|
27 | EdgeIterator inEdgeBegin() const;
|
---|
28 | EdgeIterator inEdgeEnd() const;
|
---|
29 | void clearEdges();
|
---|
30 | };
|
---|
31 |
|
---|
32 | class Edge {
|
---|
33 | public:
|
---|
34 | unsigned int index() const;
|
---|
35 | VertexDesc source() const;
|
---|
36 | VertexDesc target() const;
|
---|
37 | };
|
---|
38 |
|
---|
39 | class Graph {
|
---|
40 | public:
|
---|
41 | std::pair<EdgeIterator, EdgeIterator> edges() const;
|
---|
42 | std::pair<VertexIterator, VertexIterator> vertices() const;
|
---|
43 | unsigned int vertexCount() const;
|
---|
44 | unsigned int edgeCount() const;
|
---|
45 | std::pair<EdgeDesc, bool> findEdge(VertexDesc source, VertexDesc target) const;
|
---|
46 | VertexDesc addVertex();
|
---|
47 | void removeVertex(VertexDesc vertex);
|
---|
48 | std::pair<EdgeDesc, bool> addEdge(VertexDesc source, VertexDesc target);
|
---|
49 | void removeEdge(EdgeDesc edge);
|
---|
50 | };
|
---|
51 |
|
---|
52 | } // namespace MyGraph
|
---|
53 |
|
---|
54 | /// An adapter to allow the user defined graph MyGraph to be used as a Boost Graph.
|
---|
55 | namespace boost {
|
---|
56 |
|
---|
57 | /// The Boost Graph Library algorithms use graph_traits to obtain
|
---|
58 | /// information about the types to use to access the graph.
|
---|
59 | template <>
|
---|
60 | struct graph_traits<MyGraph::Graph> {
|
---|
61 |
|
---|
62 | // Our user defined graph models all of the following concepts:
|
---|
63 | struct bidir_adj_list_traversal_tag :
|
---|
64 | public virtual vertex_list_graph_tag,
|
---|
65 | public virtual incidence_graph_tag,
|
---|
66 | public virtual adjacency_graph_tag,
|
---|
67 | public virtual edge_list_graph_tag,
|
---|
68 | public virtual bidirectional_graph_tag { };
|
---|
69 |
|
---|
70 | // Graph requires:
|
---|
71 | typedef MyGraph::VertexDesc vertex_descriptor;
|
---|
72 | typedef MyGraph::EdgeDesc edge_descriptor;
|
---|
73 | typedef directed_tag directed_category;
|
---|
74 | typedef disallow_parallel_edge_tag edge_parallel_category;
|
---|
75 | typedef bidir_adj_list_traversal_tag traversal_category;
|
---|
76 |
|
---|
77 | static inline vertex_descriptor null_vertex()
|
---|
78 | {
|
---|
79 | return MyGraph::VertexDesc(0);
|
---|
80 | }
|
---|
81 |
|
---|
82 | // IncidenceGraph requires:
|
---|
83 | typedef MyGraph::EdgeIterator out_edge_iterator;
|
---|
84 | typedef unsigned int degree_size_type;
|
---|
85 |
|
---|
86 | // BidirectionalGraph requires:
|
---|
87 | typedef MyGraph::EdgeIterator in_edge_iterator;
|
---|
88 |
|
---|
89 | // Adjacency Graph requires:
|
---|
90 | typedef adjacency_iterator_generator
|
---|
91 | <MyGraph::Graph, vertex_descriptor, out_edge_iterator>::type
|
---|
92 | adjacency_iterator;
|
---|
93 |
|
---|
94 | // VertexListGraph requires:
|
---|
95 | typedef MyGraph::VertexIterator vertex_iterator;
|
---|
96 | typedef unsigned int vertices_size_type;
|
---|
97 |
|
---|
98 | // EdgeListGraph requires:
|
---|
99 | typedef MyGraph::EdgeIterator edge_iterator;
|
---|
100 | typedef unsigned int edges_size_type;
|
---|
101 | };
|
---|
102 |
|
---|
103 | } // namespace boost
|
---|
104 |
|
---|
105 | /// In addition we must provide the following operations.
|
---|
106 | /// These definitions are logically part of MyGraph.
|
---|
107 | namespace MyGraph {
|
---|
108 |
|
---|
109 | /// IncidenceGraph refines Graph requires:
|
---|
110 | inline
|
---|
111 | std::pair<boost::graph_traits<MyGraph::Graph>::out_edge_iterator,
|
---|
112 | boost::graph_traits<MyGraph::Graph>::out_edge_iterator>
|
---|
113 | out_edges(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
114 | {
|
---|
115 | return v->outEdges();
|
---|
116 | }
|
---|
117 |
|
---|
118 | inline
|
---|
119 | boost::graph_traits<MyGraph::Graph>::vertex_descriptor
|
---|
120 | source(boost::graph_traits<MyGraph::Graph>::edge_descriptor e, const MyGraph::Graph& g)
|
---|
121 | {
|
---|
122 | return e->source();
|
---|
123 | }
|
---|
124 |
|
---|
125 | inline
|
---|
126 | boost::graph_traits<MyGraph::Graph>::vertex_descriptor
|
---|
127 | target(boost::graph_traits<MyGraph::Graph>::edge_descriptor e, const MyGraph::Graph& g)
|
---|
128 | {
|
---|
129 | return e->target();
|
---|
130 | }
|
---|
131 |
|
---|
132 | inline
|
---|
133 | boost::graph_traits<MyGraph::Graph>::degree_size_type
|
---|
134 | out_degree(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
135 | {
|
---|
136 | return v->outEdgeCount();
|
---|
137 | }
|
---|
138 |
|
---|
139 |
|
---|
140 | /// BidirectionalGraph refines IncidenceGraph and requires:
|
---|
141 | inline
|
---|
142 | std::pair<boost::graph_traits<MyGraph::Graph>::in_edge_iterator, boost::graph_traits<MyGraph::Graph>::in_edge_iterator>
|
---|
143 | in_edges(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
144 | {
|
---|
145 | return v->inEdges();
|
---|
146 | }
|
---|
147 |
|
---|
148 | inline
|
---|
149 | boost::graph_traits<MyGraph::Graph>::degree_size_type
|
---|
150 | in_degree(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
151 | {
|
---|
152 | return v->inEdgeCount();
|
---|
153 | }
|
---|
154 |
|
---|
155 | inline
|
---|
156 | boost::graph_traits<MyGraph::Graph>::degree_size_type
|
---|
157 | degree(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
158 | {
|
---|
159 | return in_degree(v, g) + out_degree(v, g);
|
---|
160 | }
|
---|
161 |
|
---|
162 | /// AdjacencyGraph refines Graph and requires:
|
---|
163 | inline
|
---|
164 | std::pair<boost::graph_traits<MyGraph::Graph>::adjacency_iterator, boost::graph_traits<MyGraph::Graph>::adjacency_iterator>
|
---|
165 | adjacent_vertices(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
166 | {
|
---|
167 | boost::graph_traits<MyGraph::Graph>::adjacency_iterator begin(v->outEdgeBegin(), &g);
|
---|
168 | boost::graph_traits<MyGraph::Graph>::adjacency_iterator end(v->outEdgeEnd(), &g);
|
---|
169 | return std::make_pair(begin, end);
|
---|
170 | }
|
---|
171 |
|
---|
172 | /// VertexListGraph refines IncidenceGraph and AdjacencyGraph and requires:
|
---|
173 | inline
|
---|
174 | std::pair<boost::graph_traits<MyGraph::Graph>::vertex_iterator, boost::graph_traits<MyGraph::Graph>::vertex_iterator>
|
---|
175 | vertices(const MyGraph::Graph& g)
|
---|
176 | {
|
---|
177 | return g.vertices();
|
---|
178 | }
|
---|
179 |
|
---|
180 | inline
|
---|
181 | boost::graph_traits<MyGraph::Graph>::vertices_size_type
|
---|
182 | num_vertices(const MyGraph::Graph& g)
|
---|
183 | {
|
---|
184 | return g.vertexCount();
|
---|
185 | }
|
---|
186 |
|
---|
187 | /// EdgeListGraph refines Graph and requires:
|
---|
188 | inline
|
---|
189 | std::pair<boost::graph_traits<MyGraph::Graph>::edge_iterator, boost::graph_traits<MyGraph::Graph>::edge_iterator>
|
---|
190 | edges(const MyGraph::Graph& g)
|
---|
191 | {
|
---|
192 | return g.edges();
|
---|
193 | }
|
---|
194 |
|
---|
195 | inline
|
---|
196 | boost::graph_traits<MyGraph::Graph>::edges_size_type
|
---|
197 | num_edges(const MyGraph::Graph& g)
|
---|
198 | {
|
---|
199 | return g.edgeCount();
|
---|
200 | }
|
---|
201 |
|
---|
202 | /// AdjacencyMatrix refines Graph and requires:
|
---|
203 | inline
|
---|
204 | std::pair<boost::graph_traits<MyGraph::Graph>::edge_descriptor, bool>
|
---|
205 | edge(boost::graph_traits<MyGraph::Graph>::vertex_descriptor u,
|
---|
206 | boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, const MyGraph::Graph& g)
|
---|
207 | {
|
---|
208 | return g.findEdge(u, v);
|
---|
209 | }
|
---|
210 |
|
---|
211 | /// MutableGraph refines Graph and requires:
|
---|
212 | inline
|
---|
213 | boost::graph_traits<MyGraph::Graph>::vertex_descriptor
|
---|
214 | add_vertex(MyGraph::Graph& g)
|
---|
215 | {
|
---|
216 | return g.addVertex();
|
---|
217 | }
|
---|
218 |
|
---|
219 | inline
|
---|
220 | void
|
---|
221 | clear_vertex(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, MyGraph::Graph& g)
|
---|
222 | {
|
---|
223 | v->clearEdges();
|
---|
224 | }
|
---|
225 |
|
---|
226 | inline
|
---|
227 | void
|
---|
228 | remove_vertex(boost::graph_traits<MyGraph::Graph>::vertex_descriptor v, MyGraph::Graph& g)
|
---|
229 | {
|
---|
230 | g.removeVertex(v);
|
---|
231 | }
|
---|
232 |
|
---|
233 | inline
|
---|
234 | std::pair<boost::graph_traits<MyGraph::Graph>::edge_descriptor, bool>
|
---|
235 | add_edge(boost::graph_traits<MyGraph::Graph>::vertex_descriptor u, boost::graph_traits<MyGraph::Graph>::vertex_descriptor v,
|
---|
236 | MyGraph::Graph& g)
|
---|
237 | {
|
---|
238 | return g.addEdge(u, v);
|
---|
239 | }
|
---|
240 |
|
---|
241 | inline
|
---|
242 | void
|
---|
243 | remove_edge(boost::graph_traits<MyGraph::Graph>::vertex_descriptor u, boost::graph_traits<MyGraph::Graph>::vertex_descriptor v,
|
---|
244 | MyGraph::Graph& g)
|
---|
245 | {
|
---|
246 | std::pair<MyGraph::EdgeDesc, bool> edge_pair = g.findEdge(u, v);
|
---|
247 | if (edge_pair.second){
|
---|
248 | g.removeEdge(edge_pair.first);
|
---|
249 | }
|
---|
250 |
|
---|
251 | }
|
---|
252 |
|
---|
253 | inline
|
---|
254 | void
|
---|
255 | remove_edge(boost::graph_traits<MyGraph::Graph>::edge_descriptor e, MyGraph::Graph& g)
|
---|
256 | {
|
---|
257 | g.removeEdge(e);
|
---|
258 | }
|
---|
259 |
|
---|
260 | inline
|
---|
261 | void
|
---|
262 | remove_edge(boost::graph_traits<MyGraph::Graph>::edge_iterator e_iter, MyGraph::Graph& g)
|
---|
263 | {
|
---|
264 | g.removeEdge(*e_iter);
|
---|
265 | }
|
---|
266 |
|
---|
267 | /// We also need to provide the predefined property maps used by the algorithms we will use.
|
---|
268 |
|
---|
269 | /// The vertex_index_t property map:
|
---|
270 | class VertexDescMap
|
---|
271 | : public boost::put_get_helper<unsigned int, VertexDescMap>
|
---|
272 | {
|
---|
273 | public:
|
---|
274 | typedef boost::readable_property_map_tag category;
|
---|
275 | typedef unsigned int value_type;
|
---|
276 | typedef unsigned int reference;
|
---|
277 | typedef MyGraph::VertexDesc key_type;
|
---|
278 | VertexDescMap()
|
---|
279 | {
|
---|
280 | }
|
---|
281 | VertexDescMap(const MyGraph::Graph& g)
|
---|
282 | {
|
---|
283 | }
|
---|
284 |
|
---|
285 | unsigned int operator[](key_type v) const
|
---|
286 | {
|
---|
287 | return v->index();
|
---|
288 | }
|
---|
289 | };
|
---|
290 |
|
---|
291 | inline
|
---|
292 | VertexDescMap
|
---|
293 | get(boost::vertex_index_t, const MyGraph::Graph& g)
|
---|
294 | {
|
---|
295 | return VertexDescMap(g);
|
---|
296 | }
|
---|
297 |
|
---|
298 | /// The edge_index_t property map:
|
---|
299 | class EdgeDescMap
|
---|
300 | : public boost::put_get_helper<EdgeDesc, EdgeDescMap>
|
---|
301 | {
|
---|
302 | public:
|
---|
303 | typedef boost::readable_property_map_tag category;
|
---|
304 | typedef unsigned int value_type;
|
---|
305 | typedef unsigned int reference;
|
---|
306 | typedef MyGraph::EdgeDesc key_type;
|
---|
307 | EdgeDescMap()
|
---|
308 | {
|
---|
309 | }
|
---|
310 | EdgeDescMap(const MyGraph::Graph& g)
|
---|
311 | {
|
---|
312 | }
|
---|
313 |
|
---|
314 | unsigned int operator[](key_type e) const
|
---|
315 | {
|
---|
316 | return e->index();
|
---|
317 | }
|
---|
318 | };
|
---|
319 |
|
---|
320 | inline
|
---|
321 | EdgeDescMap
|
---|
322 | get(boost::edge_index_t, const MyGraph::Graph& g)
|
---|
323 | {
|
---|
324 | return EdgeDescMap(g);
|
---|
325 | }
|
---|
326 |
|
---|
327 | } // namespace MyGraph
|
---|
328 |
|
---|
329 | /// We must also provide specializations for property_map for our
|
---|
330 | /// graph for the predefined property maps we support.
|
---|
331 | ///
|
---|
332 | /// NOTE: This mechanism is not currently described in the
|
---|
333 | /// documentation on how to provide an adapter for a user defined
|
---|
334 | /// graph.
|
---|
335 | namespace boost {
|
---|
336 |
|
---|
337 | template<>
|
---|
338 | struct property_map<MyGraph::Graph, vertex_index_t>
|
---|
339 | {
|
---|
340 | typedef MyGraph::VertexDescMap type;
|
---|
341 |
|
---|
342 | /// The BGL graphs all seem to define their
|
---|
343 | /// property_map<...>::const_type the same as their
|
---|
344 | /// property_map<...>::type (ie both non-const). It seems that
|
---|
345 | /// ::const_type ought to be the const version of ::type.
|
---|
346 | /// However, making it a const type results in
|
---|
347 | /// make_iterator_property_map not working.
|
---|
348 | typedef const MyGraph::VertexDescMap const_type;
|
---|
349 | };
|
---|
350 |
|
---|
351 | /// We also provide a specialization for the edge_index_t which serves
|
---|
352 | /// the same purpose as vertex_index_t except for the edges.
|
---|
353 | template<>
|
---|
354 | struct property_map<MyGraph::Graph, edge_index_t>
|
---|
355 | {
|
---|
356 | typedef MyGraph::EdgeDescMap type;
|
---|
357 | typedef const MyGraph::EdgeDescMap const_type;
|
---|
358 | };
|
---|
359 |
|
---|
360 | } // namespace boost
|
---|