git-svn-id: http://igraph.rubyforge.org/svn/trunk@27 71f48855-0bbf-4aa5-930d-4df415e86613
This commit is contained in:
parent
2abe2bda3a
commit
6daa70a03f
|
@ -11,6 +11,8 @@ ext/cIGraph_basic_query.c
|
|||
ext/cIGraph_error_handlers.c
|
||||
ext/cIGraph_file.c
|
||||
ext/cIGraph_iterators.c
|
||||
ext/cIGraph_layout.c
|
||||
ext/cIGraph_matrix.c
|
||||
ext/cIGraph_operators.c
|
||||
ext/cIGraph_selectors.c
|
||||
ext/cIGraph_shortest_paths.c
|
||||
|
@ -21,10 +23,13 @@ test/tc_add_delete.rb
|
|||
test/tc_attributes.rb
|
||||
test/tc_basic_properties.rb
|
||||
test/tc_basic_query.rb
|
||||
test/tc_copy.rb
|
||||
test/tc_create.rb
|
||||
test/tc_error_handling.rb
|
||||
test/tc_file_read_write.rb
|
||||
test/tc_iterators.rb
|
||||
test/tc_layout.rb
|
||||
test/tc_matrix.rb
|
||||
test/tc_selectors.rb
|
||||
test/tc_shortest_paths.rb
|
||||
test/tc_topological_sort.rb
|
||||
|
|
|
@ -2,7 +2,14 @@ require 'hoe'
|
|||
|
||||
$LOAD_PATH.unshift("./ext")
|
||||
|
||||
require 'igraph'
|
||||
class IGraph
|
||||
VERSION = "0.0"
|
||||
end
|
||||
|
||||
begin
|
||||
require 'igraph'
|
||||
rescue RuntimeError
|
||||
end
|
||||
|
||||
hoe = Hoe.new("igraph",IGraph::VERSION) do |p|
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ void cIGraph_free(void *p){
|
|||
void cIGraph_mark(void *p){
|
||||
rb_gc_mark(((VALUE*)((igraph_t*)p)->attr)[0]);
|
||||
rb_gc_mark(((VALUE*)((igraph_t*)p)->attr)[1]);
|
||||
rb_gc_mark(((VALUE*)((igraph_t*)p)->attr)[2]);
|
||||
}
|
||||
|
||||
VALUE cIGraph_alloc(VALUE klass){
|
||||
|
@ -89,6 +90,16 @@ VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){
|
|||
igraph_vector_ptr_t vertex_attr;
|
||||
igraph_vector_ptr_t edge_attr;
|
||||
|
||||
igraph_i_attribute_record_t v_attr_rec;
|
||||
v_attr_rec.name = "__RUBY__";
|
||||
v_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
v_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
igraph_i_attribute_record_t e_attr_rec;
|
||||
e_attr_rec.name = "__RUBY__";
|
||||
e_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
e_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
rb_scan_args(argc,argv,"12", &edges, &directed, &attrs);
|
||||
|
||||
//Initialize edge vector
|
||||
|
@ -117,19 +128,22 @@ VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){
|
|||
vertex_n++;
|
||||
|
||||
//Add object to list of vertex attributes
|
||||
igraph_vector_ptr_push_back(&vertex_attr,(void*)vertex);
|
||||
rb_ary_push((VALUE)v_attr_rec.value,vertex);
|
||||
|
||||
}
|
||||
igraph_vector_push_back(&edge_v,current_vertex_id);
|
||||
if (i % 2){
|
||||
if (attrs != Qnil){
|
||||
igraph_vector_ptr_push_back(&edge_attr,(void*)RARRAY(attrs)->ptr[i/2]);
|
||||
rb_ary_push((VALUE)e_attr_rec.value,RARRAY(attrs)->ptr[i/2]);
|
||||
} else {
|
||||
igraph_vector_ptr_push_back(&edge_attr,(void*)Qnil);
|
||||
rb_ary_push((VALUE)e_attr_rec.value,Qnil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
igraph_vector_ptr_push_back(&vertex_attr, &v_attr_rec);
|
||||
igraph_vector_ptr_push_back(&edge_attr, &e_attr_rec);
|
||||
|
||||
if(igraph_vector_size(&edge_v) > 0){
|
||||
igraph_add_vertices(graph,vertex_n,&vertex_attr);
|
||||
igraph_add_edges(graph,&edge_v,&edge_attr);
|
||||
|
@ -179,6 +193,8 @@ void Init_igraph(){
|
|||
rb_define_alias (cIGraph, "get_edge_attr", "[]");
|
||||
rb_define_alias (cIGraph, "set_edge_attr", "[]=");
|
||||
|
||||
rb_define_method(cIGraph, "attributes", cIGraph_graph_attributes, 0); /* in cIGraph_attribute_handler.c */
|
||||
|
||||
rb_define_method(cIGraph, "each_vertex", cIGraph_each_vertex, 0); /* in cIGraph_iterators.c */
|
||||
rb_define_method(cIGraph, "each_edge", cIGraph_each_edge, 1); /* in cIGraph_iterators.c */
|
||||
rb_define_method(cIGraph, "each_edge_eid", cIGraph_each_edge_eid,1); /* in cIGraph_iterators.c */
|
||||
|
@ -231,7 +247,11 @@ void Init_igraph(){
|
|||
rb_define_method(cIGraph, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */
|
||||
|
||||
rb_define_singleton_method(cIGraph, "read_graph_edgelist", cIGraph_read_graph_edgelist, 2); /* in cIGraph_file.c */
|
||||
rb_define_singleton_method(cIGraph, "read_graph_graphml", cIGraph_read_graph_graphml, 2); /* in cIGraph_file.c */
|
||||
rb_define_singleton_method(cIGraph, "read_graph_pajek", cIGraph_read_graph_pajek, 2); /* in cIGraph_file.c */
|
||||
rb_define_method(cIGraph, "write_graph_edgelist", cIGraph_write_graph_edgelist, 1); /* in cIGraph_file.c */
|
||||
rb_define_method(cIGraph, "write_graph_graphml", cIGraph_write_graph_graphml, 1); /* in cIGraph_file.c */
|
||||
rb_define_method(cIGraph, "write_graph_pajek", cIGraph_write_graph_pajek, 1); /* in cIGraph_file.c */
|
||||
|
||||
rb_define_method(cIGraph, "layout_random", cIGraph_layout_random, 0);
|
||||
rb_define_method(cIGraph, "layout_circle", cIGraph_layout_circle, 0);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#include "math.h"
|
||||
#include "ruby.h"
|
||||
#include "igraph.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
//Classes
|
||||
extern VALUE cIGraph;
|
||||
extern VALUE cIGraphError;
|
||||
|
@ -25,8 +31,11 @@ VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self);
|
|||
VALUE cIGraph_init_copy(VALUE copy, VALUE orig);
|
||||
|
||||
//Attribute accessors
|
||||
int replace_i(VALUE key, VALUE val, VALUE hash);
|
||||
VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to);
|
||||
VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr);
|
||||
VALUE cIGraph_graph_attributes(VALUE self);
|
||||
igraph_i_attribute_record_t cIGraph_create_record(VALUE v);
|
||||
|
||||
//Iterators
|
||||
VALUE cIGraph_each_vertex (VALUE self);
|
||||
|
@ -83,7 +92,10 @@ VALUE cIGraph_topological_sorting(VALUE self, VALUE mode);
|
|||
//File handling
|
||||
VALUE cIGraph_read_graph_edgelist (VALUE self, VALUE file, VALUE mode);
|
||||
VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file);
|
||||
|
||||
VALUE cIGraph_read_graph_graphml (VALUE self, VALUE file, VALUE index);
|
||||
VALUE cIGraph_write_graph_graphml (VALUE self, VALUE file);
|
||||
VALUE cIGraph_read_graph_pajek (VALUE self, VALUE file);
|
||||
VALUE cIGraph_write_graph_pajek (VALUE self, VALUE file);
|
||||
|
||||
//Layouts
|
||||
VALUE cIGraph_layout_random(VALUE self);
|
||||
|
|
|
@ -32,6 +32,11 @@ VALUE cIGraph_add_edges(int argc, VALUE *argv, VALUE self){
|
|||
int i;
|
||||
igraph_vector_ptr_t edge_attr;
|
||||
|
||||
igraph_i_attribute_record_t e_attr_rec;
|
||||
e_attr_rec.name = "__RUBY__";
|
||||
e_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
e_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
rb_scan_args(argc, argv, "11", &edges, &attrs);
|
||||
|
||||
//Initialize edge vector
|
||||
|
@ -53,13 +58,15 @@ VALUE cIGraph_add_edges(int argc, VALUE *argv, VALUE self){
|
|||
igraph_vector_push_back(&edge_v,vid);
|
||||
if (i % 2){
|
||||
if (attrs != Qnil){
|
||||
igraph_vector_ptr_push_back(&edge_attr,(void*)RARRAY(attrs)->ptr[i/2]);
|
||||
rb_ary_push((VALUE)e_attr_rec.value,RARRAY(attrs)->ptr[i/2]);
|
||||
} else {
|
||||
igraph_vector_ptr_push_back(&edge_attr,(void*)Qnil);
|
||||
rb_ary_push((VALUE)e_attr_rec.value,Qnil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
igraph_vector_ptr_push_back(&edge_attr, &e_attr_rec);
|
||||
|
||||
if(igraph_vector_size(&edge_v) > 0){
|
||||
code = igraph_add_edges(graph,&edge_v,&edge_attr);
|
||||
}
|
||||
|
@ -96,6 +103,11 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){
|
|||
int i;
|
||||
igraph_vector_ptr_t vertex_attr;
|
||||
|
||||
igraph_i_attribute_record_t v_attr_rec;
|
||||
v_attr_rec.name = "__RUBY__";
|
||||
v_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
v_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
igraph_vector_ptr_init(&vertex_attr,0);
|
||||
|
||||
Data_Get_Struct(self, igraph_t, graph);
|
||||
|
@ -111,10 +123,12 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){
|
|||
//rb_raise(cIGraphError, "Vertex already added to graph");
|
||||
to_add--;
|
||||
} else {
|
||||
igraph_vector_ptr_push_back(&vertex_attr,(void*)RARRAY(vs)->ptr[i]);
|
||||
rb_ary_push((VALUE)v_attr_rec.value,RARRAY(vs)->ptr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
igraph_vector_ptr_push_back(&vertex_attr,&v_attr_rec);
|
||||
|
||||
code = igraph_add_vertices(graph,to_add,&vertex_attr);
|
||||
|
||||
return INT2NUM(code);
|
||||
|
@ -150,6 +164,11 @@ VALUE cIGraph_add_edge(int argc, VALUE *argv, VALUE self){
|
|||
VALUE to;
|
||||
VALUE attr;
|
||||
|
||||
igraph_i_attribute_record_t e_attr_rec;
|
||||
e_attr_rec.name = "__RUBY__";
|
||||
e_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
e_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
rb_scan_args(argc, argv, "21", &from, &to, &attr);
|
||||
|
||||
//Initialize edge vector
|
||||
|
@ -164,11 +183,13 @@ VALUE cIGraph_add_edge(int argc, VALUE *argv, VALUE self){
|
|||
//If graph includes this vertex then look up the vertex number
|
||||
igraph_vector_push_back(&edge_v,cIGraph_get_vertex_id(self, from));
|
||||
igraph_vector_push_back(&edge_v,cIGraph_get_vertex_id(self, to));
|
||||
igraph_vector_ptr_push_back(&edge_attr,(void*)attr);
|
||||
rb_ary_push((VALUE)e_attr_rec.value,attr);
|
||||
} else {
|
||||
rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices");
|
||||
}
|
||||
|
||||
igraph_vector_ptr_push_back(&edge_attr,&e_attr_rec);
|
||||
|
||||
code = igraph_add_edges(graph,&edge_v,&edge_attr);
|
||||
|
||||
igraph_vector_ptr_destroy(&edge_attr);
|
||||
|
@ -203,6 +224,11 @@ VALUE cIGraph_add_vertex(VALUE self, VALUE v){
|
|||
|
||||
VALUE v_ary;
|
||||
|
||||
igraph_i_attribute_record_t v_attr_rec;
|
||||
v_attr_rec.name = "__RUBY__";
|
||||
v_attr_rec.type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
v_attr_rec.value = (void*)rb_ary_new();
|
||||
|
||||
igraph_vector_ptr_init(&vertex_attr,0);
|
||||
|
||||
Data_Get_Struct(self, igraph_t, graph);
|
||||
|
@ -214,9 +240,11 @@ VALUE cIGraph_add_vertex(VALUE self, VALUE v){
|
|||
//rb_raise(cIGraphError, "Vertex already added to graph");
|
||||
return code;
|
||||
} else {
|
||||
igraph_vector_ptr_push_back(&vertex_attr,(void*)v);
|
||||
rb_ary_push((VALUE)v_attr_rec.value,v);
|
||||
}
|
||||
|
||||
igraph_vector_ptr_push_back(&vertex_attr,&v_attr_rec);
|
||||
|
||||
code = igraph_add_vertices(graph,1,&vertex_attr);
|
||||
|
||||
return INT2NUM(code);
|
||||
|
|
|
@ -44,6 +44,18 @@ VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr){
|
|||
|
||||
}
|
||||
|
||||
VALUE cIGraph_graph_attributes(VALUE self){
|
||||
|
||||
igraph_t *graph;
|
||||
VALUE hsh;
|
||||
|
||||
Data_Get_Struct(self, igraph_t, graph);
|
||||
hsh = ((VALUE*)graph->attr)[2];
|
||||
|
||||
return hsh;
|
||||
|
||||
}
|
||||
|
||||
igraph_attribute_table_t cIGraph_attribute_table = {
|
||||
cIGraph_attribute_init,
|
||||
cIGraph_attribute_destroy,
|
||||
|
@ -67,16 +79,44 @@ igraph_attribute_table_t cIGraph_attribute_table = {
|
|||
int cIGraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) {
|
||||
|
||||
VALUE* attrs;
|
||||
int i;
|
||||
VALUE key;
|
||||
VALUE value;
|
||||
|
||||
//attrs = (VALUE*)calloc(2, sizeof(VALUE));
|
||||
attrs = ALLOC_N(VALUE, 2);
|
||||
attrs = ALLOC_N(VALUE, 3);
|
||||
|
||||
if(!attrs)
|
||||
IGRAPH_ERROR("Error allocating Arrays\n", IGRAPH_ENOMEM);
|
||||
|
||||
//[0] is vertex array, [1] is edge array
|
||||
//[0] is vertex array, [1] is edge array, [2] is graph attr
|
||||
attrs[0] = rb_ary_new();
|
||||
attrs[1] = rb_ary_new();
|
||||
attrs[2] = rb_hash_new();
|
||||
|
||||
if(attr){
|
||||
for(i=0;i<igraph_vector_ptr_size(attr);i++){
|
||||
igraph_i_attribute_record_t *attr_rec;
|
||||
char *s;
|
||||
attr_rec = VECTOR(*attr)[i];
|
||||
key = rb_str_new2(attr_rec->name);
|
||||
switch (attr_rec->type) {
|
||||
case IGRAPH_ATTRIBUTE_NUMERIC:
|
||||
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]);
|
||||
break;
|
||||
case IGRAPH_ATTRIBUTE_STRING:
|
||||
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s);
|
||||
value=rb_str_new2(s);
|
||||
break;
|
||||
default:
|
||||
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
||||
value=0;
|
||||
break;
|
||||
}
|
||||
if (value){
|
||||
rb_hash_aset((VALUE)attrs[2],key,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graph->attr = attrs;
|
||||
|
||||
|
@ -90,34 +130,101 @@ void cIGraph_attribute_destroy(igraph_t *graph) {
|
|||
}
|
||||
|
||||
/* Copying */
|
||||
|
||||
int replace_i(VALUE key, VALUE val, VALUE hash){
|
||||
if (key != Qundef) {
|
||||
rb_hash_aset(hash, key, val);
|
||||
}
|
||||
|
||||
//return ST_CONTINUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cIGraph_attribute_copy(igraph_t *to, const igraph_t *from) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_copy\n");
|
||||
#endif
|
||||
|
||||
VALUE* attrs;
|
||||
VALUE vertex_array = ((VALUE*)from->attr)[0];
|
||||
VALUE edge_array = ((VALUE*)from->attr)[1];
|
||||
VALUE graph_attr = ((VALUE*)from->attr)[2];
|
||||
|
||||
//VALUE* attrs = (VALUE*)calloc(2, sizeof(VALUE));
|
||||
attrs = ALLOC_N(VALUE, 2);
|
||||
attrs = ALLOC_N(VALUE, 3);
|
||||
|
||||
attrs[0] = rb_ary_dup(vertex_array);
|
||||
attrs[1] = rb_ary_dup(edge_array);
|
||||
attrs[2] = rb_hash_new();
|
||||
|
||||
rb_hash_foreach(graph_attr, replace_i, attrs[2]);
|
||||
|
||||
to->attr = attrs;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_copy\n");
|
||||
#endif
|
||||
|
||||
return IGRAPH_SUCCESS;
|
||||
}
|
||||
|
||||
/* Adding vertices */
|
||||
int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr) {
|
||||
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_add_vertices\n");
|
||||
#endif
|
||||
|
||||
int i,j;
|
||||
VALUE vertex_array = ((VALUE*)graph->attr)[0];
|
||||
VALUE values;
|
||||
|
||||
if(attr){
|
||||
for(i=0;i<nv;i++){
|
||||
rb_ary_push(vertex_array,(VALUE)VECTOR(*attr)[i]);
|
||||
if(((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
|
||||
|
||||
values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
|
||||
Check_Type(values, T_ARRAY);
|
||||
for(i=0;i<RARRAY(values)->len;i++){
|
||||
rb_ary_push(vertex_array, RARRAY(values)->ptr[i]);
|
||||
}
|
||||
//Otherwise read each attriute into hashes and use those
|
||||
} else {
|
||||
for(i=0;i<nv;i++){
|
||||
|
||||
VALUE record;
|
||||
igraph_i_attribute_record_t *attr_rec;
|
||||
char *s;
|
||||
record = rb_hash_new();
|
||||
for (j=0; j<igraph_vector_ptr_size(attr); j++) {
|
||||
VALUE key;
|
||||
VALUE value;
|
||||
//Add key value pair
|
||||
attr_rec = VECTOR(*attr)[j];
|
||||
key = rb_str_new2(attr_rec->name);
|
||||
switch (attr_rec->type) {
|
||||
case IGRAPH_ATTRIBUTE_NUMERIC:
|
||||
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
|
||||
break;
|
||||
case IGRAPH_ATTRIBUTE_STRING:
|
||||
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
|
||||
value=rb_str_new2(s);
|
||||
break;
|
||||
default:
|
||||
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
||||
value=Qnil;
|
||||
break;
|
||||
}
|
||||
rb_hash_aset(record,key,value);
|
||||
}
|
||||
rb_ary_push(vertex_array,record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_add_vertices\n");
|
||||
#endif
|
||||
|
||||
return IGRAPH_SUCCESS;
|
||||
}
|
||||
|
@ -127,6 +234,10 @@ void cIGraph_attribute_delete_vertices(igraph_t *graph,
|
|||
const igraph_vector_t *eidx,
|
||||
const igraph_vector_t *vidx) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_delete_vertices\n");
|
||||
#endif
|
||||
|
||||
int i;
|
||||
VALUE vertex_array = ((VALUE*)graph->attr)[0];
|
||||
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
||||
|
@ -146,6 +257,10 @@ void cIGraph_attribute_delete_vertices(igraph_t *graph,
|
|||
((VALUE*)graph->attr)[0] = n_v_ary;
|
||||
((VALUE*)graph->attr)[1] = n_e_ary;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_delete_vertices\n");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -154,21 +269,69 @@ int cIGraph_attribute_add_edges(igraph_t *graph,
|
|||
const igraph_vector_t *edges,
|
||||
igraph_vector_ptr_t *attr) {
|
||||
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_add_edges\n");
|
||||
#endif
|
||||
|
||||
int i,j;
|
||||
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
||||
VALUE values;
|
||||
|
||||
if(attr){
|
||||
for(i=0;i<igraph_vector_size(edges)/2;i++){
|
||||
rb_ary_push(edge_array,(VALUE)VECTOR(*attr)[i]);
|
||||
//If the only record is of type PY_OBJ then use the values as attributes
|
||||
if(((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
|
||||
values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
|
||||
Check_Type(values, T_ARRAY);
|
||||
for(i=0;i<RARRAY(values)->len;i++){
|
||||
rb_ary_push(edge_array, RARRAY(values)->ptr[i]);
|
||||
}
|
||||
//Otherwise read each attriute into hashes and use those
|
||||
} else {
|
||||
for(i=0;i<igraph_vector_size(edges)/2;i++){
|
||||
VALUE record;
|
||||
igraph_i_attribute_record_t *attr_rec;
|
||||
char *s;
|
||||
record = rb_hash_new();
|
||||
for (j=0; j<igraph_vector_ptr_size(attr); j++) {
|
||||
VALUE key;
|
||||
VALUE value;
|
||||
//Add key value pair
|
||||
attr_rec = VECTOR(*attr)[j];
|
||||
key = rb_str_new2(attr_rec->name);
|
||||
switch (attr_rec->type) {
|
||||
case IGRAPH_ATTRIBUTE_NUMERIC:
|
||||
value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
|
||||
break;
|
||||
case IGRAPH_ATTRIBUTE_STRING:
|
||||
igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
|
||||
value=rb_str_new2(s);
|
||||
break;
|
||||
default:
|
||||
IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
|
||||
value=Qnil;
|
||||
break;
|
||||
}
|
||||
rb_hash_aset(record,key,value);
|
||||
}
|
||||
rb_ary_push(edge_array,record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_add_edges\n");
|
||||
#endif
|
||||
|
||||
return IGRAPH_SUCCESS;
|
||||
}
|
||||
|
||||
/* Deleting edges */
|
||||
void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_delete_edges\n");
|
||||
#endif
|
||||
|
||||
int i;
|
||||
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
||||
VALUE n_e_ary = rb_ary_new();
|
||||
|
@ -179,6 +342,10 @@ void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx)
|
|||
}
|
||||
|
||||
((VALUE*)graph->attr)[1] = n_e_ary;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_delete_edges\n");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -187,6 +354,10 @@ void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx)
|
|||
int cIGraph_attribute_permute_edges(igraph_t *graph,
|
||||
const igraph_vector_t *idx) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_permute_edges\n");
|
||||
#endif
|
||||
|
||||
int i;
|
||||
VALUE edge_array = ((VALUE*)graph->attr)[1];
|
||||
VALUE n_e_ary = rb_ary_new();
|
||||
|
@ -196,45 +367,218 @@ int cIGraph_attribute_permute_edges(igraph_t *graph,
|
|||
}
|
||||
|
||||
((VALUE*)graph->attr)[1] = n_e_ary;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_permute_edges\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE keys_to_strvec(VALUE data, VALUE arr){
|
||||
|
||||
VALUE key = rb_ary_entry(data, 0);
|
||||
VALUE val = rb_ary_entry(data, 1);
|
||||
|
||||
VALUE rb_names = rb_ary_entry(arr, 0);
|
||||
VALUE rb_types = rb_ary_entry(arr, 1);
|
||||
|
||||
VALUE str = StringValue(key);
|
||||
|
||||
rb_ary_push(rb_names,str);
|
||||
|
||||
if(TYPE(val) == T_STRING){
|
||||
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_STRING));
|
||||
} else if (TYPE(val) == T_FLOAT || TYPE(val) == T_FIXNUM){
|
||||
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_NUMERIC));
|
||||
} else {
|
||||
rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_PY_OBJECT));
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/* Getting attribute names and types */
|
||||
int cIGraph_attribute_get_info(const igraph_t *graph,
|
||||
igraph_strvector_t *gnames,
|
||||
igraph_vector_t *gtypes,
|
||||
igraph_strvector_t *vnames,
|
||||
igraph_vector_t *vtypes,
|
||||
igraph_strvector_t *enames,
|
||||
igraph_vector_t *etypes) {
|
||||
igraph_strvector_t *gnames,
|
||||
igraph_vector_t *gtypes,
|
||||
igraph_strvector_t *vnames,
|
||||
igraph_vector_t *vtypes,
|
||||
igraph_strvector_t *enames,
|
||||
igraph_vector_t *etypes) {
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_get_info\n");
|
||||
#endif
|
||||
|
||||
igraph_strvector_t *names[3] = { vnames, enames, gnames };
|
||||
igraph_vector_t *types[3] = { vtypes, etypes, gtypes };
|
||||
|
||||
long int i,j;
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
|
||||
igraph_strvector_t *n = names[i];
|
||||
igraph_vector_t *t = types[i];
|
||||
|
||||
VALUE rb_names = rb_ary_new();
|
||||
VALUE rb_types = rb_ary_new();
|
||||
|
||||
VALUE obj_hash;
|
||||
|
||||
//Graph attributes are different
|
||||
if (i != 2){
|
||||
|
||||
VALUE store = ((VALUE*)graph->attr)[i];
|
||||
VALUE obj = RARRAY(store)->ptr[0];
|
||||
|
||||
obj_hash = Qnil;
|
||||
if(rb_funcall(obj, rb_intern("respond_to?"), 1, rb_str_new2("to_hash")) == Qtrue){
|
||||
obj_hash = rb_funcall(obj, rb_intern("to_hash"), 0);
|
||||
}
|
||||
} else {
|
||||
obj_hash = ((VALUE*)graph->attr)[2];
|
||||
}
|
||||
|
||||
if(!NIL_P(obj_hash)){
|
||||
//Take the keys of the hash, convert to strings and put in vector n
|
||||
rb_iterate(rb_each, obj_hash, keys_to_strvec, rb_ary_new3(2,rb_names,rb_types));
|
||||
}
|
||||
|
||||
//Push names onto n and types onto t
|
||||
for(j=0;j<RARRAY(rb_names)->len;j++){
|
||||
igraph_strvector_add(n, RSTRING(RARRAY(rb_names)->ptr[j])->ptr);
|
||||
igraph_vector_push_back(t, NUM2INT(RARRAY(rb_types)->ptr[j]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_get_info\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Checks whether the graph has a graph/vertex/edge attribute with the given name */
|
||||
igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph,
|
||||
igraph_attribute_elemtype_t type,
|
||||
const char* name) {
|
||||
return 0;
|
||||
igraph_attribute_elemtype_t type,
|
||||
const char* name) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_has_attr\n");
|
||||
#endif
|
||||
|
||||
long int attrnum;
|
||||
igraph_bool_t res = 0;
|
||||
VALUE obj;
|
||||
|
||||
switch (type) {
|
||||
case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
|
||||
case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
|
||||
case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
|
||||
default: return 0; break;
|
||||
}
|
||||
|
||||
obj = ((VALUE*)graph->attr)[attrnum];
|
||||
if (attrnum != 2)
|
||||
obj = RARRAY(obj)->ptr[0];
|
||||
|
||||
if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){
|
||||
res = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_has_attr\n");
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Returns the type of a given attribute */
|
||||
int cIGraph_attribute_get_type(const igraph_t *graph,
|
||||
igraph_attribute_type_t *type,
|
||||
igraph_attribute_elemtype_t elemtype,
|
||||
const char *name) {
|
||||
igraph_attribute_type_t *type,
|
||||
igraph_attribute_elemtype_t elemtype,
|
||||
const char *name) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_attribute_get_type\n");
|
||||
#endif
|
||||
|
||||
long int attrnum;
|
||||
VALUE obj;
|
||||
VALUE val;
|
||||
|
||||
switch (elemtype) {
|
||||
case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break;
|
||||
case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break;
|
||||
case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break;
|
||||
default: return 0; break;
|
||||
}
|
||||
|
||||
obj = ((VALUE*)graph->attr)[attrnum];
|
||||
if (attrnum != 2)
|
||||
obj = RARRAY(obj)->ptr[0];
|
||||
|
||||
if(rb_funcall(obj,rb_intern("includes"), rb_str_new2(name))){
|
||||
val = rb_hash_aref(obj,rb_str_new2(name));
|
||||
if (TYPE(val) == T_STRING){
|
||||
*type = IGRAPH_ATTRIBUTE_STRING;
|
||||
} else if (TYPE(val) == T_FIXNUM || TYPE(val) == T_FLOAT){
|
||||
*type = IGRAPH_ATTRIBUTE_NUMERIC;
|
||||
} else {
|
||||
*type = IGRAPH_ATTRIBUTE_PY_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_attribute_get_type\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Getting numeric graph attributes */
|
||||
int cIGraph_get_numeric_graph_attr(const igraph_t *graph,
|
||||
const char *name, igraph_vector_t *value) {
|
||||
const char *name, igraph_vector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_numeric_graph_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE val;
|
||||
|
||||
val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
|
||||
VECTOR(*value)[0] = NUM2DBL(val);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_numeric_graph_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Getting string graph attributes */
|
||||
int cIGraph_get_string_graph_attr(const igraph_t *graph,
|
||||
const char *name, igraph_strvector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_string_graph_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE val;
|
||||
|
||||
val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
|
||||
igraph_strvector_set(value,0,RSTRING(val)->ptr);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_string_graph_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -243,6 +587,39 @@ int cIGraph_get_numeric_vertex_attr(const igraph_t *graph,
|
|||
const char *name,
|
||||
igraph_vs_t vs,
|
||||
igraph_vector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_numeric_vertex_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE array = ((VALUE*)graph->attr)[0];
|
||||
VALUE val, vertex;
|
||||
igraph_vit_t it;
|
||||
int i = 0;
|
||||
|
||||
IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
|
||||
IGRAPH_FINALLY(igraph_vit_destroy, &it);
|
||||
IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_VIT_SIZE(it)));
|
||||
|
||||
while(!IGRAPH_VIT_END(it)){
|
||||
vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
|
||||
val = rb_hash_aref(vertex,rb_str_new2(name));
|
||||
|
||||
if(val == Qnil)
|
||||
val = rb_float_new(NAN);
|
||||
|
||||
VECTOR(*value)[i] = NUM2DBL(val);
|
||||
IGRAPH_VIT_NEXT(it);
|
||||
i++;
|
||||
}
|
||||
|
||||
igraph_vit_destroy(&it);
|
||||
IGRAPH_FINALLY_CLEAN(1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_numeric_vertex_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -251,6 +628,39 @@ int cIGraph_get_string_vertex_attr(const igraph_t *graph,
|
|||
const char *name,
|
||||
igraph_vs_t vs,
|
||||
igraph_strvector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_string_vertex_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE array = ((VALUE*)graph->attr)[0];
|
||||
VALUE val, vertex;
|
||||
igraph_vit_t it;
|
||||
int i=0;
|
||||
|
||||
IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
|
||||
IGRAPH_FINALLY(igraph_vit_destroy, &it);
|
||||
IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_VIT_SIZE(it)));
|
||||
|
||||
while(!IGRAPH_VIT_END(it)){
|
||||
vertex = RARRAY(array)->ptr[(int)IGRAPH_VIT_GET(it)];
|
||||
val = rb_hash_aref(vertex,rb_str_new2(name));
|
||||
|
||||
if(val == Qnil)
|
||||
val = rb_str_new2("");
|
||||
|
||||
igraph_strvector_set(value,i,RSTRING(val)->ptr);
|
||||
IGRAPH_VIT_NEXT(it);
|
||||
i++;
|
||||
}
|
||||
|
||||
igraph_vit_destroy(&it);
|
||||
IGRAPH_FINALLY_CLEAN(1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_string_vertex_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -259,6 +669,39 @@ int cIGraph_get_numeric_edge_attr(const igraph_t *graph,
|
|||
const char *name,
|
||||
igraph_es_t es,
|
||||
igraph_vector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_numeric_edge_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE array = ((VALUE*)graph->attr)[1];
|
||||
VALUE val, vertex;
|
||||
igraph_eit_t it;
|
||||
int i = 0;
|
||||
|
||||
IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
|
||||
IGRAPH_FINALLY(igraph_eit_destroy, &it);
|
||||
IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_EIT_SIZE(it)));
|
||||
|
||||
while(!IGRAPH_EIT_END(it)){
|
||||
vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
|
||||
val = rb_hash_aref(vertex,rb_str_new2(name));
|
||||
|
||||
if(val == Qnil)
|
||||
val = rb_float_new(NAN);
|
||||
|
||||
VECTOR(*value)[i] = NUM2DBL(val);
|
||||
IGRAPH_EIT_NEXT(it);
|
||||
i++;
|
||||
}
|
||||
|
||||
igraph_eit_destroy(&it);
|
||||
IGRAPH_FINALLY_CLEAN(1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_numeric_edge_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -267,5 +710,36 @@ int cIGraph_get_string_edge_attr(const igraph_t *graph,
|
|||
const char *name,
|
||||
igraph_es_t es,
|
||||
igraph_strvector_t *value) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Entering cIGraph_get_string_edge_attr\n");
|
||||
#endif
|
||||
|
||||
VALUE array = ((VALUE*)graph->attr)[1];
|
||||
VALUE val, vertex;
|
||||
igraph_eit_t it;
|
||||
int i=0;
|
||||
|
||||
IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
|
||||
IGRAPH_FINALLY(igraph_eit_destroy, &it);
|
||||
IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it)));
|
||||
|
||||
while(!IGRAPH_EIT_END(it)){
|
||||
vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)];
|
||||
val = rb_hash_aref(vertex,rb_str_new2(name));
|
||||
if(val == Qnil)
|
||||
val = rb_str_new2("");
|
||||
igraph_strvector_set(value,i,RSTRING(val)->ptr);
|
||||
IGRAPH_EIT_NEXT(it);
|
||||
i++;
|
||||
}
|
||||
|
||||
igraph_eit_destroy(&it);
|
||||
IGRAPH_FINALLY_CLEAN(1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Leaving cIGraph_get_string_edge_attr\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,4 +21,9 @@ class TestGraph < Test::Unit::TestCase
|
|||
graph.add_edge('A','D',4)
|
||||
assert_equal 4, graph['A','D']
|
||||
end
|
||||
def test_graph_attr
|
||||
graph = IGraph.new(['A','B','C','D'],true,[1,2])
|
||||
graph.attributes['test'] = 1
|
||||
assert_equal 1, graph.attributes['test']
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,8 @@ require 'tc_basic_properties'
|
|||
require 'tc_copy'
|
||||
require 'tc_error_handling'
|
||||
require 'tc_file_read_write'
|
||||
require 'tc_layout'
|
||||
require 'tc_matrix'
|
||||
require 'tc_shortest_paths'
|
||||
require 'tc_topological_sort'
|
||||
require 'tc_vertex_neighbourhood'
|
||||
|
|
Loading…
Reference in New Issue