From 9e7c53c386c455dfb5ddcb50cd0f14f01d86756d Mon Sep 17 00:00:00 2001 From: alexgutteridge Date: Thu, 12 Jul 2007 08:11:36 +0000 Subject: [PATCH] --- README.txt | 18 +-- ext/cIGraph.c | 52 ++++++-- ext/cIGraph.h | 24 +++- ext/cIGraph_add_delete.c | 39 ++++-- ext/cIGraph_attribute_handler.c | 47 +++++++ ext/cIGraph_shortest_paths.c | 198 ++++++++++++++++++++++++++++- ext/cIGraph_utility.c | 6 +- ext/cIGraph_vertex_neighbourhood.c | 155 ++++++++++++++++++++++ test/tc_attributes.rb | 24 ++++ test/tc_shortest_paths.rb | 23 ++++ test/tc_vertex_neighbourhood.rb | 16 +++ test/test_all.rb | 2 + 12 files changed, 564 insertions(+), 40 deletions(-) create mode 100644 ext/cIGraph_attribute_handler.c create mode 100644 ext/cIGraph_vertex_neighbourhood.c create mode 100644 test/tc_attributes.rb create mode 100644 test/tc_vertex_neighbourhood.rb diff --git a/README.txt b/README.txt index be0d70c..31ccab4 100644 --- a/README.txt +++ b/README.txt @@ -1,24 +1,18 @@ == Introduction -IGraph +IGraph is a Ruby extension for using the igraph library ([http://cneurocvs.rmki.kfki.hu/igraph/]). igraph is a library for creating and manipulating graphs with a particular emphasis on network analysis functions. -IGraph +IGraph is currently pre-alpha status and should be considered unstable. There are functions for building and querying simple graphs as well as shortest path calculations. -IGraph +All bug reports, feature request and patches are welcome. == Installation A working igraph library installation is required. -An IGraph gem is available as well as a package using setup.rb. In each case the installation requires the location of your igraph library to compile the extension. If you download the setup.rb package use these incantations: +An IGraph gem is available. The installation requires the location of your igraph headers and library to compile the extension. E.g. under Ubuntu linux: - ruby setup.rb config -- --with-igraph-dir=$R_HOME - ruby setup.rb setup - ruby setup.rb install - -Using gems it is almost the same: - - gem install igraph -- --with-igraph-dir=$R_HOME + gem install igraph -- --with-igraph-include=/usr/local/include/igraph == Documentation @@ -27,6 +21,8 @@ Here is a very quick and simple example: require 'igraph' graph = IGraph.new([],true) + graph.add_edges([1,2,3,4]) + graph.vcount # returns 4 == License diff --git a/ext/cIGraph.c b/ext/cIGraph.c index cd3599a..9f39b5f 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -38,23 +38,32 @@ VALUE cIGraph_alloc(VALUE klass){ * Vertex 3 is connected to vertex 4. */ -VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ +VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){ igraph_t *graph; igraph_vector_t edge_v; VALUE vertex; VALUE object_h; VALUE id_h; + VALUE directed; + VALUE edges; + VALUE attrs; int vertex_n = 0; int current_vertex_id; + int i; + + rb_scan_args(argc,argv,"12", &edges, &directed, &attrs); igraph_set_error_handler(cIGraph_error_handler); igraph_set_warning_handler(cIGraph_warning_handler); + //igraph_i_set_attribute_table(&cIGraph_attribute_table); //New hash for mapping vertex objects to floats used by iGraph object_h = rb_iv_set(self,"@object_ids",rb_hash_new()); id_h = rb_iv_set(self,"@id_objects",rb_hash_new()); + rb_iv_set(self,"@edge_attrs",rb_hash_new()); + //Initialize edge vector igraph_vector_init_int(&edge_v,0); @@ -63,8 +72,8 @@ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ igraph_to_undirected(graph,IGRAPH_TO_UNDIRECTED_COLLAPSE); //Loop through objects in edge Array - vertex = rb_ary_shift(edges); - while(vertex != Qnil){ + for (i=0; ilen; i++) { + vertex = RARRAY(edges)->ptr[i]; if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ //If @vertices includes this vertex then look up the vertex number current_vertex_id = NUM2INT(rb_hash_aref(object_h,vertex)); @@ -76,7 +85,6 @@ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ vertex_n++; } igraph_vector_push_back(&edge_v,current_vertex_id); - vertex = rb_ary_shift(edges); } if(igraph_vector_size(&edge_v) > 0){ @@ -84,6 +92,15 @@ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ igraph_add_edges(graph,&edge_v,0); } + if(attrs != Qnil){ + for (i=0; ilen; i++) { + cIGraph_set_edge_attr(self, + RARRAY(edges)->ptr[i*2], + RARRAY(edges)->ptr[(i*2)+1], + RARRAY(attrs)->ptr[i]); + } + } + igraph_vector_destroy(&edge_v); return self; @@ -100,7 +117,12 @@ void Init_igraph(){ cIGraphError = rb_define_class("IGraphError", rb_eRuntimeError); rb_define_alloc_func(cIGraph, cIGraph_alloc); - rb_define_method(cIGraph, "initialize", cIGraph_initialize, 2); + rb_define_method(cIGraph, "initialize", cIGraph_initialize, -1); + + rb_define_method(cIGraph, "[]", cIGraph_get_edge_attr, 2); + rb_define_method(cIGraph, "[]=", cIGraph_set_edge_attr, 3); + rb_define_method(cIGraph, "get_edge_attr", cIGraph_get_edge_attr, 2); + rb_define_method(cIGraph, "set_edge_attr", cIGraph_set_edge_attr, 3); 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 */ @@ -145,16 +167,26 @@ void Init_igraph(){ rb_define_method(cIGraph, "degree", cIGraph_degree,3); /* in cIGraph_basic_query.c */ - rb_define_method(cIGraph, "add_edges", cIGraph_add_edges, 1); /* in cIGraph_add_delete.c */ + rb_define_method(cIGraph, "add_edges", cIGraph_add_edges, -1); /* in cIGraph_add_delete.c */ rb_define_method(cIGraph, "add_vertices", cIGraph_add_vertices, 1); /* in cIGraph_add_delete.c */ - rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, 2); /* in cIGraph_add_delete.c */ + rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, -1); /* in cIGraph_add_delete.c */ rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); /* in cIGraph_add_delete.c */ rb_define_method(cIGraph, "are_connected", cIGraph_are_connected,2); rb_define_method(cIGraph, "are_connected?", cIGraph_are_connected,2); /* in cIGraph_basic_properties.c */ - rb_define_method(cIGraph, "shortest_paths", cIGraph_shortest_paths,2); - rb_define_method(cIGraph, "get_shortest_paths", cIGraph_get_shortest_paths,3); + rb_define_method(cIGraph, "shortest_paths", cIGraph_shortest_paths,2); /* in cIGraph_shortest_paths.c */ + rb_define_method(cIGraph, "get_shortest_paths", cIGraph_get_shortest_paths,3); /* in cIGraph_shortest_paths.c */ + rb_define_method(cIGraph, "get_all_shortest_paths", cIGraph_get_all_shortest_paths,3); /* in cIGraph_shortest_paths.c */ + rb_define_method(cIGraph, "average_path_length", cIGraph_average_path_length,2); /* in cIGraph_shortest_paths.c */ + rb_define_method(cIGraph, "diameter", cIGraph_diameter,2); /* in cIGraph_shortest_paths.c */ + rb_define_method(cIGraph, "girth", cIGraph_girth,0); /* in cIGraph_shortest_paths.c */ -} + + rb_define_method(cIGraph, "neighbourhood_size", cIGraph_neighborhood_size, 3); /* in cIGraph_vertex_neighbourhood.c */ + rb_define_method(cIGraph, "neighborhood_size", cIGraph_neighborhood_size, 3); + rb_define_method(cIGraph, "neighbourhood", cIGraph_neighborhood, 3); /* in cIGraph_vertex_neighbourhood.c */ + rb_define_method(cIGraph, "neighborhood", cIGraph_neighborhood, 3); + rb_define_method(cIGraph, "neighbourhood_graphs", cIGraph_neighborhood_graphs, 3); /* in cIGraph_vertex_neighbourhood.c */ + rb_define_method(cIGraph, "neighborhood_graphs", cIGraph_neighborhood_graphs, 3);} diff --git a/ext/cIGraph.h b/ext/cIGraph.h index 48e7f48..818f2c2 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -18,7 +18,11 @@ VALUE cIGraph_include(VALUE self, VALUE v); void Init_igraph(void); void cIGraph_free(void *p); VALUE cIGraph_alloc(VALUE klass); -VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed); +VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self); + +//Attribute accessors +VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to); +VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr); //Iterators VALUE cIGraph_each_vertex (VALUE self); @@ -45,16 +49,26 @@ VALUE cIGraph_is_directed(VALUE self); VALUE cIGraph_degree (VALUE self, VALUE v, VALUE mode, VALUE loops); //Adding and eleting vertices and edges -VALUE cIGraph_add_edges (VALUE self, VALUE edges); +VALUE cIGraph_add_edges (int argc, VALUE *argv, VALUE self); +VALUE cIGraph_add_edge (int argc, VALUE *argv, VALUE self); VALUE cIGraph_add_vertices (VALUE self, VALUE vs); VALUE cIGraph_delete_edges (VALUE self, VALUE edges); VALUE cIGraph_delete_vertices(VALUE self, VALUE vs); -VALUE cIGraph_add_edge (VALUE self, VALUE from, VALUE to); VALUE cIGraph_add_vertex (VALUE self, VALUE v); //Basic properties VALUE cIGraph_are_connected(VALUE self, VALUE from, VALUE to); //Shortest Path Related Functions -VALUE cIGraph_shortest_paths (VALUE self, VALUE from, VALUE mode); -VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode); +VALUE cIGraph_shortest_paths (VALUE self, VALUE from, VALUE mode); +VALUE cIGraph_get_shortest_paths (VALUE self, VALUE from, VALUE to, VALUE mode); +VALUE cIGraph_get_all_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode); +VALUE cIGraph_average_path_length (VALUE self, VALUE directed, VALUE unconn); +VALUE cIGraph_diameter (VALUE self, VALUE directed, VALUE unconn); +VALUE cIGraph_girth (VALUE self); + + +//Vertex neighbourhood functions +VALUE cIGraph_neighborhood_size (VALUE self, VALUE from, VALUE order, VALUE mode); +VALUE cIGraph_neighborhood (VALUE self, VALUE from, VALUE order, VALUE mode); +VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mode); diff --git a/ext/cIGraph_add_delete.c b/ext/cIGraph_add_delete.c index fe09b51..526d441 100644 --- a/ext/cIGraph_add_delete.c +++ b/ext/cIGraph_add_delete.c @@ -19,14 +19,19 @@ * must have already been added to the graph before they can be used in * an edge (throws a IGraphError otherwise). */ -VALUE cIGraph_add_edges(VALUE self, VALUE edges){ +VALUE cIGraph_add_edges(int argc, VALUE *argv, VALUE self){ igraph_t *graph; igraph_vector_t edge_v; VALUE vertex; VALUE object_h; + VALUE edges; + VALUE attrs; int vid; int code = 0; + int i; + + rb_scan_args(argc, argv, "11", &edges, &attrs); //Initialize edge vector igraph_vector_init_int(&edge_v,0); @@ -35,8 +40,8 @@ VALUE cIGraph_add_edges(VALUE self, VALUE edges){ Data_Get_Struct(self, igraph_t, graph); //Loop through objects in edge Array - vertex = rb_ary_shift(edges); - while(vertex != Qnil){ + for (i=0; ilen; i++) { + vertex = RARRAY(edges)->ptr[i]; if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ //If @vertices includes this vertex then look up the vertex number vid = NUM2INT(rb_hash_aref(object_h,vertex)); @@ -44,13 +49,21 @@ VALUE cIGraph_add_edges(VALUE self, VALUE edges){ rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first"); } igraph_vector_push_back(&edge_v,vid); - vertex = rb_ary_shift(edges); } if(igraph_vector_size(&edge_v) > 0){ code = igraph_add_edges(graph,&edge_v,0); } + if(attrs != Qnil){ + for (i=0; ilen; i++) { + cIGraph_set_edge_attr(self, + RARRAY(edges)->ptr[i*2], + RARRAY(edges)->ptr[(i*2)+1], + RARRAY(attrs)->ptr[i]); + } + } + igraph_vector_destroy(&edge_v); return INT2NUM(code); @@ -81,6 +94,7 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ int vertex_n; int code = 0; int length; + int i; object_h = rb_iv_get(self,"@object_ids"); id_h = rb_iv_get(self,"@id_objects"); @@ -90,8 +104,8 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ Data_Get_Struct(self, igraph_t, graph); //Loop through objects in vertex array - vertex = rb_ary_shift(vs); - while(vertex != Qnil){ + for (i=0; ilen; i++) { + vertex = RARRAY(vs)->ptr[i]; if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ //If @vertices includes this vertex then raise an error //Silently ignore @@ -103,7 +117,6 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ rb_hash_aset(id_h, INT2NUM(vertex_n),vertex); vertex_n++; } - vertex = rb_ary_shift(vs); } code = igraph_add_vertices(graph,length,0); @@ -127,13 +140,18 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ * Note that vertices must have already been added to the graph before * they can be used in an edge (throws a IGraphError otherwise). */ -VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ +VALUE cIGraph_add_edge(int argc, VALUE *argv, VALUE self){ igraph_t *graph; igraph_vector_t edge_v; VALUE object_h; int vid; int code = 0; + VALUE from; + VALUE to; + VALUE attr; + + rb_scan_args(argc, argv, "21", &from, &to, &attr); //Initialize edge vector igraph_vector_init_int(&edge_v,0); @@ -159,6 +177,10 @@ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ code = igraph_add_edges(graph,&edge_v,0); + if(attr != Qnil){ + cIGraph_set_edge_attr(self, from, to, attr); + } + igraph_vector_destroy(&edge_v); return INT2NUM(code); @@ -184,7 +206,6 @@ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ VALUE cIGraph_add_vertex(VALUE self, VALUE v){ igraph_t *graph; - VALUE vertex; VALUE object_h; VALUE id_h; int vertex_n; diff --git a/ext/cIGraph_attribute_handler.c b/ext/cIGraph_attribute_handler.c new file mode 100644 index 0000000..f688e22 --- /dev/null +++ b/ext/cIGraph_attribute_handler.c @@ -0,0 +1,47 @@ +#include "igraph.h" +#include "ruby.h" +#include "cIGraph.h" + +igraph_attribute_table_t cIGraph_attribute_table; + +int cIGraph_add_edges_attr(igraph_t *graph, const igraph_vector_t *edges, + igraph_vector_ptr_t *attr){ + return 0; +} + +int cIGraph_get_numeric_edge_attr(const igraph_t *graph, const char *name, + igraph_es_t es, + igraph_vector_t *value){ + return 0; +} +int cIGraph_get_string_edge_attr(const igraph_t *graph, const char *name, + igraph_es_t es, + igraph_strvector_t *value){ + return 0; +} + +VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to){ + + VALUE eid; + VALUE attr_hash; + + eid = cIGraph_get_eid(self, from, to, 1); + + attr_hash = rb_iv_get(self,"@edge_attrs"); + return rb_hash_aref(attr_hash,eid); + +} + +VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr){ + + VALUE eid; + VALUE attr_hash; + + eid = cIGraph_get_eid(self, from, to, 1); + + attr_hash = rb_iv_get(self,"@edge_attrs"); + rb_hash_aset(attr_hash,eid,attr); + + return Qnil; + +} diff --git a/ext/cIGraph_shortest_paths.c b/ext/cIGraph_shortest_paths.c index 709f7df..d673f83 100644 --- a/ext/cIGraph_shortest_paths.c +++ b/ext/cIGraph_shortest_paths.c @@ -2,6 +2,17 @@ #include "ruby.h" #include "cIGraph.h" +/* call-seq: + * graph.shortest_paths(varray,mode) -> Array + * + * Calculates the length of the shortest paths from each of the vertices in + * the varray Array to all of the other vertices in the graph. The result + * is returned as an Array of Array. Each top-level Array contains the results + * for a vertex in the varray Array. Each entry in the Array is the path length + * to another vertex in the graph in vertex order (the order the vertices were + * added to the graph. (This should probalby be changed to give a Hash of Hash + * to allow easier look up.) + */ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){ igraph_t *graph; @@ -49,6 +60,17 @@ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){ } +/* call-seq: + * graph.get_shortest_paths(from,to_array,mode) -> Array + * + * Calculates the paths from the vertex specified as from to each vertex in the + * to_array Array. Returns an Array of Arrays. Each top level Array represents + * a path and each entry in each Array is a vertex on the path. mode + * represents the type of shortest paths to be calculated: IGraph::OUT + * the outgoing paths are calculated. IGraph::IN the incoming paths are + * calculated. IGraph::ALL the directed graph is considered as an undirected + * one for the computation. + */ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ igraph_t *graph; @@ -70,7 +92,7 @@ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ Data_Get_Struct(self, igraph_t, graph); - n_paths = NUM2INT(rb_funcall(to,rb_intern("length"),0)); + n_paths = RARRAY(to)->len; //vector to hold the results of the calculations igraph_vector_ptr_init(&res,0); @@ -93,8 +115,8 @@ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ for(i=0; i Array + * + * Calculates the paths from the vertex specified as from to each vertex + * in the to_array Arrayevery other. Returns an Array of Arrays. Each top + * level Array represents a path and each entry in each Array is a vertex on + * the path. mode represents the type of shortest paths to be calculated: + * IGraph::OUT the outgoing paths are calculated. IGraph::IN the incoming + * paths are calculated. IGraph::ALL the directed graph is considered as an + * undirected one for the computation. In contrast to + * IGraph#get_shortest_paths all possible shortest paths are reported here. + */ +VALUE cIGraph_get_all_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ + + igraph_t *graph; + + igraph_integer_t from_vid; + igraph_neimode_t pmode = NUM2INT(mode); + + igraph_vs_t to_vids; + igraph_vector_t to_vidv; + + igraph_vector_ptr_t res; + igraph_vector_t *path_v; + + int i; + int j; + VALUE path; + VALUE matrix = rb_ary_new(); + + Data_Get_Struct(self, igraph_t, graph); + + //vector to hold the results of the calculations + igraph_vector_ptr_init(&res,0); + + //The id of the vertex from where we are counting + from_vid = cIGraph_get_vertex_id(self, from); + + //Convert an array of vertices to a vector of vertex ids + cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv); + //create vertex selector from the vecotr of ids + igraph_vs_vector(&to_vids,&to_vidv); + + igraph_get_all_shortest_paths(graph,&res,NULL,from_vid,to_vids,pmode); + + for(i=0; i< igraph_vector_ptr_size(&res); i++){ + path = rb_ary_new(); + rb_ary_push(matrix,path); + for(j=0; j Float + * + * Calculates the average geodesic length in a graph. directed should be a + * boolean specifying whether to consider directed paths. unconn is another + * boolean specifying what to do about unconnected graphs. If TRUE the + * average of the geodesics within the components will be returned, + * otherwise the number of vertices is used for the length of non-existing + * geodesics. (The rationale behind this is that this is always longer than + * the longest possible geodesic in a graph.) + */ +VALUE cIGraph_average_path_length(VALUE self, VALUE directed, VALUE unconn){ + + igraph_t *graph; + igraph_bool_t directed_b = 0; + igraph_bool_t unconn_b = 0; + igraph_real_t res; + + if(directed) + directed_b = 1; + if(unconn) + unconn_b = 1; + + Data_Get_Struct(self, igraph_t, graph); + + igraph_average_path_length(graph,&res,directed_b,unconn_b); + + return rb_float_new(res); + +} + +/* call-seq: + * graph.diameter(directed,uncon) -> Array + * + * Returns the longest path in the graph. directed should be a + * boolean specifying whether to consider directed paths. unconn is another + * boolean specifying what to do about unconnected graphs. If TRUE the + * average of the geodesics within the components will be returned, + * otherwise the number of vertices is used for the length of non-existing + * geodesics. (The rationale behind this is that this is always longer than + * the longest possible diamter in a graph.) + */ +VALUE cIGraph_diameter(VALUE self, VALUE directed, VALUE unconn){ + + igraph_t *graph; + igraph_bool_t directed_b = 0; + igraph_bool_t unconn_b = 0; + igraph_vector_t res; + int i; + VALUE path = rb_ary_new(); + + if(directed) + directed_b = 1; + if(unconn) + unconn_b = 1; + + Data_Get_Struct(self, igraph_t, graph); + + //vector to hold the results of the calculations + igraph_vector_init(&res,0); + + igraph_diameter(graph,NULL,NULL,NULL,&res,directed_b,unconn_b); + + for(i=0; i Array + * + * Returns the shortest cycle in the graph. directed should be a + * boolean specifying whether to consider directed paths. unconn is another + * boolean specifying what to do about unconnected graphs. If TRUE the + * average of the geodesics within the components will be returned, + * otherwise the number of vertices is used for the length of non-existing + * geodesics. (The rationale behind this is that this is always longer than + * the longest possible diamter in a graph.) + */ +VALUE cIGraph_girth(VALUE self){ + + igraph_t *graph; + igraph_vector_t res; + int i; + VALUE path = rb_ary_new(); + + Data_Get_Struct(self, igraph_t, graph); + + //vector to hold the results of the calculations + igraph_vector_init(&res,0); + + igraph_girth(graph,NULL,&res); + + for(i=0; ilen; i++) { + vertex = RARRAY(va)->ptr[i]; igraph_vector_push_back(nv,cIGraph_get_vertex_id(graph, vertex)); - vertex = rb_ary_shift(va); } return 0; diff --git a/ext/cIGraph_vertex_neighbourhood.c b/ext/cIGraph_vertex_neighbourhood.c new file mode 100644 index 0000000..d571c9d --- /dev/null +++ b/ext/cIGraph_vertex_neighbourhood.c @@ -0,0 +1,155 @@ +#include "igraph.h" +#include "ruby.h" +#include "cIGraph.h" + +/* call-seq: + * graph.neighbourhood_size(vertices,order,mode) -> Array + * + * Calculates the length of the shortest paths from each of the vertices in + * the varray Array to all of the other vertices in the graph. The result + * is returned as an Array of Array. Each top-level Array contains the results + * for a vertex in the varray Array. Each entry in the Array is the path length + * to another vertex in the graph in vertex order (the order the vertices were + * added to the graph. (This should probalby be changed to give a Hash of Hash + * to allow easier look up.) + */ +VALUE cIGraph_neighborhood_size(VALUE self, VALUE from, VALUE order, VALUE mode){ + + igraph_t *graph; + igraph_vs_t vids; + igraph_vector_t vidv; + igraph_neimode_t pmode = NUM2INT(mode); + igraph_vector_t res; + int i; + + VALUE sizes = rb_ary_new(); + + Data_Get_Struct(self, igraph_t, graph); + + igraph_vector_init(&res,0); + + //Convert an array of vertices to a vector of vertex ids + cIGraph_vertex_arr_to_id_vec(self,from,&vidv); + //create vertex selector from the vecotr of ids + igraph_vs_vector(&vids,&vidv); + + igraph_neighborhood_size(graph,&res,vids,NUM2INT(order),pmode); + + for(i=0; i Array + * + * Calculates the length of the shortest paths from each of the vertices in + * the varray Array to all of the other vertices in the graph. The result + * is returned as an Array of Array. Each top-level Array contains the results + * for a vertex in the varray Array. Each entry in the Array is the path length + * to another vertex in the graph in vertex order (the order the vertices were + * added to the graph. (This should probalby be changed to give a Hash of Hash + * to allow easier look up.) + */ +VALUE cIGraph_neighborhood(VALUE self, VALUE from, VALUE order, VALUE mode){ + + igraph_t *graph; + igraph_vs_t vids; + igraph_vector_t vidv; + igraph_neimode_t pmode = NUM2INT(mode); + igraph_vector_ptr_t res; + igraph_vector_t *path_v; + int i; + int j; + + VALUE matrix = rb_ary_new(); + VALUE neighbourhood; + + Data_Get_Struct(self, igraph_t, graph); + + igraph_vector_ptr_init(&res,0); + + //Convert an array of vertices to a vector of vertex ids + cIGraph_vertex_arr_to_id_vec(self,from,&vidv); + //create vertex selector from the vecotr of ids + igraph_vs_vector(&vids,&vidv); + + igraph_neighborhood(graph,&res,vids,NUM2INT(order),pmode); + + for(i=0; i Array + * + * Calculates the length of the shortest paths from each of the vertices in + * the varray Array to all of the other vertices in the graph. The result + * is returned as an Array of Array. Each top-level Array contains the results + * for a vertex in the varray Array. Each entry in the Array is the path length + * to another vertex in the graph in vertex order (the order the vertices were + * added to the graph. (This should probalby be changed to give a Hash of Hash + * to allow easier look up.) + */ +VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mode){ + + igraph_t *graph; + igraph_vs_t vids; + igraph_vector_t vidv; + igraph_neimode_t pmode = NUM2INT(mode); + igraph_vector_ptr_t res; + igraph_vector_t *path_v; + int i; + + VALUE result = rb_ary_new(); + + Data_Get_Struct(self, igraph_t, graph); + + igraph_vector_ptr_init(&res,0); + + //Convert an array of vertices to a vector of vertex ids + cIGraph_vertex_arr_to_id_vec(self,from,&vidv); + //create vertex selector from the vecotr of ids + igraph_vs_vector(&vids,&vidv); + + igraph_neighborhood_graphs(graph,&res,vids,NUM2INT(order),pmode); + + for(i=0; i