Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
some test code and bugs fixed + add of some accessors to members of private data...
[simgrid.git] / src / xbt / graph.c
1
2
3 /*      $Id$     */
4
5
6 /* a generic graph library.                                                 */
7
8 /* Copyright (c) 2006 Darina Dimitrova, Arnaud Legrand. 
9    All rights reserved.                  */
10
11 /* This program is free software; you can redistribute it and/or modify it
12  * under the terms of the license (GNU LGPL) which comes with this package. */
13
14 #include <stdlib.h>
15 #include "xbt/sysdep.h"
16 #include "xbt/log.h"
17 #include "xbt/graph.h"
18 #include "graph_private.h"
19 #include "xbt/graphxml_parse.h"
20 #include "xbt/dict.h"
21
22 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(graph,xbt,"Graph");
23
24 /** Constructor
25  * \return a new graph
26  */
27 xbt_graph_t xbt_graph_new_graph(unsigned short int directed, void *data)
28 {
29   xbt_graph_t graph=NULL;
30   graph=xbt_new0(struct xbt_graph,1);
31   graph->directed=directed;
32   graph->data=data;
33   graph->nodes= xbt_dynar_new(sizeof(xbt_node_t), free);
34   graph->edges= xbt_dynar_new(sizeof(xbt_edge_t), free);
35
36   return graph;
37 }
38
39 xbt_node_t xbt_graph_new_node(xbt_graph_t g, void *data)
40 {
41   xbt_node_t node=NULL;
42   node=xbt_new0(struct xbt_node,1);
43   node->data=data;
44   node->in=xbt_dynar_new(sizeof(xbt_node_t), free);
45   node->out=xbt_dynar_new(sizeof(xbt_node_t), free);
46   xbt_dynar_push(g->nodes,&node);  
47
48   return node;
49 }
50
51
52 xbt_edge_t xbt_graph_new_edge(xbt_graph_t g,
53                              xbt_node_t src, xbt_node_t dst, void *data)
54 {
55   xbt_edge_t edge=NULL;
56
57   edge=xbt_new0(struct xbt_edge,1);
58   xbt_dynar_push(src->out,&edge); 
59   xbt_dynar_push(dst->in,&edge); 
60   edge->data=data;
61   edge->src=src;
62   edge->dst=dst;
63   if(!g->directed) 
64    {
65      xbt_dynar_push(src->in,&edge); 
66      xbt_dynar_push(dst->out,&edge); 
67    }
68
69  xbt_dynar_push(g->edges,&edge);
70
71  return edge; 
72 }
73
74
75 /** Destructor
76  * \param l poor victim
77  *
78  * Free the graph structure. 
79  */
80 void xbt_graph_free_graph(xbt_graph_t g,
81                           void node_free_function(void * ptr),
82                           void edge_free_function(void * ptr),
83                           void graph_free_function(void * ptr))
84
85   int cursor; 
86   xbt_node_t node=NULL; 
87
88   xbt_dynar_foreach(g->nodes,cursor,node)
89     xbt_graph_free_node(g,node,node_free_function);
90
91   xbt_assert0(!xbt_dynar_length(g->edges),
92               "Damnit, there are some remaining edges!");
93
94   xbt_dynar_free(&(g->nodes));
95   xbt_dynar_free(&(g->edges));
96   fprintf(stderr,"%s","after free containers\n");    
97
98
99   return;
100 }
101
102 void xbt_graph_free_node(xbt_graph_t g, xbt_node_t n, void free_function(void * ptr))
103
104   int cursor; 
105   xbt_node_t node=NULL;
106
107   if ((free_function)&&(n->data))
108     free_function(n->data);
109
110   xbt_dynar_free_container(&(n->in));
111
112   xbt_dynar_free_container(&(n->out));
113   xbt_dynar_foreach(g->nodes,cursor,node)
114     {
115       if (node==n)
116         xbt_dynar_cursor_rm(g->nodes,&cursor);   
117       
118     }
119   return;
120    
121 }
122 void xbt_graph_free_edge(xbt_graph_t g, xbt_edge_t e, void free_function(void * ptr))
123 {
124    int cursor=0; 
125    xbt_edge_t edge=NULL;
126    xbt_node_t node=NULL;
127    xbt_node_t temp=NULL;
128    
129    if ((free_function)&&(e->data))
130      free_function(e->data);
131    xbt_dynar_foreach(g->nodes,cursor,node)
132      {
133        if (node==e->src)
134          xbt_dynar_pop(node->out,temp);
135        if (g->directed)
136          xbt_dynar_pop(node->in,temp);
137         
138      }
139    node=NULL;
140    cursor=0;
141    xbt_dynar_foreach(g->nodes,cursor,node)
142      {
143         if (node==e->dst)
144           xbt_dynar_pop(node->in,temp);
145         if (g->directed)
146           xbt_dynar_pop(node->out,temp);
147         
148      }
149    cursor=0;
150    xbt_dynar_foreach(g->edges,cursor,edge)
151      if (edge==e) 
152        {
153          xbt_dynar_cursor_rm(g->edges,&cursor);
154          break;
155        }
156    
157 }
158
159 xbt_dynar_t xbt_graph_get_nodes(xbt_graph_t g)
160 {
161   return g->nodes;
162 }
163 xbt_dynar_t xbt_graph_get_edges(xbt_graph_t g)
164 {
165   return g->edges;
166 }
167
168 xbt_node_t xbt_graph_edge_get_source(xbt_edge_t e)
169 {
170   
171   return e->src;
172 }
173 xbt_node_t xbt_graph_edge_get_target(xbt_edge_t e)
174 {
175   return e->dst;
176 }
177 int xbt_get_node_index(xbt_graph_t g, xbt_node_t n)
178 {
179
180   int cursor=0;
181   xbt_node_t tmp;
182   xbt_dynar_foreach(g->nodes,cursor,tmp)
183     {
184       if (tmp==n)
185         break;
186     }
187   return (cursor-1);
188 }
189
190 void  xbt_graph_edge_set_length(xbt_edge_t e, double length)
191 {
192   e->length=length;
193   
194 }
195 double xbt_graph_edge_get_length(xbt_edge_t e)
196 {
197   return e->length;
198 }
199
200
201 /*construct the adjacency matrix corresponding to a graph,
202   the weights are the distances between nodes
203  */
204 double* xbt_graph_get_length_matrix(xbt_graph_t g)
205 {
206  fprintf(stderr,"%s","START GET LENGTHS\n" );
207  int cursor = 0;
208   int in_cursor = 0;
209   int idx,i;
210   unsigned long n;
211   xbt_edge_t edge = NULL;
212   xbt_node_t node;
213   double* d=NULL;
214
215  # define D(u,v) d[(u)*n+(v)] 
216  n = xbt_dynar_length(g->nodes);
217
218   d = (double*)xbt_malloc(n*n*(sizeof(double)));
219
220   for (i=0;i<n*n;i++)
221     {
222           d[i]=-1.0;
223     }
224
225
226   xbt_dynar_foreach(g->nodes,cursor,node)
227     {fprintf(stderr,"CURSOR:      %d\n",cursor );
228       in_cursor=0;
229       D(cursor-1,cursor-1)=0;
230       xbt_dynar_foreach(node->in,in_cursor,edge)
231         {fprintf(stderr,"EDGE IN:      %s\n",(char*)edge->data );
232 fprintf(stderr,"EDGE DST:      %s\n",(char*)edge->dst->data );
233           idx = xbt_get_node_index(g,edge->dst);
234  fprintf(stderr,"IDX: %d\n",idx );
235 fprintf(stderr,"EDGE ADR: %x\n",(int)edge );
236 fprintf(stderr,"EDGE LENGTH: %le\n", edge->length );
237           D(cursor-1,idx) = edge->length;
238         }
239     }
240  fprintf(stderr,"BEFORE RETURN\n" );
241  
242 # undef D
243
244 return d; 
245 }
246
247  /*  calculate all-pairs shortest paths */
248 /*   the shortest distance between node  i and j are stocked in  distances[i][j] */
249 void xbt_floyd_algorithm(xbt_graph_t g, double* adj,double* d,  xbt_node_t* p)
250 {
251   int i,j,k;
252  unsigned long n;
253  n = xbt_dynar_length(g->nodes);
254
255 # define D(u,v) d[(u)*n+(v)]
256 # define P(u,v) p[(u)*n+(v)]
257
258
259  
260   for(i=0;i<n*n;i++)
261     {
262       d[i]=adj[i];
263     }
264   for(i=0;i<n;i++)
265     {
266       for(j=0;j<n;j++)
267         {
268           if(D(i,j)!=-1) P(i,j)=xbt_dynar_get_ptr (g->nodes,i) ;
269         }
270     }
271         
272   for(k=0;k<n;k++)
273     {
274       for(i=0;i<n;i++)
275         {
276           for(j=0;j<n;j++)
277             {
278               if((D(i,k)!=-1) && (D(k,j)!=-1))
279                 {
280                   if((D(i,j)==-1) || (D(i,j) > D(i,k)+D(k,j)))
281                     {
282                       D(i,j) = D(i,k)+D(k,j) ;
283                       P(i,j) = P(k,j);
284                     }
285                 }
286             }
287         }
288     }
289 # undef P
290 # undef D
291 }
292
293 /*computes all-pairs shortest paths*/
294 xbt_node_t* xbt_graph_shortest_paths(xbt_graph_t g)
295 {
296   xbt_node_t* p;
297  xbt_node_t* r;
298  int i,j,k;
299  unsigned long  n; 
300  
301   double* adj=NULL;
302  double* d=NULL;
303
304 # define P(u,v) p[(u)*n+(v)]
305 # define R(u,v) r[(u)*n+(v)]
306
307  n = xbt_dynar_length(g->nodes);
308  adj= xbt_graph_get_length_matrix(g); 
309  xbt_floyd_algorithm(g,adj,d,p);
310
311  for(i=0;i<n;i++)
312    {
313      for(j=0;j<n;j++)
314        {
315          k=j;
316          while((P(i,k))&&( xbt_get_node_index(g,P(i,k))!=i))
317            { 
318              k =  xbt_get_node_index(g,P(i,k));
319            }
320          if(P(i,j)) 
321            {
322              R(i,j)=(xbt_node_t)xbt_dynar_get_ptr(g->nodes,k);
323            }
324        }
325    }
326 # undef R
327 # undef P
328
329    xbt_free(d);
330    xbt_free(p);
331  return r;
332 }
333
334 static xbt_graph_t parsed_graph=NULL;
335 static xbt_dict_t parsed_nodes=NULL;
336 static xbt_dict_t parsed_edges=NULL; 
337      
338
339 static void  __parse_graph_begin(void)
340 {
341   DEBUG0("<graph>");
342 }
343 static void  __parse_graph_end(void)
344 {
345   DEBUG0("</graph>");
346 }
347
348 static void __parse_node(void)
349 {
350  xbt_node_t node= xbt_graph_new_node(parsed_graph,(void*)A_graphxml_node_name);
351
352  xbt_dict_set( parsed_nodes,A_graphxml_node_name, (void *)node, free); 
353   
354  DEBUG1("<node label=\"%s\"/>",(char*)(node->data));
355 }
356 static void __parse_edge(void)
357 {
358    xbt_edge_t edge= xbt_graph_new_edge(parsed_graph,
359                                        xbt_dict_get(parsed_nodes,
360                                        A_graphxml_edge_source),
361                                        xbt_dict_get(parsed_nodes,
362                                        A_graphxml_edge_target),
363                                        (void*) A_graphxml_edge_name);
364
365  xbt_dict_set( parsed_edges,A_graphxml_edge_name, (void *)edge, free);
366  xbt_graph_edge_set_length(edge,atof(A_graphxml_edge_length));
367  
368   DEBUG4("<edge name=\"%s\"  source=\"%s\" target=\"%s\" length=\"%f\"/>",
369          (char*)edge->data,
370          (char*)(edge->src)->data,
371          (char*)(edge->dst)->data,
372          xbt_graph_edge_get_length(edge));
373 }
374
375 xbt_graph_t xbt_graph_read(const char *filename)
376
377   xbt_graph_t graph = xbt_graph_new_graph(1,NULL);
378
379   parsed_graph = graph;
380   parsed_nodes= xbt_dict_new();
381   parsed_edges= xbt_dict_new();
382
383
384   xbt_graph_parse_reset_parser();
385   
386   STag_graphxml_graph_fun = __parse_graph_begin;
387   ETag_graphxml_graph_fun = __parse_graph_end;
388   ETag_graphxml_node_fun = __parse_node;
389   ETag_graphxml_edge_fun = __parse_edge;
390
391
392   xbt_graph_parse_open(filename);
393   xbt_assert1((!xbt_graph_parse()),"Parse error in %s",filename);
394   xbt_graph_parse_close();
395
396   parsed_graph = NULL;
397   return graph;
398 }
399 void xbt_graph_export_surfxml(xbt_graph_t g,
400                               const char *filename,
401                               const char *(node_name)(xbt_node_t),
402                               const char *(edge_name)(xbt_edge_t)
403                               )
404 {
405   
406 }
407
408 /* ./xbt/graphxml_usage xbt/graph.xml --xbt-log=graph.thres=debug */