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,77 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* graph.layout_random -> IGraphMatrix
|
7
|
+
*
|
8
|
+
* Returns a random layout
|
9
|
+
*/
|
10
|
+
VALUE cIGraph_layout_random(VALUE self){
|
11
|
+
|
12
|
+
igraph_t *graph;
|
13
|
+
igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
|
14
|
+
|
15
|
+
Data_Get_Struct(self, igraph_t, graph);
|
16
|
+
|
17
|
+
igraph_matrix_init(res,0,0);
|
18
|
+
igraph_layout_random(graph,res);
|
19
|
+
|
20
|
+
return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
|
21
|
+
|
22
|
+
}
|
23
|
+
|
24
|
+
/* call-seq:
|
25
|
+
* graph.layout_random -> IGraphMatrix
|
26
|
+
*
|
27
|
+
* Returns a layout with nodes laid out around a circle.
|
28
|
+
*/
|
29
|
+
VALUE cIGraph_layout_circle(VALUE self){
|
30
|
+
|
31
|
+
igraph_t *graph;
|
32
|
+
igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
|
33
|
+
|
34
|
+
Data_Get_Struct(self, igraph_t, graph);
|
35
|
+
|
36
|
+
igraph_matrix_init(res,0,0);
|
37
|
+
igraph_layout_circle(graph,res);
|
38
|
+
|
39
|
+
return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
|
40
|
+
|
41
|
+
}
|
42
|
+
|
43
|
+
/* call-seq:
|
44
|
+
* graph.layout_random -> IGraphMatrix
|
45
|
+
*
|
46
|
+
* Places the vertices on a plane according to the Fruchterman-Reingold
|
47
|
+
* algorithm.
|
48
|
+
*
|
49
|
+
* This is a force-directed layout, see Fruchterman, T.M.J. and Reingold,
|
50
|
+
* E.M.: Graph Drawing by Force-directed Placement. Software -- Practice and
|
51
|
+
* Experience, 21/11, 1129--1164, 1991.
|
52
|
+
*/
|
53
|
+
VALUE cIGraph_layout_fruchterman_reingold(VALUE self,
|
54
|
+
VALUE niter,
|
55
|
+
VALUE maxdelta,
|
56
|
+
VALUE area,
|
57
|
+
VALUE coolexp,
|
58
|
+
VALUE repulserad,
|
59
|
+
VALUE use_seed){
|
60
|
+
|
61
|
+
igraph_t *graph;
|
62
|
+
igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
|
63
|
+
|
64
|
+
Data_Get_Struct(self, igraph_t, graph);
|
65
|
+
|
66
|
+
igraph_matrix_init(res,0,0);
|
67
|
+
igraph_layout_fruchterman_reingold(graph,res,
|
68
|
+
NUM2INT(niter),
|
69
|
+
NUM2DBL(maxdelta),
|
70
|
+
NUM2DBL(area),
|
71
|
+
NUM2DBL(coolexp),
|
72
|
+
NUM2DBL(repulserad),
|
73
|
+
use_seed == Qtrue ? 1: 0);
|
74
|
+
|
75
|
+
return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
|
76
|
+
|
77
|
+
}
|
@@ -0,0 +1,241 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
//Classes
|
6
|
+
VALUE cIGraphMatrix;
|
7
|
+
|
8
|
+
void cIGraph_matrix_free(void *p){
|
9
|
+
igraph_matrix_destroy(p);
|
10
|
+
}
|
11
|
+
|
12
|
+
VALUE cIGraph_matrix_alloc(VALUE klass){
|
13
|
+
|
14
|
+
igraph_matrix_t *m = malloc(sizeof(igraph_matrix_t));
|
15
|
+
VALUE obj;
|
16
|
+
|
17
|
+
igraph_matrix_init(m, 0, 0);
|
18
|
+
|
19
|
+
obj = Data_Wrap_Struct(klass, 0, cIGraph_matrix_free, m);
|
20
|
+
|
21
|
+
return obj;
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
/* Document-method: initialize_copy
|
26
|
+
*
|
27
|
+
* Internal method for copying IGraph objects.
|
28
|
+
*/
|
29
|
+
VALUE cIGraph_matrix_init_copy(VALUE copy, VALUE orig){
|
30
|
+
|
31
|
+
igraph_matrix_t *orig_m;
|
32
|
+
igraph_matrix_t *copy_m;
|
33
|
+
|
34
|
+
if (copy == orig)
|
35
|
+
return copy;
|
36
|
+
|
37
|
+
if(TYPE(orig) != T_DATA || RDATA(orig)->dfree != (RUBY_DATA_FUNC)cIGraph_free){
|
38
|
+
rb_raise(rb_eTypeError, "Wrong argument type.");
|
39
|
+
}
|
40
|
+
|
41
|
+
Data_Get_Struct(copy, igraph_matrix_t, copy_m);
|
42
|
+
Data_Get_Struct(orig, igraph_matrix_t, orig_m);
|
43
|
+
|
44
|
+
igraph_matrix_copy(copy_m,orig_m);
|
45
|
+
|
46
|
+
return copy;
|
47
|
+
|
48
|
+
}
|
49
|
+
|
50
|
+
/* call-seq:
|
51
|
+
* IGraphMatrix.new([[x,y,...],...]) -> IGraphMatrix
|
52
|
+
*
|
53
|
+
* Creates a new IGraphMatrix object. The argument should be an Array of
|
54
|
+
* Arrays which each contain the data for a row of the matrix.
|
55
|
+
*/
|
56
|
+
VALUE cIGraph_matrix_initialize(int argc, VALUE *argv, VALUE self){
|
57
|
+
|
58
|
+
igraph_matrix_t *m;
|
59
|
+
VALUE rows;
|
60
|
+
int nrows;
|
61
|
+
int ncols;
|
62
|
+
int i;
|
63
|
+
int j;
|
64
|
+
|
65
|
+
rb_scan_args(argc,argv,"0*", &rows);
|
66
|
+
|
67
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
68
|
+
|
69
|
+
nrows = RARRAY(rows)->len;
|
70
|
+
ncols = RARRAY(RARRAY(rows)->ptr[0])->len;
|
71
|
+
|
72
|
+
igraph_matrix_resize(m, nrows, ncols);
|
73
|
+
|
74
|
+
//Loop through rows
|
75
|
+
for (i=0; i<nrows; i++) {
|
76
|
+
for (j=0; j<ncols; j++){
|
77
|
+
MATRIX(*m,i,j) = NUM2DBL(RARRAY(RARRAY(rows)->ptr[i])->ptr[j]);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
return self;
|
82
|
+
|
83
|
+
}
|
84
|
+
|
85
|
+
/* call-seq:
|
86
|
+
* matrix[i,j] -> Float
|
87
|
+
*
|
88
|
+
* Returns the value stored at row i and column j.
|
89
|
+
*/
|
90
|
+
VALUE cIGraph_matrix_get(VALUE self, VALUE i, VALUE j){
|
91
|
+
|
92
|
+
igraph_matrix_t *m;
|
93
|
+
|
94
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
95
|
+
return rb_float_new(MATRIX(*m,NUM2INT(i),NUM2INT(j)));
|
96
|
+
|
97
|
+
}
|
98
|
+
|
99
|
+
/* call-seq:
|
100
|
+
* matrix[i,j]= -> Float
|
101
|
+
*
|
102
|
+
* Sets the value stored at row i and column j.
|
103
|
+
*/
|
104
|
+
VALUE cIGraph_matrix_set(VALUE self, VALUE i, VALUE j, VALUE x){
|
105
|
+
|
106
|
+
igraph_matrix_t *m;
|
107
|
+
|
108
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
109
|
+
MATRIX(*m,NUM2INT(i),NUM2INT(j)) = NUM2DBL(x);
|
110
|
+
return x;
|
111
|
+
|
112
|
+
}
|
113
|
+
|
114
|
+
/* call-seq:
|
115
|
+
* matrix.each{|v| } -> nil
|
116
|
+
*
|
117
|
+
* Iterates through each value in the matrix.
|
118
|
+
*/
|
119
|
+
VALUE cIGraph_matrix_each(VALUE self){
|
120
|
+
|
121
|
+
igraph_matrix_t *m;
|
122
|
+
int i;
|
123
|
+
int j;
|
124
|
+
|
125
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
126
|
+
|
127
|
+
for(i=0;i < m->nrow;i++){
|
128
|
+
for(j=0;j < m->ncol;j++){
|
129
|
+
rb_yield(rb_float_new(MATRIX(*m,i,j)));
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
return Qnil;
|
134
|
+
|
135
|
+
}
|
136
|
+
|
137
|
+
/* call-seq:
|
138
|
+
* matrix.size -> Integer
|
139
|
+
*
|
140
|
+
* Returns the number of elements in the matrix.
|
141
|
+
*/
|
142
|
+
VALUE cIGraph_matrix_size(VALUE self){
|
143
|
+
|
144
|
+
igraph_matrix_t *m;
|
145
|
+
|
146
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
147
|
+
return LONG2FIX(igraph_matrix_size(m));
|
148
|
+
|
149
|
+
}
|
150
|
+
|
151
|
+
/* call-seq:
|
152
|
+
* matrix.nrow -> Integer
|
153
|
+
*
|
154
|
+
* Returns the number of rows in the matrix.
|
155
|
+
*/
|
156
|
+
VALUE cIGraph_matrix_nrow(VALUE self){
|
157
|
+
|
158
|
+
igraph_matrix_t *m;
|
159
|
+
|
160
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
161
|
+
return LONG2FIX(igraph_matrix_nrow(m));
|
162
|
+
|
163
|
+
}
|
164
|
+
|
165
|
+
/* call-seq:
|
166
|
+
* matrix.ncol -> Integer
|
167
|
+
*
|
168
|
+
* Returns the number of columns in the matrix.
|
169
|
+
*/
|
170
|
+
VALUE cIGraph_matrix_ncol(VALUE self){
|
171
|
+
|
172
|
+
igraph_matrix_t *m;
|
173
|
+
|
174
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
175
|
+
return LONG2FIX(igraph_matrix_ncol(m));
|
176
|
+
|
177
|
+
}
|
178
|
+
|
179
|
+
/* call-seq:
|
180
|
+
* matrix.max -> Float
|
181
|
+
*
|
182
|
+
* Returns the value of the maximum element in the matrix.
|
183
|
+
*/
|
184
|
+
VALUE cIGraph_matrix_max(VALUE self){
|
185
|
+
|
186
|
+
igraph_matrix_t *m;
|
187
|
+
|
188
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
189
|
+
return rb_float_new(igraph_matrix_max(m));
|
190
|
+
|
191
|
+
}
|
192
|
+
|
193
|
+
/* call-seq:
|
194
|
+
* matrix * matrix -> IGraphMatrix
|
195
|
+
*
|
196
|
+
* Multiples two IGraphMatrix objects together
|
197
|
+
*/
|
198
|
+
VALUE cIGraph_matrix_multiply(VALUE self, VALUE x){
|
199
|
+
|
200
|
+
igraph_matrix_t *m;
|
201
|
+
igraph_matrix_t *n = malloc(sizeof(igraph_matrix_t));
|
202
|
+
VALUE nobj;
|
203
|
+
|
204
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
205
|
+
|
206
|
+
igraph_matrix_copy(n,m);
|
207
|
+
igraph_matrix_multiply(n, NUM2DBL(x));
|
208
|
+
|
209
|
+
nobj = Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, n);
|
210
|
+
|
211
|
+
return nobj;
|
212
|
+
|
213
|
+
}
|
214
|
+
|
215
|
+
/* call-seq:
|
216
|
+
* matrix.to_a -> Array
|
217
|
+
*
|
218
|
+
* Returns the matrix represented as an Array of Arrays.
|
219
|
+
*/
|
220
|
+
VALUE cIGraph_matrix_toa(VALUE self){
|
221
|
+
|
222
|
+
igraph_matrix_t *m;
|
223
|
+
int i;
|
224
|
+
int j;
|
225
|
+
VALUE a = rb_ary_new();
|
226
|
+
VALUE row;
|
227
|
+
|
228
|
+
Data_Get_Struct(self, igraph_matrix_t, m);
|
229
|
+
|
230
|
+
for(i=0;i < m->nrow;i++){
|
231
|
+
row = rb_ary_new();
|
232
|
+
for(j=0;j < m->ncol;j++){
|
233
|
+
rb_ary_push(row,rb_float_new(MATRIX(*m,i,j)));
|
234
|
+
}
|
235
|
+
rb_ary_push(a,row);
|
236
|
+
}
|
237
|
+
|
238
|
+
return a;
|
239
|
+
|
240
|
+
}
|
241
|
+
|
data/ext/cIGraph_selectors.c
CHANGED
@@ -18,7 +18,7 @@ VALUE cIGraph_all_v(VALUE self){
|
|
18
18
|
igraph_t *graph;
|
19
19
|
|
20
20
|
Data_Get_Struct(self, igraph_t, graph);
|
21
|
-
return
|
21
|
+
return ((VALUE*)graph->attr)[0];
|
22
22
|
|
23
23
|
}
|
24
24
|
|
@@ -67,27 +67,115 @@ VALUE cIGraph_adj_v(VALUE self, VALUE v, VALUE mode){
|
|
67
67
|
|
68
68
|
}
|
69
69
|
|
70
|
+
/* call-seq:
|
71
|
+
* graph.noadjacent_vertices(v,mode) -> Array
|
72
|
+
*
|
73
|
+
* Returns all non-neighboring vertices of a given vertex (v). The mode
|
74
|
+
* argument controls the type of neighboring vertics not to select. Possible
|
75
|
+
* values: IGRAPH_OUT, all vertices will be selected except those to which
|
76
|
+
* there is a directed edge from vid. IGRAPH_IN, all vertices will be
|
77
|
+
* selected except those from which there is a directed edge to vid.
|
78
|
+
* IGRAPH_ALL, all vertices will be selected except those from or to which
|
79
|
+
* there is a directed edge to or from vid.
|
80
|
+
*/
|
81
|
+
|
70
82
|
VALUE cIGraph_nonadj_v(VALUE self, VALUE v, VALUE mode){
|
71
83
|
|
72
|
-
|
84
|
+
igraph_t *graph;
|
85
|
+
igraph_integer_t pnode;
|
86
|
+
VALUE nonadjacent = rb_ary_new();
|
87
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
88
|
+
igraph_vs_t vs;
|
89
|
+
igraph_vit_t vit;
|
90
|
+
|
91
|
+
Data_Get_Struct(self, igraph_t, graph);
|
92
|
+
|
93
|
+
pnode = cIGraph_get_vertex_id(self,v);
|
94
|
+
|
95
|
+
igraph_vs_nonadj(&vs,pnode,pmode);
|
96
|
+
igraph_vit_create(graph, vs, &vit);
|
97
|
+
|
98
|
+
while(!IGRAPH_VIT_END(vit)) {
|
99
|
+
rb_ary_push(nonadjacent,cIGraph_get_vertex_object(self,IGRAPH_VIT_GET(vit)));
|
100
|
+
IGRAPH_VIT_NEXT(vit);
|
101
|
+
}
|
102
|
+
|
103
|
+
igraph_vit_destroy(&vit);
|
104
|
+
igraph_vs_destroy(&vs);
|
105
|
+
|
106
|
+
return nonadjacent;
|
73
107
|
|
74
108
|
}
|
75
109
|
|
110
|
+
/* call-seq:
|
111
|
+
* graph.edges(mode) -> Array
|
112
|
+
*
|
113
|
+
* Returns an Array of all edge ids in the graph. The mode argument specifies
|
114
|
+
* the order the eids are returned. Possible values: IGRAPH_EDGEORDER_ID,
|
115
|
+
* edge id order. IGRAPH_EDGEORDER_FROM, vertex id order, the id of the
|
116
|
+
* source vertex counts for directed graphs. The order of the adjacent edges
|
117
|
+
* of a given vertex is arbitrary. IGRAPH_EDGEORDER_TO, vertex id order, the
|
118
|
+
* id of the target vertex counts for directed graphs. The order of the
|
119
|
+
* adjacent edges of a given vertex is arbitrary. For undirected graph the
|
120
|
+
* latter two is the same.
|
121
|
+
*/
|
76
122
|
VALUE cIGraph_all_e(VALUE self, VALUE mode){
|
77
123
|
|
78
|
-
|
124
|
+
igraph_t *graph;
|
125
|
+
igraph_es_t es;
|
126
|
+
igraph_eit_t eit;
|
127
|
+
igraph_edgeorder_type_t pmode = NUM2INT(mode);
|
128
|
+
VALUE edge_ids = rb_ary_new();
|
129
|
+
|
130
|
+
Data_Get_Struct(self, igraph_t, graph);
|
131
|
+
|
132
|
+
igraph_es_all(&es,pmode);
|
133
|
+
igraph_eit_create(graph, es, &eit);
|
134
|
+
|
135
|
+
while(!IGRAPH_EIT_END(eit)) {
|
136
|
+
rb_ary_push(edge_ids,INT2NUM(IGRAPH_EIT_GET(eit)));
|
137
|
+
IGRAPH_EIT_NEXT(eit);
|
138
|
+
}
|
139
|
+
|
140
|
+
igraph_eit_destroy(&eit);
|
141
|
+
igraph_es_destroy(&es);
|
142
|
+
|
143
|
+
return edge_ids;
|
144
|
+
|
79
145
|
|
80
146
|
}
|
81
147
|
|
148
|
+
/* call-seq:
|
149
|
+
* graph.adjacent_edges(v,mode) -> Array
|
150
|
+
*
|
151
|
+
* Returns an Array of the eids of the adjacent edges of a vertex (v). The
|
152
|
+
* mode argument gives the type of edges to select. Possible values:
|
153
|
+
* IGRAPH_OUT, outgoing edges IGRAPH_IN, incoming edges IGRAPH_ALL, all edges
|
154
|
+
*/
|
82
155
|
VALUE cIGraph_adj_e(VALUE self, VALUE v, VALUE mode){
|
83
156
|
|
84
|
-
|
157
|
+
igraph_t *graph;
|
158
|
+
igraph_es_t es;
|
159
|
+
igraph_eit_t eit;
|
85
160
|
|
86
|
-
|
161
|
+
VALUE adjacent = rb_ary_new();
|
87
162
|
|
88
|
-
|
163
|
+
Data_Get_Struct(self, igraph_t, graph);
|
89
164
|
|
90
|
-
|
165
|
+
igraph_es_none(&es);
|
166
|
+
igraph_es_adj(&es,cIGraph_get_vertex_id(self,v),NUM2INT(mode));
|
167
|
+
igraph_eit_create(graph, es, &eit);
|
168
|
+
|
169
|
+
while(!IGRAPH_EIT_END(eit)) {
|
170
|
+
rb_ary_push(adjacent,INT2NUM(IGRAPH_EIT_GET(eit)));
|
171
|
+
IGRAPH_EIT_NEXT(eit);
|
172
|
+
}
|
173
|
+
|
174
|
+
igraph_eit_destroy(&eit);
|
175
|
+
igraph_es_destroy(&es);
|
176
|
+
|
177
|
+
return adjacent;
|
91
178
|
|
92
179
|
}
|
93
180
|
|
181
|
+
|
@@ -2,6 +2,17 @@
|
|
2
2
|
#include "ruby.h"
|
3
3
|
#include "cIGraph.h"
|
4
4
|
|
5
|
+
/* call-seq:
|
6
|
+
* graph.shortest_paths(varray,mode) -> Array
|
7
|
+
*
|
8
|
+
* Calculates the length of the shortest paths from each of the vertices in
|
9
|
+
* the varray Array to all of the other vertices in the graph. The result
|
10
|
+
* is returned as an Array of Array. Each top-level Array contains the results
|
11
|
+
* for a vertex in the varray Array. Each entry in the Array is the path length
|
12
|
+
* to another vertex in the graph in vertex order (the order the vertices were
|
13
|
+
* added to the graph. (This should probalby be changed to give a Hash of Hash
|
14
|
+
* to allow easier look up.)
|
15
|
+
*/
|
5
16
|
VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){
|
6
17
|
|
7
18
|
igraph_t *graph;
|
@@ -49,6 +60,17 @@ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){
|
|
49
60
|
|
50
61
|
}
|
51
62
|
|
63
|
+
/* call-seq:
|
64
|
+
* graph.get_shortest_paths(from,to_array,mode) -> Array
|
65
|
+
*
|
66
|
+
* Calculates the paths from the vertex specified as from to each vertex in the
|
67
|
+
* to_array Array. Returns an Array of Arrays. Each top level Array represents
|
68
|
+
* a path and each entry in each Array is a vertex on the path. mode
|
69
|
+
* represents the type of shortest paths to be calculated: IGraph::OUT
|
70
|
+
* the outgoing paths are calculated. IGraph::IN the incoming paths are
|
71
|
+
* calculated. IGraph::ALL the directed graph is considered as an undirected
|
72
|
+
* one for the computation.
|
73
|
+
*/
|
52
74
|
VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
53
75
|
|
54
76
|
igraph_t *graph;
|
@@ -70,7 +92,7 @@ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
|
70
92
|
|
71
93
|
Data_Get_Struct(self, igraph_t, graph);
|
72
94
|
|
73
|
-
n_paths =
|
95
|
+
n_paths = RARRAY(to)->len;
|
74
96
|
|
75
97
|
//vector to hold the results of the calculations
|
76
98
|
igraph_vector_ptr_init(&res,0);
|
@@ -93,8 +115,8 @@ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
|
93
115
|
for(i=0; i<n_paths; i++){
|
94
116
|
path = rb_ary_new();
|
95
117
|
rb_ary_push(matrix,path);
|
118
|
+
path_v = VECTOR(res)[i];
|
96
119
|
for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
|
97
|
-
path_v = VECTOR(res)[i];
|
98
120
|
rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
|
99
121
|
}
|
100
122
|
}
|
@@ -110,3 +132,175 @@ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
|
110
132
|
return matrix;
|
111
133
|
|
112
134
|
}
|
135
|
+
|
136
|
+
/* call-seq:
|
137
|
+
* graph.get_all_shortest_paths(from,mode) -> Array
|
138
|
+
*
|
139
|
+
* Calculates the paths from the vertex specified as from to each vertex
|
140
|
+
* in the to_array Arrayevery other. Returns an Array of Arrays. Each top
|
141
|
+
* level Array represents a path and each entry in each Array is a vertex on
|
142
|
+
* the path. mode represents the type of shortest paths to be calculated:
|
143
|
+
* IGraph::OUT the outgoing paths are calculated. IGraph::IN the incoming
|
144
|
+
* paths are calculated. IGraph::ALL the directed graph is considered as an
|
145
|
+
* undirected one for the computation. In contrast to
|
146
|
+
* IGraph#get_shortest_paths all possible shortest paths are reported here.
|
147
|
+
*/
|
148
|
+
VALUE cIGraph_get_all_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
149
|
+
|
150
|
+
igraph_t *graph;
|
151
|
+
|
152
|
+
igraph_integer_t from_vid;
|
153
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
154
|
+
|
155
|
+
igraph_vs_t to_vids;
|
156
|
+
igraph_vector_t to_vidv;
|
157
|
+
|
158
|
+
igraph_vector_ptr_t res;
|
159
|
+
igraph_vector_t *path_v;
|
160
|
+
|
161
|
+
int i;
|
162
|
+
int j;
|
163
|
+
VALUE path;
|
164
|
+
VALUE matrix = rb_ary_new();
|
165
|
+
|
166
|
+
Data_Get_Struct(self, igraph_t, graph);
|
167
|
+
|
168
|
+
//vector to hold the results of the calculations
|
169
|
+
igraph_vector_ptr_init(&res,0);
|
170
|
+
|
171
|
+
//The id of the vertex from where we are counting
|
172
|
+
from_vid = cIGraph_get_vertex_id(self, from);
|
173
|
+
|
174
|
+
//Convert an array of vertices to a vector of vertex ids
|
175
|
+
cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv);
|
176
|
+
//create vertex selector from the vecotr of ids
|
177
|
+
igraph_vs_vector(&to_vids,&to_vidv);
|
178
|
+
|
179
|
+
igraph_get_all_shortest_paths(graph,&res,NULL,from_vid,to_vids,pmode);
|
180
|
+
|
181
|
+
for(i=0; i< igraph_vector_ptr_size(&res); i++){
|
182
|
+
path = rb_ary_new();
|
183
|
+
rb_ary_push(matrix,path);
|
184
|
+
for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
|
185
|
+
path_v = VECTOR(res)[i];
|
186
|
+
rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
for(i=0;i<igraph_vector_ptr_size(&res);i++){
|
191
|
+
igraph_vector_destroy(VECTOR(res)[i]);
|
192
|
+
}
|
193
|
+
|
194
|
+
igraph_vector_ptr_destroy(&res);
|
195
|
+
|
196
|
+
return matrix;
|
197
|
+
|
198
|
+
}
|
199
|
+
|
200
|
+
/* call-seq:
|
201
|
+
* graph.average_path_length(directed,uncon) -> Float
|
202
|
+
*
|
203
|
+
* Calculates the average geodesic length in a graph. directed should be a
|
204
|
+
* boolean specifying whether to consider directed paths. unconn is another
|
205
|
+
* boolean specifying what to do about unconnected graphs. If TRUE the
|
206
|
+
* average of the geodesics within the components will be returned,
|
207
|
+
* otherwise the number of vertices is used for the length of non-existing
|
208
|
+
* geodesics. (The rationale behind this is that this is always longer than
|
209
|
+
* the longest possible geodesic in a graph.)
|
210
|
+
*/
|
211
|
+
VALUE cIGraph_average_path_length(VALUE self, VALUE directed, VALUE unconn){
|
212
|
+
|
213
|
+
igraph_t *graph;
|
214
|
+
igraph_bool_t directed_b = 0;
|
215
|
+
igraph_bool_t unconn_b = 0;
|
216
|
+
igraph_real_t res;
|
217
|
+
|
218
|
+
if(directed)
|
219
|
+
directed_b = 1;
|
220
|
+
if(unconn)
|
221
|
+
unconn_b = 1;
|
222
|
+
|
223
|
+
Data_Get_Struct(self, igraph_t, graph);
|
224
|
+
|
225
|
+
igraph_average_path_length(graph,&res,directed_b,unconn_b);
|
226
|
+
|
227
|
+
return rb_float_new(res);
|
228
|
+
|
229
|
+
}
|
230
|
+
|
231
|
+
/* call-seq:
|
232
|
+
* graph.diameter(directed,uncon) -> Array
|
233
|
+
*
|
234
|
+
* Returns the longest path in the graph. directed should be a
|
235
|
+
* boolean specifying whether to consider directed paths. unconn is another
|
236
|
+
* boolean specifying what to do about unconnected graphs. If TRUE the
|
237
|
+
* average of the geodesics within the components will be returned,
|
238
|
+
* otherwise the number of vertices is used for the length of non-existing
|
239
|
+
* geodesics. (The rationale behind this is that this is always longer than
|
240
|
+
* the longest possible diamter in a graph.)
|
241
|
+
*/
|
242
|
+
VALUE cIGraph_diameter(VALUE self, VALUE directed, VALUE unconn){
|
243
|
+
|
244
|
+
igraph_t *graph;
|
245
|
+
igraph_bool_t directed_b = 0;
|
246
|
+
igraph_bool_t unconn_b = 0;
|
247
|
+
igraph_vector_t res;
|
248
|
+
int i;
|
249
|
+
VALUE path = rb_ary_new();
|
250
|
+
|
251
|
+
if(directed)
|
252
|
+
directed_b = 1;
|
253
|
+
if(unconn)
|
254
|
+
unconn_b = 1;
|
255
|
+
|
256
|
+
Data_Get_Struct(self, igraph_t, graph);
|
257
|
+
|
258
|
+
//vector to hold the results of the calculations
|
259
|
+
igraph_vector_init(&res,0);
|
260
|
+
|
261
|
+
igraph_diameter(graph,NULL,NULL,NULL,&res,directed_b,unconn_b);
|
262
|
+
|
263
|
+
for(i=0; i<igraph_vector_size(&res); i++){
|
264
|
+
rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(res)[i]));
|
265
|
+
}
|
266
|
+
|
267
|
+
igraph_vector_destroy(&res);
|
268
|
+
|
269
|
+
return path;
|
270
|
+
|
271
|
+
}
|
272
|
+
|
273
|
+
/* call-seq:
|
274
|
+
* graph.diameter(directed,uncon) -> Array
|
275
|
+
*
|
276
|
+
* Returns the shortest cycle in the graph. directed should be a
|
277
|
+
* boolean specifying whether to consider directed paths. unconn is another
|
278
|
+
* boolean specifying what to do about unconnected graphs. If TRUE the
|
279
|
+
* average of the geodesics within the components will be returned,
|
280
|
+
* otherwise the number of vertices is used for the length of non-existing
|
281
|
+
* geodesics. (The rationale behind this is that this is always longer than
|
282
|
+
* the longest possible diamter in a graph.)
|
283
|
+
*/
|
284
|
+
VALUE cIGraph_girth(VALUE self){
|
285
|
+
|
286
|
+
igraph_t *graph;
|
287
|
+
igraph_vector_t res;
|
288
|
+
int i;
|
289
|
+
VALUE path = rb_ary_new();
|
290
|
+
|
291
|
+
Data_Get_Struct(self, igraph_t, graph);
|
292
|
+
|
293
|
+
//vector to hold the results of the calculations
|
294
|
+
igraph_vector_init(&res,0);
|
295
|
+
|
296
|
+
igraph_girth(graph,NULL,&res);
|
297
|
+
|
298
|
+
for(i=0; i<igraph_vector_size(&res); i++){
|
299
|
+
rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(res)[i]));
|
300
|
+
}
|
301
|
+
|
302
|
+
igraph_vector_destroy(&res);
|
303
|
+
|
304
|
+
return path;
|
305
|
+
|
306
|
+
}
|