igraph 0.3.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,230 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * graph.st_edge_connectivity(source,target) -> Integer
7
+ *
8
+ * Edge connectivity of a pair of vertices
9
+ *
10
+ * The edge connectivity of two vertices (source and target) in a graph is
11
+ * the minimum number of edges that have to be deleted from the graph to
12
+ * eliminate all paths from source to target.
13
+ *
14
+ * This function uses the maximum flow algorithm to calculate the edge
15
+ * connectivity.
16
+ *
17
+ */
18
+
19
+ VALUE cIGraph_st_edge_connectivity(VALUE self, VALUE source, VALUE target){
20
+
21
+ igraph_t *graph;
22
+ igraph_integer_t from_i;
23
+ igraph_integer_t to_i;
24
+ igraph_integer_t value;
25
+
26
+ int i;
27
+
28
+ Data_Get_Struct(self, igraph_t, graph);
29
+
30
+ from_i = cIGraph_get_vertex_id(self,source);
31
+ to_i = cIGraph_get_vertex_id(self,target);
32
+
33
+ igraph_st_edge_connectivity(graph,&value,from_i,to_i);
34
+
35
+ return INT2NUM(value);
36
+
37
+ }
38
+
39
+ /* call-seq:
40
+ * graph.edge_connectivity() -> Integer
41
+ *
42
+ * This is the minimum of the edge connectivity over all pairs of vertices
43
+ * in the graph.
44
+ *
45
+ */
46
+
47
+ VALUE cIGraph_edge_connectivity(VALUE self){
48
+
49
+ igraph_t *graph;
50
+ igraph_integer_t value;
51
+
52
+ Data_Get_Struct(self, igraph_t, graph);
53
+
54
+ igraph_edge_connectivity(graph,&value,1);
55
+
56
+ return INT2NUM(value);
57
+
58
+ }
59
+
60
+ /* call-seq:
61
+ * graph.st_vertex_connectivity(source,target,neigh) -> Integer
62
+ *
63
+ * The vertex connectivity of two vertices (source and target) is the minimum
64
+ * number of vertices that have to be deleted to eliminate all paths from
65
+ * source to target. Directed paths are considered in directed graphs.
66
+ *
67
+ * A constant giving what to do if the two vertices are connected. Possible
68
+ * values: IGraph::VCONN_NEI_ERROR, stop with an error message,
69
+ * IGraph::VCONN_INFINITY, return infinity (ie. 1.0/0.0).
70
+ * IGraph::VCONN_IGNORE, ignore the fact that the two vertices are connected
71
+ * and calculated the number of vertices needed to aliminate all paths except
72
+ * for the trivial (direct) paths between source and vertex.
73
+ *
74
+ */
75
+
76
+ VALUE cIGraph_st_vertex_connectivity(VALUE self, VALUE source, VALUE target, VALUE neighbours){
77
+
78
+ igraph_t *graph;
79
+ igraph_integer_t from_i;
80
+ igraph_integer_t to_i;
81
+ igraph_integer_t value;
82
+
83
+ int i;
84
+
85
+ Data_Get_Struct(self, igraph_t, graph);
86
+
87
+ from_i = cIGraph_get_vertex_id(self,source);
88
+ to_i = cIGraph_get_vertex_id(self,target);
89
+
90
+ igraph_st_vertex_connectivity(graph,&value,from_i,to_i,NUM2INT(neighbours));
91
+
92
+ return INT2NUM(value);
93
+
94
+ }
95
+
96
+ /* call-seq:
97
+ * graph.vertex_connectivity() -> Integer
98
+ *
99
+ * This is the minimum of the vertex connectivity over all pairs of vertices
100
+ * in the graph.
101
+ *
102
+ */
103
+
104
+ VALUE cIGraph_vertex_connectivity(VALUE self){
105
+
106
+ igraph_t *graph;
107
+ igraph_integer_t value;
108
+
109
+ Data_Get_Struct(self, igraph_t, graph);
110
+
111
+ igraph_vertex_connectivity(graph,&value,1);
112
+
113
+ return INT2NUM(value);
114
+
115
+ }
116
+
117
+ /* call-seq:
118
+ * graph.edge_disjoint_paths(source,target) -> Integer
119
+ *
120
+ * The maximum number of edge-disjoint paths between two vertices.
121
+ *
122
+ * A set of paths between two vertices is called edge-disjoint if they do not
123
+ * share any edges. The maximum number of edge-disjoint paths are calculated
124
+ * by this function using maximum flow techniques. Directed paths are
125
+ * considered in directed graphs.
126
+ *
127
+ */
128
+
129
+ VALUE cIGraph_edge_disjoint_paths(VALUE self, VALUE source, VALUE target){
130
+
131
+ igraph_t *graph;
132
+ igraph_integer_t from_i;
133
+ igraph_integer_t to_i;
134
+ igraph_integer_t value;
135
+
136
+ int i;
137
+
138
+ Data_Get_Struct(self, igraph_t, graph);
139
+
140
+ from_i = cIGraph_get_vertex_id(self,source);
141
+ to_i = cIGraph_get_vertex_id(self,target);
142
+
143
+ igraph_edge_disjoint_paths(graph,&value,from_i,to_i);
144
+
145
+ return INT2NUM(value);
146
+
147
+ }
148
+
149
+ /* call-seq:
150
+ * graph.vertex_disjoint_paths(source,target) -> Integer
151
+ *
152
+ * The maximum number of vertex-disjoint paths between two vertices.
153
+ *
154
+ * A set of paths between two vertices is called vertex-disjoint if they do
155
+ * not share any vertexs. The maximum number of vertex-disjoint paths are
156
+ * calculated by this function using maximum flow techniques. Directed paths
157
+ * are considered in directed graphs.
158
+ *
159
+ */
160
+
161
+ VALUE cIGraph_vertex_disjoint_paths(VALUE self, VALUE source, VALUE target){
162
+
163
+ igraph_t *graph;
164
+ igraph_integer_t from_i;
165
+ igraph_integer_t to_i;
166
+ igraph_integer_t value;
167
+
168
+ int i;
169
+
170
+ Data_Get_Struct(self, igraph_t, graph);
171
+
172
+ from_i = cIGraph_get_vertex_id(self,source);
173
+ to_i = cIGraph_get_vertex_id(self,target);
174
+
175
+ igraph_vertex_disjoint_paths(graph,&value,from_i,to_i);
176
+
177
+ return INT2NUM(value);
178
+
179
+ }
180
+
181
+ /* call-seq:
182
+ * graph.adhesion() -> Integer
183
+ *
184
+ * Graph adhesion, this is (almost) the same as edge connectivity.
185
+ *
186
+ * This quantity is defined by White and Harary in The cohesiveness of
187
+ * blocks in social networks: node connectivity and conditional density,
188
+ * (Sociological Methodology 31:305--359, 2001) and basically it is the
189
+ * edge connectivity of the graph with uniform edge weights.
190
+ *
191
+ */
192
+
193
+ VALUE cIGraph_adhesion(VALUE self){
194
+
195
+ igraph_t *graph;
196
+ igraph_integer_t value;
197
+
198
+ Data_Get_Struct(self, igraph_t, graph);
199
+
200
+ igraph_adhesion(graph,&value,1);
201
+
202
+ return INT2NUM(value);
203
+
204
+ }
205
+
206
+ /* call-seq:
207
+ * graph.cohesion() -> Integer
208
+ *
209
+ * Graph cohesion, this is the same as vertex connectivity.
210
+ *
211
+ * This quantity is defined by White and Harary in The cohesiveness of
212
+ * blocks in social networks: node connectivity and conditional density,
213
+ * (Sociological Methodology 31:305--359, 2001) and basically it is the
214
+ * edge connectivity of the graph with uniform edge weights.
215
+ *
216
+ */
217
+
218
+ VALUE cIGraph_cohesion(VALUE self){
219
+
220
+ igraph_t *graph;
221
+ igraph_integer_t value;
222
+
223
+ Data_Get_Struct(self, igraph_t, graph);
224
+
225
+ igraph_cohesion(graph,&value,1);
226
+
227
+ return INT2NUM(value);
228
+
229
+ }
230
+
@@ -3,7 +3,7 @@
3
3
  #include "cIGraph.h"
