igraph 0.1.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }
@@ -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
+ }