igraph 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,14 +10,20 @@ ext/cIGraph_attribute_handler.c
10
10
  ext/cIGraph_basic_properties.c
11
11
  ext/cIGraph_basic_query.c
12
12
  ext/cIGraph_centrality.c
13
+ ext/cIGraph_cliques.c
13
14
  ext/cIGraph_components.c
15
+ ext/cIGraph_dijkstra.c
14
16
  ext/cIGraph_direction.c
15
17
  ext/cIGraph_error_handlers.c
16
18
  ext/cIGraph_file.c
19
+ ext/cIGraph_generators_random.c
20
+ ext/cIGraph_independent_vertex_sets.c
21
+ ext/cIGraph_isomorphism.c
17
22
  ext/cIGraph_iterators.c
18
23
  ext/cIGraph_kcores.c
19
24
  ext/cIGraph_layout.c
20
25
  ext/cIGraph_matrix.c
26
+ ext/cIGraph_motif.c
21
27
  ext/cIGraph_operators.c
22
28
  ext/cIGraph_other_ops.c
23
29
  ext/cIGraph_selectors.c
@@ -30,20 +36,27 @@ ext/cIGraph_utility.c
30
36
  ext/cIGraph_vertex_neighbourhood.c
31
37
  ext/extconf.rb
32
38
  test/tc_add_delete.rb
39
+ test/tc_adj_to_distance.rb
33
40
  test/tc_attributes.rb
34
41
  test/tc_basic_properties.rb
35
42
  test/tc_basic_query.rb
36
43
  test/tc_centrality.rb
44
+ test/tc_cliques.rb
37
45
  test/tc_components.rb
38
46
  test/tc_copy.rb
39
47
  test/tc_cores.rb
40
48
  test/tc_create.rb
49
+ test/tc_dijkstra.rb
41
50
  test/tc_directedness.rb
42
51
  test/tc_error_handling.rb
43
52
  test/tc_file_read_write.rb
53
+ test/tc_generators_random.rb
54
+ test/tc_independent_vertex_sets.rb
55
+ test/tc_isomorphic.rb
44
56
  test/tc_iterators.rb
45
57
  test/tc_layout.rb
46
58
  test/tc_matrix.rb
59
+ test/tc_motif.rb
47
60
  test/tc_other_ops.rb
48
61
  test/tc_selectors.rb
49
62
  test/tc_shortest_paths.rb
@@ -54,3 +67,4 @@ test/tc_topological_sort.rb
54
67
  test/tc_transitivity.rb
55
68
  test/tc_vertex_neighbourhood.rb
56
69
  test/test_all.rb
70
+ test/test_draw.rb
@@ -3,7 +3,7 @@ require 'hoe'
3
3
  $LOAD_PATH.unshift("./ext")
4
4
 
5
5
  class IGraph
6
- VERSION = "0.0"
6
+ VERSION = "0.3.3"
7
7
  end
8
8
 
9
9
  begin
