Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:19:39

0001 /* This software is distributed under the GNU Lesser General Public License */
0002 //==========================================================================
0003 //
0004 //   graph.cpp
0005 //
0006 //==========================================================================
0007 // $Id: graph.cpp,v 1.58 2003/01/14 16:47:14 raitner Exp $
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   // _DEBUG
0038 #endif  // __GTL_MSVCC
0039 
0040 __GTL_BEGIN_NAMESPACE
0041 
0042 //--------------------------------------------------------------------------
0043 //   Con-/Destructors
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 // Output 
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 //   Directed/Undirected
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 //   Creation
0182 //--------------------------------------------------------------------------
0183 
0184 node graph::new_node()
0185 {
0186     pre_new_node_handler();
0187 
0188     // create node
0189     
0190     node n;
0191     n.data = new node_data;
0192 
0193     // set data variables
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     // done
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     // create edge
0218     
0219     edge e;
0220     e.data = new edge_data;
0221     
0222     // set id
0223 
0224     e.data->owner = this;
0225     e.data->id = new_edge_id(); 
0226     
0227     // set sources and targets
0228     
0229     e.data->nodes[0].push_back(source);
0230     e.data->nodes[1].push_back(target);
0231 
0232     // set pos
0233     
0234     e.data->pos = edges.insert(edges.end(), e);
0235     e.data->hidden = false;
0236     ++edges_count;
0237 
0238     // set adj_pos
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     // done
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     // not implemented
0256 
0257     return edge();
0258 }
0259 
0260 //--------------------------------------------------------------------------
0261 //   Deletion
0262 //--------------------------------------------------------------------------
0263 
0264 void graph::del_node(node n)
0265 {
0266     assert (n.data);
0267     assert (n.data->owner == this);
0268 
0269     // delete edges
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     // delete hidden edges adjacent to n.  
0283     // 
0284     // [ TODO ] This is only a quick fix and should be thought
0285     // over some time or the other.
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     // delete node
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     // not fully implemented:
0360     //  * update id lists !!!
0361     //  * call handlers
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     // not fully implemented:
0373     //  * update id lists !!!
0374     //  * call handlers
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 //   Informations
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     // Search all out-edges of target if they are connected to the actual
0410     // edges source.
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 //   Iterators
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 //   Node/Edge lists
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 //   Hide
0518 //   If an edge is already hidden (this really happens :-), it will not be 
0519 //   hidden for the second time
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     // remove e from all sources and targets adjacency lists
0533     //
0534     e.remove_from(0);
0535     e.remove_from(1);
0536     
0537     //
0538     // clear the list of positions
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     // remove e from the list of all edges
0547     //
0548     edges.erase (e.data->pos);
0549 
0550     //
0551     // insert e in hidden edges list
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 //   restore_edge
0563 //   An edge will be restored only if it is hidden (sounds wise, hmm ...)
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     // remove e from hidden edges list
0576     //
0577     hidden_edges.erase (e.data->pos);
0578     --hidden_edges_count;
0579 
0580     //
0581     // for each source of e insert e in its list of out-edges and store
0582     // the position in e's list of positions
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     // for each target of e insert e in its list of in-edges and store 
0594     // the pos
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 //   Hide
0612 //   If an node is already hidden (this really happens :-), it will not be 
0613 //   hidden for the second time
0614 //   Note: also all adjacent edges will be hidden
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     // hide all connected egdes
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     // hide node
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 //   restore_node
0652 //   A node will be restored only if it is hidden (sounds wise, hmm ...)
0653 //   connected nodes won't be restored automatically !
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     // node is hidden
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 //   Node/edge numbering
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 //   Utilities
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 //   Others
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     // Well, probably doesn't guarantee uniform distribution :-)
0831     return nodes.empty() ? node() : nodes.front();
0832 }
0833 
0834 //--------------------------------------------------------------------------
0835 //   I/O 
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     // This file is a valid GML-file, let's build the graph.
0863     // 
0864 
0865     clear();
0866     orig_list = key_list;
0867 
0868     
0869 
0870     //
0871     // get the first entry with key "graph" in the list
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     // GML_pair* node_entries = 0;
0890     // GML_pair* edge_entries = 0;
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     // Node and edge keys may come in arbitrary order, so sort them such
0902     // that all nodes come before all edges.
0903     //
0904     
0905     while (key_list) {
0906     if (!strcmp (key_list->key, "node")) {
0907 
0908         //
0909         // Search the list associated with this node for the id
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         // Search for source and target entries
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     // make this graph the graph decribed in list
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 // 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 
1125 __GTL_END_NAMESPACE
1126 
1127 //--------------------------------------------------------------------------
1128 //   end of file
1129 //--------------------------------------------------------------------------