igraph 0.1.1 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -2
- data/Manifest.txt +17 -0
- data/README.txt +16 -11
- data/ext/cIGraph.c +197 -61
- data/ext/cIGraph.h +155 -8
- data/ext/cIGraph_add_delete.c +146 -66
- data/ext/cIGraph_attribute_handler.c +758 -0
- data/ext/cIGraph_centrality.c +264 -0
- data/ext/cIGraph_components.c +154 -0
- data/ext/cIGraph_file.c +213 -0
- data/ext/cIGraph_layout.c +77 -0
- data/ext/cIGraph_matrix.c +241 -0
- data/ext/cIGraph_selectors.c +95 -7
- data/ext/cIGraph_shortest_paths.c +196 -2
- data/ext/cIGraph_topological_sort.c +43 -0
- data/ext/cIGraph_utility.c +29 -14
- data/ext/cIGraph_vertex_neighbourhood.c +158 -0
- data/test/tc_add_delete.rb +37 -0
- data/test/tc_attributes.rb +29 -0
- data/test/tc_basic_properties.rb +1 -1
- data/test/tc_centrality.rb +33 -0
- data/test/tc_components.rb +25 -0
- data/test/tc_copy.rb +13 -0
- data/test/tc_file_read_write.rb +161 -0
- data/test/tc_layout.rb +26 -0
- data/test/tc_matrix.rb +32 -0
- data/test/tc_selectors.rb +15 -0
- data/test/tc_shortest_paths.rb +25 -2
- data/test/tc_topological_sort.rb +10 -0
- data/test/tc_vertex_neighbourhood.rb +29 -0
- data/test/test_all.rb +9 -0
- metadata +21 -4
@@ -0,0 +1,264 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* graph.closeness(vs,mode) -> Array
|
7
|
+
*
|
8
|
+
* Returns an Array of closeness centrality measures for the vertices given in
|
9
|
+
* the vs Array. mode defines the type of shortest paths used for the
|
10
|
+
* calculation
|
11
|
+
*/
|
12
|
+
VALUE cIGraph_closeness(VALUE self, VALUE vs, VALUE mode){
|
13
|
+
|
14
|
+
igraph_t *graph;
|
15
|
+
igraph_vs_t vids;
|
16
|
+
igraph_vector_t vidv;
|
17
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
18
|
+
igraph_vector_t res;
|
19
|
+
int i;
|
20
|
+
VALUE closeness = rb_ary_new();
|
21
|
+
|
22
|
+
//vector to hold the results of the degree calculations
|
23
|
+
igraph_vector_init_int(&res,0);
|
24
|
+
|
25
|
+
Data_Get_Struct(self, igraph_t, graph);
|
26
|
+
|
27
|
+
//Convert an array of vertices to a vector of vertex ids
|
28
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
29
|
+
//create vertex selector from the vecotr of ids
|
30
|
+
igraph_vs_vector(&vids,&vidv);
|
31
|
+
|
32
|
+
igraph_closeness(graph,&res,vids,pmode);
|
33
|
+
|
34
|
+
for(i=0;i<igraph_vector_size(&res);i++){
|
35
|
+
rb_ary_push(closeness,rb_float_new(VECTOR(res)[i]));
|
36
|
+
}
|
37
|
+
|
38
|
+
igraph_vector_destroy(&vidv);
|
39
|
+
igraph_vector_destroy(&res);
|
40
|
+
igraph_vs_destroy(&vids);
|
41
|
+
|
42
|
+
return closeness;
|
43
|
+
|
44
|
+
}
|
45
|
+
|
46
|
+
/* call-seq:
|
47
|
+
* graph.betweenness(vs,mode) -> Array
|
48
|
+
*
|
49
|
+
* Returns an Array of betweenness centrality measures for the vertices given
|
50
|
+
* in the vs Array. mode defines whether directed paths or considered for
|
51
|
+
* directed graphs.
|
52
|
+
*/
|
53
|
+
VALUE cIGraph_betweenness(VALUE self, VALUE vs, VALUE directed){
|
54
|
+
|
55
|
+
igraph_t *graph;
|
56
|
+
igraph_vs_t vids;
|
57
|
+
igraph_vector_t vidv;
|
58
|
+
igraph_bool_t dir = 0;
|
59
|
+
igraph_vector_t res;
|
60
|
+
int i;
|
61
|
+
VALUE betweenness = rb_ary_new();
|
62
|
+
|
63
|
+
if(directed == Qtrue)
|
64
|
+
dir = 1;
|
65
|
+
|
66
|
+
//vector to hold the results of the degree calculations
|
67
|
+
igraph_vector_init_int(&res,0);
|
68
|
+
|
69
|
+
Data_Get_Struct(self, igraph_t, graph);
|
70
|
+
|
71
|
+
//Convert an array of vertices to a vector of vertex ids
|
72
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
73
|
+
//create vertex selector from the vecotr of ids
|
74
|
+
igraph_vs_vector(&vids,&vidv);
|
75
|
+
|
76
|
+
igraph_betweenness(graph,&res,vids,dir);
|
77
|
+
|
78
|
+
for(i=0;i<igraph_vector_size(&res);i++){
|
79
|
+
rb_ary_push(betweenness,INT2NUM((int)VECTOR(res)[i]));
|
80
|
+
}
|
81
|
+
|
82
|
+
igraph_vector_destroy(&vidv);
|
83
|
+
igraph_vector_destroy(&res);
|
84
|
+
igraph_vs_destroy(&vids);
|
85
|
+
|
86
|
+
return betweenness;
|
87
|
+
|
88
|
+
}
|
89
|
+
|
90
|
+
/* call-seq:
|
91
|
+
* graph.edge_betweenness(mode) -> Array
|
92
|
+
*
|
93
|
+
* Returns an Array of betweenness centrality measures for the edges
|
94
|
+
* in the graph. mode defines whether directed paths or considered for
|
95
|
+
* directed graphs.
|
96
|
+
*/
|
97
|
+
VALUE cIGraph_edge_betweenness(VALUE self, VALUE directed){
|
98
|
+
|
99
|
+
igraph_t *graph;
|
100
|
+
igraph_bool_t dir = 0;
|
101
|
+
igraph_vector_t res;
|
102
|
+
int i;
|
103
|
+
VALUE betweenness = rb_ary_new();
|
104
|
+
|
105
|
+
if(directed == Qtrue)
|
106
|
+
dir = 1;
|
107
|
+
|
108
|
+
//vector to hold the results of the degree calculations
|
109
|
+
igraph_vector_init_int(&res,0);
|
110
|
+
|
111
|
+
Data_Get_Struct(self, igraph_t, graph);
|
112
|
+
|
113
|
+
igraph_edge_betweenness(graph,&res,dir);
|
114
|
+
|
115
|
+
for(i=0;i<igraph_vector_size(&res);i++){
|
116
|
+
rb_ary_push(betweenness,INT2NUM((int)VECTOR(res)[i]));
|
117
|
+
}
|
118
|
+
|
119
|
+
igraph_vector_destroy(&res);
|
120
|
+
|
121
|
+
return betweenness;
|
122
|
+
|
123
|
+
}
|
124
|
+
|
125
|
+
/* call-seq:
|
126
|
+
* graph.pagerank(vs,mode,niter,eps,damping) -> Array
|
127
|
+
*
|
128
|
+
* Returns an Array of PageRank measures for the vertices
|
129
|
+
* in the graph. mode defines whether directed paths or considered for
|
130
|
+
* directed graphs.
|
131
|
+
*/
|
132
|
+
VALUE cIGraph_pagerank(VALUE self, VALUE vs, VALUE directed, VALUE niter, VALUE eps, VALUE damping){
|
133
|
+
|
134
|
+
igraph_t *graph;
|
135
|
+
igraph_vs_t vids;
|
136
|
+
igraph_vector_t vidv;
|
137
|
+
igraph_vector_t res;
|
138
|
+
int i;
|
139
|
+
VALUE pagerank = rb_ary_new();
|
140
|
+
igraph_bool_t dir = 0;
|
141
|
+
|
142
|
+
if(directed == Qtrue)
|
143
|
+
dir = 1;
|
144
|
+
|
145
|
+
//vector to hold the results of the degree calculations
|
146
|
+
igraph_vector_init_int(&res,0);
|
147
|
+
|
148
|
+
Data_Get_Struct(self, igraph_t, graph);
|
149
|
+
|
150
|
+
//Convert an array of vertices to a vector of vertex ids
|
151
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
152
|
+
//create vertex selector from the vecotr of ids
|
153
|
+
igraph_vs_vector(&vids,&vidv);
|
154
|
+
|
155
|
+
igraph_pagerank(graph,&res,vids,dir,
|
156
|
+
NUM2INT(niter),NUM2DBL(eps),NUM2DBL(damping));
|
157
|
+
|
158
|
+
for(i=0;i<igraph_vector_size(&res);i++){
|
159
|
+
rb_ary_push(pagerank,rb_float_new(VECTOR(res)[i]));
|
160
|
+
}
|
161
|
+
|
162
|
+
igraph_vector_destroy(&vidv);
|
163
|
+
igraph_vector_destroy(&res);
|
164
|
+
igraph_vs_destroy(&vids);
|
165
|
+
|
166
|
+
return pagerank;
|
167
|
+
|
168
|
+
}
|
169
|
+
|
170
|
+
/* call-seq:
|
171
|
+
* graph.constraint(vs,weights) -> Array
|
172
|
+
*
|
173
|
+
* Returns an Array of constraint measures for the vertices
|
174
|
+
* in the graph. Weights is an Array of weight measures for each edge.
|
175
|
+
*/
|
176
|
+
VALUE cIGraph_constraint(int argc, VALUE *argv, VALUE self){
|
177
|
+
|
178
|
+
igraph_t *graph;
|
179
|
+
igraph_vs_t vids;
|
180
|
+
igraph_vector_t vidv;
|
181
|
+
igraph_vector_t res;
|
182
|
+
igraph_vector_t *wght = malloc(sizeof(igraph_vector_t));
|
183
|
+
int i;
|
184
|
+
VALUE constraints = rb_ary_new();
|
185
|
+
VALUE vs, weights;
|
186
|
+
|
187
|
+
rb_scan_args(argc,argv,"11",&vs, &weights);
|
188
|
+
|
189
|
+
//vector to hold the results of the degree calculations
|
190
|
+
igraph_vector_init(&res,0);
|
191
|
+
igraph_vector_init(wght,0);
|
192
|
+
|
193
|
+
Data_Get_Struct(self, igraph_t, graph);
|
194
|
+
|
195
|
+
//Convert an array of vertices to a vector of vertex ids
|
196
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
197
|
+
//create vertex selector from the vecotr of ids
|
198
|
+
igraph_vs_vector(&vids,&vidv);
|
199
|
+
|
200
|
+
if(weights == Qnil){
|
201
|
+
igraph_vector_destroy(wght);
|
202
|
+
wght = NULL;
|
203
|
+
} else {
|
204
|
+
for(i=0;i<RARRAY(weights)->len;i++){
|
205
|
+
igraph_vector_push_back(wght,NUM2DBL(RARRAY(weights)->ptr[i]));
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
igraph_constraint(graph,&res,vids,wght);
|
210
|
+
|
211
|
+
for(i=0;i<igraph_vector_size(&res);i++){
|
212
|
+
rb_ary_push(constraints,rb_float_new(VECTOR(res)[i]));
|
213
|
+
}
|
214
|
+
|
215
|
+
igraph_vector_destroy(&vidv);
|
216
|
+
igraph_vector_destroy(&res);
|
217
|
+
if(wght != NULL)
|
218
|
+
igraph_vector_destroy(wght);
|
219
|
+
igraph_vs_destroy(&vids);
|
220
|
+
|
221
|
+
free(wght);
|
222
|
+
|
223
|
+
return constraints;
|
224
|
+
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
/* call-seq:
|
229
|
+
* graph.maxdegree(vs,mode,loops) -> Vertex
|
230
|
+
*
|
231
|
+
* Returns the vertex Object in the vs Array with the largest degree.
|
232
|
+
* mode defines the type
|
233
|
+
* of the degree. IGRAPH_OUT, out-degree, IGRAPH_IN, in-degree, IGRAPH_ALL,
|
234
|
+
* total degree (sum of the in- and out-degree). This parameter is ignored
|
235
|
+
* for undirected graphs. loops is a boolean gives whether the self-loops
|
236
|
+
* should be counted.
|
237
|
+
*/
|
238
|
+
VALUE cIGraph_maxdegree(VALUE self, VALUE vs, VALUE mode, VALUE loops){
|
239
|
+
|
240
|
+
igraph_t *graph;
|
241
|
+
igraph_bool_t loop = 0;
|
242
|
+
igraph_integer_t res;
|
243
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
244
|
+
igraph_vs_t vids;
|
245
|
+
igraph_vector_t vidv;
|
246
|
+
|
247
|
+
if(loops == Qtrue)
|
248
|
+
loop = 1;
|
249
|
+
|
250
|
+
Data_Get_Struct(self, igraph_t, graph);
|
251
|
+
|
252
|
+
//Convert an array of vertices to a vector of vertex ids
|
253
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
254
|
+
//create vertex selector from the vecotr of ids
|
255
|
+
igraph_vs_vector(&vids,&vidv);
|
256
|
+
|
257
|
+
igraph_maxdegree(graph,&res,vids,pmode,loop);
|
258
|
+
|
259
|
+
igraph_vector_destroy(&vidv);
|
260
|
+
igraph_vs_destroy(&vids);
|
261
|
+
|
262
|
+
return INT2NUM(res);
|
263
|
+
|
264
|
+
}
|
@@ -0,0 +1,154 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* graph.subcomponent(v,mode) -> Array
|
7
|
+
*
|
8
|
+
* Returns an Array of vertices that are in the same component as the vertex v.
|
9
|
+
* mode defines the type of the component for directed graphs, possible
|
10
|
+
* values: IGraph::OUT: the set of vertices reachable from the vertex,
|
11
|
+
* IGraph::IN the set of vertices from which the vertex is reachable,
|
12
|
+
* IGraph::ALL the graph is considered as an undirected graph. Note that
|
13
|
+
* this is not the same as the union of the previous two.
|
14
|
+
*/
|
15
|
+
VALUE cIGraph_subcomponent(VALUE self, VALUE v, VALUE mode){
|
16
|
+
|
17
|
+
igraph_t *graph;
|
18
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
19
|
+
igraph_vector_t neis;
|
20
|
+
int i;
|
21
|
+
VALUE component = rb_ary_new();
|
22
|
+
|
23
|
+
igraph_vector_init_int(&neis,0);
|
24
|
+
|
25
|
+
Data_Get_Struct(self, igraph_t, graph);
|
26
|
+
|
27
|
+
igraph_subcomponent(graph, &neis, cIGraph_get_vertex_id(self,v), pmode);
|
28
|
+
|
29
|
+
for(i=0;i<igraph_vector_size(&neis);i++){
|
30
|
+
rb_ary_push(component,cIGraph_get_vertex_object(self,VECTOR(neis)[i]));
|
31
|
+
}
|
32
|
+
|
33
|
+
igraph_vector_destroy(&neis);
|
34
|
+
|
35
|
+
return component;
|
36
|
+
|
37
|
+
}
|
38
|
+
|
39
|
+
/* call-seq:
|
40
|
+
* graph.subgraph(vs) -> IGraph
|
41
|
+
*
|
42
|
+
* Returns an IGraph object containing the vertices defined in the Array vs.
|
43
|
+
*/
|
44
|
+
VALUE cIGraph_subgraph(VALUE self, VALUE vs){
|
45
|
+
|
46
|
+
igraph_t *graph;
|
47
|
+
igraph_t *n_graph = malloc(sizeof(igraph_t));
|
48
|
+
igraph_vs_t vids;
|
49
|
+
igraph_vector_t vidv;
|
50
|
+
|
51
|
+
VALUE n_graph_obj;
|
52
|
+
|
53
|
+
Data_Get_Struct(self, igraph_t, graph);
|
54
|
+
|
55
|
+
//Convert an array of vertices to a vector of vertex ids
|
56
|
+
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
|
57
|
+
//create vertex selector from the vecotr of ids
|
58
|
+
igraph_vs_vector(&vids,&vidv);
|
59
|
+
|
60
|
+
igraph_subgraph(graph,n_graph,vids);
|
61
|
+
|
62
|
+
n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
|
63
|
+
|
64
|
+
igraph_vector_destroy(&vidv);
|
65
|
+
igraph_vs_destroy(&vids);
|
66
|
+
|
67
|
+
return n_graph_obj;
|
68
|
+
|
69
|
+
}
|
70
|
+
|
71
|
+
/* call-seq:
|
72
|
+
* graph.clusters(mode) -> Array
|
73
|
+
*
|
74
|
+
* Calculates the (weakly or strongly) connected components in a graph.
|
75
|
+
* Returns an Array of Arrays of vertices. Each sub-Array is a graph component
|
76
|
+
*/
|
77
|
+
VALUE cIGraph_clusters(VALUE self, VALUE mode){
|
78
|
+
|
79
|
+
igraph_t *graph;
|
80
|
+
igraph_vector_t membership;
|
81
|
+
igraph_integer_t no;
|
82
|
+
VALUE components;
|
83
|
+
VALUE v,c;
|
84
|
+
int i;
|
85
|
+
|
86
|
+
igraph_vector_init_int(&membership,0);
|
87
|
+
|
88
|
+
Data_Get_Struct(self, igraph_t, graph);
|
89
|
+
|
90
|
+
igraph_clusters(graph, &membership, NULL, &no, NUM2INT(mode));
|
91
|
+
|
92
|
+
components = rb_ary_new();
|
93
|
+
for(i=0;i<no;i++){
|
94
|
+
rb_ary_push(components,rb_ary_new());
|
95
|
+
}
|
96
|
+
|
97
|
+
for(i=0;i<igraph_vector_size(&membership);i++){
|
98
|
+
v = cIGraph_get_vertex_object(self, i);
|
99
|
+
c = rb_ary_entry(components,VECTOR(membership)[i]);
|
100
|
+
rb_ary_push(c,v);
|
101
|
+
}
|
102
|
+
|
103
|
+
igraph_vector_destroy(&membership);
|
104
|
+
|
105
|
+
return components;
|
106
|
+
|
107
|
+
}
|
108
|
+
|
109
|
+
/* call-seq:
|
110
|
+
* graph.decompose(mode,maxcomp=-1,minelem=1) -> Array
|
111
|
+
*
|
112
|
+
* Create separate graph for each component of a graph. Returns an Array
|
113
|
+
* of new IGraph object. mode specifies whether weakly and strongly connected
|
114
|
+
* components are returned. Right now only the former is implemented. maxcomp
|
115
|
+
* limits the number of components returned. Leave at the default -1 to return
|
116
|
+
* all components. minelements specifies the minimum number of vertices a
|
117
|
+
* component should contain before it is returned. Default 1 returns all
|
118
|
+
* components.
|
119
|
+
*/
|
120
|
+
VALUE cIGraph_decompose(int argc, VALUE *argv, VALUE self){
|
121
|
+
|
122
|
+
igraph_t *graph;
|
123
|
+
igraph_t *n_graph;
|
124
|
+
igraph_vector_ptr_t components;
|
125
|
+
VALUE mode,maxcomp, minelem, components_a;
|
126
|
+
VALUE n_graph_obj;
|
127
|
+
int i;
|
128
|
+
|
129
|
+
rb_scan_args(argc,argv,"12", &mode, &maxcomp, &minelem);
|
130
|
+
|
131
|
+
if(maxcomp == Qnil)
|
132
|
+
maxcomp = INT2NUM(-1);
|
133
|
+
if(minelem == Qnil)
|
134
|
+
minelem = INT2NUM(1);
|
135
|
+
|
136
|
+
igraph_vector_ptr_init(&components,0);
|
137
|
+
|
138
|
+
Data_Get_Struct(self, igraph_t, graph);
|
139
|
+
|
140
|
+
igraph_decompose(graph, &components, NUM2INT(mode), NUM2INT(maxcomp), NUM2INT(minelem));
|
141
|
+
|
142
|
+
components_a = rb_ary_new();
|
143
|
+
|
144
|
+
for(i=0; i<igraph_vector_ptr_size(&components); i++){
|
145
|
+
n_graph = VECTOR(components)[i];
|
146
|
+
n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
|
147
|
+
rb_ary_push(components_a,n_graph_obj);
|
148
|
+
}
|
149
|
+
|
150
|
+
igraph_vector_ptr_destroy(&components);
|
151
|
+
|
152
|
+
return components_a;
|
153
|
+
|
154
|
+
}
|
data/ext/cIGraph_file.c
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* IGraph.read_graph_edgelist(file,mode) -> IGraph
|
7
|
+
*
|
8
|
+
* Reads an edge list from a File (or any IO) and creates a graph.
|
9
|
+
*
|
10
|
+
* This format is simply a series of even number integers separated by
|
11
|
+
* whitespace. The one edge (ie. two integers) per line format is thus not
|
12
|
+
* required (but recommended for readability). Edges of directed graphs are
|
13
|
+
* assumed to be in from, to order.
|
14
|
+
*/
|
15
|
+
VALUE cIGraph_read_graph_edgelist(VALUE self, VALUE file, VALUE directed){
|
16
|
+
|
17
|
+
VALUE string;
|
18
|
+
FILE *stream;
|
19
|
+
VALUE new_graph;
|
20
|
+
VALUE v_ary;
|
21
|
+
igraph_t *graph;
|
22
|
+
igraph_bool_t directed_b = 0;
|
23
|
+
|
24
|
+
igraph_vs_t vs;
|
25
|
+
igraph_vit_t vit;
|
26
|
+
|
27
|
+
int vid;
|
28
|
+
|
29
|
+
if(directed)
|
30
|
+
directed_b = 1;
|
31
|
+
|
32
|
+
new_graph = cIGraph_alloc(cIGraph);
|
33
|
+
Data_Get_Struct(new_graph, igraph_t, graph);
|
34
|
+
|
35
|
+
string = rb_funcall(file, rb_intern("read"), 0);
|
36
|
+
stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
|
37
|
+
|
38
|
+
igraph_read_graph_edgelist(graph, stream, 0, directed_b);
|
39
|
+
|
40
|
+
fclose(stream);
|
41
|
+
|
42
|
+
igraph_vs_all(&vs);
|
43
|
+
igraph_vit_create(graph, vs, &vit);
|
44
|
+
|
45
|
+
v_ary = ((VALUE*)graph->attr)[0];
|
46
|
+
|
47
|
+
while (!IGRAPH_VIT_END(vit)) {
|
48
|
+
vid = IGRAPH_VIT_GET(vit);
|
49
|
+
rb_ary_push(v_ary,INT2NUM(vid));
|
50
|
+
IGRAPH_VIT_NEXT(vit);
|
51
|
+
}
|
52
|
+
|
53
|
+
igraph_vit_destroy(&vit);
|
54
|
+
igraph_vs_destroy(&vs);
|
55
|
+
|
56
|
+
return new_graph;
|
57
|
+
|
58
|
+
}
|
59
|
+
|
60
|
+
/* call-seq:
|
61
|
+
* graph.write_graph_edgelist(file) -> Integer
|
62
|
+
*
|
63
|
+
* Writes an edge list to an IO
|
64
|
+
*
|
65
|
+
* This format is simply a series of even number integers separated by
|
66
|
+
* whitespace. The one edge (ie. two integers) per line format is thus not
|
67
|
+
* required (but recommended for readability). Edges of directed graphs are
|
68
|
+
* assumed to be in from, to order.
|
69
|
+
*/
|
70
|
+
VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file){
|
71
|
+
|
72
|
+
char *buf;
|
73
|
+
size_t size;
|
74
|
+
FILE *stream;
|
75
|
+
igraph_t *graph;
|
76
|
+
int e;
|
77
|
+
|
78
|
+
Data_Get_Struct(self, igraph_t, graph);
|
79
|
+
|
80
|
+
stream = open_memstream(&buf,&size);
|
81
|
+
e = igraph_write_graph_edgelist(graph, stream);
|
82
|
+
fflush(stream);
|
83
|
+
|
84
|
+
rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
|
85
|
+
|
86
|
+
fclose(stream);
|
87
|
+
|
88
|
+
return e;
|
89
|
+
|
90
|
+
}
|
91
|
+
|
92
|
+
/* call-seq:
|
93
|
+
* IGraph.read_graph_graphml(file,index) -> IGraph
|
94
|
+
*
|
95
|
+
* Reads a graph from a GraphML file specified as the File object file.
|
96
|
+
*
|
97
|
+
* GraphML is an XML-based file format for representing various types of
|
98
|
+
* graphs. Currently only the most basic import functionality is implemented
|
99
|
+
* in igraph: it can read GraphML files without nested graphs and hyperedges.
|
100
|
+
*
|
101
|
+
* If the GraphML file contains more than one graph, the one specified by
|
102
|
+
* this index will be loaded. Indices start from zero, so supply zero here
|
103
|
+
* if your GraphML file contains only a single graph.
|
104
|
+
*/
|
105
|
+
VALUE cIGraph_read_graph_graphml(VALUE self, VALUE file, VALUE index){
|
106
|
+
|
107
|
+
VALUE string;
|
108
|
+
FILE *stream;
|
109
|
+
VALUE new_graph;
|
110
|
+
igraph_t *graph;
|
111
|
+
|
112
|
+
new_graph = cIGraph_alloc(cIGraph);
|
113
|
+
Data_Get_Struct(new_graph, igraph_t, graph);
|
114
|
+
|
115
|
+
string = rb_funcall(file, rb_intern("read"), 0);
|
116
|
+
stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
|
117
|
+
|
118
|
+
igraph_read_graph_graphml(graph, stream, NUM2INT(index));
|
119
|
+
|
120
|
+
fclose(stream);
|
121
|
+
|
122
|
+
return new_graph;
|
123
|
+
|
124
|
+
}
|
125
|
+
|
126
|
+
/* call-seq:
|
127
|
+
* graph.write_graph_graphml(file) -> Integer
|
128
|
+
*
|
129
|
+
* Writes the graph to a File in GraphML format
|
130
|
+
*
|
131
|
+
* GraphML is an XML-based file format for representing various types of
|
132
|
+
* graphs. See the GraphML Primer
|
133
|
+
* (http://graphml.graphdrawing.org/primer/graphml-primer.html) for detailed
|
134
|
+
* format description.
|
135
|
+
*/
|
136
|
+
VALUE cIGraph_write_graph_graphml(VALUE self, VALUE file){
|
137
|
+
|
138
|
+
char *buf;
|
139
|
+
size_t size;
|
140
|
+
FILE *stream;
|
141
|
+
igraph_t *graph;
|
142
|
+
int e;
|
143
|
+
|
144
|
+
Data_Get_Struct(self, igraph_t, graph);
|
145
|
+
|
146
|
+
stream = open_memstream(&buf,&size);
|
147
|
+
e = igraph_write_graph_graphml(graph, stream);
|
148
|
+
fflush(stream);
|
149
|
+
|
150
|
+
rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
|
151
|
+
|
152
|
+
fclose(stream);
|
153
|
+
|
154
|
+
return e;
|
155
|
+
|
156
|
+
}
|
157
|
+
|
158
|
+
/* call-seq:
|
159
|
+
* IGraph.read_graph_pajek(file) -> IGraph
|
160
|
+
*
|
161
|
+
* Reads a file in Pajek format
|
162
|
+
*
|
163
|
+
* Only a subset of the Pajek format is implemented. This is partially
|
164
|
+
* because this format is not very well documented, but also because
|
165
|
+
* igraph does not support some Pajek features, like multigraphs.
|
166
|
+
*/
|
167
|
+
VALUE cIGraph_read_graph_pajek(VALUE self, VALUE file){
|
168
|
+
|
169
|
+
VALUE string;
|
170
|
+
FILE *stream;
|
171
|
+
VALUE new_graph;
|
172
|
+
igraph_t *graph;
|
173
|
+
|
174
|
+
new_graph = cIGraph_alloc(cIGraph);
|
175
|
+
Data_Get_Struct(new_graph, igraph_t, graph);
|
176
|
+
|
177
|
+
string = rb_funcall(file, rb_intern("read"), 0);
|
178
|
+
stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r");
|
179
|
+
|
180
|
+
igraph_read_graph_pajek(graph, stream);
|
181
|
+
|
182
|
+
fclose(stream);
|
183
|
+
|
184
|
+
return new_graph;
|
185
|
+
|
186
|
+
}
|
187
|
+
|
188
|
+
/* call-seq:
|
189
|
+
* graph.write_graph_pajek(file) -> Integer
|
190
|
+
*
|
191
|
+
* Writes a graph to a file in Pajek format.
|
192
|
+
*/
|
193
|
+
VALUE cIGraph_write_graph_pajek(VALUE self, VALUE file){
|
194
|
+
|
195
|
+
char *buf;
|
196
|
+
size_t size;
|
197
|
+
FILE *stream;
|
198
|
+
igraph_t *graph;
|
199
|
+
int e;
|
200
|
+
|
201
|
+
Data_Get_Struct(self, igraph_t, graph);
|
202
|
+
|
203
|
+
stream = open_memstream(&buf,&size);
|
204
|
+
e = igraph_write_graph_pajek(graph, stream);
|
205
|
+
fflush(stream);
|
206
|
+
|
207
|
+
rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size));
|
208
|
+
|
209
|
+
fclose(stream);
|
210
|
+
|
211
|
+
return e;
|
212
|
+
|
213
|
+
}
|