igraph 0.1.1 → 0.3
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.
- 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
|
+
}
|