igraph 0.3.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  *