1 //=======================================================================
2 // Copyright 2002 Indiana University.
3 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
9 
10 #include <boost/config.hpp>
11 
12 #include <iostream>
13 #include <vector>
14 #include <set>
15 #include <utility>
16 #include <algorithm>
17 
18 #define VERBOSE 0
19 
20 #include <boost/utility.hpp>
21 #include <boost/graph/graph_utility.hpp>
22 #include <boost/graph/random.hpp>
23 #include <boost/pending/indirect_cmp.hpp>
24 
25 #include <boost/random/mersenne_twister.hpp>
26 
27 
28 enum vertex_id_t { vertex_id = 500 };
29 enum edge_id_t { edge_id = 501 };
30 namespace boost {
31   BOOST_INSTALL_PROPERTY(vertex, id);
32   BOOST_INSTALL_PROPERTY(edge, id);
33 }
34 
35 
36 #include "graph_type.hpp" // this provides a typedef for Graph
37 
38 using namespace boost;
39 
40 /*
41   This program tests models of the MutableGraph concept.
42  */
43 
44 using std::cout;
45 using std::endl;
46 using std::cerr;
47 using std::find;
48 
49 
50 template <class Graph, class Vertex, class ID>
check_vertex_cleared(Graph & g,Vertex v,ID id)51 bool check_vertex_cleared(Graph& g, Vertex v, ID id)
52 {
53   typename graph_traits<Graph>::vertex_iterator vi, viend;
54   for (boost::tie(vi,viend) = vertices(g); vi != viend; ++vi) {
55     typename graph_traits<Graph>::adjacency_iterator ai, aiend, found;
56     boost::tie(ai, aiend) = adjacent_vertices(*vi, g);
57     boost::indirect_cmp<ID, std::equal_to<std::size_t> > cmp(id);
58 
59 #if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) && defined(__SGI_STL_PORT)
60     // seeing internal compiler errors when using std::find_if()
61     found = aiend;
62     for ( ; ai != aiend; ++ai)
63       if (cmp(*ai, v)) {
64         found = ai;
65         break;
66       }
67 #else
68     found = std::find_if(ai, aiend, std::bind1st(cmp,v));
69 #endif
70 
71     if ( found != aiend ) {
72 #if VERBOSE
73       std::cerr << "should not have found vertex " << id[*found] << std::endl;
74 #endif
75       return false;
76     }
77   }
78   return true;
79 }
80 
81 template <class Graph, class Edge, class EdgeID>
check_edge_added(Graph & g,Edge e,typename graph_traits<Graph>::vertex_descriptor a,typename graph_traits<Graph>::vertex_descriptor b,EdgeID edge_id,std::size_t correct_id,bool inserted)82 bool check_edge_added(Graph& g, Edge e,
83                       typename graph_traits<Graph>::vertex_descriptor a,
84                       typename graph_traits<Graph>::vertex_descriptor b,
85                       EdgeID edge_id, std::size_t correct_id,
86                       bool inserted)
87 {
88   if (! (source(e, g) == a)) {
89 #if VERBOSE
90     cerr << "    Failed, vertex a not source of e."<< endl;
91 #endif
92     return false;
93   } else if (! (target(e, g) == b)) {
94 #if VERBOSE
95     cerr << "    Failed, vertex b not source of e."<< endl;
96 #endif
97     return false;
98   } else if (! is_adjacent(g, a, b)) {
99 #if VERBOSE
100     cerr << "    Failed, not adj."<< endl;
101 #endif
102     return false;
103   } else if (! in_edge_set(g,e)) {
104 #if VERBOSE
105     cerr << "    Failed, not in edge set."<< endl;
106 #endif
107     return false;
108   } else if (inserted && edge_id[e] != correct_id) {
109 #if VERBOSE
110     cerr << "    Failed, invalid edge property."<< endl;
111 #endif
112     return false;
113   } else if (!inserted && edge_id[e] != edge_id[edge(a, b, g).first]) {
114 #if VERBOSE
115     cerr << "    Failed, invalid edge property."<< endl;
116 #endif
117     return false;
118   } else if (num_edges(g) != count_edges(g)) {
119 #if VERBOSE
120     cerr << "    Failed, invalid number of edges."<< endl;
121 #endif
122     return false;
123   }
124   return true;
125 }
126 
127 
128 template <class Graph>
count_edges(Graph & g)129 std::size_t count_edges(Graph& g)
130 {
131   std::size_t e = 0;
132   typename boost::graph_traits<Graph>::edge_iterator ei,ei_end;
133   for (boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
134     ++e;
135   return e;
136 }
137 
138 
main(int,char * [])139 int main(int, char* [])
140 {
141   int ret = 0;
142   std::size_t N = 5, E = 0;
143   std::size_t old_N;
144 
145   typedef ::Graph Graph;
146   Graph g;
147   typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
148   typedef boost::graph_traits<Graph>::edge_descriptor Edge;
149 
150   int i, j;
151   std::size_t current_vertex_id = 0;
152   std::size_t current_edge_id = 0;
153 
154   bool is_failed = false;
155 
156   property_map<Graph, vertex_id_t>::type vertex_id_map = get(vertex_id, g);
157 
158   property_map<Graph, edge_id_t>::type edge_id_map = get(edge_id, g);
159 
160   for (std::size_t k = 0; k < N; ++k)
161     add_vertex(current_vertex_id++, g);
162 
163   // also need to test EdgeIterator graph constructor -JGS
164   mt19937 gen;
165 
166   for (j=0; j < 10; ++j) {
167 
168     // add_edge
169 #if VERBOSE
170     cerr << "Testing add_edge ..." << endl;
171 #endif
172     for (i=0; i < 6; ++i) {
173       Vertex a, b;
174       a = random_vertex(g, gen);
175       do {
176         b = random_vertex(g, gen);
177       } while ( a == b ); // don't do self edges
178 #if VERBOSE
179       cerr << "add_edge(" << vertex_id_map[a] << "," << vertex_id_map[b] <<")" << endl;
180 #endif
181       Edge e;
182       bool inserted;
183       boost::tie(e, inserted) = add_edge(a, b, current_edge_id++, g);
184 #if VERBOSE
185       std::cout << "inserted: " << inserted << std::endl;
186       std::cout << "source(e,g)" << source(e,g) << endl;
187       std::cout << "target(e,g)" << target(e,g) << endl;
188       std::cout << "edge_id[e] = " << edge_id_map[e] << std::endl;
189       print_edges2(g, vertex_id_map, edge_id_map);
190       print_graph(g, vertex_id_map);
191       std::cout << "finished printing" << std::endl;
192       //      print_in_edges(g, vertex_id_map);
193 #endif
194       if (! check_edge_added(g, e, a, b, edge_id_map,
195                              current_edge_id - 1, inserted)) {
196         ret = -1;
197         break;
198       }
199       ++E;
200     }
201 
202     // remove_edge(u, v, g)
203 #if VERBOSE
204     cerr << "Testing remove_edge(u, v, g) ..." << endl; is_failed = false;
205 #endif
206     for (i = 0; i < 2; ++i) {
207 #if VERBOSE
208       print_edges(g, vertex_id_map);
209 #endif
210       Vertex a, b;
211 
212       Edge e = random_edge(g, gen);
213       boost::tie(a,b) = boost::incident(e, g);
214       --E;
215 #if VERBOSE
216       cerr << "remove_edge(" << vertex_id_map[a] << "," << vertex_id_map[b] << ")" << endl;
217 #endif
218       remove_edge(a, b, g);
219 #if VERBOSE
220       print_graph(g, vertex_id_map);
221       //      print_in_edges(g, vertex_id_map);
222       print_edges(g, vertex_id_map);
223 #endif
224       is_failed = is_failed || is_adjacent(g, a, b) || in_edge_set(g, a, b)
225         || num_edges(g) != count_edges(g);
226       if (is_failed)
227         break;
228     }
229     if ( is_failed ) {
230       ret = -1;
231 #if VERBOSE
232       cerr << "    Failed."<< endl;
233 #endif
234     } else {
235 #if VERBOSE
236       cerr << "           Passed."<< endl;
237 #endif
238     }
239 
240     // remove_edge(e, g)
241 #if VERBOSE
242     cerr << "Testing remove_edge(e, g) ..." << endl; is_failed = false;
243 #endif
244     for (i = 0; i < 2; ++i) {
245 #if VERBOSE
246       print_edges(g, vertex_id_map);
247 #endif
248       Vertex a, b;
249       Edge e = random_edge(g, gen);
250       boost::tie(a,b) = boost::incident(e, g);
251       --E;
252 #if VERBOSE
253       cerr << "remove_edge(" << vertex_id_map[a] << "," << vertex_id_map[b] << ")" << endl;
254 #endif
255       graph_traits<Graph>::edges_size_type old_E = num_edges(g);
256       remove_edge(e, g);
257 
258 #if VERBOSE
259       print_graph(g, vertex_id_map);
260       //      print_in_edges(g, vertex_id_map);
261       print_edges(g, vertex_id_map);
262 #endif
263 
264       is_failed = is_failed || old_E != num_edges(g) + 1
265         || num_edges(g) != count_edges(g);
266       if (is_failed)
267         break;
268     }
269     if ( is_failed ) {
270       ret = -1;
271 #if VERBOSE
272       cerr << "    Failed."<< endl;
273 #endif
274     } else {
275 #if VERBOSE
276       cerr << "           Passed."<< endl;
277 #endif
278     }
279 
280     // add_vertex
281 #if VERBOSE
282     cerr << "Testing add_vertex ..." << endl; is_failed = false;
283 #endif
284     old_N = num_vertices(g);
285     graph_traits<Graph>::vertex_descriptor vid = add_vertex(g),
286       vidp1 = add_vertex(g);
287     vertex_id_map[vid] = current_vertex_id++;
288     vertex_id_map[vidp1] = current_vertex_id++;
289 
290 #if VERBOSE
291     print_vertices(g,vertex_id_map);
292     print_graph(g,vertex_id_map);
293     //    print_in_edges(g,vertex_id_map);
294     print_edges(g,vertex_id_map);
295 #endif
296     // make sure the two added vertices are in the graph's vertex set
297     {
298       if (!in_vertex_set(g, vid)) {
299 #if VERBOSE
300         cerr << "   Failed, " << vertex_id_map[vid] << " not in vertices(g)" << endl;
301 #endif
302         ret = -1;
303         break;
304       }
305       if (!in_vertex_set(g, vidp1)) {
306 #if VERBOSE
307         cerr << "   Failed, " << vertex_id_map[vidp1] << " not in vertices(g)" << endl;
308 #endif
309         ret = -1;
310         break;
311       }
312     }
313 
314     // make sure the vertices do not have any out edges yet
315     {
316       graph_traits<Graph>::out_edge_iterator e, e_end;
317       boost::tie(e,e_end) = out_edges(vid,g);
318       if (e != e_end) {
319 #if VERBOSE
320         cerr << "   Failed, " << vertex_id_map[vid]
321              << " should not have any out-edges yet" << endl;
322 #endif
323         ret = -1;
324         break;
325       }
326       boost::tie(e,e_end) = out_edges(vidp1,g);
327       if (e != e_end) {
328 #if VERBOSE
329         cerr << "   Failed, " << vertex_id_map[vidp1]
330              << " should not have any out-edges yet" << endl;
331 #endif
332         ret = -1;
333         break;
334       }
335     }
336 
337     // make sure the vertices do not yet appear in any of the edges
338     {
339       graph_traits<Graph>::edge_iterator e, e_end;
340       for (boost::tie(e, e_end) = edges(g); e != e_end; ++e) {
341         if (source(*e,g) == vid || target(*e,g) == vid) {
342 #if VERBOSE
343           cerr << "   Failed, " << vertex_id_map[vid]
344                << " should not have any edges" << endl;
345 #endif
346           ret = -1;
347           break;
348         }
349         if (source(*e,g) == vidp1 || target(*e,g) == vidp1) {
350 #if VERBOSE
351           cerr << "   Failed, " << vertex_id_map[vidp1]
352                << " should not have any edges" << endl;
353 #endif
354           ret = -1;
355           break;
356         }
357       }
358     }
359     // Make sure num_vertices(g) has been updated
360     N = num_vertices(g);
361     if ( (N - 2) != old_N ) {
362       ret = -1;
363 #if VERBOSE
364       cerr << "    Failed. N = " << N
365            << " but should be " << old_N + 2 << endl;
366 #endif
367       break;
368     } else {
369 #if VERBOSE
370       cerr << "           Passed."<< endl;
371 #endif
372     }
373     // add_edge again
374 #if VERBOSE
375     cerr << "Testing add_edge after add_vertex ..." << endl; is_failed = false;
376 #endif
377 
378     for (i=0; i<2; ++i) {
379       Vertex a = random_vertex(g, gen), b = random_vertex(g, gen);
380       while ( a == vid ) a = random_vertex(g, gen);
381       while ( b == vidp1 ) b = random_vertex(g, gen);
382       Edge e;
383       bool inserted;
384 #if VERBOSE
385       cerr << "add_edge(" << vertex_id_map[vid] << "," << vertex_id_map[a] <<")" << endl;
386 #endif
387       boost::tie(e,inserted) = add_edge(vid, a, EdgeID(current_edge_id++), g);
388 
389       if (! check_edge_added(g, e, vid, a, edge_id_map, current_edge_id - 1,
390                              inserted)) {
391         ret = -1;
392         break;
393       }
394 
395 #if VERBOSE
396       cerr << "add_edge(" << vertex_id_map[b] << "," << vertex_id_map[vidp1] <<")" << endl;
397 #endif
398       // add_edge without plugin
399       boost::tie(e,inserted) = add_edge(b, vidp1, g);
400       if (inserted)
401         edge_id_map[e] = current_edge_id;
402       ++current_edge_id;
403 
404       if (! check_edge_added(g, e, b, vidp1, edge_id_map,
405                              current_edge_id - 1, inserted)) {
406         ret = -1;
407         break;
408       }
409     }
410 
411     // clear_vertex
412     Vertex c = random_vertex(g, gen);
413 #if VERBOSE
414     cerr << "Testing clear vertex ..." << endl; is_failed = false;
415     print_graph(g, vertex_id_map);
416     //    print_in_edges(g, vertex_id_map);
417     cerr << "clearing vertex " << vertex_id_map[c] << endl;
418 #endif
419     clear_vertex(c, g);
420 #if VERBOSE
421     print_graph(g, vertex_id_map);
422     //    print_in_edges(g, vertex_id_map);
423     print_edges(g, vertex_id_map);
424 #endif
425     if (check_vertex_cleared(g, c, vertex_id_map) && num_edges(g) == count_edges(g)) {
426 #if VERBOSE
427       cerr << " Passed."<< endl;
428 #endif
429     } else {
430 #if VERBOSE
431       cerr << "**** Failed" << endl;
432 #endif
433       ret = -1;
434       break;
435     }
436 
437 #if VERBOSE
438     cerr << "Testing remove vertex ..." << endl; is_failed = false;
439     cerr << "removing vertex " << vertex_id_map[c] << endl;
440 #endif
441 
442     old_N = num_vertices(g);
443     remove_vertex(c, g);
444 #if VERBOSE
445     print_graph(g,vertex_id_map);
446     //    print_in_edges(g,vertex_id_map);
447     print_edges(g, vertex_id_map);
448 #endif
449     // can't check in_vertex_set here because the vertex_descriptor c
450     // is no longer valid, we'll just make sure the vertex set has
451     // one fewer vertex
452     {
453       graph_traits<Graph>::vertex_iterator v, v_end;
454       boost::tie(v, v_end) = vertices(g);
455       for (N = 0; v != v_end; ++v) ++N; // N = std::distance(v, v_end);
456       if (N != old_N - 1) {
457         ret = -1;
458 #if VERBOSE
459         cerr << "    Failed. N = " << N
460              << " but should be " << old_N - 1 << endl;
461 #endif
462       }
463     }
464 
465     N = num_vertices(g);
466     if (N != old_N - 1) {
467       ret = -1;
468 #if VERBOSE
469       cerr << "    Failed. N = " << N
470            << " but should be " << old_N - 1 << endl;
471 #endif
472     } else {
473 #if VERBOSE
474       cerr << "           Passed."<< endl;
475 #endif
476     }
477   }
478   if (ret == 0)
479     std::cout << "tests passed" << std::endl;
480 
481   return ret;
482 }
483