@@ -184,7 +184,7 @@ void Init_igraph(){
184
184
 
185
185
  rb_include_module(cIGraph, rb_mEnumerable);
186
186
 
187
- rb_define_const(cIGraph, "VERSION", rb_str_new2("0.3.2"));
187
+ rb_define_const(cIGraph, "VERSION", rb_str_new2("0.3.3"));
188
188
 
189
189
  rb_define_const(cIGraph, "EDGEORDER_ID", INT2NUM(1));
190
190
  rb_define_const(cIGraph, "EDGEORDER_FROM", INT2NUM(2));
@@ -207,6 +207,14 @@ void Init_igraph(){
207
207
  rb_define_const(cIGraph, "GET_ADJACENCY_LOWER", INT2NUM(1));
208
208
  rb_define_const(cIGraph, "GET_ADJACENCY_BOTH", INT2NUM(2));
209
209
 
210
+ rb_define_const(cIGraph, "ERDOS_RENYI_GNP", INT2NUM(0));
211
+ rb_define_const(cIGraph, "ERDOS_RENYI_GNM", INT2NUM(1));
212
+
213
+ rb_define_singleton_method(cIGraph, "grg_game", cIGraph_grg_game, 3); /* in cIGraph_generators_random.c */
214
+ rb_define_singleton_method(cIGraph, "barabasi_game", cIGraph_barabasi_game, 4); /* in cIGraph_generators_random.c */
215
+ rb_define_singleton_method(cIGraph, "nonlinear_barabasi_game", cIGraph_nonlinear_barabasi_game, 6); /* in cIGraph_generators_random.c */
216
+ rb_define_singleton_method(cIGraph, "erdos_renyi_game", cIGraph_erdos_renyi_game, 5); /* in cIGraph_generators_random.c */
217
+
210
218
  rb_define_method(cIGraph, "[]", cIGraph_get_edge_attr, 2); /* in cIGraph_attribute_handler.c */
211
219
  rb_define_method(cIGraph, "[]=", cIGraph_set_edge_attr, 3); /* in cIGraph_attribute_handler.c */
212
220
  rb_define_alias (cIGraph, "get_edge_attr", "[]");
@@ -256,6 +264,9 @@ void Init_igraph(){
256
264
  rb_define_method(cIGraph, "diameter", cIGraph_diameter, 2); /* in cIGraph_shortest_paths.c */
257
265
  rb_define_method(cIGraph, "girth", cIGraph_girth, 0); /* in cIGraph_shortest_paths.c */
258
266
 
267
+
268
+ rb_define_method(cIGraph, "dijkstra_shortest_paths", cIGraph_dijkstra_shortest_paths, 3);
269
+
259
270
  rb_define_method(cIGraph, "neighbourhood_size", cIGraph_neighborhood_size, 3); /* in cIGraph_vertex_neighbourhood.c */
260
271
  rb_define_method(cIGraph, "neighbourhood", cIGraph_neighborhood, 3); /* in cIGraph_vertex_neighbourhood.c */
261
272
  rb_define_method(cIGraph, "neighbourhood_graphs", cIGraph_neighborhood_graphs, 3); /* in cIGraph_vertex_neighbourhood.c */
@@ -296,6 +307,26 @@ void Init_igraph(){
296
307
  rb_define_method(cIGraph, "cocitation", cIGraph_cocitation, 1); /* in cIGraph_other_ops.c */
297
308
  rb_define_method(cIGraph, "get_adjacency", cIGraph_get_adjacency, 1); /* in cIGraph_other_ops.c */
298
309
 
310
+ rb_define_method(cIGraph, "cliques", cIGraph_cliques, 2); /* in cIGraph_cliques.c */
311
+ rb_define_method(cIGraph, "largest_cliques", cIGraph_largest_cliques, 0); /* in cIGraph_cliques.c */
312
+ rb_define_method(cIGraph, "maximal_cliques", cIGraph_maximal_cliques, 0); /* in cIGraph_cliques.c */
313
+ rb_define_method(cIGraph, "clique_number", cIGraph_clique_number, 0); /* in cIGraph_cliques.c */
314
+
315
+ rb_define_method(cIGraph, "independent_vertex_sets", cIGraph_independent_vertex_sets, 2); /* in cIGraph_independent_vertex_sets.c */
316
+ rb_define_method(cIGraph, "largest_independent_vertex_sets", cIGraph_largest_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */
317
+ rb_define_method(cIGraph, "maximal_independent_vertex_sets", cIGraph_maximal_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */
318
+ rb_define_method(cIGraph, "independence_number", cIGraph_independence_number, 0); /* in cIGraph_independent_vertex_sets.c */
319
+
320
+ rb_define_method(cIGraph, "isomorphic", cIGraph_isomorphic, 1); /* in cIGraph_isomorphism.c */
321
+ rb_define_method(cIGraph, "isomorphic_vf2", cIGraph_isomorphic_vf2, 1); /* in cIGraph_isomorphism.c */
322
+ rb_define_method(cIGraph, "isoclass", cIGraph_isoclass, 0); /* in cIGraph_isomorphism.c */
323
+ rb_define_method(cIGraph, "isoclass_subgraph", cIGraph_isoclass_subgraph, 1); /* in cIGraph_isomorphism.c */
324
+ rb_define_singleton_method(cIGraph, "isoclass_create", cIGraph_isoclass_create, 3); /* in cIGraph_isomorphism.c */
325
+
326
+ rb_define_method(cIGraph, "motifs_randesu", cIGraph_motifs_randesu, 2); /* in cIGraph_motif.c */
327
+ rb_define_method(cIGraph, "motifs_randesu_no", cIGraph_motifs_randesu_no, 2); /* in cIGraph_motif.c */
328
+ rb_define_method(cIGraph, "motifs_randesu_estimate", cIGraph_motifs_randesu_estimate, 4); /* in cIGraph_motif.c */
329
+
299
330
  rb_define_method(cIGraph, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */
300
331
 
301
332
  rb_define_singleton_method(cIGraph, "read_graph_edgelist", cIGraph_read_graph_edgelist, 2); /* in cIGraph_file.c */
@@ -305,9 +336,14 @@ void Init_igraph(){
305
336
  rb_define_method(cIGraph, "write_graph_graphml", cIGraph_write_graph_graphml, 1); /* in cIGraph_file.c */
306
337
  rb_define_method(cIGraph, "write_graph_pajek", cIGraph_write_graph_pajek, 1); /* in cIGraph_file.c */
307
338
 
308
- rb_define_method(cIGraph, "layout_random", cIGraph_layout_random, 0); /* in cIGraph_layout.c */
309
- rb_define_method(cIGraph, "layout_circle", cIGraph_layout_circle, 0); /* in cIGraph_layout.c */
310
- rb_define_method(cIGraph, "layout_fruchterman_reingold", cIGraph_layout_fruchterman_reingold, 6); /* in cIGraph_layout.c */
339
+ rb_define_method(cIGraph, "layout_random", cIGraph_layout_random, 0); /* in cIGraph_layout.c */
340
+ rb_define_method(cIGraph, "layout_circle", cIGraph_layout_circle, 0); /* in cIGraph_layout.c */
341
+ rb_define_method(cIGraph, "layout_fruchterman_reingold", cIGraph_layout_fruchterman_reingold, 6); /* in cIGraph_layout.c */
342
+ rb_define_method(cIGraph, "layout_kamada_kawai", cIGraph_layout_kamada_kawai, 5); /* in cIGraph_layout.c */
343
+ rb_define_method(cIGraph, "layout_reingold_tilford", cIGraph_layout_reingold_tilford, 1); /* in cIGraph_layout.c */
344
+ rb_define_method(cIGraph, "layout_reingold_tilford_circular", cIGraph_layout_reingold_tilford_circular, 1); /* in cIGraph_layout.c */
345
+ rb_define_method(cIGraph, "layout_grid_fruchterman_reingold", cIGraph_layout_grid_fruchterman_reingold, 7); /* in cIGraph_layout.c */
346
+ rb_define_method(cIGraph, "layout_lgl", cIGraph_layout_lgl, 7); /* in cIGraph_layout.c */
311
347
 
312
348
  //Matrix class
313
349
  cIGraphMatrix = rb_define_class("IGraphMatrix", rb_cObject);
@@ -30,6 +30,15 @@ VALUE cIGraph_alloc(VALUE klass);
30
30
  VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self);
31
31
  VALUE cIGraph_init_copy(VALUE copy, VALUE orig);
32
32
 
33
+ //Random graph generators
34
+ VALUE cIGraph_grg_game (VALUE self, VALUE nodes,
35
+ VALUE radius, VALUE torus);
36
+ VALUE cIGraph_barabasi_game(VALUE self, VALUE nodes,
37
+ VALUE m, VALUE outpref, VALUE directed);
38
+ VALUE cIGraph_nonlinear_barabasi_game(VALUE self, VALUE nodes, VALUE power,
39
+ VALUE m, VALUE outpref, VALUE zeroappeal, VALUE directed);
40
+ VALUE cIGraph_erdos_renyi_game (VALUE self, VALUE type, VALUE nodes, VALUE mp, VALUE directed, VALUE loops);
41
+
33
42
  //Attribute accessors
34
43
  int replace_i(VALUE key, VALUE val, VALUE hash);
35
44
  VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to);
@@ -81,6 +90,13 @@ VALUE cIGraph_average_path_length (VALUE self, VALUE directed, VALUE unconn);
81
90
  VALUE cIGraph_diameter (VALUE self, VALUE directed, VALUE unconn);
82
91
  VALUE cIGraph_girth (VALUE self);
83
92
 
93
+ VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VALUE mode);
94
+ int igraph_dijkstra_shortest_paths(const igraph_t *graph,
95
+ igraph_matrix_t *res,
96
+ const igraph_vs_t from,
97
+ const igraph_vector_t *wghts,
98
+ igraph_neimode_t mode);
99
+
84
100
  //Vertex neighbourhood functions
85
101
  VALUE cIGraph_neighborhood_size (VALUE self, VALUE from, VALUE order, VALUE mode);
86
102
  VALUE cIGraph_neighborhood (VALUE self, VALUE from, VALUE order, VALUE mode);
@@ -130,6 +146,31 @@ VALUE cIGraph_bibcoupling (VALUE self, VALUE vs);
130
146
  VALUE cIGraph_cocitation (VALUE self, VALUE vs);
131
147
  VALUE cIGraph_get_adjacency(VALUE self, VALUE mode);
132
148
 
149
+ //Cliques
150
+ VALUE cIGraph_cliques(VALUE self, VALUE min, VALUE max);
151
+ VALUE cIGraph_largest_cliques(VALUE self);
152
+ VALUE cIGraph_maximal_cliques(VALUE self);
153
+ VALUE cIGraph_clique_number(VALUE self);
154
+
155
+ //Independent vertex sets
156
+ VALUE cIGraph_independent_vertex_sets(VALUE self, VALUE min, VALUE max);
157
+ VALUE cIGraph_largest_independent_vertex_sets(VALUE self);
158
+ VALUE cIGraph_maximal_independent_vertex_sets(VALUE self);
159
+ VALUE cIGraph_independence_number(VALUE self);
160
+
161
+ //Graph isomorphism
162
+ VALUE cIGraph_isomorphic (VALUE self, VALUE g);
163
+ VALUE cIGraph_isomorphic_vf2 (VALUE self, VALUE g);
164
+ VALUE cIGraph_isoclass (VALUE self);
165
+ VALUE cIGraph_isoclass_subgraph(VALUE self, VALUE vs);
166
+ VALUE cIGraph_isoclass_create (VALUE self, VALUE vn, VALUE iso, VALUE dir);
167
+
168
+ //Motifs
169
+ VALUE cIGraph_motifs_randesu (VALUE self, VALUE size, VALUE cuts);
170
+ VALUE cIGraph_motifs_randesu_no (VALUE self, VALUE size, VALUE cuts);
171
+ VALUE cIGraph_motifs_randesu_estimate(VALUE self, VALUE size, VALUE cuts,
172
+ VALUE samplen, VALUE samplev);
173
+
133
174
  //File handling
134
175
  VALUE cIGraph_read_graph_edgelist (VALUE self, VALUE file, VALUE mode);
135
176
  VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file);
@@ -139,8 +180,8 @@ VALUE cIGraph_read_graph_pajek (VALUE self, VALUE file);
139
180
  VALUE cIGraph_write_graph_pajek (VALUE self, VALUE file);
140
181
 
141
182
  //Layouts
142
- VALUE cIGraph_layout_random(VALUE self);
143
- VALUE cIGraph_layout_circle(VALUE self);
183
+ VALUE cIGraph_layout_random (VALUE self);
184
+ VALUE cIGraph_layout_circle (VALUE self);
144
185
  VALUE cIGraph_layout_fruchterman_reingold(VALUE self,
145
186
  VALUE niter,
146
187
  VALUE maxdelta,
@@ -148,6 +189,33 @@ VALUE cIGraph_layout_fruchterman_reingold(VALUE self,
148
189
  VALUE coolexp,
149
190
  VALUE repulserad,
150
191
  VALUE use_seed);
192
+ VALUE cIGraph_layout_kamada_kawai (VALUE self,
193
+ VALUE niter,
194
+ VALUE sigma,
195
+ VALUE initemp,
196
+ VALUE coolexp,
197
+ VALUE kkconst);
198
+ VALUE cIGraph_layout_reingold_tilford (VALUE self,
199
+ VALUE root);
200
+ VALUE cIGraph_layout_reingold_tilford_circular(VALUE self,
201
+ VALUE root);
202
+ VALUE cIGraph_layout_grid_fruchterman_reingold(VALUE self,
203
+ VALUE niter,
204
+ VALUE maxdelta,
205
+ VALUE area,
206
+ VALUE coolexp,
207
+ VALUE repulserad,
208
+ VALUE cellsize,
209
+ VALUE use_seed);
210
+ VALUE cIGraph_layout_lgl(VALUE self,
211
+ VALUE maxit,
212
+ VALUE maxdelta,
213
+ VALUE area,
214
+ VALUE coolexp,
215
+ VALUE repulserad,
216
+ VALUE cellsize,
217
+ VALUE proot);
218
+
151
219
 
152
220
  //Attributes
153
221
  int cIGraph_attribute_init(igraph_t *graph,
@@ -189,6 +189,7 @@ int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_p
189
189
  VALUE values;
190
190
 
191
191
  if(attr){
192
+
192
193
  if(igraph_vector_ptr_size(attr) > 0 && ((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
193
194
 
194
195
  values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
@@ -234,6 +235,11 @@ int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_p
234
235
  rb_ary_push(vertex_array,record);
235
236
  }
236
237
  }
238
+ } else {
239
+ //Default: Add numbered vertices.
240
+ for(i=0;i<nv;i++){
241
+ rb_ary_push(vertex_array,INT2NUM(i));
242
+ }
237
243
  }
238
244
 
239
245
  #ifdef DEBUG
@@ -0,0 +1,178 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * graph.cliques(min_size,max_size) -> Array
7
+ *
8
+ * Find all or some cliques in a graph
9
+ *
10
+ * Cliques are fully connected subgraphs of a graph.
11
+ *
12
+ * If you are only interested in the size of the largest clique in the
13
+ * graph, use IGraph#clique_number instead.
14
+ */
15
+
16
+ VALUE cIGraph_cliques(VALUE self, VALUE min, VALUE max){
17
+
18
+ igraph_t *graph;
19
+ igraph_vector_ptr_t res;
20
+ igraph_vector_t *vec;
21
+ int i;
22
+ int j;
23
+ VALUE clique;
24
+ VALUE object;
25
+ VALUE cliques = rb_ary_new();
26
+
27
+ Data_Get_Struct(self, igraph_t, graph);
28
+
29
+ igraph_vector_ptr_init(&res,0);
30
+
31
+ igraph_cliques(graph, &res, NUM2INT(min), NUM2INT(max));
32
+
33
+ for(i=0; i<igraph_vector_ptr_size(&res); i++){
34
+ clique = rb_ary_new();
35
+ rb_ary_push(cliques,clique);
36
+ vec = VECTOR(res)[i];
37
+ for(j=0; j<igraph_vector_size(vec); j++){
38
+ vec = VECTOR(res)[i];
39
+ object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]);
40
+ rb_ary_push(clique,object);
41
+ }
42
+ }
43
+
44
+ for(i=0;i<igraph_vector_ptr_size(&res);i++){
45
+ igraph_vector_destroy(VECTOR(res)[i]);
46
+ free(VECTOR(res)[i]);
47
+ }
48
+
49
+ igraph_vector_ptr_destroy(&res);
50
+
51
+ return cliques;
52
+
53
+ }
54
+
55
+ /* call-seq:
56
+ * graph.largest_cliques() -> Array
57
+ *
58
+ * Finds the largest clique(s) in a graph.
59
+ *
60
+ * A clique is largest (quite intuitively) if there is no other clique in
61
+ * the graph which contains more vertices.
62
+ *
63
+ * Note that this is not neccessarily the same as a maximal clique, ie.
64
+ * the largest cliques are always maximal but a maximal clique is not always
65
+ * largest.
66
+ */
67
+
68
+ VALUE cIGraph_largest_cliques(VALUE self){
69
+
70
+ igraph_t *graph;
71
+ igraph_vector_ptr_t res;
72
+ igraph_vector_t *vec;
73
+ int i;
74
+ int j;
75
+ VALUE clique;
76
+ VALUE object;
77
+ VALUE cliques = rb_ary_new();
78
+
79
+ Data_Get_Struct(self, igraph_t, graph);
80
+
81
+ igraph_vector_ptr_init(&res,0);
82
+
83
+ igraph_largest_cliques(graph, &res);
84
+
85
+ for(i=0; i<igraph_vector_ptr_size(&res); i++){
86
+ clique = rb_ary_new();
87
+ rb_ary_push(cliques,clique);
88
+ vec = VECTOR(res)[i];
89
+ for(j=0; j<igraph_vector_size(vec); j++){
90
+ vec = VECTOR(res)[i];
91
+ object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]);
92
+ rb_ary_push(clique,object);
93
+ }
94
+ }
95
+
96
+ for(i=0;i<igraph_vector_ptr_size(&res);i++){
97
+ igraph_vector_destroy(VECTOR(res)[i]);
98
+ free(VECTOR(res)[i]);
99
+ }
100
+
101
+ igraph_vector_ptr_destroy(&res);
102
+
103
+ return cliques;
104
+
105
+ }
106
+
107
+ /* call-seq:
108
+ * graph.maximal_cliques() -> Array
109
+ *
110
+ * Find all maximal cliques of a graph
111
+ *
112
+ * A maximal clique is a clique which can't be extended any more by adding a
113
+ * new vertex to it. This is actually implemented by looking for a maximal
114
+ * independent vertex set in the complementer of the graph.
115
+ *
116
+ * If you are only interested in the size of the largest clique in the
117
+ * graph, use IGraph#clique_number instead.
118
+ */
119
+
120
+ VALUE cIGraph_maximal_cliques(VALUE self){
121
+
122
+ igraph_t *graph;
123
+ igraph_vector_ptr_t res;
124
+ igraph_vector_t *vec;
125
+ int i;
126
+ int j;
127
+ VALUE clique;
128
+ VALUE object;
129
+ VALUE cliques = rb_ary_new();
130
+
131
+ Data_Get_Struct(self, igraph_t, graph);
132
+
133
+ igraph_vector_ptr_init(&res,0);
134
+
135
+ igraph_maximal_cliques(graph, &res);
136
+
137
+ for(i=0; i<igraph_vector_ptr_size(&res); i++){
138
+ clique = rb_ary_new();
139
+ rb_ary_push(cliques,clique);
140
+ vec = VECTOR(res)[i];
141
+ for(j=0; j<igraph_vector_size(vec); j++){
142
+ vec = VECTOR(res)[i];
143
+ object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]);
144
+ rb_ary_push(clique,object);
145
+ }
146
+ }
147
+
148
+ for(i=0;i<igraph_vector_ptr_size(&res);i++){
149
+ igraph_vector_destroy(VECTOR(res)[i]);
150
+ free(VECTOR(res)[i]);
151
+ }
152
+
153
+ igraph_vector_ptr_destroy(&res);
154
+
155
+ return cliques;
156
+
157
+ }
158
+
159
+ /* call-seq:
160
+ * graph.clique_number() -> Integer
161
+ *
162
+ * Find the clique number of the graph
163
+ *
164
+ * The clique number of a graph is the size of the largest clique.
165
+ */
166
+
167
+ VALUE cIGraph_clique_number(VALUE self){
168
+
169
+ igraph_t *graph;
170
+ igraph_integer_t res;
171
+
172
+ Data_Get_Struct(self, igraph_t, graph);
173
+
174
+ igraph_clique_number(graph, &res);
175
+
176
+ return INT2NUM(res);
177
+
178
+ }
@@ -0,0 +1,258 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * graph.dijkstra_shortest_paths(varray,weights,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 given a set of
10
+ * edge weights given in the weights Array. The result
11
+ * is returned as an Array of Array. Each top-level Array contains the results
12
+ * for a vertex in the varray Array. Each entry in the Array is the path length
13
+ * to another vertex in the graph in vertex order (the order the vertices were
14
+ * added to the graph. (This should probalby be changed to give a Hash of Hash
15
+ * to allow easier look up.)
16
+ */
17
+ VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VALUE mode){
18
+
19
+ igraph_t *graph;
20
+ igraph_vs_t vids;
21
+ igraph_vector_t vidv;
22
+ igraph_vector_t wghts;
23
+ igraph_neimode_t pmode = NUM2INT(mode);
24
+ igraph_matrix_t res;
25
+ int i;
26
+ int j;
27
+ VALUE row;
28
+ VALUE path_length;
29
+ VALUE matrix = rb_ary_new();
30
+ int n_row;
31
+ int n_col;
32
+
33
+ Data_Get_Struct(self, igraph_t, graph);
34
+
35
+ n_row = NUM2INT(rb_funcall(from,rb_intern("length"),0));
36
+ n_col = igraph_vcount(graph);
37
+
38
+ //matrix to hold the results of the calculations
39
+ igraph_matrix_init(&res,n_row,n_col);
40
+
41
+ igraph_vector_init(&wghts,RARRAY(weights)->len);
42
+
43
+ for(i=0;i<RARRAY(weights)->len;i++){
44
+ VECTOR(wghts)[i] = NUM2DBL(RARRAY(weights)->ptr[i]);
45
+ }
46
+
47
+ //Convert an array of vertices to a vector of vertex ids
48
+ igraph_vector_init_int(&vidv,0);
49
+ cIGraph_vertex_arr_to_id_vec(self,from,&vidv);
50
+ //create vertex selector from the vecotr of ids
51
+ igraph_vs_vector(&vids,&vidv);
52
+
53
+ igraph_dijkstra_shortest_paths(graph,&res,vids,&wghts,pmode);
54
+
55
+ for(i=0; i<igraph_matrix_nrow(&res); i++){
56
+ row = rb_ary_new();
57
+ rb_ary_push(matrix,row);
58
+ for(j=0; j<igraph_matrix_ncol(&res); j++){
59
+ path_length = MATRIX(res,i,j) == n_col ? Qnil : rb_float_new(MATRIX(res,i,j));
60
+ rb_ary_push(row,path_length);
61
+ }
62
+ }
63
+
64
+ igraph_vector_destroy(&vidv);
65
+ igraph_matrix_destroy(&res);
66
+ igraph_vs_destroy(&vids);
67
+
68
+ return matrix;
69
+
70
+ }
71
+
72
+ /* call-seq:
73
+ * graph.get_shortest_paths(from,to_array,mode) -> Array
74
+ *
75
+ * Calculates the paths from the vertex specified as from to each vertex in the
76
+ * to_array Array. Returns an Array of Arrays. Each top level Array represents
77
+ * a path and each entry in each Array is a vertex on the path. mode
78
+ * represents the type of shortest paths to be calculated: IGraph::OUT
79
+ * the outgoing paths are calculated. IGraph::IN the incoming paths are
80
+ * calculated. IGraph::ALL the directed graph is considered as an undirected
81
+ * one for the computation.
82
+ */
83
+ VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
84
+
85
+ igraph_t *graph;
86
+
87
+ igraph_integer_t from_vid;
88
+ igraph_vs_t to_vids;
89
+ igraph_vector_t to_vidv;
90
+
91
+ igraph_neimode_t pmode = NUM2INT(mode);
92
+
93
+ igraph_vector_ptr_t res;
94
+ igraph_vector_t *path_v;
95
+
96
+ int i;
97
+ int j;
98
+ VALUE path;
99
+ VALUE matrix = rb_ary_new();
100
+ int n_paths;
101
+
102
+ Data_Get_Struct(self, igraph_t, graph);
103
+
104
+ n_paths = RARRAY(to)->len;
105
+
106
+ //vector to hold the results of the calculations
107
+ igraph_vector_ptr_init(&res,0);
108
+ for(i=0;i<n_paths;i++){
109
+ path_v = malloc(sizeof(igraph_vector_t));
110
+ igraph_vector_init(path_v,0);
111
+ igraph_vector_ptr_push_back(&res,path_v);
112
+ }
113
+
114
+ //Convert an array of vertices to a vector of vertex ids
115
+ igraph_vector_init_int(&to_vidv,0);
116
+ cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv);
117
+ //create vertex selector from the vecotr of ids
118
+ igraph_vs_vector(&to_vids,&to_vidv);
119
+
120
+ //The id of the vertex from where we are counting
121
+ from_vid = cIGraph_get_vertex_id(self, from);
122
+
123
+ igraph_get_shortest_paths(graph,&res,from_vid,to_vids,pmode);
124
+
125
+ for(i=0; i<n_paths; i++){
126
+ path = rb_ary_new();
127
+ rb_ary_push(matrix,path);
128
+ path_v = VECTOR(res)[i];
129
+ for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
130
+ rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
131
+ }
132
+ }
133
+
134
+ for(i=0;i<n_paths;i++){
135
+ igraph_vector_destroy(VECTOR(res)[i]);
136
+ free(VECTOR(res)[i]);
137
+ }
138
+
139
+ igraph_vector_destroy(&to_vidv);
140
+ igraph_vector_ptr_destroy(&res);
141
+ igraph_vs_destroy(&to_vids);
142
+
143
+ return matrix;
144
+
145
+ }
146
+
147
+ int igraph_dijkstra_shortest_paths(const igraph_t *graph,
148
+ igraph_matrix_t *res,
149
+ const igraph_vs_t from,
150
+ const igraph_vector_t *wghts,
151
+ igraph_neimode_t mode) {
152
+
153
+ long int no_of_nodes=igraph_vcount(graph);
154
+ long int no_of_from;
155
+ igraph_real_t *shortest;
156
+ igraph_real_t min,alt;
157
+
158
+ int i, j, uj, included;
159
+ igraph_integer_t eid, u,v;
160
+ igraph_vector_t q;
161
+ igraph_vit_t fromvit;
162
+ igraph_vector_t neis;
163
+
164
+ IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
165
+ IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);
166
+
167
+ no_of_from=IGRAPH_VIT_SIZE(fromvit);
168
+
169
+ if (mode != IGRAPH_OUT && mode != IGRAPH_IN &&
170
+ mode != IGRAPH_ALL) {
171
+ IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
172
+ }
173
+ shortest=calloc(no_of_nodes, sizeof(igraph_real_t));
174
+ if (shortest==0) {
175
+ IGRAPH_ERROR("shortest paths failed", IGRAPH_ENOMEM);
176
+ }
177
+ IGRAPH_FINALLY(free, shortest);
178
+
179
+ IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_nodes));
180
+ igraph_matrix_null(res);
181
+
182
+ for (IGRAPH_VIT_RESET(fromvit), i=0;
183
+ !IGRAPH_VIT_END(fromvit);
184
+ IGRAPH_VIT_NEXT(fromvit), i++) {
185
+
186
+ //Start shortest and previous
187
+ for(j=0;j<no_of_nodes;j++){
188
+ shortest[j] = INFINITY;
189
+ //memset(previous,NAN, no_of_nodes);
190
+ }
191
+
192
+ shortest[(int)IGRAPH_VIT_GET(fromvit)] = 0;
193
+ igraph_vector_init_seq(&q,0,no_of_nodes-1);
194
+
195
+ while(igraph_vector_size(&q) != 0){
196
+
197
+ min = INFINITY;
198
+ u = no_of_nodes;
199
+ uj = igraph_vector_size(&q);
200
+ for(j=0;j<igraph_vector_size(&q);j++){
201
+ v = VECTOR(q)[j];
202
+ if(shortest[(int)v] < min){
203
+ min = shortest[(int)v];
204
+ u = v;
205
+ uj = j;
206
+ }
207
+ }
208
+
209
+ if(min == INFINITY)
210
+ break;
211
+
212
+ igraph_vector_remove(&q,uj);
213
+
214
+ igraph_vector_init(&neis,0);
215
+ igraph_neighbors(graph,&neis,u,mode);
216
+
217
+ for(j=0;j<igraph_vector_size(&neis);j++){
218
+
219
+ v = VECTOR(neis)[j];
220
+
221
+ //v must be in Q
222
+ included = 0;
223
+ for(j=0;j<igraph_vector_size(&q);j++){
224
+ if(v == VECTOR(q)[j]){
225
+ included = 1;
226
+ break;
227
+ }
228
+ }
229
+
230
+ if(!included)
231
+ continue;
232
+
233
+ igraph_get_eid(graph,&eid,u,v,1);
234
+
235
+ alt = shortest[(int)u] + VECTOR(*wghts)[(int)eid];
236
+
237
+ if(alt < shortest[(int)v]){
238
+ shortest[(int)v] = alt;
239
+ }
240
+ }
241
+ igraph_vector_destroy(&neis);
242
+ }
243
+
244
+ for(j=0;j<no_of_nodes;j++){
245
+ MATRIX(*res,i,j) = shortest[j];
246
+ }
247
+
248
+ igraph_vector_destroy(&q);
249
+
250
+ }
251
+
252
+ /* Clean */
253
+ free(shortest);
254
+ igraph_vit_destroy(&fromvit);
255
+ IGRAPH_FINALLY_CLEAN(2);
256
+
257
+ return 0;
258
+ }