You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cIGraph_attribute_handler.c 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. #include "igraph.h"
  2. #include "ruby.h"
  3. #include "cIGraph.h"
  4. /* call-seq:
  5. * graph[u,v] -> Object
  6. *
  7. * Returns the object associated with the edge connecting vertices u and v.
  8. * Aliased to graph.get_edge_attr(u,v)
  9. */
  10. VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to){
  11. int idx;
  12. igraph_t *graph;
  13. VALUE e_ary;
  14. Data_Get_Struct(self, igraph_t, graph);
  15. e_ary = ((VALUE*)graph->attr)[1];
  16. idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
  17. return rb_ary_entry(e_ary,idx);
  18. }
  19. /* call-seq:
  20. * graph[u,v] = w
  21. *
  22. * Sets the object associated with the edge connecting vertices u and v.
  23. * Aliased to graph.set_edge_attr(u,v)
  24. */
  25. VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr){
  26. int idx;
  27. igraph_t *graph;
  28. VALUE e_ary;
  29. Data_Get_Struct(self, igraph_t, graph);
  30. e_ary = ((VALUE*)graph->attr)[1];
  31. idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
  32. rb_ary_store(e_ary,idx,attr);
  33. return Qtrue;
  34. }
  35. /* call-seq:
  36. * graph.attributes -> Hash
  37. *
  38. * Returns the graph attributes. This is usually only used when reading in
  39. * graphs from GraphML format. Feel free to use instance variables on the
  40. * graph object if you like (they won't get copied though!).
  41. */
  42. VALUE cIGraph_graph_attributes(VALUE self){
  43. igraph_t *graph;
  44. VALUE hsh;
  45. Data_Get_Struct(self, igraph_t, graph);
  46. hsh = ((VALUE*)graph->attr)[2];
  47. return hsh;
  48. }
  49. igraph_attribute_table_t cIGraph_attribute_table = {
  50. cIGraph_attribute_init,
  51. cIGraph_attribute_destroy,
  52. cIGraph_attribute_copy,
  53. cIGraph_attribute_add_vertices,
  54. cIGraph_attribute_delete_vertices,
  55. cIGraph_attribute_add_edges,
  56. cIGraph_attribute_delete_edges,
  57. cIGraph_attribute_permute_edges,
  58. cIGraph_attribute_get_info,
  59. cIGraph_attribute_has_attr,
  60. cIGraph_attribute_get_type,
  61. cIGraph_get_numeric_graph_attr,
  62. cIGraph_get_string_graph_attr,
  63. cIGraph_get_numeric_vertex_attr,
  64. cIGraph_get_string_vertex_attr,
  65. cIGraph_get_numeric_edge_attr,
  66. cIGraph_get_string_edge_attr,
  67. };
  68. int cIGraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) {
  69. VALUE* attrs;
  70. int i;
  71. VALUE key;
  72. VALUE value;
  73. attrs = (VALUE*)calloc(3, sizeof(VALUE));
  74. if(!attrs)
  75. IGRAPH_ERROR("Error allocating Arrays\n", IGRAPH_ENOMEM);
  76. //[0] is vertex array, [1] is edge array, [2] is graph attr
  77. attrs[0] = rb_ary_new();
  78. attrs[1] = rb_ary_new();
  79. attrs[2] = rb_hash_new();
  80. if(attr){
  81. for(i=0;i<igraph_vector_ptr_size(attr);i++){
  82. igraph_i_attribute_record_t *attr_rec;
  83. char *s;
  84. attr_rec = VECTOR(*attr)[i];
  85. key = rb_str_new2(attr_rec->name);
  86. switch (attr_rec->type) {
  87. case IGRAPH_ATTRIBUTE_NUMERIC:
  88. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]);
  89. break;
  90. case IGRAPH_ATTRIBUTE_STRING:
  91. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s);
  92. value=rb_str_new2(s);
  93. break;
  94. default:
  95. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  96. value=0;
  97. break;
  98. }
  99. if (value){
  100. rb_hash_aset((VALUE)attrs[2],key,value);
  101. }
  102. }
  103. }
  104. graph->attr = attrs;
  105. return IGRAPH_SUCCESS;
  106. }
  107. /* Destruction */
  108. void cIGraph_attribute_destroy(igraph_t *graph) {
  109. VALUE *attrs = (VALUE*)graph->attr;
  110. free(attrs);
  111. return;
  112. }
  113. /* Copying */
  114. int replace_i(VALUE key, VALUE val, VALUE hash){
  115. if (key != Qundef) {
  116. rb_hash_aset(hash, key, val);
  117. }
  118. //return ST_CONTINUE;
  119. return 0;
  120. }
  121. int cIGraph_attribute_copy(igraph_t *to, const igraph_t *from) {
  122. #ifdef DEBUG
  123. printf("Entering cIGraph_attribute_copy\n");
  124. #endif
  125. VALUE* attrs;
  126. VALUE vertex_array = ((VALUE*)from->attr)[0];
  127. VALUE edge_array = ((VALUE*)from->attr)[1];
  128. VALUE graph_attr = ((VALUE*)from->attr)[2];
  129. attrs = ALLOC_N(VALUE, 3);
  130. attrs[0] = rb_ary_dup(vertex_array);
  131. attrs[1] = rb_ary_dup(edge_array);
  132. attrs[2] = rb_hash_new();
  133. rb_hash_foreach(graph_attr, replace_i, attrs[2]);
  134. to->attr = attrs;
  135. #ifdef DEBUG
  136. printf("Leaving cIGraph_attribute_copy\n");
  137. #endif
  138. return IGRAPH_SUCCESS;
  139. }
  140. /* Adding vertices */
  141. int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr) {
  142. #ifdef DEBUG
  143. printf("Entering cIGraph_attribute_add_vertices\n");
  144. #endif
  145. int i,j;
  146. VALUE vertex_array = ((VALUE*)graph->attr)[0];
  147. VALUE values;
  148. if(attr){
  149. if(igraph_vector_ptr_size(attr) > 0 && ((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
  150. values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
  151. Check_Type(values, T_ARRAY);
  152. for(i=0;i<RARRAY(values)->len;i++){
  153. rb_ary_push(vertex_array, RARRAY(values)->ptr[i]);
  154. }
  155. //Otherwise read each attriute into hashes and use those
  156. } else {
  157. for(i=0;i<nv;i++){
  158. VALUE record;
  159. igraph_i_attribute_record_t *attr_rec;
  160. char *s;
  161. record = rb_hash_new();
  162. //For when no attributes are given
  163. if(igraph_vector_ptr_size(attr) == 0){
  164. record = INT2NUM(i+1);
  165. }
  166. for (j=0; j<igraph_vector_ptr_size(attr); j++) {
  167. VALUE key;
  168. VALUE value;
  169. //Add key value pair
  170. attr_rec = VECTOR(*attr)[j];
  171. key = rb_str_new2(attr_rec->name);
  172. switch (attr_rec->type) {
  173. case IGRAPH_ATTRIBUTE_NUMERIC:
  174. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
  175. break;
  176. case IGRAPH_ATTRIBUTE_STRING:
  177. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
  178. value=rb_str_new2(s);
  179. break;
  180. default:
  181. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  182. value=Qnil;
  183. break;
  184. }
  185. rb_hash_aset(record,key,value);
  186. }
  187. rb_ary_push(vertex_array,record);
  188. }
  189. }
  190. }
  191. #ifdef DEBUG
  192. printf("Leaving cIGraph_attribute_add_vertices\n");
  193. #endif
  194. return IGRAPH_SUCCESS;
  195. }
  196. /* Deleting vertices */
  197. void cIGraph_attribute_delete_vertices(igraph_t *graph,
  198. const igraph_vector_t *eidx,
  199. const igraph_vector_t *vidx) {
  200. #ifdef DEBUG
  201. printf("Entering cIGraph_attribute_delete_vertices\n");
  202. #endif
  203. int i;
  204. VALUE vertex_array = ((VALUE*)graph->attr)[0];
  205. VALUE edge_array = ((VALUE*)graph->attr)[1];
  206. VALUE n_v_ary = rb_ary_new();
  207. VALUE n_e_ary = rb_ary_new();
  208. for(i=0;i<igraph_vector_size(vidx);i++){
  209. if(VECTOR(*vidx)[i] != 0)
  210. rb_ary_store(n_v_ary,VECTOR(*vidx)[i]-1,rb_ary_entry(vertex_array,i));
  211. }
  212. for(i=0;i<igraph_vector_size(eidx);i++){
  213. if(VECTOR(*eidx)[i] != 0)
  214. rb_ary_store(n_e_ary,VECTOR(*eidx)[i]-1,rb_ary_entry(edge_array,i));
  215. }
  216. ((VALUE*)graph->attr)[0] = n_v_ary;
  217. ((VALUE*)graph->attr)[1] = n_e_ary;
  218. #ifdef DEBUG
  219. printf("Leaving cIGraph_attribute_delete_vertices\n");
  220. #endif
  221. return;
  222. }
  223. /* Adding edges */
  224. int cIGraph_attribute_add_edges(igraph_t *graph,
  225. const igraph_vector_t *edges,
  226. igraph_vector_ptr_t *attr) {
  227. #ifdef DEBUG
  228. printf("Entering cIGraph_attribute_add_edges\n");
  229. #endif
  230. int i,j;
  231. VALUE edge_array = ((VALUE*)graph->attr)[1];
  232. VALUE values;
  233. if(attr){
  234. //If the only record is of type PY_OBJ then use the values as attributes
  235. if(((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
  236. values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
  237. Check_Type(values, T_ARRAY);
  238. for(i=0;i<RARRAY(values)->len;i++){
  239. rb_ary_push(edge_array, RARRAY(values)->ptr[i]);
  240. }
  241. //Otherwise read each attriute into hashes and use those
  242. } else {
  243. for(i=0;i<igraph_vector_size(edges)/2;i++){
  244. VALUE record;
  245. igraph_i_attribute_record_t *attr_rec;
  246. char *s;
  247. record = rb_hash_new();
  248. for (j=0; j<igraph_vector_ptr_size(attr); j++) {
  249. VALUE key;
  250. VALUE value;
  251. //Add key value pair
  252. attr_rec = VECTOR(*attr)[j];
  253. key = rb_str_new2(attr_rec->name);
  254. switch (attr_rec->type) {
  255. case IGRAPH_ATTRIBUTE_NUMERIC:
  256. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
  257. break;
  258. case IGRAPH_ATTRIBUTE_STRING:
  259. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
  260. value=rb_str_new2(s);
  261. break;
  262. default:
  263. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  264. value=Qnil;
  265. break;
  266. }
  267. rb_hash_aset(record,key,value);
  268. }
  269. rb_ary_push(edge_array,record);
  270. }
  271. }
  272. }
  273. #ifdef DEBUG
  274. printf("Leaving cIGraph_attribute_add_edges\n");
  275. #endif
  276. return IGRAPH_SUCCESS;
  277. }
  278. /* Deleting edges */
  279. void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) {
  280. #ifdef DEBUG
  281. printf("Entering cIGraph_attribute_delete_edges\n");
  282. #endif
  283. int i;
  284. VALUE edge_array = ((VALUE*)graph->attr)[1];
  285. VALUE n_e_ary = rb_ary_new();
  286. for(i=0;i<igraph_vector_size(idx);i++){
  287. if(VECTOR(*idx)[i] != 0)
  288. rb_ary_store(n_e_ary,VECTOR(*idx)[i]-1,rb_ary_entry(edge_array,i));
  289. }
  290. ((VALUE*)graph->attr)[1] = n_e_ary;
  291. #ifdef DEBUG
  292. printf("Leaving cIGraph_attribute_delete_edges\n");
  293. #endif
  294. return;
  295. }
  296. /* Permuting edges */
  297. int cIGraph_attribute_permute_edges(igraph_t *graph,
  298. const igraph_vector_t *idx) {
  299. #ifdef DEBUG
  300. printf("Entering cIGraph_attribute_permute_edges\n");
  301. #endif
  302. int i;
  303. VALUE edge_array = ((VALUE*)graph->attr)[1];
  304. VALUE n_e_ary = rb_ary_new();
  305. for(i=0;i<igraph_vector_size(idx);i++){
  306. rb_ary_push(n_e_ary,rb_ary_entry(edge_array,VECTOR(*idx)[i]));
  307. }
  308. ((VALUE*)graph->attr)[1] = n_e_ary;
  309. #ifdef DEBUG
  310. printf("Leaving cIGraph_attribute_permute_edges\n");
  311. #endif
  312. return 0;
  313. }
  314. VALUE keys_to_strvec(VALUE data, VALUE arr){
  315. VALUE key = rb_ary_entry(data, 0);
  316. VALUE val = rb_ary_entry(data, 1);
  317. VALUE rb_names = rb_ary_entry(arr, 0);
  318. VALUE rb_types = rb_ary_entry(arr, 1);
  319. VALUE str = StringValue(key);
  320. rb_ary_push(rb_names,str);
  321. if(TYPE(val) == T_STRING){
  322. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_STRING));
  323. } else if (TYPE(val) == T_FLOAT || TYPE(val) == T_FIXNUM){
  324. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_NUMERIC));
  325. } else {
  326. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_PY_OBJECT));
  327. }
  328. return data;
  329. }
  330. /* Getting attribute names and types */
  331. int cIGraph_attribute_get_info(const igraph_t *graph,
  332. igraph_strvector_t *gnames,
  333. igraph_vector_t *gtypes,
  334. igraph_strvector_t *vnames,
  335. igraph_vector_t *vtypes,
  336. igraph_strvector_t *enames,
  337. igraph_vector_t *etypes) {
  338. #ifdef DEBUG
  339. printf("Entering cIGraph_attribute_get_info\n");
  340. #endif
  341. igraph_strvector_t *names[3] = { vnames, enames, gnames };
  342. igraph_vector_t *types[3] = { vtypes, etypes, gtypes };
  343. long int i,j;
  344. for (i=0; i<3; i++) {
  345. igraph_strvector_t *n = names[i];
  346. igraph_vector_t *t = types[i];
  347. VALUE rb_names = rb_ary_new();
  348. VALUE rb_types = rb_ary_new();
  349. VALUE obj_hash;
  350. //Graph attributes are different
  351. if (i != 2){
  352. VALUE store = ((VALUE*)graph->attr)[i];
  353. VALUE obj = RARRAY(store)->ptr[0];
  354. obj_hash = Qnil;
  355. if(rb_funcall(obj, rb_intern("respond_to?"), 1, rb_str_new2("to_hash")) == Qtrue){
  356. obj_hash = rb_funcall(obj, rb_intern("to_hash"), 0);
  357. }
  358. } else {
  359. obj_hash = ((VALUE*)graph->attr)[2];
  360. }
  361. if(!NIL_P(obj_hash)){
  362. //Take the keys of the hash, convert to strings and put in vector n
  363. rb_iterate(rb_each, obj_hash, keys_to_strvec, rb_ary_new3(2,rb_names,rb_types));
  364. }
  365. //Push names onto n and types onto t
  366. for(j=0;j<RARRAY(rb_names)->len;j++){
  367. igraph_strvector_add(n, RSTRING(RARRAY(rb_names)->ptr[j])->ptr);
  368. igraph_vector_push_back(t, NUM2INT(RARRAY(rb_types)->ptr[j]));
  369. }
  370. }
  371. #ifdef DEBUG
  372. printf("Leaving cIGraph_attribute_get_info\n");
  373. #endif
  374. return 0;
  375. }
  376. /* Checks whether the graph has a graph/vertex/edge attribute with the given name */
  377. igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph,
  378. igraph_attribute_elemtype_t type,
  379. const char* name) {
  380. #ifdef DEBUG
  381. printf("Entering cIGraph_attribute_has_attr\n");
  382. #endif
  383. long int attrnum;
  384. igraph_bool_t res = 0;
  385. VALUE obj;
  386. switch (type) {
  387. case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
  388. case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
  389. case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
  390. default: return 0; break;
  391. }
  392. obj = ((VALUE*)graph->attr)[attrnum];
  393. if (attrnum != 2)
  394. obj = RARRAY(obj)->ptr[0];
  395. if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){
  396. res = 1;
  397. }
  398. #ifdef DEBUG
  399. printf("Leaving cIGraph_attribute_has_attr\n");
  400. #endif
  401. return res;
  402. }
  403. /* Returns the type of a given attribute */
  404. int cIGraph_attribute_get_type(const igraph_t *graph,
  405. igraph_attribute_type_t *type,
  406. igraph_attribute_elemtype_t elemtype,
  407. const char *name) {
  408. #ifdef DEBUG
  409. printf("Entering cIGraph_attribute_get_type\n");
  410. #endif
  411. long int attrnum;
  412. VALUE obj;
  413. VALUE val;
  414. switch (elemtype) {
  415. case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
  416. case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
  417. case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
  418. default: return 0; break;
  419. }
  420. obj = ((VALUE*)graph->attr)[attrnum];
  421. if (attrnum != 2)
  422. obj = RARRAY(obj)->ptr[0];
  423. if(rb_funcall(obj,rb_intern("includes"), rb_str_new2(name))){
  424. val = rb_hash_aref(obj,rb_str_new2(name));
  425. if (TYPE(val) == T_STRING){
  426. *type = IGRAPH_ATTRIBUTE_STRING;
  427. } else if (TYPE(val) == T_FIXNUM || TYPE(val) == T_FLOAT){
  428. *type = IGRAPH_ATTRIBUTE_NUMERIC;
  429. } else {
  430. *type = IGRAPH_ATTRIBUTE_PY_OBJECT;
  431. }
  432. }
  433. #ifdef DEBUG
  434. printf("Leaving cIGraph_attribute_get_type\n");
  435. #endif
  436. return 0;
  437. }
  438. /* Getting numeric graph attributes */
  439. int cIGraph_get_numeric_graph_attr(const igraph_t *graph,
  440. const char *name, igraph_vector_t *value) {
  441. #ifdef DEBUG
  442. printf("Entering cIGraph_get_numeric_graph_attr\n");
  443. #endif
  444. VALUE val;
  445. val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
  446. VECTOR(*value)[0] = NUM2DBL(val);
  447. #ifdef DEBUG
  448. printf("Leaving cIGraph_get_numeric_graph_attr\n");
  449. #endif
  450. return 0;
  451. }
  452. /* Getting string graph attributes */
  453. int cIGraph_get_string_graph_attr(const igraph_t *graph,
  454. const char *name, igraph_strvector_t *value) {
  455. #ifdef DEBUG
  456. printf("Entering cIGraph_get_string_graph_attr\n");
  457. #endif
  458. VALUE val;
  459. val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
  460. igraph_strvector_set(value,0,RSTRING(val)->ptr);
  461. #ifdef DEBUG
  462. printf("Leaving cIGraph_get_string_graph_attr\n");
  463. #endif
  464. return 0;
  465. }
  466. /* Getting numeric vertex attributes */
  467. int cIGraph_get_numeric_vertex_attr(const igraph_t *graph,
  468. const char *name,
  469. igraph_vs_t vs,
  470. igraph_vector_t *value) {
  471. #ifdef DEBUG
  472. printf("Entering cIGraph_get_numeric_vertex_attr\n");
  473. #endif
  474. VALUE array = ((VALUE*)graph->attr)[0];
  475. VALUE val, vertex;
  476. igraph_vit_t it;
  477. int i = 0;
  478. IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
  479. IGRAPH_FINALLY(igraph_vit_destroy, &it);
  480. IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_VIT_SIZE(it)));
  481. while(!IGRAPH_VIT_END(it)){
  482. vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
  483. val = rb_hash_aref(vertex,rb_str_new2(name));
  484. if(val == Qnil)
  485. val = rb_float_new(NAN);
  486. VECTOR(*value)[i] = NUM2DBL(val);
  487. IGRAPH_VIT_NEXT(it);
  488. i++;
  489. }
  490. igraph_vit_destroy(&it);
  491. IGRAPH_FINALLY_CLEAN(1);
  492. #ifdef DEBUG
  493. printf("Leaving cIGraph_get_numeric_vertex_attr\n");
  494. #endif
  495. return 0;
  496. }
  497. /* Getting string vertex attributes */
  498. int cIGraph_get_string_vertex_attr(const igraph_t *graph,
  499. const char *name,
  500. igraph_vs_t vs,
  501. igraph_strvector_t *value) {
  502. #ifdef DEBUG
  503. printf("Entering cIGraph_get_string_vertex_attr\n");
  504. #endif
  505. VALUE array = ((VALUE*)graph->attr)[0];
  506. VALUE val, vertex;
  507. igraph_vit_t it;
  508. int i=0;
  509. IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
  510. IGRAPH_FINALLY(igraph_vit_destroy, &it);
  511. IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_VIT_SIZE(it)));
  512. while(!IGRAPH_VIT_END(it)){
  513. vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
  514. val = rb_hash_aref(vertex,rb_str_new2(name));
  515. if(val == Qnil)
  516. val = rb_str_new2("");
  517. igraph_strvector_set(value,i,RSTRING(val)->ptr);
  518. IGRAPH_VIT_NEXT(it);
  519. i++;
  520. }
  521. igraph_vit_destroy(&it);
  522. IGRAPH_FINALLY_CLEAN(1);
  523. #ifdef DEBUG
  524. printf("Leaving cIGraph_get_string_vertex_attr\n");
  525. #endif
  526. return 0;
  527. }
  528. /* Getting numeric edge attributes */
  529. int cIGraph_get_numeric_edge_attr(const igraph_t *graph,
  530. const char *name,
  531. igraph_es_t es,
  532. igraph_vector_t *value) {
  533. #ifdef DEBUG
  534. printf("Entering cIGraph_get_numeric_edge_attr\n");
  535. #endif
  536. VALUE array = ((VALUE*)graph->attr)[1];
  537. VALUE val, vertex;
  538. igraph_eit_t it;
  539. int i = 0;
  540. IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
  541. IGRAPH_FINALLY(igraph_eit_destroy, &it);
  542. IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_EIT_SIZE(it)));
  543. while(!IGRAPH_EIT_END(it)){
  544. vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
  545. val = rb_hash_aref(vertex,rb_str_new2(name));
  546. if(val == Qnil)
  547. val = rb_float_new(NAN);
  548. VECTOR(*value)[i] = NUM2DBL(val);
  549. IGRAPH_EIT_NEXT(it);
  550. i++;
  551. }
  552. igraph_eit_destroy(&it);
  553. IGRAPH_FINALLY_CLEAN(1);
  554. #ifdef DEBUG
  555. printf("Leaving cIGraph_get_numeric_edge_attr\n");
  556. #endif
  557. return 0;
  558. }
  559. /* Getting string edge attributes */
  560. int cIGraph_get_string_edge_attr(const igraph_t *graph,
  561. const char *name,
  562. igraph_es_t es,
  563. igraph_strvector_t *value) {
  564. #ifdef DEBUG
  565. printf("Entering cIGraph_get_string_edge_attr\n");
  566. #endif
  567. VALUE array = ((VALUE*)graph->attr)[1];
  568. VALUE val, vertex;
  569. igraph_eit_t it;
  570. int i=0;
  571. IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
  572. IGRAPH_FINALLY(igraph_eit_destroy, &it);
  573. IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it)));
  574. while(!IGRAPH_EIT_END(it)){
  575. vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
  576. val = rb_hash_aref(vertex,rb_str_new2(name));
  577. if(val == Qnil)
  578. val = rb_str_new2("");
  579. igraph_strvector_set(value,i,RSTRING(val)->ptr);
  580. IGRAPH_EIT_NEXT(it);
  581. i++;
  582. }
  583. igraph_eit_destroy(&it);
  584. IGRAPH_FINALLY_CLEAN(1);
  585. #ifdef DEBUG
  586. printf("Leaving cIGraph_get_string_edge_attr\n");
  587. #endif
  588. return 0;
  589. }

Ruby binding for the igraph library.