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
data/ext/cIGraph_add_delete.c
CHANGED
@@ -19,39 +19,60 @@
|
|
19
19
|
* must have already been added to the graph before they can be used in
|
20
20
|
* an edge (throws a IGraphError otherwise).
|
21
21
|
*/
|
22
|
-
VALUE cIGraph_add_edges(VALUE
|
22
|
+
VALUE cIGraph_add_edges(int argc, VALUE *argv, VALUE self){
|
23
23
|
|
24
24
|
igraph_t *graph;
|
25
25
|
igraph_vector_t edge_v;
|
26
26
|
VALUE vertex;
|
27
|
-
VALUE
|
27
|
+
VALUE edges;
|
28
|
+
VALUE attrs;
|
29
|
+
VALUE v_ary;
|
28
30
|
int vid;
|
29
31
|
int code = 0;
|
32
|
+
int i;
|
33
|
+
igraph_vector_ptr_t edge_attr;
|
34
|
+
|
35
|
+
igraph_i_attribute_record_t e_attr_rec;
|
36
|
+
e_attr_rec.name = "__RUBY__";
|
37
|
+
e_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
38
|
+
e_attr_rec.value = (void*)rb_ary_new();
|
39
|
+
|
40
|
+
rb_scan_args(argc, argv, "11", &edges, &attrs);
|
30
41
|
|
31
42
|
//Initialize edge vector
|
32
43
|
igraph_vector_init_int(&edge_v,0);
|
33
|
-
|
44
|
+
igraph_vector_ptr_init(&edge_attr,0);
|
34
45
|
|
35
46
|
Data_Get_Struct(self, igraph_t, graph);
|
36
47
|
|
48
|
+
v_ary = ((VALUE*)graph->attr)[0];
|
49
|
+
|
37
50
|
//Loop through objects in edge Array
|
38
|
-
|
39
|
-
|
40
|
-
if(
|
41
|
-
|
42
|
-
vid = NUM2INT(rb_hash_aref(object_h,vertex));
|
51
|
+
for (i=0; i<RARRAY(edges)->len; i++) {
|
52
|
+
vertex = RARRAY(edges)->ptr[i];
|
53
|
+
if(rb_ary_includes(v_ary,vertex)){
|
54
|
+
vid = cIGraph_get_vertex_id(self, vertex);
|
43
55
|
} else {
|
44
56
|
rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first");
|
45
57
|
}
|
46
58
|
igraph_vector_push_back(&edge_v,vid);
|
47
|
-
|
59
|
+
if (i % 2){
|
60
|
+
if (attrs != Qnil){
|
61
|
+
rb_ary_push((VALUE)e_attr_rec.value,RARRAY(attrs)->ptr[i/2]);
|
62
|
+
} else {
|
63
|
+
rb_ary_push((VALUE)e_attr_rec.value,Qnil);
|
64
|
+
}
|
65
|
+
}
|
48
66
|
}
|
49
67
|
|
68
|
+
igraph_vector_ptr_push_back(&edge_attr, &e_attr_rec);
|
69
|
+
|
50
70
|
if(igraph_vector_size(&edge_v) > 0){
|
51
|
-
code = igraph_add_edges(graph,&edge_v
|
71
|
+
code = igraph_add_edges(graph,&edge_v,&edge_attr);
|
52
72
|
}
|
53
73
|
|
54
74
|
igraph_vector_destroy(&edge_v);
|
75
|
+
igraph_vector_ptr_destroy(&edge_attr);
|
55
76
|
|
56
77
|
return INT2NUM(code);
|
57
78
|
|
@@ -76,36 +97,39 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){
|
|
76
97
|
|
77
98
|
igraph_t *graph;
|
78
99
|
VALUE vertex;
|
79
|
-
VALUE
|
80
|
-
VALUE id_h;
|
81
|
-
int vertex_n;
|
100
|
+
VALUE v_ary;
|
82
101
|
int code = 0;
|
83
|
-
int
|
102
|
+
int to_add;
|
103
|
+
int i;
|
104
|
+
igraph_vector_ptr_t vertex_attr;
|
105
|
+
|
106
|
+
igraph_i_attribute_record_t v_attr_rec;
|
107
|
+
v_attr_rec.name = "__RUBY__";
|
108
|
+
v_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
109
|
+
v_attr_rec.value = (void*)rb_ary_new();
|
84
110
|
|
85
|
-
|
86
|
-
id_h = rb_iv_get(self,"@id_objects");
|
87
|
-
length = NUM2INT(rb_funcall(vs, rb_intern("length"),0));
|
88
|
-
vertex_n = NUM2INT(rb_funcall(object_h,rb_intern("length"),0));
|
111
|
+
igraph_vector_ptr_init(&vertex_attr,0);
|
89
112
|
|
90
113
|
Data_Get_Struct(self, igraph_t, graph);
|
114
|
+
v_ary = ((VALUE*)graph->attr)[0];
|
115
|
+
|
116
|
+
to_add = RARRAY(vs)->len;
|
91
117
|
|
92
118
|
//Loop through objects in vertex array
|
93
|
-
|
94
|
-
|
95
|
-
if(
|
96
|
-
//
|
97
|
-
//Silently ignore
|
119
|
+
for (i=0; i<RARRAY(vs)->len; i++) {
|
120
|
+
vertex = RARRAY(vs)->ptr[i];
|
121
|
+
if(rb_ary_includes(v_ary,vertex)){
|
122
|
+
//Silently ignore duplicated additions
|
98
123
|
//rb_raise(cIGraphError, "Vertex already added to graph");
|
99
|
-
|
124
|
+
to_add--;
|
100
125
|
} else {
|
101
|
-
|
102
|
-
rb_hash_aset(object_h,vertex,INT2NUM(vertex_n));
|
103
|
-
rb_hash_aset(id_h, INT2NUM(vertex_n),vertex);
|
104
|
-
vertex_n++;
|
126
|
+
rb_ary_push((VALUE)v_attr_rec.value,RARRAY(vs)->ptr[i]);
|
105
127
|
}
|
106
|
-
vertex = rb_ary_shift(vs);
|
107
128
|
}
|
108
|
-
|
129
|
+
|
130
|
+
igraph_vector_ptr_push_back(&vertex_attr,&v_attr_rec);
|
131
|
+
|
132
|
+
code = igraph_add_vertices(graph,to_add,&vertex_attr);
|
109
133
|
|
110
134
|
return INT2NUM(code);
|
111
135
|
|
@@ -127,38 +151,48 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){
|
|
127
151
|
* Note that vertices must have already been added to the graph before
|
128
152
|
* they can be used in an edge (throws a IGraphError otherwise).
|
129
153
|
*/
|
130
|
-
VALUE cIGraph_add_edge(
|
154
|
+
VALUE cIGraph_add_edge(int argc, VALUE *argv, VALUE self){
|
131
155
|
|
132
156
|
igraph_t *graph;
|
133
157
|
igraph_vector_t edge_v;
|
134
|
-
|
135
|
-
|
158
|
+
igraph_vector_ptr_t edge_attr;
|
159
|
+
|
136
160
|
int code = 0;
|
137
161
|
|
162
|
+
VALUE v_ary;
|
163
|
+
VALUE from;
|
164
|
+
VALUE to;
|
165
|
+
VALUE attr;
|
166
|
+
|
167
|
+
igraph_i_attribute_record_t e_attr_rec;
|
168
|
+
e_attr_rec.name = "__RUBY__";
|
169
|
+
e_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
170
|
+
e_attr_rec.value = (void*)rb_ary_new();
|
171
|
+
|
172
|
+
rb_scan_args(argc, argv, "21", &from, &to, &attr);
|
173
|
+
|
138
174
|
//Initialize edge vector
|
139
175
|
igraph_vector_init_int(&edge_v,0);
|
140
|
-
|
176
|
+
igraph_vector_ptr_init(&edge_attr,0);
|
141
177
|
|
142
178
|
Data_Get_Struct(self, igraph_t, graph);
|
143
179
|
|
144
|
-
|
145
|
-
//If @vertices includes this vertex then look up the vertex number
|
146
|
-
vid = NUM2INT(rb_hash_aref(object_h,from));
|
147
|
-
} else {
|
148
|
-
rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first");
|
149
|
-
}
|
150
|
-
igraph_vector_push_back(&edge_v,vid);
|
180
|
+
v_ary = ((VALUE*)graph->attr)[0];
|
151
181
|
|
152
|
-
if(
|
153
|
-
//If
|
154
|
-
|
182
|
+
if(rb_ary_includes(v_ary,from) && rb_ary_includes(v_ary,to)){
|
183
|
+
//If graph includes this vertex then look up the vertex number
|
184
|
+
igraph_vector_push_back(&edge_v,cIGraph_get_vertex_id(self, from));
|
185
|
+
igraph_vector_push_back(&edge_v,cIGraph_get_vertex_id(self, to));
|
186
|
+
rb_ary_push((VALUE)e_attr_rec.value,attr);
|
155
187
|
} else {
|
156
|
-
rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices
|
188
|
+
rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices");
|
157
189
|
}
|
158
|
-
igraph_vector_push_back(&edge_v,vid);
|
159
190
|
|
160
|
-
|
191
|
+
igraph_vector_ptr_push_back(&edge_attr,&e_attr_rec);
|
161
192
|
|
193
|
+
code = igraph_add_edges(graph,&edge_v,&edge_attr);
|
194
|
+
|
195
|
+
igraph_vector_ptr_destroy(&edge_attr);
|
162
196
|
igraph_vector_destroy(&edge_v);
|
163
197
|
|
164
198
|
return INT2NUM(code);
|
@@ -184,36 +218,82 @@ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){
|
|
184
218
|
VALUE cIGraph_add_vertex(VALUE self, VALUE v){
|
185
219
|
|
186
220
|
igraph_t *graph;
|
187
|
-
|
188
|
-
|
189
|
-
VALUE id_h;
|
190
|
-
int vertex_n;
|
221
|
+
igraph_vector_ptr_t vertex_attr;
|
222
|
+
|
191
223
|
int code = 0;
|
192
|
-
int length;
|
193
224
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
225
|
+
VALUE v_ary;
|
226
|
+
|
227
|
+
igraph_i_attribute_record_t v_attr_rec;
|
228
|
+
v_attr_rec.name = "__RUBY__";
|
229
|
+
v_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
230
|
+
v_attr_rec.value = (void*)rb_ary_new();
|
231
|
+
|
232
|
+
igraph_vector_ptr_init(&vertex_attr,0);
|
198
233
|
|
199
234
|
Data_Get_Struct(self, igraph_t, graph);
|
200
235
|
|
236
|
+
v_ary = ((VALUE*)graph->attr)[0];
|
237
|
+
|
201
238
|
//Loop through objects in vertex array
|
202
|
-
if(
|
203
|
-
//If @vertices includes this vertex then raise an error
|
204
|
-
//Silently ignore
|
239
|
+
if(rb_ary_includes(v_ary,v)){
|
205
240
|
//rb_raise(cIGraphError, "Vertex already added to graph");
|
206
|
-
|
241
|
+
return code;
|
207
242
|
} else {
|
208
|
-
|
209
|
-
rb_hash_aset(object_h,v,INT2NUM(vertex_n));
|
210
|
-
rb_hash_aset(id_h, INT2NUM(vertex_n),v);
|
211
|
-
vertex_n++;
|
243
|
+
rb_ary_push((VALUE)v_attr_rec.value,v);
|
212
244
|
}
|
213
245
|
|
214
|
-
|
215
|
-
|
246
|
+
igraph_vector_ptr_push_back(&vertex_attr,&v_attr_rec);
|
247
|
+
|
248
|
+
code = igraph_add_vertices(graph,1,&vertex_attr);
|
216
249
|
|
217
250
|
return INT2NUM(code);
|
218
251
|
|
219
252
|
}
|
253
|
+
|
254
|
+
/* call-seq:
|
255
|
+
* graph.delete_edge(from,to)
|
256
|
+
*
|
257
|
+
* Deletes the edge connecting the two vertices given.
|
258
|
+
*/
|
259
|
+
VALUE cIGraph_delete_edge(VALUE self, VALUE from, VALUE to){
|
260
|
+
|
261
|
+
igraph_t *graph;
|
262
|
+
igraph_integer_t eid = 0;
|
263
|
+
int from_i;
|
264
|
+
int to_i;
|
265
|
+
|
266
|
+
Data_Get_Struct(self, igraph_t, graph);
|
267
|
+
|
268
|
+
from_i = cIGraph_get_vertex_id(self,from);
|
269
|
+
to_i = cIGraph_get_vertex_id(self,to);
|
270
|
+
|
271
|
+
igraph_get_eid(graph,&eid,from_i,to_i,1);
|
272
|
+
|
273
|
+
igraph_delete_edges(graph,igraph_ess_1(eid));
|
274
|
+
|
275
|
+
return Qnil;
|
276
|
+
|
277
|
+
}
|
278
|
+
|
279
|
+
/* call-seq:
|
280
|
+
* graph.delete_vertex(v)
|
281
|
+
*
|
282
|
+
* Delete the vertex specified.
|
283
|
+
*/
|
284
|
+
VALUE cIGraph_delete_vertex(VALUE self, VALUE v){
|
285
|
+
|
286
|
+
igraph_t *graph;
|
287
|
+
igraph_vs_t vs;
|
288
|
+
|
289
|
+
Data_Get_Struct(self, igraph_t, graph);
|
290
|
+
|
291
|
+
igraph_vs_1(&vs, cIGraph_get_vertex_id(self,v));
|
292
|
+
|
293
|
+
igraph_delete_vertices(graph,vs);
|
294
|
+
|
295
|
+
igraph_vs_destroy(&vs);
|
296
|
+
|
297
|
+
return Qnil;
|
298
|
+
|
299
|
+
}
|
@@ -0,0 +1,758 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* graph[u,v] -> Object
|
7
|
+
*
|
8
|
+
* Returns the object associated with the edge connecting vertices u and v.
|
9
|
+
* Aliased to graph.get_edge_attr(u,v)
|
10
|
+
*/
|
11
|
+
VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to){
|
12
|
+
|
13
|
+
int idx;
|
14
|
+
igraph_t *graph;
|
15
|
+
VALUE e_ary;
|
16
|
+
|
17
|
+
Data_Get_Struct(self, igraph_t, graph);
|
18
|
+
e_ary = ((VALUE*)graph->attr)[1];
|
19
|
+
|
20
|
+
idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
|
21
|
+
return rb_ary_entry(e_ary,idx);
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
/* call-seq:
|
26
|
+
* graph[u,v] = w
|
27
|
+
*
|
28
|
+
* Sets the object associated with the edge connecting vertices u and v.
|
29
|
+
* Aliased to graph.set_edge_attr(u,v)
|
30
|
+
*/
|
31
|
+
VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr){
|
32
|
+
|
33
|
+
int idx;
|
34
|
+
igraph_t *graph;
|
35
|
+
VALUE e_ary;
|
36
|
+
|
37
|
+
Data_Get_Struct(self, igraph_t, graph);
|
38
|
+
e_ary = ((VALUE*)graph->attr)[1];
|
39
|
+
|
40
|
+
idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
|
41
|
+
rb_ary_store(e_ary,idx,attr);
|
42
|
+
|
43
|
+
return Qtrue;
|
44
|
+
|
45
|
+
}
|
46
|
+
|
47
|
+
/* call-seq:
|
48
|
+
* graph.attributes -> Hash
|
49
|
+
*
|
50
|
+
* Returns the graph attributes. This is usually only used when reading in
|
51
|
+
* graphs from GraphML format. Feel free to use instance variables on the
|
52
|
+
* graph object if you like (they won't get copied though!).
|
53
|
+
*/
|
54
|
+
VALUE cIGraph_graph_attributes(VALUE self){
|
55
|
+
|
56
|
+
igraph_t *graph;
|
57
|
+
VALUE hsh;
|
58
|
+
|
59
|
+
Data_Get_Struct(self, igraph_t, graph);
|
60
|
+
hsh = ((VALUE*)graph->attr)[2];
|
61
|
+
|
62
|
+
return hsh;
|
63
|
+
|
64
|
+
}
|
65
|
+
|
66
|
+
igraph_attribute_table_t cIGraph_attribute_table = {
|
67
|
+
cIGraph_attribute_init,
|
68
|
+
cIGraph_attribute_destroy,
|
69
|
+
cIGraph_attribute_copy,
|
70
|
+
cIGraph_attribute_add_vertices,
|
71
|
+
cIGraph_attribute_delete_vertices,
|
72
|
+
cIGraph_attribute_add_edges,
|
73
|
+
cIGraph_attribute_delete_edges,
|
74
|
+
cIGraph_attribute_permute_edges,
|
75
|
+
cIGraph_attribute_get_info,
|
76
|
+
cIGraph_attribute_has_attr,
|
77
|
+
cIGraph_attribute_get_type,
|
78
|
+
cIGraph_get_numeric_graph_attr,
|
79
|
+
cIGraph_get_string_graph_attr,
|
80
|
+
cIGraph_get_numeric_vertex_attr,
|
81
|
+
cIGraph_get_string_vertex_attr,
|
82
|
+
cIGraph_get_numeric_edge_attr,
|
83
|
+
cIGraph_get_string_edge_attr,
|
84
|
+
};
|
85
|
+
|
86
|
+
int cIGraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) {
|
87
|
+
|
88
|
+
VALUE* attrs;
|
89
|
+
int i;
|
90
|
+
VALUE key;
|
91
|
+
VALUE value;
|
92
|
+
|
93
|
+
attrs = ALLOC_N(VALUE, 3);
|
94
|
+
|
95
|
+
if(!attrs)
|
96
|
+
IGRAPH_ERROR("Error allocating Arrays\n", IGRAPH_ENOMEM);
|
97
|
+
|
98
|
+
//[0] is vertex array, [1] is edge array, [2] is graph attr
|
99
|
+
attrs[0] = rb_ary_new();
|
100
|
+
attrs[1] = rb_ary_new();
|
101
|
+
attrs[2] = rb_hash_new();
|
102
|
+
|
103
|
+
if(attr){
|
104
|
+
for(i=0;i<igraph_vector_ptr_size(attr);i++){
|
105
|
+
igraph_i_attribute_record_t *attr_rec;
|
106
|
+
char *s;
|
107
|
+
attr_rec = VECTOR(*attr)[i];
|
108
|
+
key = rb_str_new2(attr_rec->name);
|
109
|
+
switch (attr_rec->type) {
|
110
|
+
case IGRAPH_ATTRIBUTE_NUMERIC:
|
111
|
+
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]);
|
112
|
+
break;
|
113
|
+
case IGRAPH_ATTRIBUTE_STRING:
|
114
|
+
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s);
|
115
|
+
value=rb_str_new2(s);
|
116
|
+
break;
|
117
|
+
default:
|
118
|
+
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
119
|
+
value=0;
|
120
|
+
break;
|
121
|
+
}
|
122
|
+
if (value){
|
123
|
+
rb_hash_aset((VALUE)attrs[2],key,value);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
graph->attr = attrs;
|
129
|
+
|
130
|
+
return IGRAPH_SUCCESS;
|
131
|
+
}
|
132
|
+
|
133
|
+
/* Destruction */
|
134
|
+
void cIGraph_attribute_destroy(igraph_t *graph) {
|
135
|
+
free(graph->attr);
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
|
139
|
+
/* Copying */
|
140
|
+
|
141
|
+
int replace_i(VALUE key, VALUE val, VALUE hash){
|
142
|
+
if (key != Qundef) {
|
143
|
+
rb_hash_aset(hash, key, val);
|
144
|
+
}
|
145
|
+
|
146
|
+
//return ST_CONTINUE;
|
147
|
+
return 0;
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
int cIGraph_attribute_copy(igraph_t *to, const igraph_t *from) {
|
152
|
+
|
153
|
+
#ifdef DEBUG
|
154
|
+
printf("Entering cIGraph_attribute_copy\n");
|
155
|
+
#endif
|
156
|
+
|
157
|
+
VALUE* attrs;
|
158
|
+
VALUE vertex_array = ((VALUE*)from->attr)[0];
|
159
|
+
VALUE edge_array = ((VALUE*)from->attr)[1];
|
160
|
+
VALUE graph_attr = ((VALUE*)from->attr)[2];
|
161
|
+
|
162
|
+
attrs = ALLOC_N(VALUE, 3);
|
163
|
+
|
164
|
+
attrs[0] = rb_ary_dup(vertex_array);
|
165
|
+
attrs[1] = rb_ary_dup(edge_array);
|
166
|
+
attrs[2] = rb_hash_new();
|
167
|
+
|
168
|
+
rb_hash_foreach(graph_attr, replace_i, attrs[2]);
|
169
|
+
|
170
|
+
to->attr = attrs;
|
171
|
+
|
172
|
+
#ifdef DEBUG
|
173
|
+
printf("Leaving cIGraph_attribute_copy\n");
|
174
|
+
#endif
|
175
|
+
|
176
|
+
return IGRAPH_SUCCESS;
|
177
|
+
}
|
178
|
+
|
179
|
+
/* Adding vertices */
|
180
|
+
int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr) {
|
181
|
+
|
182
|
+
#ifdef DEBUG
|
183
|
+
printf("Entering cIGraph_attribute_add_vertices\n");
|
184
|
+
#endif
|
185
|
+
|
186
|
+
int i,j;
|
187
|
+
VALUE vertex_array = ((VALUE*)graph->attr)[0];
|
188
|
+
VALUE values;
|
189
|
+
|
190
|
+
if(attr){
|
191
|
+
if(igraph_vector_ptr_size(attr) > 0 && ((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
|
192
|
+
|
193
|
+
values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
|
194
|
+
Check_Type(values, T_ARRAY);
|
195
|
+
for(i=0;i<RARRAY(values)->len;i++){
|
196
|
+
rb_ary_push(vertex_array, RARRAY(values)->ptr[i]);
|
197
|
+
}
|
198
|
+
//Otherwise read each attriute into hashes and use those
|
199
|
+
} else {
|
200
|
+
for(i=0;i<nv;i++){
|
201
|
+
|
202
|
+
VALUE record;
|
203
|
+
igraph_i_attribute_record_t *attr_rec;
|
204
|
+
char *s;
|
205
|
+
record = rb_hash_new();
|
206
|
+
|
207
|
+
//For when no attributes are given
|
208
|
+
if(igraph_vector_ptr_size(attr) == 0){
|
209
|
+
record = INT2NUM(i+1);
|
210
|
+
}
|
211
|
+
|
212
|
+
for (j=0; j<igraph_vector_ptr_size(attr); j++) {
|
213
|
+
VALUE key;
|
214
|
+
VALUE value;
|
215
|
+
//Add key value pair
|
216
|
+
attr_rec = VECTOR(*attr)[j];
|
217
|
+
key = rb_str_new2(attr_rec->name);
|
218
|
+
switch (attr_rec->type) {
|
219
|
+
case IGRAPH_ATTRIBUTE_NUMERIC:
|
220
|
+
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
|
221
|
+
break;
|
222
|
+
case IGRAPH_ATTRIBUTE_STRING:
|
223
|
+
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
|
224
|
+
value=rb_str_new2(s);
|
225
|
+
break;
|
226
|
+
default:
|
227
|
+
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
228
|
+
value=Qnil;
|
229
|
+
break;
|
230
|
+
}
|
231
|
+
rb_hash_aset(record,key,value);
|
232
|
+
}
|
233
|
+
rb_ary_push(vertex_array,record);
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
#ifdef DEBUG
|
239
|
+
printf("Leaving cIGraph_attribute_add_vertices\n");
|
240
|
+
#endif
|
241
|
+
|
242
|
+
return IGRAPH_SUCCESS;
|
243
|
+
}
|
244
|
+
|
245
|
+
/* Deleting vertices */
|
246
|
+
void cIGraph_attribute_delete_vertices(igraph_t *graph,
|
247
|
+
const igraph_vector_t *eidx,
|
248
|
+
const igraph_vector_t *vidx) {
|
249
|
+
|
250
|
+
#ifdef DEBUG
|
251
|
+
printf("Entering cIGraph_attribute_delete_vertices\n");
|
252
|
+
#endif
|
253
|
+
|
254
|
+
int i;
|
255
|
+
VALUE vertex_array = ((VALUE*)graph->attr)[0];
|
256
|
+
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
257
|
+
|
258
|
+
VALUE n_v_ary = rb_ary_new();
|
259
|
+
VALUE n_e_ary = rb_ary_new();
|
260
|
+
|
261
|
+
for(i=0;i<igraph_vector_size(vidx);i++){
|
262
|
+
if(VECTOR(*vidx)[i] != 0)
|
263
|
+
rb_ary_store(n_v_ary,VECTOR(*vidx)[i]-1,rb_ary_entry(vertex_array,i));
|
264
|
+
}
|
265
|
+
for(i=0;i<igraph_vector_size(eidx);i++){
|
266
|
+
if(VECTOR(*eidx)[i] != 0)
|
267
|
+
rb_ary_store(n_e_ary,VECTOR(*eidx)[i]-1,rb_ary_entry(edge_array,i));
|
268
|
+
}
|
269
|
+
|
270
|
+
((VALUE*)graph->attr)[0] = n_v_ary;
|
271
|
+
((VALUE*)graph->attr)[1] = n_e_ary;
|
272
|
+
|
273
|
+
#ifdef DEBUG
|
274
|
+
printf("Leaving cIGraph_attribute_delete_vertices\n");
|
275
|
+
#endif
|
276
|
+
|
277
|
+
return;
|
278
|
+
}
|
279
|
+
|
280
|
+
/* Adding edges */
|
281
|
+
int cIGraph_attribute_add_edges(igraph_t *graph,
|
282
|
+
const igraph_vector_t *edges,
|
283
|
+
igraph_vector_ptr_t *attr) {
|
284
|
+
|
285
|
+
#ifdef DEBUG
|
286
|
+
printf("Entering cIGraph_attribute_add_edges\n");
|
287
|
+
#endif
|
288
|
+
|
289
|
+
int i,j;
|
290
|
+
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
291
|
+
VALUE values;
|
292
|
+
|
293
|
+
if(attr){
|
294
|
+
//If the only record is of type PY_OBJ then use the values as attributes
|
295
|
+
if(((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
|
296
|
+
values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
|
297
|
+
Check_Type(values, T_ARRAY);
|
298
|
+
for(i=0;i<RARRAY(values)->len;i++){
|
299
|
+
rb_ary_push(edge_array, RARRAY(values)->ptr[i]);
|
300
|
+
}
|
301
|
+
//Otherwise read each attriute into hashes and use those
|
302
|
+
} else {
|
303
|
+
for(i=0;i<igraph_vector_size(edges)/2;i++){
|
304
|
+
VALUE record;
|
305
|
+
igraph_i_attribute_record_t *attr_rec;
|
306
|
+
char *s;
|
307
|
+
record = rb_hash_new();
|
308
|
+
for (j=0; j<igraph_vector_ptr_size(attr); j++) {
|
309
|
+
VALUE key;
|
310
|
+
VALUE value;
|
311
|
+
//Add key value pair
|
312
|
+
attr_rec = VECTOR(*attr)[j];
|
313
|
+
key = rb_str_new2(attr_rec->name);
|
314
|
+
switch (attr_rec->type) {
|
315
|
+
case IGRAPH_ATTRIBUTE_NUMERIC:
|
316
|
+
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
|
317
|
+
break;
|
318
|
+
case IGRAPH_ATTRIBUTE_STRING:
|
319
|
+
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
|
320
|
+
value=rb_str_new2(s);
|
321
|
+
break;
|
322
|
+
default:
|
323
|
+
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
324
|
+
value=Qnil;
|
325
|
+
break;
|
326
|
+
}
|
327
|
+
rb_hash_aset(record,key,value);
|
328
|
+
}
|
329
|
+
rb_ary_push(edge_array,record);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
#ifdef DEBUG
|
335
|
+
printf("Leaving cIGraph_attribute_add_edges\n");
|
336
|
+
#endif
|
337
|
+
|
338
|
+
return IGRAPH_SUCCESS;
|
339
|
+
}
|
340
|
+
|
341
|
+
/* Deleting edges */
|
342
|
+
void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) {
|
343
|
+
|
344
|
+
#ifdef DEBUG
|
345
|
+
printf("Entering cIGraph_attribute_delete_edges\n");
|
346
|
+
#endif
|
347
|
+
|
348
|
+
int i;
|
349
|
+
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
350
|
+
VALUE n_e_ary = rb_ary_new();
|
351
|
+
|
352
|
+
for(i=0;i<igraph_vector_size(idx);i++){
|
353
|
+
if(VECTOR(*idx)[i] != 0)
|
354
|
+
rb_ary_store(n_e_ary,VECTOR(*idx)[i]-1,rb_ary_entry(edge_array,i));
|
355
|
+
}
|
356
|
+
|
357
|
+
((VALUE*)graph->attr)[1] = n_e_ary;
|
358
|
+
|
359
|
+
#ifdef DEBUG
|
360
|
+
printf("Leaving cIGraph_attribute_delete_edges\n");
|
361
|
+
#endif
|
362
|
+
|
363
|
+
return;
|
364
|
+
}
|
365
|
+
|
366
|
+
/* Permuting edges */
|
367
|
+
int cIGraph_attribute_permute_edges(igraph_t *graph,
|
368
|
+
const igraph_vector_t *idx) {
|
369
|
+
|
370
|
+
#ifdef DEBUG
|
371
|
+
printf("Entering cIGraph_attribute_permute_edges\n");
|
372
|
+
#endif
|
373
|
+
|
374
|
+
int i;
|
375
|
+
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
376
|
+
VALUE n_e_ary = rb_ary_new();
|
377
|
+
|
378
|
+
for(i=0;i<igraph_vector_size(idx);i++){
|
379
|
+
rb_ary_push(n_e_ary,rb_ary_entry(edge_array,VECTOR(*idx)[i]));
|
380
|
+
}
|
381
|
+
|
382
|
+
((VALUE*)graph->attr)[1] = n_e_ary;
|
383
|
+
|
384
|
+
#ifdef DEBUG
|
385
|
+
printf("Leaving cIGraph_attribute_permute_edges\n");
|
386
|
+
#endif
|
387
|
+
|
388
|
+
return 0;
|
389
|
+
}
|
390
|
+
|
391
|
+
VALUE keys_to_strvec(VALUE data, VALUE arr){
|
392
|
+
|
393
|
+
VALUE key = rb_ary_entry(data, 0);
|
394
|
+
VALUE val = rb_ary_entry(data, 1);
|
395
|
+
|
396
|
+
VALUE rb_names = rb_ary_entry(arr, 0);
|
397
|
+
VALUE rb_types = rb_ary_entry(arr, 1);
|
398
|
+
|
399
|
+
VALUE str = StringValue(key);
|
400
|
+
|
401
|
+
rb_ary_push(rb_names,str);
|
402
|
+
|
403
|
+
if(TYPE(val) == T_STRING){
|
404
|
+
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_STRING));
|
405
|
+
} else if (TYPE(val) == T_FLOAT || TYPE(val) == T_FIXNUM){
|
406
|
+
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_NUMERIC));
|
407
|
+
} else {
|
408
|
+
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_PY_OBJECT));
|
409
|
+
}
|
410
|
+
|
411
|
+
return data;
|
412
|
+
|
413
|
+
}
|
414
|
+
|
415
|
+
/* Getting attribute names and types */
|
416
|
+
int cIGraph_attribute_get_info(const igraph_t *graph,
|
417
|
+
igraph_strvector_t *gnames,
|
418
|
+
igraph_vector_t *gtypes,
|
419
|
+
igraph_strvector_t *vnames,
|
420
|
+
igraph_vector_t *vtypes,
|
421
|
+
igraph_strvector_t *enames,
|
422
|
+
igraph_vector_t *etypes) {
|
423
|
+
|
424
|
+
|
425
|
+
#ifdef DEBUG
|
426
|
+
printf("Entering cIGraph_attribute_get_info\n");
|
427
|
+
#endif
|
428
|
+
|
429
|
+
igraph_strvector_t *names[3] = { vnames, enames, gnames };
|
430
|
+
igraph_vector_t *types[3] = { vtypes, etypes, gtypes };
|
431
|
+
|
432
|
+
long int i,j;
|
433
|
+
|
434
|
+
for (i=0; i<3; i++) {
|
435
|
+
|
436
|
+
igraph_strvector_t *n = names[i];
|
437
|
+
igraph_vector_t *t = types[i];
|
438
|
+
|
439
|
+
VALUE rb_names = rb_ary_new();
|
440
|
+
VALUE rb_types = rb_ary_new();
|
441
|
+
|
442
|
+
VALUE obj_hash;
|
443
|
+
|
444
|
+
//Graph attributes are different
|
445
|
+
if (i != 2){
|
446
|
+
|
447
|
+
VALUE store = ((VALUE*)graph->attr)[i];
|
448
|
+
VALUE obj = RARRAY(store)->ptr[0];
|
449
|
+
|
450
|
+
obj_hash = Qnil;
|
451
|
+
if(rb_funcall(obj, rb_intern("respond_to?"), 1, rb_str_new2("to_hash")) == Qtrue){
|
452
|
+
obj_hash = rb_funcall(obj, rb_intern("to_hash"), 0);
|
453
|
+
}
|
454
|
+
} else {
|
455
|
+
obj_hash = ((VALUE*)graph->attr)[2];
|
456
|
+
}
|
457
|
+
|
458
|
+
if(!NIL_P(obj_hash)){
|
459
|
+
//Take the keys of the hash, convert to strings and put in vector n
|
460
|
+
rb_iterate(rb_each, obj_hash, keys_to_strvec, rb_ary_new3(2,rb_names,rb_types));
|
461
|
+
}
|
462
|
+
|
463
|
+
//Push names onto n and types onto t
|
464
|
+
for(j=0;j<RARRAY(rb_names)->len;j++){
|
465
|
+
igraph_strvector_add(n, RSTRING(RARRAY(rb_names)->ptr[j])->ptr);
|
466
|
+
igraph_vector_push_back(t, NUM2INT(RARRAY(rb_types)->ptr[j]));
|
467
|
+
}
|
468
|
+
|
469
|
+
}
|
470
|
+
|
471
|
+
#ifdef DEBUG
|
472
|
+
printf("Leaving cIGraph_attribute_get_info\n");
|
473
|
+
#endif
|
474
|
+
|
475
|
+
return 0;
|
476
|
+
|
477
|
+
}
|
478
|
+
|
479
|
+
/* Checks whether the graph has a graph/vertex/edge attribute with the given name */
|
480
|
+
igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph,
|
481
|
+
igraph_attribute_elemtype_t type,
|
482
|
+
const char* name) {
|
483
|
+
|
484
|
+
#ifdef DEBUG
|
485
|
+
printf("Entering cIGraph_attribute_has_attr\n");
|
486
|
+
#endif
|
487
|
+
|
488
|
+
long int attrnum;
|
489
|
+
igraph_bool_t res = 0;
|
490
|
+
VALUE obj;
|
491
|
+
|
492
|
+
switch (type) {
|
493
|
+
case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
|
494
|
+
case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
|
495
|
+
case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
|
496
|
+
default: return 0; break;
|
497
|
+
}
|
498
|
+
|
499
|
+
obj = ((VALUE*)graph->attr)[attrnum];
|
500
|
+
if (attrnum != 2)
|
501
|
+
obj = RARRAY(obj)->ptr[0];
|
502
|
+
|
503
|
+
if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){
|
504
|
+
res = 1;
|
505
|
+
}
|
506
|
+
|
507
|
+
#ifdef DEBUG
|
508
|
+
printf("Leaving cIGraph_attribute_has_attr\n");
|
509
|
+
#endif
|
510
|
+
|
511
|
+
return res;
|
512
|
+
}
|
513
|
+
|
514
|
+
/* Returns the type of a given attribute */
|
515
|
+
int cIGraph_attribute_get_type(const igraph_t *graph,
|
516
|
+
igraph_attribute_type_t *type,
|
517
|
+
igraph_attribute_elemtype_t elemtype,
|
518
|
+
const char *name) {
|
519
|
+
|
520
|
+
#ifdef DEBUG
|
521
|
+
printf("Entering cIGraph_attribute_get_type\n");
|
522
|
+
#endif
|
523
|
+
|
524
|
+
long int attrnum;
|
525
|
+
VALUE obj;
|
526
|
+
VALUE val;
|
527
|
+
|
528
|
+
switch (elemtype) {
|
529
|
+
case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
|
530
|
+
case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
|
531
|
+
case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
|
532
|
+
default: return 0; break;
|
533
|
+
}
|
534
|
+
|
535
|
+
obj = ((VALUE*)graph->attr)[attrnum];
|
536
|
+
if (attrnum != 2)
|
537
|
+
obj = RARRAY(obj)->ptr[0];
|
538
|
+
|
539
|
+
if(rb_funcall(obj,rb_intern("includes"), rb_str_new2(name))){
|
540
|
+
val = rb_hash_aref(obj,rb_str_new2(name));
|
541
|
+
if (TYPE(val) == T_STRING){
|
542
|
+
*type = IGRAPH_ATTRIBUTE_STRING;
|
543
|
+
} else if (TYPE(val) == T_FIXNUM || TYPE(val) == T_FLOAT){
|
544
|
+
*type = IGRAPH_ATTRIBUTE_NUMERIC;
|
545
|
+
} else {
|
546
|
+
*type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
|
550
|
+
#ifdef DEBUG
|
551
|
+
printf("Leaving cIGraph_attribute_get_type\n");
|
552
|
+
#endif
|
553
|
+
|
554
|
+
return 0;
|
555
|
+
|
556
|
+
}
|
557
|
+
|
558
|
+
/* Getting numeric graph attributes */
|
559
|
+
int cIGraph_get_numeric_graph_attr(const igraph_t *graph,
|
560
|
+
const char *name, igraph_vector_t *value) {
|
561
|
+
|
562
|
+
#ifdef DEBUG
|
563
|
+
printf("Entering cIGraph_get_numeric_graph_attr\n");
|
564
|
+
#endif
|
565
|
+
|
566
|
+
VALUE val;
|
567
|
+
|
568
|
+
val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
|
569
|
+
VECTOR(*value)[0] = NUM2DBL(val);
|
570
|
+
|
571
|
+
#ifdef DEBUG
|
572
|
+
printf("Leaving cIGraph_get_numeric_graph_attr\n");
|
573
|
+
#endif
|
574
|
+
|
575
|
+
return 0;
|
576
|
+
}
|
577
|
+
|
578
|
+
/* Getting string graph attributes */
|
579
|
+
int cIGraph_get_string_graph_attr(const igraph_t *graph,
|
580
|
+
const char *name, igraph_strvector_t *value) {
|
581
|
+
|
582
|
+
#ifdef DEBUG
|
583
|
+
printf("Entering cIGraph_get_string_graph_attr\n");
|
584
|
+
#endif
|
585
|
+
|
586
|
+
VALUE val;
|
587
|
+
|
588
|
+
val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
|
589
|
+
igraph_strvector_set(value,0,RSTRING(val)->ptr);
|
590
|
+
|
591
|
+
#ifdef DEBUG
|
592
|
+
printf("Leaving cIGraph_get_string_graph_attr\n");
|
593
|
+
#endif
|
594
|
+
|
595
|
+
return 0;
|
596
|
+
}
|
597
|
+
|
598
|
+
/* Getting numeric vertex attributes */
|
599
|
+
int cIGraph_get_numeric_vertex_attr(const igraph_t *graph,
|
600
|
+
const char *name,
|
601
|
+
igraph_vs_t vs,
|
602
|
+
igraph_vector_t *value) {
|
603
|
+
|
604
|
+
#ifdef DEBUG
|
605
|
+
printf("Entering cIGraph_get_numeric_vertex_attr\n");
|
606
|
+
#endif
|
607
|
+
|
608
|
+
VALUE array = ((VALUE*)graph->attr)[0];
|
609
|
+
VALUE val, vertex;
|
610
|
+
igraph_vit_t it;
|
611
|
+
int i = 0;
|
612
|
+
|
613
|
+
IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
|
614
|
+
IGRAPH_FINALLY(igraph_vit_destroy, &it);
|
615
|
+
IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_VIT_SIZE(it)));
|
616
|
+
|
617
|
+
while(!IGRAPH_VIT_END(it)){
|
618
|
+
vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
|
619
|
+
val = rb_hash_aref(vertex,rb_str_new2(name));
|
620
|
+
|
621
|
+
if(val == Qnil)
|
622
|
+
val = rb_float_new(NAN);
|
623
|
+
|
624
|
+
VECTOR(*value)[i] = NUM2DBL(val);
|
625
|
+
IGRAPH_VIT_NEXT(it);
|
626
|
+
i++;
|
627
|
+
}
|
628
|
+
|
629
|
+
igraph_vit_destroy(&it);
|
630
|
+
IGRAPH_FINALLY_CLEAN(1);
|
631
|
+
|
632
|
+
#ifdef DEBUG
|
633
|
+
printf("Leaving cIGraph_get_numeric_vertex_attr\n");
|
634
|
+
#endif
|
635
|
+
|
636
|
+
return 0;
|
637
|
+
}
|
638
|
+
|
639
|
+
/* Getting string vertex attributes */
|
640
|
+
int cIGraph_get_string_vertex_attr(const igraph_t *graph,
|
641
|
+
const char *name,
|
642
|
+
igraph_vs_t vs,
|
643
|
+
igraph_strvector_t *value) {
|
644
|
+
|
645
|
+
#ifdef DEBUG
|
646
|
+
printf("Entering cIGraph_get_string_vertex_attr\n");
|
647
|
+
#endif
|
648
|
+
|
649
|
+
VALUE array = ((VALUE*)graph->attr)[0];
|
650
|
+
VALUE val, vertex;
|
651
|
+
igraph_vit_t it;
|
652
|
+
int i=0;
|
653
|
+
|
654
|
+
IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
|
655
|
+
IGRAPH_FINALLY(igraph_vit_destroy, &it);
|
656
|
+
IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_VIT_SIZE(it)));
|
657
|
+
|
658
|
+
while(!IGRAPH_VIT_END(it)){
|
659
|
+
vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
|
660
|
+
val = rb_hash_aref(vertex,rb_str_new2(name));
|
661
|
+
|
662
|
+
if(val == Qnil)
|
663
|
+
val = rb_str_new2("");
|
664
|
+
|
665
|
+
igraph_strvector_set(value,i,RSTRING(val)->ptr);
|
666
|
+
IGRAPH_VIT_NEXT(it);
|
667
|
+
i++;
|
668
|
+
}
|
669
|
+
|
670
|
+
igraph_vit_destroy(&it);
|
671
|
+
IGRAPH_FINALLY_CLEAN(1);
|
672
|
+
|
673
|
+
#ifdef DEBUG
|
674
|
+
printf("Leaving cIGraph_get_string_vertex_attr\n");
|
675
|
+
#endif
|
676
|
+
|
677
|
+
return 0;
|
678
|
+
}
|
679
|
+
|
680
|
+
/* Getting numeric edge attributes */
|
681
|
+
int cIGraph_get_numeric_edge_attr(const igraph_t *graph,
|
682
|
+
const char *name,
|
683
|
+
igraph_es_t es,
|
684
|
+
igraph_vector_t *value) {
|
685
|
+
|
686
|
+
#ifdef DEBUG
|
687
|
+
printf("Entering cIGraph_get_numeric_edge_attr\n");
|
688
|
+
#endif
|
689
|
+
|
690
|
+
VALUE array = ((VALUE*)graph->attr)[1];
|
691
|
+
VALUE val, vertex;
|
692
|
+
igraph_eit_t it;
|
693
|
+
int i = 0;
|
694
|
+
|
695
|
+
IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
|
696
|
+
IGRAPH_FINALLY(igraph_eit_destroy, &it);
|
697
|
+
IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_EIT_SIZE(it)));
|
698
|
+
|
699
|
+
while(!IGRAPH_EIT_END(it)){
|
700
|
+
vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
|
701
|
+
val = rb_hash_aref(vertex,rb_str_new2(name));
|
702
|
+
|
703
|
+
if(val == Qnil)
|
704
|
+
val = rb_float_new(NAN);
|
705
|
+
|
706
|
+
VECTOR(*value)[i] = NUM2DBL(val);
|
707
|
+
IGRAPH_EIT_NEXT(it);
|
708
|
+
i++;
|
709
|
+
}
|
710
|
+
|
711
|
+
igraph_eit_destroy(&it);
|
712
|
+
IGRAPH_FINALLY_CLEAN(1);
|
713
|
+
|
714
|
+
#ifdef DEBUG
|
715
|
+
printf("Leaving cIGraph_get_numeric_edge_attr\n");
|
716
|
+
#endif
|
717
|
+
|
718
|
+
return 0;
|
719
|
+
}
|
720
|
+
|
721
|
+
/* Getting string edge attributes */
|
722
|
+
int cIGraph_get_string_edge_attr(const igraph_t *graph,
|
723
|
+
const char *name,
|
724
|
+
igraph_es_t es,
|
725
|
+
igraph_strvector_t *value) {
|
726
|
+
|
727
|
+
#ifdef DEBUG
|
728
|
+
printf("Entering cIGraph_get_string_edge_attr\n");
|
729
|
+
#endif
|
730
|
+
|
731
|
+
VALUE array = ((VALUE*)graph->attr)[1];
|
732
|
+
VALUE val, vertex;
|
733
|
+
igraph_eit_t it;
|
734
|
+
int i=0;
|
735
|
+
|
736
|
+
IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
|
737
|
+
IGRAPH_FINALLY(igraph_eit_destroy, &it);
|
738
|
+
IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it)));
|
739
|
+
|
740
|
+
while(!IGRAPH_EIT_END(it)){
|
741
|
+
vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
|
742
|
+
val = rb_hash_aref(vertex,rb_str_new2(name));
|
743
|
+
if(val == Qnil)
|
744
|
+
val = rb_str_new2("");
|
745
|
+
igraph_strvector_set(value,i,RSTRING(val)->ptr);
|
746
|
+
IGRAPH_EIT_NEXT(it);
|
747
|
+
i++;
|
748
|
+
}
|
749
|
+
|
750
|
+
igraph_eit_destroy(&it);
|
751
|
+
IGRAPH_FINALLY_CLEAN(1);
|
752
|
+
|
753
|
+
#ifdef DEBUG
|
754
|
+
printf("Leaving cIGraph_get_string_edge_attr\n");
|
755
|
+
#endif
|
756
|
+
|
757
|
+
return 0;
|
758
|
+
}
|