1 // This is brl/bbas/bgrl2/bgrl2_graph.hxx
2 #ifndef bgrl2_graph_hxx_
3 #define bgrl2_graph_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include <vector>
9 #include "bgrl2_graph.h"
10 
11 #include <cassert>
12 #ifdef _MSC_VER
13 #  include <vcl_msvc_warnings.h>
14 #endif
15 
16 //-------------------------------------------------------------------
17 // Graph building functions
18 //-------------------------------------------------------------------
19 
20 //: Adds a new vertex to the graph
21 template<class V, class E>
add_vertex(V_sptr v)22 bool bgrl2_graph<V,E>::add_vertex(V_sptr v)
23 {
24   if (!v) return false;
25   vertices_.push_back(v);
26 
27   return true; //not doing a duplicate check anymore
28 }
29 
30 //: check existence
31 template<class V, class E>
exists(V_sptr v)32 bool bgrl2_graph<V,E>::exists(V_sptr v)
33 {
34   for ( vertex_iterator v_itr = vertices_.begin();
35         v_itr != vertices_.end(); ++v_itr )
36   {
37     if ((*v_itr) == v)
38       return true;
39   }
40   return false;
41 }
42 
43 
44 //: Deletes a vertex in the graph
45 template<class V, class E>
remove_vertex(V_sptr v)46 bool bgrl2_graph<V,E>::remove_vertex(V_sptr v)
47 {
48   if (!v) return false;
49 
50   vertices_.remove(v);
51 
52   //delete all the edges connected to this vertex
53   while (v->out_edges().size()>0)
54     remove_edge(*v->out_edges_begin());
55 
56   while (v->in_edges().size()>0)
57     remove_edge(*v->in_edges_begin());
58 
59   return true;
60 }
61 
62 //: Add an edge
63 template<class V, class E>
add_edge(E_sptr e)64 bool bgrl2_graph<V,E>::add_edge(E_sptr e)
65 {
66   // verify that this edge is not already present
67   vertex_edge_iterator e_itr = e->source()->out_edges_begin();
68   for (; e_itr != e->source()->out_edges_end(); ++e_itr )
69     if ((*e_itr)->target() == e->target())
70       return false;
71 
72   edges_.push_back(e);
73   return true;
74 }
75 
76 //: Add an edge with no duplicate checking
77 template<class V, class E>
add_edge_no_check(E_sptr e)78 bool bgrl2_graph<V,E>::add_edge_no_check(E_sptr e)
79 {
80   if (!e)
81     return false;
82   edges_.push_back(e);
83   return true;
84 }
85 
86 
87 //: Add an edge between \p v1 and \p v2
88 template<class V, class E>
add_edge(V_sptr v1,V_sptr v2)89 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::add_edge(V_sptr v1, V_sptr v2)
90 {
91   if (!v1 || !v2)
92     return nullptr;
93   if (v1==v2)
94     return nullptr; //can't add the edge to itself
95 
96   //add the vertices first
97   if (!this->exists(v1))
98     this->add_vertex(v1);
99   if (!this->exists(v2))
100     this->add_vertex(v2);
101 
102   //if ( vertices_.count(v1) == 0 && !this->add_vertex(v1) )
103   //  return false;
104   //if ( vertices_.count(v2) == 0 && !this->add_vertex(v2) )
105   //  return false;
106 
107   //set the source and target nodes
108   E_sptr e = new E(v1, v2);
109 
110   if (this->add_edge(e)){
111     //if this is a valid edge, add the links from the nodes to this edge
112     v1->add_outgoing_edge(e);
113     v2->add_incoming_edge(e);
114 
115     return e;
116   }
117 
118   return nullptr; //edge wasn't added
119 }
120 
121 //: Remove an edge
122 template<class V, class E>
remove_edge(E_sptr e)123 bool bgrl2_graph<V,E>::remove_edge(E_sptr e)
124 {
125   if (!e) return false;
126 
127   edges_.remove(e);
128 
129   //update connectivity from nodes
130   bool success = e->source()->del_out_edge(e);
131 
132   //the edge might not have a target node
133   if (e->target())
134     success = success && e->target()->del_in_edge(e);
135 
136   return success;
137 }
138 
139 //: Remove the edge between \p v1 and \p v2
140 // \todo {finish this.}
141 template<class V, class E>
remove_edge(V_sptr v1,V_sptr v2)142 bool bgrl2_graph<V,E>::remove_edge(V_sptr v1, V_sptr v2 )
143 {
144   if (!v1 || !v2) return false;
145 
146   // verify that this edge is not already present
147   vertex_edge_iterator e_itr = v1->out_edges_begin();
148   for (; e_itr != v1->out_edges_end(); ++e_itr )
149   {
150     if ((*e_itr)->target() == v2){
151       E_sptr e = (*e_itr);
152 
153       return remove_edge(e);
154     }
155   }
156 
157   return false;
158 }
159 
160 //: delete all the vertices
161 template<class V, class E>
del_all_vertices()162 void  bgrl2_graph<V,E>::del_all_vertices()
163 {
164   while (vertices_.size()>0){
165     remove_vertex(*vertices_.begin());
166   }
167 }
168 
169 //: delete all the edges
170 template<class V, class E>
del_all_edges()171 void  bgrl2_graph<V,E>::del_all_edges()
172 {
173   while (edges_.size()>0){
174     remove_edge(*edges_.begin());
175   }
176 }
177 
178 //: delete all vertices in the graph that are not adjacent to any edges
179 template<class V, class E>
purge_isolated_vertices()180 void bgrl2_graph<V,E>::purge_isolated_vertices()
181 {
182   std::vector<V_sptr> vert_to_del;
183   for ( vertex_iterator v_itr = vertices_.begin();
184         v_itr != vertices_.end(); ++v_itr )
185   {
186     if ((*v_itr)->degree()==0)
187       vert_to_del.push_back(*v_itr);
188   }
189 
190   //is there a better way to do this ???
191   for (unsigned int i=0; i<vert_to_del.size(); i++)
192     remove_vertex(vert_to_del[i]);
193 
194   vert_to_del.clear();
195 }
196 
197 //: return all vertices with degree one
198 template<class V, class E>
get_all_degree_one_vertices(std::vector<V_sptr> & vertices)199 void bgrl2_graph<V,E>::get_all_degree_one_vertices(std::vector<V_sptr>& vertices)
200 {
201   for ( vertex_iterator v_itr = vertices_.begin();
202         v_itr != vertices_.end(); ++v_itr )
203   {
204     if ((*v_itr)->degree()==1)
205       vertices.push_back(*v_itr);
206   }
207 }
208 
209 //: clear all the nodes and edges of this graph
210 template<class V, class E>
clear()211 void bgrl2_graph<V,E>::clear()
212 {
213   del_all_edges();
214   del_all_vertices();
215 }
216 
217 //-------------------------------------------------------------------
218 // Directed graph operations
219 //-------------------------------------------------------------------
220 
221 //:  returns the successor of edge e in the adjacency list of node source(e) (nil if it does not exist).
222 template<class V, class E>
adj_succ(E_sptr e)223 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::adj_succ(E_sptr e)
224 {
225   return adj_succ(e, e->source());
226 }
227 
228 //:  returns the predecessor of edge e in the adjacency list of node source(e) (nil if it does not exist).
229 template<class V, class E>
adj_pred(E_sptr e)230 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::adj_pred(E_sptr e)
231 {
232   return adj_pred(e, e->source());
233 }
234 
235 //:  returns the cyclic successor of edge e in the adjacency list of node source(e).
236 template<class V, class E>
cyclic_adj_succ(E_sptr e)237 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_adj_succ(E_sptr e)
238 {
239   return cyclic_adj_succ(e, e->source());
240 }
241 
242 //:  returns the cyclic predecessor of edge e in the adjacency list of node source(e).
243 template<class V, class E>
cyclic_adj_pred(E_sptr e)244 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_adj_pred(E_sptr e)
245 {
246   return cyclic_adj_pred(e, e->source());
247 }
248 
249 //: returns the first edge of in_edges(v) (nil if this list is empty).
250 template<class V, class E>
first_in_edge(V_sptr v)251 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::first_in_edge(V_sptr v)
252 {
253   if (v->in_edges().size()>0)
254     return v->in_edges().front();
255   else
256     return nullptr;
257 }
258 
259 //:  returns the last edge of in_edges(v) (nil if this list is empty).
260 template<class V, class E>
last_in_edge(V_sptr v)261 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::last_in_edge(V_sptr v)
262 {
263   if (v->in_edges().size()>0)
264     return v->in_edges().back();
265   else
266     return nullptr;
267 }
268 
269 //: returns the first edge of out_edges(v) (nil if this list is empty).
270 template<class V, class E>
first_out_edge(V_sptr v)271 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::first_out_edge(V_sptr v)
272 {
273   if (v->out_edges().size()>0)
274     return v->out_edges().front();
275   else
276     return nullptr;
277 }
278 
279 //:  returns the last edge of out_edges(v) (nil if this list is empty).
280 template<class V, class E>
last_out_edge(V_sptr v)281 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::last_out_edge(V_sptr v)
282 {
283   if (v->out_edges().size()>0)
284     return v->out_edges().back();
285   else
286     return nullptr;
287 }
288 
289 //:  returns the successor of edge e in in_edges(target(e)) (nil if it does not exist).
290 template<class V, class E>
in_succ(E_sptr e)291 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::in_succ(E_sptr e)
292 {
293   return adj_succ(e, e->target());
294 }
295 
296 //:  returns the predecessor of edge e in in_edges(target(e)) (nil if it does not exist).
297 template<class V, class E>
in_pred(E_sptr e)298 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::in_pred(E_sptr e)
299 {
300   return adj_pred(e, e->target());
301 }
302 
303 //:  returns the cyclic successor of edge e in in_edges(target(e)) (nil if it does not exist).
304 template<class V, class E>
cyclic_in_succ(E_sptr e)305 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_in_succ(E_sptr e)
306 {
307   return cyclic_adj_succ(e, e->target());
308 }
309 
310 //:  returns the cyclic predecessor of edge e in in_edges(target(e)) (nil if it does not exist).
311 template<class V, class E>
cyclic_in_pred(E_sptr e)312 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_in_pred(E_sptr e)
313 {
314   return cyclic_adj_pred(e, e->target());
315 }
316 
317 //-------------------------------------------------------------------
318 // Undirected graph operations
319 //-------------------------------------------------------------------
320 
321 // IMPORTANT WARNING to users of this graph class to work with DIRECTED graphs:
322 //                   e.g. you have the following graph with times of creation of the edges
323 //                        as noted by the numbers
324 //                                 2
325 //                                 ^
326 //                                 |
327 //                            1 -> A <- 3
328 //                                 |
329 //                                 v
330 //                                 4
331 //                   Ideally, cyclic_adj_succ(1,A) should return 2
332 //                   however, in this implementation it returns 3 (the next in_edge)
333 //                   (When this class is used for shock_graphs because of special properties
334 //                    of shock_graphs, this is not a problem, i.e. the case in our example
335 //                    never happens in a shock graph, it is against the nature of flows
336 //                    that gives rise to directed shock graphs.)
337 //
338 //                   This should be noted and corrected or undirected graph operations
339 //                   should never be used on directed graphs where the example case can occur
340 
341 //:  returns the first edge in the adjacency list of v (nil if this list is empty).
342 template<class V, class E>
first_adj_edge(V_sptr v)343 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::first_adj_edge(V_sptr v)
344 {
345   if (first_in_edge(v))
346     return first_in_edge(v);
347   else
348     return first_out_edge(v);
349 }
350 
351 //:  returns the last edge in the adjacency list of v (nil if this list is empty).
352 template<class V, class E>
last_adj_edge(V_sptr v)353 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::last_adj_edge(V_sptr v)
354 {
355   if (last_out_edge(v))
356     return last_out_edge(v);
357   else
358     return last_in_edge(v);
359 }
360 
361 //: returns the successor of edge e in the adjacency list of v.
362 //  Precondition: e is incident to v.
363 template<class V, class E>
adj_succ(E_sptr,V_sptr)364 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::adj_succ(E_sptr /*e*/, V_sptr /*v*/)
365 {
366   return nullptr;
367 }
368 
369 //: returns the predecessor of edge e in the adjacency list of v.
370 //  Precondition: e is incident to v.
371 template<class V, class E>
adj_pred(E_sptr,V_sptr)372 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::adj_pred(E_sptr /*e*/, V_sptr /*v*/)
373 {
374   return nullptr;
375 }
376 
377 //: returns the cyclic successor(CW) of edge e in the adjacency list of v.
378 //  Precondition: e is incident to v.
379 //  if this is a leaf edge, it should return itself
380 template<class V, class E>
cyclic_adj_succ(E_sptr e,V_sptr v)381 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_adj_succ(E_sptr e, V_sptr v)
382 {
383   E_sptr adj_edge=nullptr;
384 
385   //find the edge e in the adjacency list of v
386 
387   //look in the in_edges list first
388   for ( vertex_edge_iterator itr = v->in_edges_begin();
389         itr != v->in_edges_end(); ++itr )
390   {
391     if ((*itr) == e) //edge found
392     {
393       itr++;
394       if (itr != v->in_edges_end()){
395         adj_edge = (*itr);
396       }
397       else { //last in_edge, check out_edges
398         if (v->out_edges().size()>0)
399           adj_edge = v->out_edges().front();
400         else //no out_edges
401           adj_edge = v->in_edges().front();
402       }
403       break;
404     }
405   }
406 
407   //if not found look in the out_edges
408   if (!adj_edge)
409   {
410     for ( vertex_edge_iterator itr = v->out_edges_begin();
411           itr != v->out_edges_end(); ++itr )
412     {
413       if ((*itr) == e) //edge found
414       {
415         itr++;
416         if (itr != v->out_edges_end())
417           adj_edge = (*itr);
418         else  //last out_edge, check in_edges
419         {
420           if (v->in_edges().size()>0)
421             adj_edge = v->in_edges().front();
422           else  //no in_edges
423             adj_edge = v->out_edges().front();
424         }
425         break;
426       }
427     }
428   }
429 
430   //make sure we found it
431   //assert (adj_edge);
432 
433   return adj_edge;
434 }
435 
436 //: returns the cyclic predecessor(CW) of edge e in the adjacency list of v.
437 //  Precondition: e is incident to v.
438 //  if this is a leaf edge, it should return itself
439 template<class V, class E>
cyclic_adj_pred(E_sptr e,V_sptr v)440 typename bgrl2_graph<V,E>::E_sptr bgrl2_graph<V,E>::cyclic_adj_pred(E_sptr e, V_sptr v)
441 {
442   E_sptr adj_edge=nullptr;
443 
444   //find the edge e in the adjacency list of v
445 
446   //look in the in_edges list first
447   for ( vertex_edge_iterator itr = v->in_edges_begin();
448         itr != v->in_edges_end(); ++itr )
449   {
450     if ((*itr) == e) //edge found
451     {
452       if (itr == v->in_edges_begin())
453       {
454         //first in_edge, look in out_edges
455         if (v->out_edges().size()>0)
456           adj_edge = v->out_edges().back();
457         else //no out_edges
458           adj_edge = v->in_edges().back();
459       }
460       else {
461         itr--;
462         adj_edge = (*itr);
463       }
464       break;
465     }
466   }
467 
468   //if not found look in the out_edges
469   if (!adj_edge)
470   {
471     for ( vertex_edge_iterator itr = v->out_edges_begin();
472           itr != v->out_edges_end(); ++itr )
473     {
474       if ((*itr) == e) //edge found
475       {
476         if (itr == v->out_edges_begin())
477         {
478           //first out_edge, check in_edges
479           if (v->in_edges().size()>0)
480             adj_edge = v->in_edges().back();
481           else //no in_edges
482             adj_edge = v->out_edges().back();
483         }
484         else {
485           itr--;
486           adj_edge = (*itr);
487         }
488         break;
489       }
490     }
491   }
492 
493   //make sure we found it
494   assert (adj_edge);
495 
496   return adj_edge;
497 }
498 
499 //-------------------------------------------------------------------
500 // Standard Graph functions
501 //-------------------------------------------------------------------
502 
503 //: Return true if the graph contains a cycle
504 //  This method can go to bgrl2_algo
505 template<class V, class E>
has_cycle()506 bool bgrl2_graph<V,E>::has_cycle()
507 {
508   //: Theorem: given an undirected graph G(V,E), there exists a cycle within the graph if |E| >= |V|
509   if (edges_.size() >= vertices_.size())
510     return true;
511   else
512     return false;
513 }
514 
515 //-------------------------------------------------------------------
516 // Miscellaneous
517 //-------------------------------------------------------------------
518 
519 //: Print an ascii summary to the stream
520 template<class V, class E>
print_summary(std::ostream & os) const521 void bgrl2_graph<V,E>::print_summary( std::ostream& os ) const
522 {
523   os << this->number_of_vertices() << " vertices";
524 }
525 
526 #if 0 // these I/O methods commented out!
527 
528 //: Return IO version number
529 short bgrl2_graph<V,E>::version() const
530 {
531   return 1;
532 }
533 
534 //: Binary save self to stream.
535 void bgrl2_graph<V,E>::b_write(vsl_b_ostream &os) const
536 {
537   vsl_b_write(os, version());
538   vsl_b_write(os, vertices_);
539   vsl_b_write(os, edges_);
540 }
541 
542 //: Binary load self from stream.
543 void bgrl2_graph<V,E>::b_read(vsl_b_istream &is)
544 {
545   if (!is) return;
546 
547   short ver;
548   vsl_b_read(is, ver);
549   switch (ver)
550   {
551   case 1:
552   {
553     vsl_b_read(is, vertices_);
554     vsl_b_read(is, edges_);
555     break;
556   }
557   default:
558     std::cerr << "I/O ERROR: bgrl2_graph<V,E>::b_read(vsl_b_istream&)\n"
559              << "           Unknown version number "<< ver << '\n';
560     is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
561   }
562   return;
563 }
564 #endif // 0
565 
566 #define BGRL2_GRAPH_INSTANTIATE(V, E) \
567 template class bgrl2_graph<V , E >
568 
569 #endif // bgrl2_graph_hxx_
570