4
4
 
5
5
  /* call-seq:
6
- * IGraph.read_graph_edgelist(file,mode) -> IGraph
6
+ * IGraph::FileRead.read_graph_edgelist(file,mode) -> IGraph
7
7
  *
8
8
  * Reads an edge list from a File (or any IO) and creates a graph.
9
9
  *
@@ -90,7 +90,577 @@ VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file){
90
90
  }
91
91
 
92
92
  /* call-seq:
93
- * IGraph.read_graph_graphml(file,index) -> IGraph
93
+ * IGraph::FileRead.read_graph_ncol(file,predefnames,names,weights,directed) -> IGraph
94
+ *
95
+ * Reads a .ncol file used by LGL, also useful for creating graphs from
96
+ * 'named' (and optionally weighted) edge lists.
97
+ *
98
+ * This format is used by the Large Graph Layout program
99
+ * (http://bioinformatics.icmb.utexas.edu/lgl/), and it is simply a symbolic
100
+ * weighted edge list. It is a simple text file with one edge per line. An
101
+ * edge is defined by two symbolic vertex names separated by whitespace.
102
+ * (The symbolic vertex names themselves cannot contain whitespace. They
103
+ * might follow by an optional number, this will be the weight of the edge;
104
+ * the number can be negative and can be in scientific notation. If there is
105
+ * no weight specified to an edge it is assumed to be zero.
106
+ *
107
+ * The resulting graph is always undirected. LGL cannot deal with files which
108
+ * contain multiple or loop edges, this is however not checked here, as
109
+ * igraph is happy with these.
110
+ *
111
+ * file: A File or IO object to read from.
112
+ *
113
+ * predefnames: Array of the symbolic names of the vertices in the file.
114
+ * If empty then vertex ids will be assigned to vertex names in the order of
115
+ * their appearence in the .ncol file.
116
+ *
117
+ * names: Logical value, if TRUE the symbolic names of the vertices will be
118
+ * added to the graph as a vertex attribute called 'name'.
119
+ *
120
+ * weights: Logical value, if TRUE the weights of the edges is added to the
121
+ * graph as an edge attribute called 'weight'.
122
+ *
123
+ * directed: Whether to create a directed graph. As this format was originally
124
+ * used only for undirected graphs there is no information in the file about
125
+ * the directedness of the graph. Set this parameter to IGRAPH_DIRECTED or
126
+ * IGRAPH_UNDIRECTED to create a directed or undirected graph.
127
+ */
128
+ VALUE cIGraph_read_graph_ncol(VALUE self, VALUE file, VALUE predefnames, VALUE names, VALUE weights, VALUE directed){
129
+
130
+ VALUE string;
131
+ FILE *stream;
132
+ VALUE new_graph;
133
+ VALUE v_ary;
134
+ VALUE e_ary;
135
+ VALUE new_ary;
136
+
137
+ igraph_t *graph;
138
+ igraph_strvector_t names_vec;
139
+ igraph_bool_t directed_b = 0;
140
+ igraph_bool_t weights_b = 0;
141
+ igraph_bool_t names_b = 0;
142
+
143
+ int i;
144
+
145
+ if(directed)
146
+ directed_b = 1;
147
+
148
+ if(names)
149
+ names_b = 1;
150
+
151
+ if(weights)
152
+ weights_b = 1;
153
+
154
+ new_graph = cIGraph_alloc(cIGraph);
155
+ Data_Get_Struct(new_graph, igraph_t, graph);
156
+
157
+ igraph_strvector_init(&names_vec,RARRAY(predefnames)->len);
158
+
159
+ for(i=0;i<RARRAY(predefnames)->len;i++){
160
+ igraph_strvector_set(&names_vec, i, RSTRING(RARRAY(predefnames)->ptr[i])->ptr);
161
+ }
162
+
163
+ string = rb_funcall(file, rb_intern("read"), 0);
164
+ stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
165
+
166
+ if (RARRAY(predefnames)->len == 0){
167
+ igraph_read_graph_ncol(graph, stream, NULL, names_b, weights_b, directed_b);
168
+ } else {
169
+ igraph_read_graph_ncol(graph, stream, &names_vec, names_b, weights_b, directed_b);
170
+ }
171
+
172
+ fclose(stream);
173
+
174
+ //Convert the Hash of names to Strings instead
175
+ if(names){
176
+ v_ary = ((VALUE*)graph->attr)[0];
177
+ new_ary = rb_ary_new();
178
+ for(i=0;i<RARRAY(v_ary)->len;i++){
179
+ rb_ary_push(new_ary, rb_hash_aref(RARRAY(v_ary)->ptr[i], rb_str_new2("name")));
180
+ }
181
+ ((VALUE*)graph->attr)[0] = new_ary;
182
+ }
183
+ //Convert the Hash of weights to floats instead
184
+ if(weights){
185
+ e_ary = ((VALUE*)graph->attr)[1];
186
+ new_ary = rb_ary_new();
187
+ for(i=0;i<RARRAY(e_ary)->len;i++){
188
+ rb_ary_push(new_ary, rb_hash_aref(RARRAY(e_ary)->ptr[i], rb_str_new2("weight")));
189
+ }
190
+ ((VALUE*)graph->attr)[1] = new_ary;
191
+ }
192
+
193
+ igraph_strvector_destroy(&names_vec);
194
+
195
+ return new_graph;
196
+
197
+ }
198
+
199
+ /* call-seq:
200
+ * graph.write_graph_ncol(file,names,weights) -> Integer
201
+ *
202
+ * Writes the graph to a file in .ncol format
203
+ *
204
+ * .ncol is a format used by LGL, see igraph_read_graph_ncol() for details.
205
+ *
206
+ * Note that having multiple or loop edges in an .ncol file breaks the LGL
207
+ * software but igraph does not check for this condition.
208
+ *
209
+ * file: The file object to write to, it should be writable.
210
+ *
211
+ * names: The name of the vertex attribute, if symbolic names are to be
212
+ * written to the file.
213
+ *
214
+ * weights: The name of the edge attribute, if they are also written to the
215
+ * file.
216
+ */
217
+ VALUE cIGraph_write_graph_ncol(VALUE self, VALUE file, VALUE names, VALUE weights){
218
+
219
+ char *buf;
220
+ size_t size;
221
+ FILE *stream;
222
+ igraph_t *graph;
223
+ int e, i;
224
+
225
+ VALUE v_ary;
226
+ VALUE e_ary;
227
+ VALUE new_v_ary;
228
+ VALUE new_e_ary;
229
+
230
+ VALUE vertex_h;
231
+ VALUE edge_h;
232
+
233
+ char *weights_b = "0";
234
+ char *names_b = "0";
235
+
236
+ if(names)
237
+ names_b = "name";
238
+
239
+ if(weights)
240
+ weights_b = "weight";
241
+
242
+ Data_Get_Struct(self, igraph_t, graph);
243
+
244
+ //Convert each object to it's String representation and each edge to
245
+ //it's Float
246
+ if(names){
247
+ v_ary = ((VALUE*)graph->attr)[0];
248
+ new_v_ary = rb_ary_new();
249
+ for(i=0;i<RARRAY(v_ary)->len;i++){
250
+ vertex_h = rb_hash_new();
251
+ rb_hash_aset(vertex_h, rb_str_new2("name"), StringValue(RARRAY(v_ary)->ptr[i]));
252
+ rb_ary_push(new_v_ary, vertex_h);
253
+ }
254
+ ((VALUE*)graph->attr)[0] = new_v_ary;
255
+ }
256
+ if(weights){
257
+ e_ary = ((VALUE*)graph->attr)[1];
258
+ new_e_ary = rb_ary_new();
259
+ for(i=0;i<RARRAY(e_ary)->len;i++){
260
+ edge_h = rb_hash_new();
261
+ rb_hash_aset(edge_h, rb_str_new2("weight"), rb_funcall(RARRAY(e_ary)->ptr[i],rb_intern("to_f"),0));
262
+ rb_ary_push(new_e_ary, edge_h);
263
+ }
264
+ ((VALUE*)graph->attr)[1] = new_e_ary;
265
+ }
266
+
267
+ stream = open_memstream(&buf,&size);
268
+ e = igraph_write_graph_ncol(graph, stream, names_b, weights_b);
269
+ fflush(stream);
270
+ rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
271
+ fclose(stream);
272
+
273
+ //Replace initital vertices and edges
274
+ if(names){
275
+ ((VALUE*)graph->attr)[0] = v_ary;
276
+ }
277
+ if(weights){
278
+ ((VALUE*)graph->attr)[0] = e_ary;
279
+ }
280
+
281
+ return e;
282
+
283
+ }
284
+
285
+ /* call-seq:
286
+ * IGraph::FileRead.read_graph_lgl(file,predefnames,names,weights) -> IGraph
287
+ *
288
+ * Reads a graph from an .lgl file
289
+ *
290
+ * The .lgl format is used by the Large Graph Layout visualization software
291
+ * (http://bioinformatics.icmb.utexas.edu/lgl/), it can describe undirected
292
+ * optionally weighted graphs. From the LGL manual:
293
+ *
294
+ * The second format is the LGL file format ( .lgl file suffix). This is yet
295
+ * another graph file format that tries to be as stingy as possible with
296
+ * space, yet keeping the edge file in a human readable (not binary) format.
297
+ * The format itself is like the following:
298
+ *
299
+ * # vertex1name
300
+ * vertex2name [optionalWeight]
301
+ * vertex3name [optionalWeight]
302
+ *
303
+ * Here, the first vertex of an edge is preceded with a pound sign '#'.
304
+ * Then each vertex that shares an edge with that vertex is listed one per
305
+ * line on subsequent lines.
306
+ *
307
+ * LGL cannot handle loop and multiple edges or directed graphs, but in
308
+ * igraph it is not an error to have multiple and loop edges.
309
+ *
310
+ * file: A File or IO object to read from.
311
+ *
312
+ * names: Logical value, if TRUE the symbolic names of the vertices will be
313
+ * added to the graph as a vertex attribute called $B!H(Bname$B!I(B.
314
+ *
315
+ * weights: Logical value, if TRUE the weights of the edges is added to the
316
+ * graph as an edge attribute called $B!H(Bweight$B!I(B.
317
+ */
318
+ VALUE cIGraph_read_graph_lgl(VALUE self, VALUE file, VALUE names, VALUE weights){
319
+
320
+ VALUE string;
321
+ FILE *stream;
322
+ VALUE new_graph;
323
+ VALUE v_ary;
324
+ VALUE e_ary;
325
+ VALUE new_ary;
326
+
327
+ igraph_t *graph;
328
+ igraph_bool_t weights_b = 0;
329
+ igraph_bool_t names_b = 0;
330
+
331
+ int i;
332
+
333
+ if(names)
334
+ names_b = 1;
335
+
336
+ if(weights)
337
+ weights_b = 1;
338
+
339
+ new_graph = cIGraph_alloc(cIGraph);
340
+ Data_Get_Struct(new_graph, igraph_t, graph);
341
+
342
+ string = rb_funcall(file, rb_intern("read"), 0);
343
+ stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
344
+
345
+ igraph_read_graph_lgl(graph, stream, names_b, weights_b);
346
+
347
+ fclose(stream);
348
+
349
+ //Convert the Hash of names to Strings instead
350
+ if(names){
351
+ v_ary = ((VALUE*)graph->attr)[0];
352
+ new_ary = rb_ary_new();
353
+ for(i=0;i<RARRAY(v_ary)->len;i++){
354
+ rb_ary_push(new_ary, rb_hash_aref(RARRAY(v_ary)->ptr[i], rb_str_new2("name")));
355
+ }
356
+ ((VALUE*)graph->attr)[0] = new_ary;
357
+ }
358
+ //Convert the Hash of weights to floats instead
359
+ if(weights){
360
+ e_ary = ((VALUE*)graph->attr)[1];
361
+ new_ary = rb_ary_new();
362
+ for(i=0;i<RARRAY(e_ary)->len;i++){
363
+ rb_ary_push(new_ary, rb_hash_aref(RARRAY(e_ary)->ptr[i], rb_str_new2("weight")));
364
+ }
365
+ ((VALUE*)graph->attr)[1] = new_ary;
366
+ }
367
+
368
+ return new_graph;
369
+
370
+ }
371
+
372
+ /* call-seq:
373
+ * graph.write_graph_lgl(file,names,weights,isolates) -> Integer
374
+ *
375
+ * Writes the graph to a file in .lgl format
376
+ *
377
+ * .lgl is a format used by LGL, see read_graph_lgl() for details.
378
+ *
379
+ * Note that having multiple or loop edges in an .lgl file breaks the LGL
380
+ * software but igraph does not check for this condition.
381
+ *
382
+ * file: The File object to write to, it should be writable.
383
+ *
384
+ * names: The name of the vertex attribute, if symbolic names are written to
385
+ * the file.
386
+ *
387
+ * weights: The name of the edge attribute, if they are also written to the
388
+ * file.
389
+ *
390
+ * isolates: Logical, if TRUE isolated vertices are also written to the file.
391
+ * If FALSE they will be omitted.
392
+ */
393
+ VALUE cIGraph_write_graph_lgl(VALUE self, VALUE file, VALUE names, VALUE weights, VALUE isolates){
394
+
395
+ char *buf;
396
+ size_t size;
397
+ FILE *stream;
398
+ igraph_t *graph;
399
+ int e, i;
400
+
401
+ VALUE v_ary;
402
+ VALUE e_ary;
403
+ VALUE new_v_ary;
404
+ VALUE new_e_ary;
405
+
406
+ VALUE vertex_h;
407
+ VALUE edge_h;
408
+
409
+ char *weights_b = "0";
410
+ char *names_b = "0";
411
+
412
+ igraph_bool_t isolates_b;
413
+
414
+ if(names)
415
+ names_b = "name";
416
+
417
+ if(weights)
418
+ weights_b = "weight";
419
+
420
+ if(isolates)
421
+ isolates_b = 1;
422
+
423
+ Data_Get_Struct(self, igraph_t, graph);
424
+
425
+ //Convert each object to it's String representation and each edge to
426
+ //it's Float
427
+ if(names){
428
+ v_ary = ((VALUE*)graph->attr)[0];
429
+ new_v_ary = rb_ary_new();
430
+ for(i=0;i<RARRAY(v_ary)->len;i++){
431
+ vertex_h = rb_hash_new();
432
+ rb_hash_aset(vertex_h, rb_str_new2("name"), StringValue(RARRAY(v_ary)->ptr[i]));
433
+ rb_ary_push(new_v_ary, vertex_h);
434
+ }
435
+ ((VALUE*)graph->attr)[0] = new_v_ary;
436
+ }
437
+ if(weights){
438
+ e_ary = ((VALUE*)graph->attr)[1];
439
+ new_e_ary = rb_ary_new();
440
+ for(i=0;i<RARRAY(e_ary)->len;i++){
441
+ edge_h = rb_hash_new();
442
+ rb_hash_aset(edge_h, rb_str_new2("weight"), rb_funcall(RARRAY(e_ary)->ptr[i],rb_intern("to_f"),0));
443
+ rb_ary_push(new_e_ary, edge_h);
444
+ }
445
+ ((VALUE*)graph->attr)[1] = new_e_ary;
446
+ }
447
+
448
+ stream = open_memstream(&buf,&size);
449
+ e = igraph_write_graph_lgl(graph, stream, names_b, weights_b, isolates);
450
+ fflush(stream);
451
+ rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
452
+ fclose(stream);
453
+
454
+ //Replace initital vertices and edges
455
+ if(names){
456
+ ((VALUE*)graph->attr)[0] = v_ary;
457
+ }
458
+ if(weights){
459
+ ((VALUE*)graph->attr)[0] = e_ary;
460
+ }
461
+
462
+ return e;
463
+
464
+ }
465
+
466
+ /* call-seq:
467
+ * IGraph::FileRead.read_graph_dimacs(file,directed) -> IGraph
468
+ *
469
+ * This function reads the DIMACS file format, more specifically the version
470
+ * for network flow problems, see the files at
471
+ * ftp://dimacs.rutgers.edu/pub/netflow/general-info/
472
+ *
473
+ * This is a line-oriented text file (ASCII) format. The first character of
474
+ * each line defines the type of the line. If the first character is c the
475
+ * line is a comment line and it is ignored. There is one problem line ( p in
476
+ * the file, it must appear before any node and arc descriptor lines. The
477
+ * problem line has three fields separated by spaces: the problem type
478
+ * ( min , max or asn ), the number of vertices and number of edges in the
479
+ * graph. Exactly two node identification lines are expected ( n ), one for
480
+ * the source, one for the target vertex. These have two fields: the id of
481
+ * the vertex and the type of the vertex, either s (=source) or t (=target).
482
+ * Arc lines start with a and have three fields: the source vertex, the
483
+ * target vertex and the edge capacity.
484
+ *
485
+ * Vertex ids are numbered from 1. The source, target vertices and edge
486
+ * capacities are added as attributes of the graph.
487
+ * I.e: g.attributes['source'].
488
+ *
489
+ * file: The File to read from.
490
+ *
491
+ * directed: Boolean, whether to create a directed graph.
492
+ */
493
+ VALUE cIGraph_read_graph_dimacs(VALUE self, VALUE file, VALUE directed){
494
+
495
+ VALUE string;
496
+ FILE *stream;
497
+ VALUE new_graph;
498
+
499
+ igraph_integer_t source;
500
+ igraph_integer_t target;
501
+ igraph_vector_t capacity;
502
+
503
+ igraph_t *graph;
504
+ igraph_bool_t directed_b = 0;
505
+
506
+ igraph_vs_t vs;
507
+ igraph_vit_t vit;
508
+
509
+ VALUE v_ary;
510
+ VALUE g_hsh;
511
+
512
+ int i;
513
+ int vid;
514
+
515
+ if(directed)
516
+ directed_b = 1;
517
+
518
+ igraph_vector_init(&capacity, 0);
519
+
520
+ new_graph = cIGraph_alloc(cIGraph);
521
+ Data_Get_Struct(new_graph, igraph_t, graph);
522
+
523
+ string = rb_funcall(file, rb_intern("read"), 0);
524
+ stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
525
+
526
+ igraph_read_graph_dimacs(graph, stream, &source, &target, &capacity, directed_b);
527
+
528
+ fclose(stream);
529
+
530
+ igraph_vs_all(&vs);
531
+ igraph_vit_create(graph, vs, &vit);
532
+
533
+ //Push Integer onto vertex array
534
+ v_ary = ((VALUE*)graph->attr)[0];
535
+
536
+ while (!IGRAPH_VIT_END(vit)) {
537
+ vid = IGRAPH_VIT_GET(vit);
538
+ rb_ary_push(v_ary,INT2NUM(vid));
539
+ IGRAPH_VIT_NEXT(vit);
540
+ }
541
+
542
+ g_hsh = ((VALUE*)graph->attr)[2];
543
+
544
+ rb_hash_aset(g_hsh, rb_str_new2("source"), INT2NUM(source));
545
+ rb_hash_aset(g_hsh, rb_str_new2("target"), INT2NUM(target));
546
+ rb_hash_aset(g_hsh, rb_str_new2("capacity"), rb_ary_new());
547
+
548
+ for(i=0;i<igraph_vector_size(&capacity);i++){
549
+ rb_ary_push(rb_hash_aref(g_hsh, rb_str_new2("capacity")), rb_float_new(VECTOR(capacity)[i]));
550
+ }
551
+
552
+ igraph_vit_destroy(&vit);
553
+ igraph_vs_destroy(&vs);
554
+
555
+ return new_graph;
556
+
557
+ }
558
+
559
+ /* call-seq:
560
+ * graph.write_graph_dimacs(file,source,target,capacity) -> Integer
561
+ *
562
+ * This function writes a graph to an output stream in DIMACS format,
563
+ * describing a maximum flow problem. See
564
+ * ftp://dimacs.rutgers.edu/pub/netflow/general-info/
565
+ *
566
+ * This file format is discussed in the documentation of read_graph_dimacs(),
567
+ * see that for more information.
568
+ *
569
+ * file: IO object to write to.
570
+ *
571
+ * source: The source vertex for the maximum flow.
572
+ *
573
+ * target: The target vertex.
574
+ *
575
+ * capacity: Array containing the edge capacity values.
576
+ */
577
+ VALUE cIGraph_write_graph_dimacs(VALUE self, VALUE file, VALUE source, VALUE target, VALUE capacity){
578
+
579
+ char *buf;
580
+ size_t size;
581
+ FILE *stream;
582
+ igraph_t *graph;
583
+ int e, i;
584
+
585
+ igraph_vector_t capacity_v;
586
+
587
+ Data_Get_Struct(self, igraph_t, graph);
588
+
589
+ igraph_vector_init(&capacity_v,0);
590
+
591
+ for(i=0;i<RARRAY(capacity)->len;i++){
592
+ igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i]));
593
+ }
594
+
595
+ stream = open_memstream(&buf,&size);
596
+ e = igraph_write_graph_dimacs(graph, stream, NUM2INT(source), NUM2INT(target), &capacity_v);
597
+ fflush(stream);
598
+ rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
599
+ fclose(stream);
600
+
601
+ return e;
602
+
603
+ }
604
+
605
+ /* call-seq:
606
+ * IGraph::FileRead.read_graph_graphdb(file,directed) -> IGraph
607
+ *
608
+ * Read a graph in the binary graph database format.
609
+ *
610
+ * file: The IO object to read from.
611
+ *
612
+ * directed: Boolean, whether to create a directed graph.
613
+ */
614
+ VALUE cIGraph_read_graph_graphdb(VALUE self, VALUE file, VALUE directed){
615
+
616
+ VALUE string;
617
+ FILE *stream;
618
+ VALUE new_graph;
619
+
620
+ VALUE v_ary;
621
+
622
+ igraph_t *graph;
623
+ igraph_bool_t directed_b = 0;
624
+
625
+ igraph_vs_t vs;
626
+ igraph_vit_t vit;
627
+
628
+ int vid;
629
+
630
+ if(directed)
631
+ directed_b = 1;
632
+
633
+ new_graph = cIGraph_alloc(cIGraph);
634
+ Data_Get_Struct(new_graph, igraph_t, graph);
635
+
636
+ string = rb_funcall(file, rb_intern("read"), 0);
637
+ stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
638
+
639
+ igraph_read_graph_graphdb(graph, stream, directed_b);
640
+
641
+ fclose(stream);
642
+
643
+ igraph_vs_all(&vs);
644
+ igraph_vit_create(graph, vs, &vit);
645
+
646
+ //Push Integer onto vertex array
647
+ v_ary = ((VALUE*)graph->attr)[0];
648
+
649
+ while (!IGRAPH_VIT_END(vit)) {
650
+ vid = IGRAPH_VIT_GET(vit);
651
+ rb_ary_push(v_ary,INT2NUM(vid));
652
+ IGRAPH_VIT_NEXT(vit);
653
+ }
654
+
655
+ igraph_vit_destroy(&vit);
656
+ igraph_vs_destroy(&vs);
657
+
658
+ return new_graph;
659
+
660
+ }
661
+
662
+ /* call-seq:
663
+ * IGraph::FileRead.read_graph_graphml(file,index) -> IGraph
94
664
  *
95
665
  * Reads a graph from a GraphML file specified as the File object file.
96
666
  *
@@ -156,7 +726,68 @@ VALUE cIGraph_write_graph_graphml(VALUE self, VALUE file){
156
726
  }
157
727
 
158
728
  /* call-seq:
159
- * IGraph.read_graph_pajek(file) -> IGraph
729
+ * IGraph::FileRead.read_graph_gml(file) -> IGraph
730
+ *
731
+ * Reads a graph from a GraphML file.
732
+ *
733
+ * GraphML is an XML-based file format for representing various types of
734
+ * graphs. Currently only the most basic import functionality is implemented
735
+ * in igraph: it can read GraphML files without nested graphs and hyperedges.
736
+ *
737
+ * file: IO object to read from
738
+ */
739
+ VALUE cIGraph_read_graph_gml(VALUE self, VALUE file){
740
+
741
+ VALUE string;
742
+ FILE *stream;
743
+ VALUE new_graph;
744
+ igraph_t *graph;
745
+
746
+ new_graph = cIGraph_alloc(cIGraph);
747
+ Data_Get_Struct(new_graph, igraph_t, graph);
748
+
749
+ string = rb_funcall(file, rb_intern("read"), 0);
750
+ stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
751
+
752
+ igraph_read_graph_gml(graph, stream);
753
+
754
+ fclose(stream);
755
+
756
+ return new_graph;
757
+
758
+ }
759
+
760
+ /* call-seq:
761
+ * graph.write_graph_gml(file) -> IGraph
762
+ *
763
+ * Writes the graph to a file in GraphML format.
764
+ *
765
+ * file: IO object to write to
766
+ */
767
+ VALUE cIGraph_write_graph_gml(VALUE self, VALUE file){
768
+
769
+ char *buf;
770
+ size_t size;
771
+ FILE *stream;
772
+ igraph_t *graph;
773
+ int e;
774
+
775
+ Data_Get_Struct(self, igraph_t, graph);
776
+
777
+ stream = open_memstream(&buf,&size);
778
+ e = igraph_write_graph_gml(graph, stream, NULL, 0);
779
+ fflush(stream);
780
+
781
+ rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
782
+
783
+ fclose(stream);
784
+
785
+ return e;
786
+
787
+ }
788
+
789
+ /* call-seq:
790
+ * IGraph::FileRead.read_graph_pajek(file) -> IGraph
160
791
  *
161
792
  * Reads a file in Pajek format
162
793
  *