igraph 0.3.3 → 0.9.0

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.
@@ -247,3 +247,46 @@ VALUE cIGraph_layout_lgl(VALUE self,
247
247
 
248
248
  }
249
249
 
250
+ /* call-seq:
251
+ * graph.layout_merge_dla(graphs,layouts) -> IGraphMatrix
252
+ *
253
+ * Merge multiple layouts by using a DLA algorithm
254
+ *
255
+ * First each layout is covered by a circle. Then the layout of the largest
256
+ * graph is placed at the origin. Then the other layouts are placed by the
257
+ * DLA algorithm, larger ones first and smaller ones last.
258
+ *
259
+ * graphs: Array of IGraph objects
260
+ *
261
+ * layouts: Array of IGraphMatrix layouts
262
+ */
263
+ VALUE cIGraph_layout_merge_dla(VALUE self, VALUE graphs, VALUE layouts){
264
+
265
+ igraph_vector_ptr_t thegraphs;
266
+ igraph_vector_ptr_t coords;
267
+ int i;
268
+ igraph_t *graph;
269
+ igraph_matrix_t *coord;
270
+ igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
271
+
272
+ igraph_vector_ptr_init(&thegraphs,0);
273
+ igraph_vector_ptr_init(&coords,0);
274
+ igraph_matrix_init(res,0,0);
275
+
276
+ for(i=0;i<RARRAY(graphs)->len;i++){
277
+ Data_Get_Struct(RARRAY(graphs)->ptr[i], igraph_t, graph);
278
+ igraph_vector_ptr_push_back(&thegraphs,graph);
279
+ }
280
+ for(i=0;i<RARRAY(layouts)->len;i++){
281
+ Data_Get_Struct(RARRAY(layouts)->ptr[i], igraph_matrix_t, coord);
282
+ igraph_vector_ptr_push_back(&coords,coord);
283
+ }
284
+
285
+ igraph_layout_merge_dla(&thegraphs, &coords, res);
286
+
287
+ igraph_vector_ptr_destroy(&thegraphs);
288
+ igraph_vector_ptr_destroy(&coords);
289
+
290
+ return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
291
+
292
+ }
@@ -0,0 +1,119 @@
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 in 3D.
9
+ */
10
+ VALUE cIGraph_layout_random_3d(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_3d(graph,res);
19
+
20
+ return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
21
+
22
+ }
23
+
24
+ /* call-seq:
25
+ * graph.layout_sphere -> IGraphMatrix
26
+ *
27
+ * Places vertices (more or less) uniformly on a sphere.
28
+ *
29
+ * The algorithm was described in the following paper: Distributing many
30
+ * points on a sphere by E.B. Saff and A.B.J. Kuijlaars, Mathematical
31
+ * Intelligencer 19.1 (1997) 5--11.
32
+ */
33
+ VALUE cIGraph_layout_sphere(VALUE self){
34
+
35
+ igraph_t *graph;
36
+ igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
37
+
38
+ Data_Get_Struct(self, igraph_t, graph);
39
+
40
+ igraph_matrix_init(res,0,0);
41
+ igraph_layout_sphere(graph,res);
42
+
43
+ return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
44
+
45
+ }
46
+
47
+ /* call-seq:
48
+ * graph.layout_fruchterman_reingold_3d(niter,maxdelta,volume,coolexp,repulserad) -> IGraphMatrix
49
+ *
50
+ * This is the 3D version of the force based Fruchterman-Reingold layout.
51
+ *
52
+ * niter: The number of iterations to do.
53
+ *
54
+ * maxdelta: The maximum distance to move a vertex in an iteration.
55
+ *
56
+ * volume: The volume parameter of the algorithm.
57
+ *
58
+ * coolexp: The cooling exponent of the simulated annealing.
59
+ *
60
+ * repulserad: Determines the radius at which vertex-vertex repulsion
61
+ * cancels out attraction of adjacent vertices.
62
+ */
63
+ VALUE cIGraph_layout_fruchterman_reingold_3d(VALUE self,
64
+ VALUE niter,
65
+ VALUE maxdelta,
66
+ VALUE volume,
67
+ VALUE coolexp,
68
+ VALUE repulserad){
69
+
70
+ igraph_t *graph;
71
+ igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
72
+
73
+ Data_Get_Struct(self, igraph_t, graph);
74
+
75
+ igraph_matrix_init(res,0,0);
76
+ igraph_layout_fruchterman_reingold_3d(graph,res,
77
+ NUM2INT(niter),
78
+ NUM2DBL(maxdelta),
79
+ NUM2DBL(volume),
80
+ NUM2DBL(coolexp),
81
+ NUM2DBL(repulserad),
82
+ 1);
83
+
84
+ return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
85
+
86
+ }
87
+
88
+ /* call-seq:
89
+ * graph.layout_kamada_kawai_3d -> IGraphMatrix
90
+ *
91
+ * Places the vertices on a plane according the Kamada-Kawai algorithm.
92
+ *
93
+ * This is a force directed layout, see Kamada, T. and Kawai, S.: An
94
+ * Algorithm for Drawing General Undirected Graphs. Information Processing
95
+ * Letters, 31/1, 7--15, 1989.
96
+ */
97
+ VALUE cIGraph_layout_kamada_kawai_3d(VALUE self,
98
+ VALUE niter,
99
+ VALUE sigma,
100
+ VALUE initemp,
101
+ VALUE coolexp,
102
+ VALUE kkconst){
103
+
104
+ igraph_t *graph;
105
+ igraph_matrix_t *res = malloc(sizeof(igraph_matrix_t));
106
+
107
+ Data_Get_Struct(self, igraph_t, graph);
108
+
109
+ igraph_matrix_init(res,0,0);
110
+ igraph_layout_kamada_kawai_3d(graph,res,
111
+ NUM2INT(niter),
112
+ NUM2DBL(sigma),
113
+ NUM2DBL(initemp),
114
+ NUM2DBL(coolexp),
115
+ NUM2DBL(kkconst));
116
+
117
+ return Data_Wrap_Struct(cIGraphMatrix, 0, cIGraph_matrix_free, res);
118
+
119
+ }
@@ -0,0 +1,195 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * graph.maxflow_value(source,target,capacity) -> Max Flow
7
+ *
8
+ * Maximum flow in a network with the push/relabel algorithm
9
+ *
10
+ * This function implements the Goldberg-Tarjan algorithm for calculating
11
+ * value of the maximum flow in a directed or undirected graph. The algorithm
12
+ * was given in Andrew V. Goldberg, Robert E. Tarjan: A New Approach to the
13
+ * Maximum-Flow Problem, Journal of the ACM, 35(4), 921-940, 1988.
14
+ *
15
+ * Note that the value of the maximum flow is the same as the minimum cut in
16
+ * the graph.
17
+ *
18
+ */
19
+
20
+ VALUE cIGraph_maxflow_value(VALUE self, VALUE source, VALUE target, VALUE capacity){
21
+
22
+ igraph_t *graph;
23
+ igraph_integer_t from_i;
24
+ igraph_integer_t to_i;
25
+ igraph_real_t value;
26
+
27
+ int i;
28
+
29
+ igraph_vector_t capacity_v;
30
+
31
+ igraph_vector_init(&capacity_v, 0);
32
+ for(i=0;i<RARRAY(capacity)->len;i++){
33
+ igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i]));
34
+ }
35
+
36
+ Data_Get_Struct(self, igraph_t, graph);
37
+
38
+ from_i = cIGraph_get_vertex_id(self,source);
39
+ to_i = cIGraph_get_vertex_id(self,target);
40
+
41
+ igraph_maxflow_value(graph,&value,from_i,to_i,&capacity_v);
42
+
43
+ igraph_vector_destroy(&capacity_v);
44
+
45
+ return rb_float_new(value);
46
+
47
+ }
48
+
49
+ /* call-seq:
50
+ * graph.st_mincut_value(source,target,capacity) -> Max Flow
51
+ *
52
+ * Maximum flow in a network with the push/relabel algorithm
53
+ *
54
+ * This function implements the Goldberg-Tarjan algorithm for calculating
55
+ * value of the maximum flow in a directed or undirected graph. The algorithm
56
+ * was given in Andrew V. Goldberg, Robert E. Tarjan: A New Approach to the
57
+ * Maximum-Flow Problem, Journal of the ACM, 35(4), 921-940, 1988.
58
+ *
59
+ * Note that the value of the maximum flow is the same as the minimum cut in
60
+ * the graph.
61
+ *
62
+ */
63
+
64
+ VALUE cIGraph_st_mincut_value(VALUE self, VALUE source, VALUE target, VALUE capacity){
65
+
66
+ igraph_t *graph;
67
+ igraph_integer_t from_i;
68
+ igraph_integer_t to_i;
69
+ igraph_real_t value;
70
+
71
+ int i;
72
+
73
+ igraph_vector_t capacity_v;
74
+
75
+ igraph_vector_init(&capacity_v, 0);
76
+ for(i=0;i<RARRAY(capacity)->len;i++){
77
+ igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i]));
78
+ }
79
+
80
+ Data_Get_Struct(self, igraph_t, graph);
81
+
82
+ from_i = cIGraph_get_vertex_id(self,source);
83
+ to_i = cIGraph_get_vertex_id(self,target);
84
+
85
+ igraph_st_mincut_value(graph,&value,from_i,to_i,&capacity_v);
86
+
87
+ igraph_vector_destroy(&capacity_v);
88
+
89
+ return rb_float_new(value);
90
+
91
+ }
92
+
93
+ /* call-seq:
94
+ * graph.mincut_value(capacity) -> Float
95
+ *
96
+ * The minimum edge cut in a graph is the total minimum weight of the edges
97
+ * needed to remove from the graph to make the graph not strongly connected.
98
+ * (If the original graph is not strongly connected then this is zero.) Note
99
+ * that in undirected graphs strong connectedness is the same as weak
100
+ * connectedness.
101
+ *
102
+ */
103
+
104
+ VALUE cIGraph_mincut_value(VALUE self, VALUE capacity){
105
+
106
+ igraph_t *graph;
107
+ igraph_real_t value;
108
+
109
+ int i;
110
+
111
+ igraph_vector_t capacity_v;
112
+
113
+ igraph_vector_init(&capacity_v, 0);
114
+ for(i=0;i<RARRAY(capacity)->len;i++){
115
+ igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i]));
116
+ }
117
+
118
+ Data_Get_Struct(self, igraph_t, graph);
119
+
120
+ igraph_mincut_value(graph,&value,&capacity_v);
121
+
122
+ igraph_vector_destroy(&capacity_v);
123
+
124
+ return rb_float_new(value);
125
+
126
+ }
127
+
128
+ /* call-seq:
129
+ * graph.mincut(capacity) -> Array
130
+ *
131
+ * Calculates the minimum cut in a graph. This function calculates the
132
+ * minimum cut in a graph. Right now it is implemented only for undirected
133
+ * graphs, in which case it uses the Stoer-Wagner algorithm, as described
134
+ * in M. Stoer and F. Wagner: A simple min-cut algorithm, Journal of the
135
+ * ACM, 44 585-591, 1997.
136
+ *
137
+ */
138
+
139
+ VALUE cIGraph_mincut(VALUE self, VALUE capacity){
140
+
141
+ VALUE res_ary;
142
+
143
+ VALUE p1_a;
144
+ VALUE p2_a;
145
+ VALUE cut_a;
146
+
147
+ igraph_t *graph;
148
+ igraph_real_t value;
149
+
150
+ int i;
151
+
152
+ igraph_vector_t p1;
153
+ igraph_vector_t p2;
154
+ igraph_vector_t cut;
155
+
156
+ igraph_vector_t capacity_v;
157
+
158
+ igraph_vector_init(&p1, 0);
159
+ igraph_vector_init(&p2, 0);
160
+ igraph_vector_init(&cut, 0);
161
+
162
+ igraph_vector_init(&capacity_v, 0);
163
+ for(i=0;i<RARRAY(capacity)->len;i++){
164
+ igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i]));
165
+ }
166
+
167
+ Data_Get_Struct(self, igraph_t, graph);
168
+
169
+ igraph_mincut(graph,&value,&p1,&p2,&cut,&capacity_v);
170
+
171
+ p1_a = rb_ary_new();
172
+ for(i=0;i<igraph_vector_size(&p1);i++){
173
+ rb_ary_push(p1_a,cIGraph_get_vertex_object(self,VECTOR(p1)[i]));
174
+ }
175
+ p2_a = rb_ary_new();
176
+ for(i=0;i<igraph_vector_size(&p2);i++){
177
+ rb_ary_push(p2_a,cIGraph_get_vertex_object(self,VECTOR(p2)[i]));
178
+ }
179
+ cut_a = rb_ary_new();
180
+ for(i=0;i<igraph_vector_size(&cut);i++){
181
+ rb_ary_push(cut_a,INT2NUM(VECTOR(cut)[i]));
182
+ }
183
+
184
+ res_ary = rb_ary_new3(4,rb_float_new(value),p1_a,p2_a,cut_a);
185
+
186
+ igraph_vector_destroy(&p1);
187
+ igraph_vector_destroy(&p2);
188
+ igraph_vector_destroy(&cut);
189
+
190
+ igraph_vector_destroy(&capacity_v);
191
+
192
+ return res_ary;
193
+
194
+ }
195
+
@@ -0,0 +1,57 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * g.rewire_edges(prob) -> IGraph
7
+ *
8
+ * Rewire the edges of a graph with constant probability This function
9
+ * rewires the edges of a graph with a constant probability. More precisely
10
+ * each end point of each edge is rewired to an uniformly randomly chosen
11
+ * vertex with constant probability prob.
12
+ *
13
+ * prob: The rewiring probability a constant between zero and one (inclusive).
14
+ */
15
+ VALUE cIGraph_rewire_edges(VALUE self, VALUE prop){
16
+
17
+ igraph_t *graph;
18
+ igraph_t *copy_graph;
19
+ VALUE new_graph;
20
+
21
+ new_graph = cIGraph_alloc(cIGraph);
22
+ Data_Get_Struct(new_graph, igraph_t, copy_graph);
23
+ Data_Get_Struct(self, igraph_t, graph);
24
+
25
+ igraph_copy(copy_graph,graph);
26
+ igraph_rewire_edges(copy_graph,NUM2DBL(prop));
27
+
28
+ return new_graph;
29
+
30
+ }
31
+
32
+ /* call-seq:
33
+ * g.rewire(n) -> IGraph
34
+ *
35
+ * Randomly rewires a graph while preserving the degree distribution.
36
+ *
37
+ * This function generates a new graph based on the original one by randomly
38
+ * rewiring edges while preserving the original graph's degree distribution.
39
+ *
40
+ * n: Number of rewiring trials to perform.
41
+ */
42
+ VALUE cIGraph_rewire(VALUE self, VALUE n){
43
+
44
+ igraph_t *graph;
45
+ igraph_t *copy_graph;
46
+ VALUE new_graph;
47
+
48
+ new_graph = cIGraph_alloc(cIGraph);
49
+ Data_Get_Struct(new_graph, igraph_t, copy_graph);
50
+ Data_Get_Struct(self, igraph_t, graph);
51
+
52
+ igraph_copy(copy_graph,graph);
53
+ igraph_rewire(copy_graph,NUM2INT(n),0);
54
+
55
+ return new_graph;
56
+
57
+ }
@@ -8,6 +8,8 @@ igraph_integer_t cIGraph_get_vertex_id(VALUE graph, VALUE v){
8
8
  VALUE idx;
9
9
  igraph_t *igraph;
10
10
 
11
+ VALUE str;
12
+
11
13
  Data_Get_Struct(graph, igraph_t, igraph);
12
14
  v_ary = ((VALUE*)igraph->attr)[0];
13
15
 
@@ -56,6 +56,27 @@ class TestGraph < Test::Unit::TestCase
56
56
  assert_equal 1, graph.ecount
57
57
  end
58
58
 
59
+ def test_delete_large
60
+ vs = (0..99).to_a
61
+ h = IGraph.new([],true)
62
+ vs.each do |id|
63
+ h.add_vertex(id)
64
+ end
65
+
66
+ g = h.dup
67
+
68
+ delete_ids = (0..99).to_a.sort_by{rand}[0..19]
69
+ assert_nothing_raised do
70
+ delete_ids.each do |id|
71
+ g.delete_vertex(id)
72
+ end
73
+ end
74
+ delete_ids.each do |id|
75
+ assert_equal false, g.include?(id)
76
+ end
77
+ assert_equal 80, g.vcount
78
+ end
79
+
59
80
  def test_delete_edge
60
81
  graph = IGraph.new(['A','B','C','D'],true)
61
82
  assert_equal true, graph.are_connected?('A','B')