igraph 0.3.3 → 0.9.0

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