Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
graph.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file graph.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // graph.cpp
5 //
6 //==========================================================================
7 // $Id: graph.cpp,v 1.58 2003/01/14 16:47:14 raitner Exp $
8 
9 #include <GTL/graph.h>
10 #include <GTL/node_data.h>
11 #include <GTL/edge_data.h>
12 #include <GTL/node_map.h>
13 
14 #include <GTL/dfs.h>
15 #include <GTL/topsort.h>
16 
17 #include <cassert>
18 #include <cstdio>
19 
20 #include <algorithm>
21 #include <queue>
22 #include <set>
23 #include <map>
24 
25 #include <iostream>
26 #include <fstream>
27 #include <string>
28 #include <cstring>
29 #ifdef __GTL_MSVCC
30 # ifdef _DEBUG
31 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
32 # error SEARCH NOT ENABLED
33 # endif
34 # define new DEBUG_NEW
35 # undef THIS_FILE
36  static char THIS_FILE[] = __FILE__;
37 # endif // _DEBUG
38 #endif // __GTL_MSVCC
39 
41 
42 //--------------------------------------------------------------------------
43 // Con-/Destructors
44 //--------------------------------------------------------------------------
45 
47  directed(true),
48  nodes_count(0), edges_count(0),
49  hidden_nodes_count(0), hidden_edges_count(0),
50  free_node_ids_count(0), free_edge_ids_count(0)
51 {
52 }
53 
54 graph::graph(const graph &G) :
55  directed(G.directed),
56  nodes_count(0), edges_count(0),
57  hidden_nodes_count(0), hidden_edges_count(0),
58  free_node_ids_count(0), free_edge_ids_count(0)
59 {
60  copy (G, G.nodes.begin(), G.nodes.end());
61 }
62 
63 
64 graph::graph (const graph& G, const list<node>& nod) :
65  directed(G.directed),
66  nodes_count(0), edges_count(0),
67  hidden_nodes_count(0), hidden_edges_count(0),
68  free_node_ids_count(0), free_edge_ids_count(0)
69 {
70  copy (G, nod.begin(), nod.end());
71 }
72 
73 
74 graph::graph (const graph& G,
75  list<node>::const_iterator it,
76  list<node>::const_iterator end) :
77  directed(G.directed),
78  nodes_count(0), edges_count(0),
79  hidden_nodes_count(0), hidden_edges_count(0),
80  free_node_ids_count(0), free_edge_ids_count(0)
81 {
82  copy (G, it, end);
83 }
84 
85 void graph::copy (const graph& G,
86  list<node>::const_iterator it,
87  list<node>::const_iterator end)
88 {
89  node_map<node> copy (G, node());
90  list<node>::const_iterator n_it;
91  list<node>::const_iterator n_end;
92 
93  for(n_it = it, n_end = end; n_it != n_end; ++n_it)
94  {
95  copy[*n_it] = new_node();
96  }
97 
98  for(n_it = it, n_end = end; n_it != n_end; ++n_it)
99  {
100  node::out_edges_iterator e_it, e_end;
101 
102  for (e_it = (*n_it).out_edges_begin(), e_end = (*n_it).out_edges_end();
103  e_it != e_end; ++e_it) {
104 
105  if (copy[e_it->target()] != node()) {
106  new_edge(copy[e_it->source()], copy[e_it->target()]);
107  }
108  }
109  }
110 }
111 
112 
113 
115 {
116  clear();
117 }
118 
119 //-------------------------------------------------------------------------
120 // Output
121 //-------------------------------------------------------------------------
122 
123 GTL_EXTERN ostream& operator<< (ostream& os, const graph& G) {
124  node n;
125  edge out;
126  string conn;
127 
128  if (G.is_directed())
129  conn = "-->";
130  else
131  conn = "<-->";
132 
133  forall_nodes (n, G) {
134  os << n << ":: ";
135 
136  forall_adj_edges (out, n) {
137  os << conn << n.opposite (out);
138  }
139 
140  os << endl;
141  }
142 
143  return os;
144 }
145 
146 //--------------------------------------------------------------------------
147 // Directed/Undirected
148 //--------------------------------------------------------------------------
149 
151 {
152  if (!directed)
153  {
155  directed = true;
157  }
158 }
159 
161 {
162  if (directed)
163  {
165  directed = false;
167  }
168 }
169 
170 bool graph::is_directed() const
171 {
172  return directed;
173 }
174 
176 {
177  return !directed;
178 }
179 
180 //--------------------------------------------------------------------------
181 // Creation
182 //--------------------------------------------------------------------------
183 
185 {
187 
188  // create node
189 
190  node n;
191  n.data = new node_data;
192 
193  // set data variables
194 
195  n.data->id = new_node_id();
196  n.data->owner = this;
197  n.data->pos = nodes.insert(nodes.end(), n);
198  n.data->hidden = false;
199  ++nodes_count;
200 
201  // done
202 
204 
205  return n;
206 }
207 
209 {
210  assert(source.data);
211  assert(target.data);
212  assert(source.data->owner == this);
213  assert(target.data->owner == this);
214 
215  pre_new_edge_handler(source, target);
216 
217  // create edge
218 
219  edge e;
220  e.data = new edge_data;
221 
222  // set id
223 
224  e.data->owner = this;
225  e.data->id = new_edge_id();
226 
227  // set sources and targets
228 
229  e.data->nodes[0].push_back(source);
230  e.data->nodes[1].push_back(target);
231 
232  // set pos
233 
234  e.data->pos = edges.insert(edges.end(), e);
235  e.data->hidden = false;
236  ++edges_count;
237 
238  // set adj_pos
239 
240  list<edge> &source_adj = source.data->edges[1];
241  list<edge> &target_adj = target.data->edges[0];
242 
243  e.data->adj_pos[0].push_back(source_adj.insert(source_adj.begin(), e));
244  e.data->adj_pos[1].push_back(target_adj.insert(target_adj.begin(), e));
245 
246  // done
247 
249 
250  return e;
251 }
252 
253 edge graph::new_edge(const list<node> &sources, const list<node> &targets)
254 {
255  // not implemented
256 
257  return edge();
258 }
259 
260 //--------------------------------------------------------------------------
261 // Deletion
262 //--------------------------------------------------------------------------
263 
265 {
266  assert (n.data);
267  assert (n.data->owner == this);
268 
269  // delete edges
270 
271  while(n.in_edges_begin() != n.in_edges_end())
272  {
273  del_edge (*n.in_edges_begin());
274  }
275 
276  while(n.out_edges_begin() != n.out_edges_end())
277  {
278  del_edge (*n.out_edges_begin());
279  }
280 
281  //
282  // delete hidden edges adjacent to n.
283  //
284  // [ TODO ] This is only a quick fix and should be thought
285  // over some time or the other.
286  //
287 
288  list<edge>::iterator it = hidden_edges.begin();
289  list<edge>::iterator end = hidden_edges.end();
290 
291  while (it != end)
292  {
293  if ((*it).source() == n || (*it).target() == n)
294  {
295  delete (*it).data;
296  it = hidden_edges.erase (it);
297  }
298  else
299  {
300  ++it;
301  }
302  }
303 
304  // delete node
305 
307 
308  nodes.erase(n.data->pos);
309  --nodes_count;
310  free_node_ids.push_back(n.data->id);
312  delete n.data;
313 
315 }
316 
318 {
319  assert (e.data->owner == this);
320  assert (e.data->owner == this);
321 
323  node s = e.source();
324  node t = e.target();
325 
326  e.remove_from(0);
327  e.remove_from(1);
328  edges.erase(e.data->pos);
329  --edges_count;
330  free_edge_ids.push_back(e.data->id);
332  delete e.data;
333 
334  post_del_edge_handler(s, t);
335 }
336 
338 {
340 
341  del_list(edges);
343  del_list(nodes);
345 
346  free_node_ids.clear();
347  free_edge_ids.clear();
348 
349  nodes_count = edges_count = 0;
352 
354 }
355 
357 {
358  assert(false);
359  // not fully implemented:
360  // * update id lists !!!
361  // * call handlers
362 
363  del_list(edges);
364  del_list(nodes);
365 
366  nodes_count = edges_count = 0;
367 }
368 
370 {
371  assert(false);
372  // not fully implemented:
373  // * update id lists !!!
374  // * call handlers
375  del_list(edges);
376 
377  edges_count = 0;
378 
379  list<node>::iterator it = nodes.begin();
380  list<node>::iterator end = nodes.end();
381 
382  while(it != end)
383  {
384  it->data->edges[0].clear();
385  it->data->edges[1].clear();
386  }
387 }
388 
389 //--------------------------------------------------------------------------
390 // Informations
391 //--------------------------------------------------------------------------
392 
393 
394 
396  edge e1;
397  node target, source;
398  bool bidirected = true;
401 
402  forall_edges (e1, *this) {
403  target = e1.target ();
404  source = e1.source ();
405  end = target.out_edges_end ();
406  it = target.out_edges_begin ();
407 
408  //
409  // Search all out-edges of target if they are connected to the actual
410  // edges source.
411  //
412 
413  while (it != end) {
414  if ((*it).target () == source) {
415  break;
416  }
417  ++it;
418  }
419 
420  if (it == end) {
421  bidirected = false;
422  rev[e1] = edge ();
423  } else {
424  rev[e1] = *it;
425  }
426  }
427 
428  return bidirected;
429 }
430 
432 {
433  bool save_directed = directed;
434  directed = false;
435 
436  dfs d;
437  d.run(*const_cast<graph *>(this));
438 
439  directed = save_directed;
440 
442 }
443 
444 bool graph::is_acyclic() const
445 {
446  topsort t;
447  t.run(*const_cast<graph *>(this));
448 
449  return t.is_acyclic();
450 }
451 
453 {
455 }
456 
458 {
460 }
461 
463 {
464  int min_excentricity = number_of_nodes()+1;
465  node n, center;
466  forall_nodes(n, *this)
467  {
468  int excentricity = n.excentricity();
469  if(excentricity < min_excentricity)
470  {
471  center = n;
472  min_excentricity = excentricity;
473  }
474  }
475  return center;
476 }
477 
478 //--------------------------------------------------------------------------
479 // Iterators
480 //--------------------------------------------------------------------------
481 
483 {
484  return nodes.begin();
485 }
486 
488 {
489  return nodes.end();
490 }
491 
493 {
494  return edges.begin();
495 }
496 
498 {
499  return edges.end();
500 }
501 
502 //--------------------------------------------------------------------------
503 // Node/Edge lists
504 //--------------------------------------------------------------------------
505 
506 list<node> graph::all_nodes() const
507 {
508  return nodes;
509 }
510 
511 list<edge> graph::all_edges() const
512 {
513  return edges;
514 }
515 
516 //--------------------------------------------------------------------------
517 // Hide
518 // If an edge is already hidden (this really happens :-), it will not be
519 // hidden for the second time
520 //--------------------------------------------------------------------------
521 
523 {
524  assert (e.data->owner == this);
525  assert (e.data->owner == this);
526 
528 
529  if (!e.is_hidden()) {
530 
531  //
532  // remove e from all sources and targets adjacency lists
533  //
534  e.remove_from(0);
535  e.remove_from(1);
536 
537  //
538  // clear the list of positions
539  //
540  e.data->adj_pos[0].erase
541  (e.data->adj_pos[0].begin(), e.data->adj_pos[0].end());
542  e.data->adj_pos[1].erase
543  (e.data->adj_pos[1].begin(), e.data->adj_pos[1].end());
544 
545  //
546  // remove e from the list of all edges
547  //
548  edges.erase (e.data->pos);
549 
550  //
551  // insert e in hidden edges list
552  //
553  e.data->pos = hidden_edges.insert(hidden_edges.end(), e);
554  e.data->hidden = true;
556  }
557 
559 }
560 
561 //--------------------------------------------------------------------------
562 // restore_edge
563 // An edge will be restored only if it is hidden (sounds wise, hmm ...)
564 //--------------------------------------------------------------------------
565 
567 {
568  assert (e.data->owner == this);
569  assert (e.data->owner == this);
570 
572 
573  if (e.is_hidden()) {
574  //
575  // remove e from hidden edges list
576  //
577  hidden_edges.erase (e.data->pos);
579 
580  //
581  // for each source of e insert e in its list of out-edges and store
582  // the position in e's list of positions
583  //
584  list<node>::iterator it;
585  list<node>::iterator end = e.data->nodes[0].end();
586 
587  for (it = e.data->nodes[0].begin (); it != end; ++it) {
588  list<edge> &adj = (*it).data->edges[1];
589  e.data->adj_pos[0].push_back(adj.insert(adj.begin(), e));
590  }
591 
592  //
593  // for each target of e insert e in its list of in-edges and store
594  // the pos
595  //
596  end = e.data->nodes[1].end();
597 
598  for (it = e.data->nodes[1].begin (); it != end; ++it) {
599  list<edge> &adj = (*it).data->edges[0];
600  e.data->adj_pos[1].push_back(adj.insert(adj.begin(), e));
601  }
602 
603  e.data->pos = edges.insert(edges.end(), e);
604  e.data->hidden = false;
605  }
606 
608 }
609 
610 //--------------------------------------------------------------------------
611 // Hide
612 // If an node is already hidden (this really happens :-), it will not be
613 // hidden for the second time
614 // Note: also all adjacent edges will be hidden
615 //--------------------------------------------------------------------------
616 
617 list<edge> graph::hide_node (node n)
618 {
619  assert (n.data->owner == this);
620 
622  list<edge> implicitly_hidden_edges;
623 
624  if (!n.is_hidden()){
625  // hide all connected egdes
626  for (int i = 0; i <= 1; ++i)
627  {
628  list<edge>::iterator end = n.data->edges[i].end();
629  list<edge>::iterator edge = n.data->edges[i].begin();
630  while (edge != end)
631  {
632  implicitly_hidden_edges.push_back(*edge);
633  hide_edge(*edge);
634  edge = n.data->edges[i].begin();
635  }
636  }
637 
638  // hide node
639  hidden_nodes.push_back(n);
640  nodes.erase(n.data->pos);
641  n.data->hidden = true;
643  }
644 
646 
647  return implicitly_hidden_edges;
648 }
649 
650 //--------------------------------------------------------------------------
651 // restore_node
652 // A node will be restored only if it is hidden (sounds wise, hmm ...)
653 // connected nodes won't be restored automatically !
654 //--------------------------------------------------------------------------
655 
657 {
658  assert (n.data->owner == this);
659 
661 
662  if (n.is_hidden()) {
663  // node is hidden
664 
665  nodes.push_back(n);
666  n.data->pos = --nodes.end();
667 
668  hidden_nodes.remove(n);
669  n.data->hidden = false;
671  }
672 
674 }
675 
676 
677 void graph::induced_subgraph (list<node>& sub_nodes)
678 {
679  node_map<int> in_sub (*this, 0);
680  list<node>::iterator it, end, tmp;
681 
682  for (it = sub_nodes.begin(), end = sub_nodes.end(); it != end; ++it) {
683  in_sub[*it] = 1;
684  }
685 
686  it = nodes.begin();
687  end = nodes.end();
688 
689  while (it != end) {
690  tmp = it;
691  ++tmp;
692 
693  if (!in_sub[*it]) {
694  hide_node (*it);
695  }
696 
697  it = tmp;
698  }
699 }
700 
702 {
703  list<node>::iterator it, end, tmp;
704 
705  it = hidden_nodes.begin();
706  end = hidden_nodes.end();
707 
708  while (it != end) {
709  tmp = it;
710  ++tmp;
711  restore_node (*it);
712  it = tmp;
713  }
714 
715  list<edge>::iterator e_it, e_end, e_tmp;
716 
717  e_it = hidden_edges.begin();
718  e_end = hidden_edges.end();
719 
720  while (e_it != e_end) {
721  e_tmp = e_it;
722  ++e_tmp;
723  restore_edge (*e_it);
724  e_it = e_tmp;
725  }
726 }
727 
728 //--------------------------------------------------------------------------
729 // Node/edge numbering
730 //--------------------------------------------------------------------------
731 
733 {
734  return
736  nodes_count;
737 }
738 
740 {
741  return
743  edges_count;
744 }
745 
747 {
748  if(free_node_ids.empty())
749  return nodes_count;
750 
751  int id = free_node_ids.back();
752  free_node_ids.pop_back();
754  return id;
755 }
756 
758 {
759  if(free_edge_ids.empty())
760  return edges_count;
761 
762  int id = free_edge_ids.back();
763  free_edge_ids.pop_back();
765  return id;
766 }
767 
768 //--------------------------------------------------------------------------
769 // Utilities
770 //--------------------------------------------------------------------------
771 
772 void graph::del_list(list<node> &l)
773 {
774  list<node>::const_iterator it = l.begin();
775  list<node>::const_iterator end = l.end();
776 
777  while(it != end)
778  {
779  delete it->data;
780  ++it;
781  }
782 
783  l.clear();
784 }
785 
786 void graph::del_list(list<edge> &l)
787 {
788  list<edge>::const_iterator it = l.begin();
789  list<edge>::const_iterator end = l.end();
790 
791  while(it != end)
792  {
793  delete it->data;
794  ++it;
795  }
796 
797  l.clear();
798 }
799 
800 //--------------------------------------------------------------------------
801 // Others
802 //--------------------------------------------------------------------------
803 
805  list<edge> rev;
806  edge e;
807 
809 
810  forall_edges (e, *this) {
811  it = e.target().out_edges_begin();
812  end = e.target().out_edges_end();
813 
814  while (it != end) {
815  if ((*it).target() == e.source())
816  break;
817  ++it;
818  }
819 
820  if (it == end) {
821  rev.push_back(new_edge (e.target(), e.source()));
822  }
823  }
824 
825  return rev;
826 }
827 
829 {
830  // Well, probably doesn't guarantee uniform distribution :-)
831  return nodes.empty() ? node() : nodes.front();
832 }
833 
834 //--------------------------------------------------------------------------
835 // I/O
836 //--------------------------------------------------------------------------
837 
838 GML_error graph::load (const char* filename, bool preserve_ids) {
839 
840  GML_stat stat;
841  stat.key_list = NULL;
842  GML_pair* key_list;
843  GML_pair* orig_list;
844 
845  FILE* file = fopen (filename, "r");
846 
847  if (!file) {
849  return stat.err;
850  }
851 
852  GML_init ();
853  key_list = GML_parser (file, &stat, 0);
854  fclose (file);
855 
856  if (stat.err.err_num != GML_OK) {
857  GML_free_list (key_list, stat.key_list);
858  return stat.err;
859  }
860 
861  //
862  // This file is a valid GML-file, let's build the graph.
863  //
864 
865  clear();
866  orig_list = key_list;
867 
868 
869 
870  //
871  // get the first entry with key "graph" in the list
872  //
873 
874  while (key_list) {
875  if (!strcmp ( "graph", key_list->key)) {
876  break;
877  }
878 
879  key_list = key_list->next;
880  }
881 
882  assert (key_list);
883 
884  key_list = key_list->value.list;
885  GML_pair* graph_list = key_list;
886 
887  GML_pair* tmp_list;
888  GML_pair* tmp_prev;
889  // GML_pair* node_entries = 0;
890  // GML_pair* edge_entries = 0;
891 
892  list<pair<int,GML_pair*> > node_entries;
893  list<pair<pair<int,int>,GML_pair*> > edge_entries;
894 
895  int num_nodes = 0;
896 
897  bool target_found;
898  bool source_found;
899 
900  //
901  // Node and edge keys may come in arbitrary order, so sort them such
902  // that all nodes come before all edges.
903  //
904 
905  while (key_list) {
906  if (!strcmp (key_list->key, "node")) {
907 
908  //
909  // Search the list associated with this node for the id
910  //
911 
912  assert (key_list->kind == GML_LIST);
913  tmp_list = key_list->value.list;
914  tmp_prev = 0;
915  pair<int,GML_pair*> n;
916  n.second = tmp_list;
917 
918  while (tmp_list) {
919  if (!strcmp (tmp_list->key, "id")) {
920  assert (tmp_list->kind == GML_INT);
921  n.first = tmp_list->value.integer;
922  break;
923  }
924 
925  tmp_list = tmp_list->next;
926  }
927 
928  assert (tmp_list);
929  node_entries.push_back(n);
930  ++num_nodes;
931 
932  } else if (!strcmp (key_list->key, "edge")) {
933 
934  //
935  // Search for source and target entries
936  //
937 
938  assert (key_list->kind == GML_LIST);
939  tmp_list = key_list->value.list;
940  tmp_prev = 0;
941  source_found = false;
942  target_found = false;
943  pair<pair<int,int>,GML_pair*> e;
944  e.second = tmp_list;
945 
946  while (tmp_list) {
947  if (!strcmp (tmp_list->key, "source")) {
948  assert (tmp_list->kind == GML_INT);
949  source_found = true;
950  e.first.first = tmp_list->value.integer;
951  if (target_found) break;
952 
953  } else if (!strcmp (tmp_list->key, "target")) {
954  assert (tmp_list->kind == GML_INT);
955  target_found = true;
956  e.first.second = tmp_list->value.integer;
957  if (source_found) break;
958  }
959 
960  tmp_list = tmp_list->next;
961  }
962 
963  assert (source_found && target_found);
964  edge_entries.push_back (e);
965 
966  } else if (!strcmp (key_list->key, "directed")) {
967  directed = (key_list->value.integer != 0);
968  }
969 
970  key_list = key_list->next;
971  }
972 
973  //
974  // make this graph the graph decribed in list
975  //
976 
977  map<int, node> id_2_node;
978  node source, target;
979  node tmp_node;
980  edge tmp_edge;
981  list<pair<int,GML_pair*> >::iterator it, end;
982  vector<int> node_ids;
983  node_ids.reserve(num_nodes);
984 
985  for (it = node_entries.begin(), end = node_entries.end();
986  it != end; ++it) {
987  tmp_node = new_node ();
988  if (preserve_ids) {
989  tmp_node.data->id = (*it).first;
990  node_ids.push_back((*it).first);
991  }
992  id_2_node[(*it).first] = tmp_node;
993  load_node_info_handler (tmp_node, (*it).second);
994  }
995 
996  list<pair<pair<int,int>,GML_pair*> >::iterator eit, eend;
997  for (eit = edge_entries.begin(), eend = edge_entries.end();
998  eit != eend; ++eit) {
999  source = id_2_node[(*eit).first.first];
1000  target = id_2_node[(*eit).first.second];
1001  tmp_edge = new_edge (source, target);
1002  load_edge_info_handler (tmp_edge, (*eit).second);
1003  }
1004 
1005  load_graph_info_handler (graph_list);
1006  top_level_key_handler (orig_list);
1007 
1008  sort(node_ids.begin(),node_ids.end());
1009 
1010  vector<int>::iterator iit, iend;
1011  int prev = 0;
1012 
1013  for (iit = node_ids.begin(), iend = node_ids.end();
1014  iit != iend; ++iit)
1015  {
1016  if (iit != node_ids.begin()) {
1017  free_node_ids_count += *iit - prev - 1;
1018  } else {
1019  free_node_ids_count += *iit;
1020  }
1021  prev = *iit;
1022  }
1023 
1024  GML_free_list (orig_list, stat.key_list);
1025  stat.err.err_num = GML_OK;
1026  return stat.err;
1027 }
1028 
1030 }
1031 
1032 
1034 }
1035 
1037 }
1038 
1040 }
1041 
1042 
1043 void graph::save (ostream* file) const {
1044  pre_graph_save_handler (file);
1045  (*file) << "graph [" << endl;
1046  (*file) << "directed " << (directed ? "1" : "0") << endl;
1047 
1050 
1051  for (;it != end; ++it) {
1052  (*file) << "node [\n" << "id " << (*it).id() << "\n";
1053  save_node_info_handler (file, *it);
1054  (*file) << " ]" << endl;
1055  }
1056 
1057  edge_iterator e_it = edges_begin();
1058  edge_iterator e_end = edges_end();
1059 
1060  for (; e_it != e_end; ++e_it) {
1061  (*file) << "edge [\n" << "source " << (*e_it).source().id() << "\n";
1062  (*file) << "target " << (*e_it).target().id() << "\n";
1063  save_edge_info_handler (file, *e_it);
1064  (*file) << " ]" << endl;
1065  }
1066 
1067  save_graph_info_handler (file);
1068 
1069  (*file) << "]" << endl;
1070  after_graph_save_handler (file);
1071 }
1072 
1073 int graph::save (const char* filename) const {
1074 
1075  ofstream file (filename);
1076  if (!file) return 0;
1077 
1078  save (&file);
1079 
1080  return 1;
1081 }
1082 
1083 
1084 // void graph::top_level_key_handler (GML_pair_list::const_iterator it,
1085 // GML_pair_list::const_iterator end)
1086 // {
1087 // cout << "TOP_LEVEL_HANDLER" << endl;
1088 
1089 // for (; it != end; ++it) {
1090 // cout << *it << endl;
1091 // }
1092 // }
1093 
1094 // void graph::load_graph_info_handler (GML_pair_list::const_iterator it,
1095 // GML_pair_list::const_iterator end)
1096 // {
1097 // cout << "GRAPH_INFO_HANDLER" << endl;
1098 
1099 // for (; it != end; ++it) {
1100 // cout << *it << endl;
1101 // }
1102 // }
1103 
1104 // void graph::load_node_info_handler (node n, GML_pair_list::const_iterator it,
1105 // GML_pair_list::const_iterator end)
1106 // {
1107 // cout << "NODE_INFO_HANDLER for " << n << endl;
1108 
1109 // for (; it != end; ++it) {
1110 // cout << *it << endl;
1111 // }
1112 // }
1113 
1114 // void graph::load_edge_info_handler (edge e, GML_pair_list::const_iterator it,
1115 // GML_pair_list::const_iterator end)
1116 // {
1117 // cout << "EDGE_INFO_HANDLER for " << e.source() << "-->"
1118 // << e.target() << endl;
1119 
1120 // for (; it != end; ++it) {
1121 // cout << *it << endl;
1122 // }
1123 // }
1124 
1126 
1127 //--------------------------------------------------------------------------
1128 // end of file
1129 //--------------------------------------------------------------------------