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

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

Ruby binding for the igraph library.