diff --git a/ext/cIGraph.c b/ext/cIGraph.c index c100316..94b66d2 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -198,6 +198,11 @@ void Init_igraph(){ rb_define_const(cIGraph, "WEAK", INT2NUM(1)); rb_define_const(cIGraph, "STRONG", INT2NUM(2)); + rb_define_const(cIGraph, "ARBITRARY", INT2NUM(0)); + rb_define_const(cIGraph, "MUTUAL", INT2NUM(1)); + rb_define_const(cIGraph, "EACH", INT2NUM(0)); + rb_define_const(cIGraph, "COLLAPSE", INT2NUM(1)); + rb_define_method(cIGraph, "[]", cIGraph_get_edge_attr, 2); /* in cIGraph_attribute_handler.c */ rb_define_method(cIGraph, "[]=", cIGraph_set_edge_attr, 3); /* in cIGraph_attribute_handler.c */ rb_define_alias (cIGraph, "get_edge_attr", "[]"); @@ -269,9 +274,16 @@ void Init_igraph(){ rb_define_method(cIGraph, "minimum_spanning_tree_unweighted", cIGraph_minimum_spanning_tree_unweighted, 0); /* in cIGraph_spanning.c */ rb_define_method(cIGraph, "minimum_spanning_tree_prim", cIGraph_minimum_spanning_tree_prim, 1); /* in cIGraph_spanning.c */ - rb_define_method(cIGraph, "transitivity", cIGraph_transitivity, 0); - rb_define_method(cIGraph, "transitivity_local", cIGraph_transitivity_local, 1); - rb_define_method(cIGraph, "transitivity_avglocal", cIGraph_transitivity_avglocal, 0); + rb_define_method(cIGraph, "transitivity", cIGraph_transitivity, 0); /* in cIGraph_transitivity.c */ + rb_define_method(cIGraph, "transitivity_local", cIGraph_transitivity_local, 1); /* in cIGraph_transitivity.c */ + rb_define_method(cIGraph, "transitivity_avglocal", cIGraph_transitivity_avglocal, 0); /* in cIGraph_transitivity.c */ + + rb_define_method(cIGraph, "to_directed", cIGraph_to_directed, 1); /* in cIGraph_direction.c */ + rb_define_method(cIGraph, "to_undirected", cIGraph_to_undirected, 1); /* in cIGraph_direction.c */ + + rb_define_method(cIGraph, "laplacian", cIGraph_laplacian, 1); /* in cIGraph_spectral.c */ + + rb_define_method(cIGraph, "coreness", cIGraph_coreness, 1); /* in cIGraph_kcores.c */ rb_define_method(cIGraph, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */ diff --git a/ext/cIGraph.h b/ext/cIGraph.h index ce89b4c..1090d44 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -109,6 +109,16 @@ VALUE cIGraph_transitivity (VALUE self); VALUE cIGraph_transitivity_local (VALUE self, VALUE vs); VALUE cIGraph_transitivity_avglocal(VALUE self); +//Directedness conversion +VALUE cIGraph_to_directed (VALUE self, VALUE mode); +VALUE cIGraph_to_undirected(VALUE self, VALUE mode); + +//Spectral properties +VALUE cIGraph_laplacian(VALUE self, VALUE mode); + +//K-Cores +VALUE cIGraph_coreness(VALUE self, VALUE mode); + //Topological sorting VALUE cIGraph_topological_sorting(VALUE self, VALUE mode); diff --git a/ext/cIGraph_direction.c b/ext/cIGraph_direction.c new file mode 100644 index 0000000..f34e17e --- /dev/null +++ b/ext/cIGraph_direction.c @@ -0,0 +1,39 @@ +#include "igraph.h" +#include "ruby.h" +#include "cIGraph.h" + +/* call-seq: + * graph.to_directed(mode) + * + * Converts the graph to a directed graph. + */ +VALUE cIGraph_to_directed(VALUE self, VALUE mode){ + + igraph_t *graph; + igraph_neimode_t pmode = NUM2INT(mode); + int ret; + + Data_Get_Struct(self, igraph_t, graph); + IGRAPH_CHECK(ret = igraph_to_directed(graph,pmode)); + + return INT2NUM(ret); + +} + +/* call-seq: + * graph.to_undirected(mode) + * + * Converts the graph to a directed graph. + */ +VALUE cIGraph_to_undirected(VALUE self, VALUE mode){ + + igraph_t *graph; + igraph_neimode_t pmode = NUM2INT(mode); + int ret; + + Data_Get_Struct(self, igraph_t, graph); + IGRAPH_CHECK(ret = igraph_to_undirected(graph,pmode)); + + return INT2NUM(ret); + +} diff --git a/ext/cIGraph_kcores.c b/ext/cIGraph_kcores.c new file mode 100644 index 0000000..b96524d --- /dev/null +++ b/ext/cIGraph_kcores.c @@ -0,0 +1,39 @@ +#include "igraph.h" +#include "ruby.h" +#include "cIGraph.h" + +/* call-seq: + * graph.coreness(mode) -> Array + * + * Finding the coreness of the vertices in a network. The k-core of a + * graph is a maximal subgraph in which each vertex has at least degree k. + * (Degree here means the degree in the subgraph of course.). The coreness + * of a vertex is the highest order of a k-core containing the vertex. + * + * This function implements the algorithm presented in Vladimir Batagelj, + * Matjaz Zaversnik: An O(m) Algorithm for Cores Decomposition of Networks. + */ +VALUE cIGraph_coreness(VALUE self, VALUE mode){ + + igraph_t *graph; + igraph_neimode_t pmode = NUM2INT(mode); + igraph_vector_t cores; + int i; + VALUE result = rb_ary_new(); + + Data_Get_Struct(self, igraph_t, graph); + + //vector to hold the results of the calculations + igraph_vector_init(&cores,0); + + igraph_coreness(graph,&cores,pmode); + + for(i=0; i< igraph_vector_size(&cores); i++){ + rb_ary_push(result,VECTOR(cores)[i]); + } + + igraph_vector_destroy(&cores); + + return result; + +} diff --git a/ext/cIGraph_spectral.c b/ext/cIGraph_spectral.c new file mode 100644 index 0000000..ddc1b01 --- /dev/null +++ b/ext/cIGraph_spectral.c @@ -0,0 +1,57 @@ +#include "igraph.h" +#include "ruby.h" +#include "cIGraph.h" + +/* call-seq: + * graph.laplacian(mode) -> Array + * + * Returns the Laplacian matrix of a graph + * + * The graph Laplacian matrix is similar to an adjacency matrix but + * contains -1's instead of 1's and the vertex degrees are included + * in the diagonal. So the result for edge i--j is -1 if i!=j and is + * equal to the degree of vertex i if i==j. igraph_laplacian will work + * on a directed graph (although this does not seem to make much sense) + * and ignores loops. + * + * Mode is a boolean specifying whether the normalized version should be used + * The normalised Laplacian matrix has 1 in the diagonal + * and -1/sqrt(d[i]d[j]) if there is an edge from i to j. + * + * The first version of this function was written by Vincent Matossian. + */ +VALUE cIGraph_laplacian(VALUE self, VALUE mode){ + + igraph_t *graph; + igraph_bool_t pmode = 0; + igraph_matrix_t res; + int i; + int j; + VALUE row; + VALUE val; + VALUE matrix = rb_ary_new(); + + if(mode = Qtrue) + pmode = 1; + + Data_Get_Struct(self, igraph_t, graph); + + //matrix to hold the results of the calculations + igraph_matrix_init(&res,igraph_vcount(graph),igraph_vcount(graph)); + + IGRAPH_CHECK(igraph_laplacian(graph,&res,pmode)); + + for(i=0; i