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.
@@ -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
+ }