File indexing completed on 2025-08-03 08:19:39
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <GTL/graph.h>
0010 #include <GTL/node_data.h>
0011 #include <GTL/edge_data.h>
0012 #include <GTL/node_map.h>
0013
0014 #include <GTL/dfs.h>
0015 #include <GTL/topsort.h>
0016
0017 #include <cassert>
0018 #include <cstdio>
0019
0020 #include <algorithm>
0021 #include <queue>
0022 #include <set>
0023 #include <map>
0024
0025 #include <iostream>
0026 #include <fstream>
0027 #include <string>
0028 #include <cstring>
0029 #ifdef __GTL_MSVCC
0030 # ifdef _DEBUG
0031 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
0032 # error SEARCH NOT ENABLED
0033 # endif
0034 # define new DEBUG_NEW
0035 # undef THIS_FILE
0036 static char THIS_FILE[] = __FILE__;
0037 # endif
0038 #endif
0039
0040 __GTL_BEGIN_NAMESPACE
0041
0042
0043
0044
0045
0046 graph::graph() :
0047 directed(true),
0048 nodes_count(0), edges_count(0),
0049 hidden_nodes_count(0), hidden_edges_count(0),
0050 free_node_ids_count(0), free_edge_ids_count(0)
0051 {
0052 }
0053
0054 graph::graph(const graph &G) :
0055 directed(G.directed),
0056 nodes_count(0), edges_count(0),
0057 hidden_nodes_count(0), hidden_edges_count(0),
0058 free_node_ids_count(0), free_edge_ids_count(0)
0059 {
0060 copy (G, G.nodes.begin(), G.nodes.end());
0061 }
0062
0063
0064 graph::graph (const graph& G, const list<node>& nod) :
0065 directed(G.directed),
0066 nodes_count(0), edges_count(0),
0067 hidden_nodes_count(0), hidden_edges_count(0),
0068 free_node_ids_count(0), free_edge_ids_count(0)
0069 {
0070 copy (G, nod.begin(), nod.end());
0071 }
0072
0073
0074 graph::graph (const graph& G,
0075 list<node>::const_iterator it,
0076 list<node>::const_iterator end) :
0077 directed(G.directed),
0078 nodes_count(0), edges_count(0),
0079 hidden_nodes_count(0), hidden_edges_count(0),
0080 free_node_ids_count(0), free_edge_ids_count(0)
0081 {
0082 copy (G, it, end);
0083 }
0084
0085 void graph::copy (const graph& G,
0086 list<node>::const_iterator it,
0087 list<node>::const_iterator end)
0088 {
0089 node_map<node> copy (G, node());
0090 list<node>::const_iterator n_it;
0091 list<node>::const_iterator n_end;
0092
0093 for(n_it = it, n_end = end; n_it != n_end; ++n_it)
0094 {
0095 copy[*n_it] = new_node();
0096 }
0097
0098 for(n_it = it, n_end = end; n_it != n_end; ++n_it)
0099 {
0100 node::out_edges_iterator e_it, e_end;
0101
0102 for (e_it = (*n_it).out_edges_begin(), e_end = (*n_it).out_edges_end();
0103 e_it != e_end; ++e_it) {
0104
0105 if (copy[e_it->target()] != node()) {
0106 new_edge(copy[e_it->source()], copy[e_it->target()]);
0107 }
0108 }
0109 }
0110 }
0111
0112
0113
0114 graph::~graph()
0115 {
0116 clear();
0117 }
0118
0119
0120
0121
0122
0123 GTL_EXTERN ostream& operator<< (ostream& os, const graph& G) {
0124 node n;
0125 edge out;
0126 string conn;
0127
0128 if (G.is_directed())
0129 conn = "-->";
0130 else
0131 conn = "<-->";
0132
0133 forall_nodes (n, G) {
0134 os << n << ":: ";
0135
0136 forall_adj_edges (out, n) {
0137 os << conn << n.opposite (out);
0138 }
0139
0140 os << endl;
0141 }
0142
0143 return os;
0144 }
0145
0146
0147
0148
0149
0150 void graph::make_directed()
0151 {
0152 if (!directed)
0153 {
0154 pre_make_directed_handler();
0155 directed = true;
0156 post_make_directed_handler();
0157 }
0158 }
0159
0160 void graph::make_undirected()
0161 {
0162 if (directed)
0163 {
0164 pre_make_undirected_handler();
0165 directed = false;
0166 post_make_undirected_handler();
0167 }
0168 }
0169
0170 bool graph::is_directed() const
0171 {
0172 return directed;
0173 }
0174
0175 bool graph::is_undirected() const
0176 {
0177 return !directed;
0178 }
0179
0180
0181
0182
0183
0184 node graph::new_node()
0185 {
0186 pre_new_node_handler();
0187
0188
0189
0190 node n;
0191 n.data = new node_data;
0192
0193
0194
0195 n.data->id = new_node_id();
0196 n.data->owner = this;
0197 n.data->pos = nodes.insert(nodes.end(), n);
0198 n.data->hidden = false;
0199 ++nodes_count;
0200
0201
0202
0203 post_new_node_handler(n);
0204
0205 return n;
0206 }
0207
0208 edge graph::new_edge(node source, node target)
0209 {
0210 assert(source.data);
0211 assert(target.data);
0212 assert(source.data->owner == this);
0213 assert(target.data->owner == this);
0214
0215 pre_new_edge_handler(source, target);
0216
0217
0218
0219 edge e;
0220 e.data = new edge_data;
0221
0222
0223
0224 e.data->owner = this;
0225 e.data->id = new_edge_id();
0226
0227
0228
0229 e.data->nodes[0].push_back(source);
0230 e.data->nodes[1].push_back(target);
0231
0232
0233
0234 e.data->pos = edges.insert(edges.end(), e);
0235 e.data->hidden = false;
0236 ++edges_count;
0237
0238
0239
0240 list<edge> &source_adj = source.data->edges[1];
0241 list<edge> &target_adj = target.data->edges[0];
0242
0243 e.data->adj_pos[0].push_back(source_adj.insert(source_adj.begin(), e));
0244 e.data->adj_pos[1].push_back(target_adj.insert(target_adj.begin(), e));
0245
0246
0247
0248 post_new_edge_handler(e);
0249
0250 return e;
0251 }
0252
0253 edge graph::new_edge(const list<node> &sources, const list<node> &targets)
0254 {
0255
0256
0257 return edge();
0258 }
0259
0260
0261
0262
0263
0264 void graph::del_node(node n)
0265 {
0266 assert (n.data);
0267 assert (n.data->owner == this);
0268
0269
0270
0271 while(n.in_edges_begin() != n.in_edges_end())
0272 {
0273 del_edge (*n.in_edges_begin());
0274 }
0275
0276 while(n.out_edges_begin() != n.out_edges_end())
0277 {
0278 del_edge (*n.out_edges_begin());
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288 list<edge>::iterator it = hidden_edges.begin();
0289 list<edge>::iterator end = hidden_edges.end();
0290
0291 while (it != end)
0292 {
0293 if ((*it).source() == n || (*it).target() == n)
0294 {
0295 delete (*it).data;
0296 it = hidden_edges.erase (it);
0297 }
0298 else
0299 {
0300 ++it;
0301 }
0302 }
0303
0304
0305
0306 pre_del_node_handler(n);
0307
0308 nodes.erase(n.data->pos);
0309 --nodes_count;
0310 free_node_ids.push_back(n.data->id);
0311 ++free_node_ids_count;
0312 delete n.data;
0313
0314 post_del_node_handler();
0315 }
0316
0317 void graph::del_edge(edge e)
0318 {
0319 assert (e.data->owner == this);
0320 assert (e.data->owner == this);
0321
0322 pre_del_edge_handler(e);
0323 node s = e.source();
0324 node t = e.target();
0325
0326 e.remove_from(0);
0327 e.remove_from(1);
0328 edges.erase(e.data->pos);
0329 --edges_count;
0330 free_edge_ids.push_back(e.data->id);
0331 ++free_edge_ids_count;
0332 delete e.data;
0333
0334 post_del_edge_handler(s, t);
0335 }
0336
0337 void graph::clear()
0338 {
0339 pre_clear_handler();
0340
0341 del_list(edges);
0342 del_list(hidden_edges);
0343 del_list(nodes);
0344 del_list(hidden_nodes);
0345
0346 free_node_ids.clear();
0347 free_edge_ids.clear();
0348
0349 nodes_count = edges_count = 0;
0350 hidden_nodes_count = hidden_edges_count = 0;
0351 free_node_ids_count = free_edge_ids_count = 0;
0352
0353 post_clear_handler();
0354 }
0355
0356 void graph::del_all_nodes()
0357 {
0358 assert(false);
0359
0360
0361
0362
0363 del_list(edges);
0364 del_list(nodes);
0365
0366 nodes_count = edges_count = 0;
0367 }
0368
0369 void graph::del_all_edges()
0370 {
0371 assert(false);
0372
0373
0374
0375 del_list(edges);
0376
0377 edges_count = 0;
0378
0379 list<node>::iterator it = nodes.begin();
0380 list<node>::iterator end = nodes.end();
0381
0382 while(it != end)
0383 {
0384 it->data->edges[0].clear();
0385 it->data->edges[1].clear();
0386 }
0387 }
0388
0389
0390
0391
0392
0393
0394
0395 bool graph::is_bidirected(edge_map<edge>& rev) const {
0396 edge e1;
0397 node target, source;
0398 bool bidirected = true;
0399 node::out_edges_iterator it;
0400 node::out_edges_iterator end;
0401
0402 forall_edges (e1, *this) {
0403 target = e1.target ();
0404 source = e1.source ();
0405 end = target.out_edges_end ();
0406 it = target.out_edges_begin ();
0407
0408
0409
0410
0411
0412
0413 while (it != end) {
0414 if ((*it).target () == source) {
0415 break;
0416 }
0417 ++it;
0418 }
0419
0420 if (it == end) {
0421 bidirected = false;
0422 rev[e1] = edge ();
0423 } else {
0424 rev[e1] = *it;
0425 }
0426 }
0427
0428 return bidirected;
0429 }
0430
0431 bool graph::is_connected() const
0432 {
0433 bool save_directed = directed;
0434 directed = false;
0435
0436 dfs d;
0437 d.run(*const_cast<graph *>(this));
0438
0439 directed = save_directed;
0440
0441 return d.number_of_reached_nodes() == number_of_nodes();
0442 }
0443
0444 bool graph::is_acyclic() const
0445 {
0446 topsort t;
0447 t.run(*const_cast<graph *>(this));
0448
0449 return t.is_acyclic();
0450 }
0451
0452 int graph::number_of_nodes() const
0453 {
0454 return nodes_count - hidden_nodes_count;
0455 }
0456
0457 int graph::number_of_edges() const
0458 {
0459 return edges_count - hidden_edges_count;
0460 }
0461
0462 node graph::center() const
0463 {
0464 int min_excentricity = number_of_nodes()+1;
0465 node n, center;
0466 forall_nodes(n, *this)
0467 {
0468 int excentricity = n.excentricity();
0469 if(excentricity < min_excentricity)
0470 {
0471 center = n;
0472 min_excentricity = excentricity;
0473 }
0474 }
0475 return center;
0476 }
0477
0478
0479
0480
0481
0482 graph::node_iterator graph::nodes_begin() const
0483 {
0484 return nodes.begin();
0485 }
0486
0487 graph::node_iterator graph::nodes_end() const
0488 {
0489 return nodes.end();
0490 }
0491
0492 graph::edge_iterator graph::edges_begin() const
0493 {
0494 return edges.begin();
0495 }
0496
0497 graph::edge_iterator graph::edges_end() const
0498 {
0499 return edges.end();
0500 }
0501
0502
0503
0504
0505
0506 list<node> graph::all_nodes() const
0507 {
0508 return nodes;
0509 }
0510
0511 list<edge> graph::all_edges() const
0512 {
0513 return edges;
0514 }
0515
0516
0517
0518
0519
0520
0521
0522 void graph::hide_edge (edge e)
0523 {
0524 assert (e.data->owner == this);
0525 assert (e.data->owner == this);
0526
0527 pre_hide_edge_handler (e);
0528
0529 if (!e.is_hidden()) {
0530
0531
0532
0533
0534 e.remove_from(0);
0535 e.remove_from(1);
0536
0537
0538
0539
0540 e.data->adj_pos[0].erase
0541 (e.data->adj_pos[0].begin(), e.data->adj_pos[0].end());
0542 e.data->adj_pos[1].erase
0543 (e.data->adj_pos[1].begin(), e.data->adj_pos[1].end());
0544
0545
0546
0547
0548 edges.erase (e.data->pos);
0549
0550
0551
0552
0553 e.data->pos = hidden_edges.insert(hidden_edges.end(), e);
0554 e.data->hidden = true;
0555 ++hidden_edges_count;
0556 }
0557
0558 post_hide_edge_handler (e);
0559 }
0560
0561
0562
0563
0564
0565
0566 void graph::restore_edge (edge e)
0567 {
0568 assert (e.data->owner == this);
0569 assert (e.data->owner == this);
0570
0571 pre_restore_edge_handler (e);
0572
0573 if (e.is_hidden()) {
0574
0575
0576
0577 hidden_edges.erase (e.data->pos);
0578 --hidden_edges_count;
0579
0580
0581
0582
0583
0584 list<node>::iterator it;
0585 list<node>::iterator end = e.data->nodes[0].end();
0586
0587 for (it = e.data->nodes[0].begin (); it != end; ++it) {
0588 list<edge> &adj = (*it).data->edges[1];
0589 e.data->adj_pos[0].push_back(adj.insert(adj.begin(), e));
0590 }
0591
0592
0593
0594
0595
0596 end = e.data->nodes[1].end();
0597
0598 for (it = e.data->nodes[1].begin (); it != end; ++it) {
0599 list<edge> &adj = (*it).data->edges[0];
0600 e.data->adj_pos[1].push_back(adj.insert(adj.begin(), e));
0601 }
0602
0603 e.data->pos = edges.insert(edges.end(), e);
0604 e.data->hidden = false;
0605 }
0606
0607 post_restore_edge_handler (e);
0608 }
0609
0610
0611
0612
0613
0614
0615
0616
0617 list<edge> graph::hide_node (node n)
0618 {
0619 assert (n.data->owner == this);
0620
0621 pre_hide_node_handler (n);
0622 list<edge> implicitly_hidden_edges;
0623
0624 if (!n.is_hidden()){
0625
0626 for (int i = 0; i <= 1; ++i)
0627 {
0628 list<edge>::iterator end = n.data->edges[i].end();
0629 list<edge>::iterator edge = n.data->edges[i].begin();
0630 while (edge != end)
0631 {
0632 implicitly_hidden_edges.push_back(*edge);
0633 hide_edge(*edge);
0634 edge = n.data->edges[i].begin();
0635 }
0636 }
0637
0638
0639 hidden_nodes.push_back(n);
0640 nodes.erase(n.data->pos);
0641 n.data->hidden = true;
0642 ++hidden_nodes_count;
0643 }
0644
0645 post_hide_node_handler (n);
0646
0647 return implicitly_hidden_edges;
0648 }
0649
0650
0651
0652
0653
0654
0655
0656 void graph::restore_node (node n)
0657 {
0658 assert (n.data->owner == this);
0659
0660 pre_restore_node_handler (n);
0661
0662 if (n.is_hidden()) {
0663
0664
0665 nodes.push_back(n);
0666 n.data->pos = --nodes.end();
0667
0668 hidden_nodes.remove(n);
0669 n.data->hidden = false;
0670 --hidden_nodes_count;
0671 }
0672
0673 post_restore_node_handler (n);
0674 }
0675
0676
0677 void graph::induced_subgraph (list<node>& sub_nodes)
0678 {
0679 node_map<int> in_sub (*this, 0);
0680 list<node>::iterator it, end, tmp;
0681
0682 for (it = sub_nodes.begin(), end = sub_nodes.end(); it != end; ++it) {
0683 in_sub[*it] = 1;
0684 }
0685
0686 it = nodes.begin();
0687 end = nodes.end();
0688
0689 while (it != end) {
0690 tmp = it;
0691 ++tmp;
0692
0693 if (!in_sub[*it]) {
0694 hide_node (*it);
0695 }
0696
0697 it = tmp;
0698 }
0699 }
0700
0701 void graph::restore_graph ()
0702 {
0703 list<node>::iterator it, end, tmp;
0704
0705 it = hidden_nodes.begin();
0706 end = hidden_nodes.end();
0707
0708 while (it != end) {
0709 tmp = it;
0710 ++tmp;
0711 restore_node (*it);
0712 it = tmp;
0713 }
0714
0715 list<edge>::iterator e_it, e_end, e_tmp;
0716
0717 e_it = hidden_edges.begin();
0718 e_end = hidden_edges.end();
0719
0720 while (e_it != e_end) {
0721 e_tmp = e_it;
0722 ++e_tmp;
0723 restore_edge (*e_it);
0724 e_it = e_tmp;
0725 }
0726 }
0727
0728
0729
0730
0731
0732 int graph::number_of_ids(node) const
0733 {
0734 return
0735 free_node_ids_count +
0736 nodes_count;
0737 }
0738
0739 int graph::number_of_ids(edge) const
0740 {
0741 return
0742 free_edge_ids_count +
0743 edges_count;
0744 }
0745
0746 int graph::new_node_id()
0747 {
0748 if(free_node_ids.empty())
0749 return nodes_count;
0750
0751 int id = free_node_ids.back();
0752 free_node_ids.pop_back();
0753 --free_node_ids_count;
0754 return id;
0755 }
0756
0757 int graph::new_edge_id()
0758 {
0759 if(free_edge_ids.empty())
0760 return edges_count;
0761
0762 int id = free_edge_ids.back();
0763 free_edge_ids.pop_back();
0764 --free_edge_ids_count;
0765 return id;
0766 }
0767
0768
0769
0770
0771
0772 void graph::del_list(list<node> &l)
0773 {
0774 list<node>::const_iterator it = l.begin();
0775 list<node>::const_iterator end = l.end();
0776
0777 while(it != end)
0778 {
0779 delete it->data;
0780 ++it;
0781 }
0782
0783 l.clear();
0784 }
0785
0786 void graph::del_list(list<edge> &l)
0787 {
0788 list<edge>::const_iterator it = l.begin();
0789 list<edge>::const_iterator end = l.end();
0790
0791 while(it != end)
0792 {
0793 delete it->data;
0794 ++it;
0795 }
0796
0797 l.clear();
0798 }
0799
0800
0801
0802
0803
0804 list<edge> graph::insert_reverse_edges() {
0805 list<edge> rev;
0806 edge e;
0807
0808 node::out_edges_iterator it, end;
0809
0810 forall_edges (e, *this) {
0811 it = e.target().out_edges_begin();
0812 end = e.target().out_edges_end();
0813
0814 while (it != end) {
0815 if ((*it).target() == e.source())
0816 break;
0817 ++it;
0818 }
0819
0820 if (it == end) {
0821 rev.push_back(new_edge (e.target(), e.source()));
0822 }
0823 }
0824
0825 return rev;
0826 }
0827
0828 node graph::choose_node () const
0829 {
0830
0831 return nodes.empty() ? node() : nodes.front();
0832 }
0833
0834
0835
0836
0837
0838 GML_error graph::load (const char* filename, bool preserve_ids) {
0839
0840 GML_stat stat;
0841 stat.key_list = NULL;
0842 GML_pair* key_list;
0843 GML_pair* orig_list;
0844
0845 FILE* file = fopen (filename, "r");
0846
0847 if (!file) {
0848 stat.err.err_num = GML_FILE_NOT_FOUND;
0849 return stat.err;
0850 }
0851
0852 GML_init ();
0853 key_list = GML_parser (file, &stat, 0);
0854 fclose (file);
0855
0856 if (stat.err.err_num != GML_OK) {
0857 GML_free_list (key_list, stat.key_list);
0858 return stat.err;
0859 }
0860
0861
0862
0863
0864
0865 clear();
0866 orig_list = key_list;
0867
0868
0869
0870
0871
0872
0873
0874 while (key_list) {
0875 if (!strcmp ( "graph", key_list->key)) {
0876 break;
0877 }
0878
0879 key_list = key_list->next;
0880 }
0881
0882 assert (key_list);
0883
0884 key_list = key_list->value.list;
0885 GML_pair* graph_list = key_list;
0886
0887 GML_pair* tmp_list;
0888 GML_pair* tmp_prev;
0889
0890
0891
0892 list<pair<int,GML_pair*> > node_entries;
0893 list<pair<pair<int,int>,GML_pair*> > edge_entries;
0894
0895 int num_nodes = 0;
0896
0897 bool target_found;
0898 bool source_found;
0899
0900
0901
0902
0903
0904
0905 while (key_list) {
0906 if (!strcmp (key_list->key, "node")) {
0907
0908
0909
0910
0911
0912 assert (key_list->kind == GML_LIST);
0913 tmp_list = key_list->value.list;
0914 tmp_prev = 0;
0915 pair<int,GML_pair*> n;
0916 n.second = tmp_list;
0917
0918 while (tmp_list) {
0919 if (!strcmp (tmp_list->key, "id")) {
0920 assert (tmp_list->kind == GML_INT);
0921 n.first = tmp_list->value.integer;
0922 break;
0923 }
0924
0925 tmp_list = tmp_list->next;
0926 }
0927
0928 assert (tmp_list);
0929 node_entries.push_back(n);
0930 ++num_nodes;
0931
0932 } else if (!strcmp (key_list->key, "edge")) {
0933
0934
0935
0936
0937
0938 assert (key_list->kind == GML_LIST);
0939 tmp_list = key_list->value.list;
0940 tmp_prev = 0;
0941 source_found = false;
0942 target_found = false;
0943 pair<pair<int,int>,GML_pair*> e;
0944 e.second = tmp_list;
0945
0946 while (tmp_list) {
0947 if (!strcmp (tmp_list->key, "source")) {
0948 assert (tmp_list->kind == GML_INT);
0949 source_found = true;
0950 e.first.first = tmp_list->value.integer;
0951 if (target_found) break;
0952
0953 } else if (!strcmp (tmp_list->key, "target")) {
0954 assert (tmp_list->kind == GML_INT);
0955 target_found = true;
0956 e.first.second = tmp_list->value.integer;
0957 if (source_found) break;
0958 }
0959
0960 tmp_list = tmp_list->next;
0961 }
0962
0963 assert (source_found && target_found);
0964 edge_entries.push_back (e);
0965
0966 } else if (!strcmp (key_list->key, "directed")) {
0967 directed = (key_list->value.integer != 0);
0968 }
0969
0970 key_list = key_list->next;
0971 }
0972
0973
0974
0975
0976
0977 map<int, node> id_2_node;
0978 node source, target;
0979 node tmp_node;
0980 edge tmp_edge;
0981 list<pair<int,GML_pair*> >::iterator it, end;
0982 vector<int> node_ids;
0983 node_ids.reserve(num_nodes);
0984
0985 for (it = node_entries.begin(), end = node_entries.end();
0986 it != end; ++it) {
0987 tmp_node = new_node ();
0988 if (preserve_ids) {
0989 tmp_node.data->id = (*it).first;
0990 node_ids.push_back((*it).first);
0991 }
0992 id_2_node[(*it).first] = tmp_node;
0993 load_node_info_handler (tmp_node, (*it).second);
0994 }
0995
0996 list<pair<pair<int,int>,GML_pair*> >::iterator eit, eend;
0997 for (eit = edge_entries.begin(), eend = edge_entries.end();
0998 eit != eend; ++eit) {
0999 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
1029 void graph::load_node_info_handler (node n, GML_pair* li) {
1030 }
1031
1032
1033 void graph::load_edge_info_handler (edge e, GML_pair* li) {
1034 }
1035
1036 void graph::load_graph_info_handler (GML_pair* li) {
1037 }
1038
1039 void graph::top_level_key_handler (GML_pair* li) {
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
1048 node_iterator it = nodes_begin();
1049 node_iterator end = nodes_end();
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
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125 __GTL_END_NAMESPACE
1126
1127
1128
1129