]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/graph/test/parallel_edges_loops_test.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / graph / test / parallel_edges_loops_test.cpp
CommitLineData
7c673cae
FG
1//=======================================================================
2// Copyright 2007 Aaron Windsor
3//
4// Distributed under the Boost Software License, Version 1.0. (See
5// accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//=======================================================================
8
9/*
10
11This test is almost identical to all_planar_input_files_test.cpp
12except that parallel edges and loops are added to the graphs as
13they are read in.
14
15This test needs to be linked against Boost.Filesystem.
16
17*/
18
19#define BOOST_FILESYSTEM_VERSION 3
20
21#include <iostream>
22#include <fstream>
23#include <vector>
24#include <string>
25#include <utility>
26
7c673cae
FG
27#include <boost/property_map/property_map.hpp>
28#include <boost/lexical_cast.hpp>
29#include <boost/tuple/tuple.hpp>
30#include <boost/filesystem.hpp>
31#include <boost/algorithm/string.hpp>
f67539c2 32#include <boost/core/lightweight_test.hpp>
7c673cae
FG
33
34#include <boost/graph/adjacency_list.hpp>
35#include <boost/graph/depth_first_search.hpp>
36#include <boost/graph/properties.hpp>
37#include <boost/graph/graph_traits.hpp>
38#include <boost/graph/planar_canonical_ordering.hpp>
39#include <boost/graph/make_connected.hpp>
40#include <boost/graph/make_biconnected_planar.hpp>
41#include <boost/graph/make_maximal_planar.hpp>
42#include <boost/graph/is_straight_line_drawing.hpp>
43#include <boost/graph/is_kuratowski_subgraph.hpp>
44#include <boost/graph/chrobak_payne_drawing.hpp>
45#include <boost/graph/boyer_myrvold_planar_test.hpp>
46#include <boost/graph/planar_detail/add_edge_visitors.hpp>
47
f67539c2 48using namespace boost;
7c673cae 49
f67539c2
TL
50struct coord_t
51{
52 std::size_t x;
53 std::size_t y;
54};
7c673cae 55
f67539c2
TL
56template < typename Graph >
57void read_dimacs(Graph& g, const std::string& filename)
58{
7c673cae 59
f67539c2
TL
60 // every <vertex_stride>th vertex has a self-loop
61 int vertex_stride = 5;
7c673cae 62
f67539c2
TL
63 // on vertices with self loops, there are between 1 and
64 // <max_loop_multiplicity> loops
65 int max_loop_multiplicity = 6;
7c673cae 66
f67539c2
TL
67 // every <edge_stride>th edge is a parallel edge
68 int edge_stride = 7;
7c673cae 69
f67539c2
TL
70 // parallel edges come in groups of 2 to <max_edge_multiplicity> + 1
71 int max_edge_multiplicity = 5;
7c673cae 72
f67539c2
TL
73 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
74 typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
75 std::vector< vertex_t > vertices_by_index;
7c673cae 76
f67539c2 77 std::ifstream in(filename.c_str());
7c673cae 78
f67539c2
TL
79 long num_edges_added = 0;
80 long num_parallel_edges = 0;
7c673cae 81
f67539c2 82 while (!in.eof())
7c673cae 83 {
f67539c2
TL
84
85 char buffer[256];
86 in.getline(buffer, 256);
87 std::string s(buffer);
88
89 if (s.size() == 0)
90 continue;
91
92 std::vector< std::string > v;
93 split(v, buffer, is_any_of(" \t\n"));
94
95 if (v[0] == "p")
7c673cae 96 {
f67539c2
TL
97 // v[1] == "edge"
98 long num_vertices = boost::lexical_cast< long >(v[2].c_str());
99 g = Graph(num_vertices);
100
101 vertex_iterator_t vi, vi_end;
102 long count = 0;
103 long mult_count = 0;
104 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
7c673cae 105 {
f67539c2 106 if (count % vertex_stride == 0)
7c673cae 107 {
f67539c2
TL
108 for (int i = 0;
109 i < (mult_count % max_loop_multiplicity) + 1; ++i)
7c673cae 110 {
f67539c2 111 add_edge(*vi, *vi, g);
7c673cae 112 }
f67539c2 113 ++mult_count;
7c673cae 114 }
f67539c2 115 ++count;
7c673cae 116 }
f67539c2
TL
117
118 std::copy(vertices(g).first, vertices(g).second,
119 std::back_inserter(vertices_by_index));
7c673cae 120 }
f67539c2 121 else if (v[0] == "e")
7c673cae 122 {
f67539c2
TL
123 add_edge(
124 vertices_by_index[boost::lexical_cast< long >(v[1].c_str())],
125 vertices_by_index[boost::lexical_cast< long >(v[2].c_str())],
126 g);
7c673cae 127
f67539c2 128 if (num_edges_added % edge_stride == 0)
7c673cae 129 {
f67539c2
TL
130 for (int i = 0;
131 i < (num_parallel_edges % max_edge_multiplicity) + 1; ++i)
7c673cae 132 {
f67539c2
TL
133 add_edge(vertices_by_index[boost::lexical_cast< long >(
134 v[1].c_str())],
135 vertices_by_index[boost::lexical_cast< long >(
136 v[2].c_str())],
137 g);
7c673cae 138 }
f67539c2 139 ++num_parallel_edges;
7c673cae 140 }
f67539c2 141 ++num_edges_added;
7c673cae
FG
142 }
143 }
144}
145
7c673cae
FG
146struct face_counter : planar_face_traversal_visitor
147{
148
f67539c2 149 face_counter() : m_num_faces(0) {}
7c673cae 150
f67539c2 151 void begin_face() { ++m_num_faces; }
7c673cae 152
f67539c2 153 long num_faces() { return m_num_faces; }
7c673cae 154
f67539c2
TL
155private:
156 long m_num_faces;
7c673cae
FG
157};
158
f67539c2
TL
159int test_graph(const std::string& dimacs_filename)
160{
7c673cae 161
f67539c2
TL
162 typedef adjacency_list< listS, vecS, undirectedS,
163 property< vertex_index_t, int >, property< edge_index_t, int > >
164 graph;
165
166 typedef graph_traits< graph >::edge_descriptor edge_t;
167 typedef graph_traits< graph >::edge_iterator edge_iterator_t;
168 typedef graph_traits< graph >::vertex_iterator vertex_iterator_t;
169 typedef graph_traits< graph >::edges_size_type e_size_t;
170 typedef graph_traits< graph >::vertex_descriptor vertex_t;
171 typedef edge_index_update_visitor<
172 property_map< graph, edge_index_t >::type >
173 edge_visitor_t;
174
175 vertex_iterator_t vi, vi_end;
176 edge_iterator_t ei, ei_end;
177
178 graph g;
179 read_dimacs(g, dimacs_filename);
180
181 // Initialize the interior edge index
182 property_map< graph, edge_index_t >::type e_index = get(edge_index, g);
183 e_size_t edge_count = 0;
184 for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
185 put(e_index, *ei, edge_count++);
186
187 // Initialize the interior vertex index - not needed if the vertices
188 // are stored with a vecS
189 /*
190 property_map<graph, vertex_index_t>::type v_index = get(vertex_index, g);
191 v_size_t vertex_count = 0;
192 for(boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
193 put(v_index, *vi, vertex_count++);
194 */
195
196 // This edge_updater will automatically update the interior edge
197 // index of the graph as edges are created.
198 edge_visitor_t edge_updater(get(edge_index, g), num_edges(g));
199
200 // The input graph may not be maximal planar, but the Chrobak-Payne straight
201 // line drawing needs a maximal planar graph as input. So, we make a copy of
202 // the original graph here, then add edges to the graph to make it maximal
203 // planar. When we're done creating a drawing of the maximal planar graph,
204 // we can use the same mapping of vertices to points on the grid to embed
205 // the original, non-maximal graph.
206 graph g_copy(g);
207
208 // Add edges to make g connected, if it isn't already
209 make_connected(g, get(vertex_index, g), edge_updater);
210
211 std::vector< graph_traits< graph >::edge_descriptor > kuratowski_edges;
212
213 typedef std::vector< std::vector< edge_t > > edge_permutation_storage_t;
214 typedef boost::iterator_property_map< edge_permutation_storage_t::iterator,
215 property_map< graph, vertex_index_t >::type >
216 edge_permutation_t;
217
218 edge_permutation_storage_t edge_permutation_storage(num_vertices(g));
219 edge_permutation_t perm(
220 edge_permutation_storage.begin(), get(vertex_index, g));
221
222 // Test for planarity, computing the planar embedding or the kuratowski
223 // subgraph.
224 if (!boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
225 boyer_myrvold_params::embedding = perm,
226 boyer_myrvold_params::kuratowski_subgraph
227 = std::back_inserter(kuratowski_edges)))
228 {
229 std::cerr << "Not planar. ";
230 BOOST_TEST(is_kuratowski_subgraph(
231 g, kuratowski_edges.begin(), kuratowski_edges.end()));
7c673cae 232
f67539c2
TL
233 return 0;
234 }
7c673cae 235
f67539c2
TL
236 // If we get this far, we have a connected planar graph.
237 make_biconnected_planar(g, perm, get(edge_index, g), edge_updater);
7c673cae 238
f67539c2
TL
239 // Compute the planar embedding of the (now) biconnected planar graph
240 BOOST_TEST(boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
241 boyer_myrvold_params::embedding = perm));
7c673cae 242
f67539c2
TL
243 // If we get this far, we have a biconnected planar graph
244 make_maximal_planar(
245 g, perm, get(vertex_index, g), get(edge_index, g), edge_updater);
7c673cae 246
f67539c2
TL
247 // Now the graph is triangulated - we can compute the final planar embedding
248 BOOST_TEST(boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
249 boyer_myrvold_params::embedding = perm));
7c673cae 250
f67539c2
TL
251 // Make sure Euler's formula holds
252 face_counter vis;
253 planar_face_traversal(g, perm, vis, get(edge_index, g));
7c673cae 254
f67539c2 255 BOOST_TEST(num_vertices(g) - num_edges(g) + vis.num_faces() == 2);
7c673cae 256
f67539c2
TL
257 // Compute a planar canonical ordering of the vertices
258 std::vector< vertex_t > ordering;
259 planar_canonical_ordering(g, perm, std::back_inserter(ordering));
7c673cae 260
f67539c2 261 BOOST_TEST(ordering.size() == num_vertices(g));
7c673cae 262
f67539c2
TL
263 typedef std::vector< coord_t > drawing_storage_t;
264 typedef boost::iterator_property_map< drawing_storage_t::iterator,
265 property_map< graph, vertex_index_t >::type >
266 drawing_map_t;
7c673cae 267
f67539c2
TL
268 drawing_storage_t drawing_vector(num_vertices(g));
269 drawing_map_t drawing(drawing_vector.begin(), get(vertex_index, g));
7c673cae 270
f67539c2
TL
271 // Compute a straight line drawing
272 chrobak_payne_straight_line_drawing(
273 g, perm, ordering.begin(), ordering.end(), drawing);
7c673cae 274
f67539c2
TL
275 std::cerr << "Planar. ";
276 BOOST_TEST(is_straight_line_drawing(g, drawing));
7c673cae 277
f67539c2
TL
278 return 0;
279}
280
281int main(int argc, char* argv[])
7c673cae
FG
282{
283
f67539c2
TL
284 std::string input_directory_str = "planar_input_graphs";
285 if (argc > 1)
7c673cae 286 {
f67539c2 287 input_directory_str = std::string(argv[1]);
7c673cae
FG
288 }
289
f67539c2
TL
290 std::cout << "Reading planar input files from " << input_directory_str
291 << std::endl;
7c673cae 292
f67539c2
TL
293 filesystem::path input_directory
294 = filesystem::system_complete(filesystem::path(input_directory_str));
295 const std::string dimacs_extension = ".dimacs";
7c673cae 296
f67539c2
TL
297 filesystem::directory_iterator dir_end;
298 for (filesystem::directory_iterator dir_itr(input_directory);
299 dir_itr != dir_end; ++dir_itr)
300 {
7c673cae 301
f67539c2
TL
302 if (dir_itr->path().extension() != dimacs_extension)
303 continue;
7c673cae 304
f67539c2
TL
305 std::cerr << "Testing " << dir_itr->path().leaf() << "... ";
306 BOOST_TEST(test_graph(dir_itr->path().string()) == 0);
7c673cae 307
f67539c2
TL
308 std::cerr << std::endl;
309 }
7c673cae 310
f67539c2 311 return boost::report_errors();
7c673cae 312}