| @@ -256,6 +256,9 @@ void Init_igraph(){ | |||
| 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, "dijkstra_shortest_paths", cIGraph_dijkstra_shortest_paths, 3); | |||
| rb_define_method(cIGraph, "neighbourhood_size", cIGraph_neighborhood_size, 3); /* in cIGraph_vertex_neighbourhood.c */ | |||
| rb_define_method(cIGraph, "neighbourhood", cIGraph_neighborhood, 3); /* in cIGraph_vertex_neighbourhood.c */ | |||
| rb_define_method(cIGraph, "neighbourhood_graphs", cIGraph_neighborhood_graphs, 3); /* in cIGraph_vertex_neighbourhood.c */ | |||
| @@ -301,6 +304,21 @@ void Init_igraph(){ | |||
| rb_define_method(cIGraph, "maximal_cliques", cIGraph_maximal_cliques, 0); /* in cIGraph_cliques.c */ | |||
| rb_define_method(cIGraph, "clique_number", cIGraph_clique_number, 0); /* in cIGraph_cliques.c */ | |||
| rb_define_method(cIGraph, "independent_vertex_sets", cIGraph_independent_vertex_sets, 2); /* in cIGraph_independent_vertex_sets.c */ | |||
| rb_define_method(cIGraph, "largest_independent_vertex_sets", cIGraph_largest_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ | |||
| rb_define_method(cIGraph, "maximal_independent_vertex_sets", cIGraph_maximal_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ | |||
| rb_define_method(cIGraph, "independence_number", cIGraph_independence_number, 0); /* in cIGraph_independent_vertex_sets.c */ | |||
| rb_define_method(cIGraph, "isomorphic", cIGraph_isomorphic, 1); /* in cIGraph_isomorphic.c */ | |||
| rb_define_method(cIGraph, "isomorphic_vf2", cIGraph_isomorphic_vf2, 1); /* in cIGraph_isomorphic.c */ | |||
| rb_define_method(cIGraph, "isoclass", cIGraph_isoclass, 0); /* in cIGraph_isomorphic.c */ | |||
| rb_define_method(cIGraph, "isoclass_subgraph", cIGraph_isoclass_subgraph, 1); /* in cIGraph_isomorphic.c */ | |||
| rb_define_singleton_method(cIGraph, "isoclass_create", cIGraph_isoclass_create, 3); /* in cIGraph_isomorphic.c */ | |||
| rb_define_method(cIGraph, "motifs_randesu", cIGraph_motifs_randesu, 2); /* in cIGraph_motif.c */ | |||
| rb_define_method(cIGraph, "motifs_randesu_no", cIGraph_motifs_randesu_no, 2); /* in cIGraph_motif.c */ | |||
| rb_define_method(cIGraph, "motifs_randesu_estimate", cIGraph_motifs_randesu_estimate, 4); /* in cIGraph_motif.c */ | |||
| 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 */ | |||
| @@ -81,6 +81,13 @@ 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); | |||
| VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VALUE mode); | |||
| int igraph_dijkstra_shortest_paths(const igraph_t *graph, | |||
| igraph_matrix_t *res, | |||
| const igraph_vs_t from, | |||
| const igraph_vector_t *wghts, | |||
| igraph_neimode_t mode); | |||
| //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); | |||
| @@ -136,6 +143,25 @@ VALUE cIGraph_largest_cliques(VALUE self); | |||
| VALUE cIGraph_maximal_cliques(VALUE self); | |||
| VALUE cIGraph_clique_number(VALUE self); | |||
| //Independent vertex sets | |||
| VALUE cIGraph_independent_vertex_sets(VALUE self, VALUE min, VALUE max); | |||
| VALUE cIGraph_largest_independent_vertex_sets(VALUE self); | |||
| VALUE cIGraph_maximal_independent_vertex_sets(VALUE self); | |||
| VALUE cIGraph_independence_number(VALUE self); | |||
| //Graph isomorphism | |||
| VALUE cIGraph_isomorphic (VALUE self, VALUE g); | |||
| VALUE cIGraph_isomorphic_vf2 (VALUE self, VALUE g); | |||
| VALUE cIGraph_isoclass (VALUE self); | |||
| VALUE cIGraph_isoclass_subgraph(VALUE self, VALUE vs); | |||
| VALUE cIGraph_isoclass_create (VALUE self, VALUE vn, VALUE iso, VALUE dir); | |||
| //Motifs | |||
| VALUE cIGraph_motifs_randesu (VALUE self, VALUE size, VALUE cuts); | |||
| VALUE cIGraph_motifs_randesu_no (VALUE self, VALUE size, VALUE cuts); | |||
| VALUE cIGraph_motifs_randesu_estimate(VALUE self, VALUE size, VALUE cuts, | |||
| VALUE samplen, VALUE samplev); | |||
| //File handling | |||
| VALUE cIGraph_read_graph_edgelist (VALUE self, VALUE file, VALUE mode); | |||
| VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file); | |||
| @@ -189,6 +189,7 @@ int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_p | |||
| VALUE values; | |||
| if(attr){ | |||
| if(igraph_vector_ptr_size(attr) > 0 && ((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){ | |||
| values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value; | |||
| @@ -234,6 +235,11 @@ int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_p | |||
| rb_ary_push(vertex_array,record); | |||
| } | |||
| } | |||
| } else { | |||
| //Default: Add numbered vertices. | |||
| for(i=0;i<nv;i++){ | |||
| rb_ary_push(vertex_array,INT2NUM(i)); | |||
| } | |||
| } | |||
| #ifdef DEBUG | |||
| @@ -0,0 +1,258 @@ | |||
| #include "igraph.h" | |||
| #include "ruby.h" | |||
| #include "cIGraph.h" | |||
| /* call-seq: | |||
| * graph.dijkstra_shortest_paths(varray,weights,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 given a set of | |||
| * edge weights given in the weights Array. 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_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VALUE mode){ | |||
| igraph_t *graph; | |||
| igraph_vs_t vids; | |||
| igraph_vector_t vidv; | |||
| igraph_vector_t wghts; | |||
| igraph_neimode_t pmode = NUM2INT(mode); | |||
| igraph_matrix_t res; | |||
| int i; | |||
| int j; | |||
| VALUE row; | |||
| VALUE path_length; | |||
| VALUE matrix = rb_ary_new(); | |||
| int n_row; | |||
| int n_col; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| n_row = NUM2INT(rb_funcall(from,rb_intern("length"),0)); | |||
| n_col = igraph_vcount(graph); | |||
| //matrix to hold the results of the calculations | |||
| igraph_matrix_init(&res,n_row,n_col); | |||
| igraph_vector_init(&wghts,RARRAY(weights)->len); | |||
| for(i=0;i<RARRAY(weights)->len;i++){ | |||
| VECTOR(wghts)[i] = NUM2DBL(RARRAY(weights)->ptr[i]); | |||
| } | |||
| //Convert an array of vertices to a vector of vertex ids | |||
| igraph_vector_init_int(&vidv,0); | |||
| cIGraph_vertex_arr_to_id_vec(self,from,&vidv); | |||
| //create vertex selector from the vecotr of ids | |||
| igraph_vs_vector(&vids,&vidv); | |||
| igraph_dijkstra_shortest_paths(graph,&res,vids,&wghts,pmode); | |||
| for(i=0; i<igraph_matrix_nrow(&res); i++){ | |||
| row = rb_ary_new(); | |||
| rb_ary_push(matrix,row); | |||
| for(j=0; j<igraph_matrix_ncol(&res); j++){ | |||
| path_length = MATRIX(res,i,j) == n_col ? Qnil : rb_float_new(MATRIX(res,i,j)); | |||
| rb_ary_push(row,path_length); | |||
| } | |||
| } | |||
| igraph_vector_destroy(&vidv); | |||
| igraph_matrix_destroy(&res); | |||
| igraph_vs_destroy(&vids); | |||
| return matrix; | |||
| } | |||
| /* 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_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ | |||
| igraph_t *graph; | |||
| igraph_integer_t from_vid; | |||
| igraph_vs_t to_vids; | |||
| igraph_vector_t to_vidv; | |||
| igraph_neimode_t pmode = NUM2INT(mode); | |||
| igraph_vector_ptr_t res; | |||
| igraph_vector_t *path_v; | |||
| int i; | |||
| int j; | |||
| VALUE path; | |||
| VALUE matrix = rb_ary_new(); | |||
| int n_paths; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| n_paths = RARRAY(to)->len; | |||
| //vector to hold the results of the calculations | |||
| igraph_vector_ptr_init(&res,0); | |||
| for(i=0;i<n_paths;i++){ | |||
| path_v = malloc(sizeof(igraph_vector_t)); | |||
| igraph_vector_init(path_v,0); | |||
| igraph_vector_ptr_push_back(&res,path_v); | |||
| } | |||
| //Convert an array of vertices to a vector of vertex ids | |||
| igraph_vector_init_int(&to_vidv,0); | |||
| 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); | |||
| //The id of the vertex from where we are counting | |||
| from_vid = cIGraph_get_vertex_id(self, from); | |||
| igraph_get_shortest_paths(graph,&res,from_vid,to_vids,pmode); | |||
| for(i=0; i<n_paths; i++){ | |||
| path = rb_ary_new(); | |||
| rb_ary_push(matrix,path); | |||
| path_v = VECTOR(res)[i]; | |||
| for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){ | |||
| rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j])); | |||
| } | |||
| } | |||
| for(i=0;i<n_paths;i++){ | |||
| igraph_vector_destroy(VECTOR(res)[i]); | |||
| free(VECTOR(res)[i]); | |||
| } | |||
| igraph_vector_destroy(&to_vidv); | |||
| igraph_vector_ptr_destroy(&res); | |||
| igraph_vs_destroy(&to_vids); | |||
| return matrix; | |||
| } | |||
| int igraph_dijkstra_shortest_paths(const igraph_t *graph, | |||
| igraph_matrix_t *res, | |||
| const igraph_vs_t from, | |||
| const igraph_vector_t *wghts, | |||
| igraph_neimode_t mode) { | |||
| long int no_of_nodes=igraph_vcount(graph); | |||
| long int no_of_from; | |||
| igraph_real_t *shortest; | |||
| igraph_real_t min,alt; | |||
| int i, j, uj, included; | |||
| igraph_integer_t eid, u,v; | |||
| igraph_vector_t q; | |||
| igraph_vit_t fromvit; | |||
| igraph_vector_t neis; | |||
| IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit)); | |||
| IGRAPH_FINALLY(igraph_vit_destroy, &fromvit); | |||
| no_of_from=IGRAPH_VIT_SIZE(fromvit); | |||
| if (mode != IGRAPH_OUT && mode != IGRAPH_IN && | |||
| mode != IGRAPH_ALL) { | |||
| IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE); | |||
| } | |||
| shortest=calloc(no_of_nodes, sizeof(igraph_real_t)); | |||
| if (shortest==0) { | |||
| IGRAPH_ERROR("shortest paths failed", IGRAPH_ENOMEM); | |||
| } | |||
| IGRAPH_FINALLY(free, shortest); | |||
| IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_nodes)); | |||
| igraph_matrix_null(res); | |||
| for (IGRAPH_VIT_RESET(fromvit), i=0; | |||
| !IGRAPH_VIT_END(fromvit); | |||
| IGRAPH_VIT_NEXT(fromvit), i++) { | |||
| //Start shortest and previous | |||
| for(j=0;j<no_of_nodes;j++){ | |||
| shortest[j] = INFINITY; | |||
| //memset(previous,NAN, no_of_nodes); | |||
| } | |||
| shortest[(int)IGRAPH_VIT_GET(fromvit)] = 0; | |||
| igraph_vector_init_seq(&q,0,no_of_nodes-1); | |||
| while(igraph_vector_size(&q) != 0){ | |||
| min = INFINITY; | |||
| u = no_of_nodes; | |||
| uj = igraph_vector_size(&q); | |||
| for(j=0;j<igraph_vector_size(&q);j++){ | |||
| v = VECTOR(q)[j]; | |||
| if(shortest[(int)v] < min){ | |||
| min = shortest[(int)v]; | |||
| u = v; | |||
| uj = j; | |||
| } | |||
| } | |||
| if(min == INFINITY) | |||
| break; | |||
| igraph_vector_remove(&q,uj); | |||
| igraph_vector_init(&neis,0); | |||
| igraph_neighbors(graph,&neis,u,mode); | |||
| for(j=0;j<igraph_vector_size(&neis);j++){ | |||
| v = VECTOR(neis)[j]; | |||
| //v must be in Q | |||
| included = 0; | |||
| for(j=0;j<igraph_vector_size(&q);j++){ | |||
| if(v == VECTOR(q)[j]){ | |||
| included = 1; | |||
| break; | |||
| } | |||
| } | |||
| if(!included) | |||
| continue; | |||
| igraph_get_eid(graph,&eid,u,v,1); | |||
| alt = shortest[(int)u] + VECTOR(*wghts)[(int)eid]; | |||
| if(alt < shortest[(int)v]){ | |||
| shortest[(int)v] = alt; | |||
| } | |||
| } | |||
| igraph_vector_destroy(&neis); | |||
| } | |||
| for(j=0;j<no_of_nodes;j++){ | |||
| MATRIX(*res,i,j) = shortest[j]; | |||
| } | |||
| igraph_vector_destroy(&q); | |||
| } | |||
| /* Clean */ | |||
| free(shortest); | |||
| igraph_vit_destroy(&fromvit); | |||
| IGRAPH_FINALLY_CLEAN(2); | |||
| return 0; | |||
| } | |||
| @@ -0,0 +1,182 @@ | |||
| #include "igraph.h" | |||
| #include "ruby.h" | |||
| #include "cIGraph.h" | |||
| /* call-seq: | |||
| * graph.independent_vertex_sets(min_size,max_size) -> Array | |||
| * | |||
| * Find all independent vertex sets in a graph | |||
| * | |||
| * A vertex set is considered independent if there are no edges between them. | |||
| * | |||
| * If you are interested in the size of the largest independent vertex set, | |||
| * use IGraph#independence_number() instead. | |||
| */ | |||
| VALUE cIGraph_independent_vertex_sets(VALUE self, VALUE min, VALUE max){ | |||
| igraph_t *graph; | |||
| igraph_vector_ptr_t res; | |||
| igraph_vector_t *vec; | |||
| int i; | |||
| int j; | |||
| VALUE independent_vertex_set; | |||
| VALUE object; | |||
| VALUE independent_vertex_sets = rb_ary_new(); | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_vector_ptr_init(&res,0); | |||
| igraph_independent_vertex_sets(graph, &res, NUM2INT(min), NUM2INT(max)); | |||
| for(i=0; i<igraph_vector_ptr_size(&res); i++){ | |||
| independent_vertex_set = rb_ary_new(); | |||
| rb_ary_push(independent_vertex_sets,independent_vertex_set); | |||
| vec = VECTOR(res)[i]; | |||
| for(j=0; j<igraph_vector_size(vec); j++){ | |||
| vec = VECTOR(res)[i]; | |||
| object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]); | |||
| rb_ary_push(independent_vertex_set,object); | |||
| } | |||
| } | |||
| for(i=0;i<igraph_vector_ptr_size(&res);i++){ | |||
| igraph_vector_destroy(VECTOR(res)[i]); | |||
| free(VECTOR(res)[i]); | |||
| } | |||
| igraph_vector_ptr_destroy(&res); | |||
| return independent_vertex_sets; | |||
| } | |||
| /* call-seq: | |||
| * graph.largest_independent_vertex_sets() -> Array | |||
| * | |||
| * Finds the largest independent vertex set(s) in a graph. | |||
| * An independent vertex set is largest if there is no other independent | |||
| * vertex set with more vertices in the graph. | |||
| */ | |||
| VALUE cIGraph_largest_independent_vertex_sets(VALUE self){ | |||
| igraph_t *graph; | |||
| igraph_vector_ptr_t res; | |||
| igraph_vector_t *vec; | |||
| int i; | |||
| int j; | |||
| VALUE independent_vertex_set; | |||
| VALUE object; | |||
| VALUE independent_vertex_sets = rb_ary_new(); | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_vector_ptr_init(&res,0); | |||
| igraph_largest_independent_vertex_sets(graph, &res); | |||
| for(i=0; i<igraph_vector_ptr_size(&res); i++){ | |||
| independent_vertex_set = rb_ary_new(); | |||
| rb_ary_push(independent_vertex_sets,independent_vertex_set); | |||
| vec = VECTOR(res)[i]; | |||
| for(j=0; j<igraph_vector_size(vec); j++){ | |||
| vec = VECTOR(res)[i]; | |||
| object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]); | |||
| rb_ary_push(independent_vertex_set,object); | |||
| } | |||
| } | |||
| for(i=0;i<igraph_vector_ptr_size(&res);i++){ | |||
| igraph_vector_destroy(VECTOR(res)[i]); | |||
| free(VECTOR(res)[i]); | |||
| } | |||
| igraph_vector_ptr_destroy(&res); | |||
| return independent_vertex_sets; | |||
| } | |||
| /* call-seq: | |||
| * graph.maximal_independent_vertex_sets() -> Array | |||
| * | |||
| * Find all maximal independent vertex sets of a graph | |||
| * | |||
| * A maximal independent vertex set is an independent vertex set which can't | |||
| * be extended any more by adding a new vertex to it. | |||
| * | |||
| * The algorithm used here is based on the following paper: S. Tsukiyama, | |||
| * M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for generating all | |||
| * the maximal independent sets. SIAM J Computing, 6:505--517, 1977. | |||
| * | |||
| * The implementation was originally written by Kevin O'Neill and modified | |||
| * by K M Briggs in the Very Nauty Graph Library. I simply re-wrote it to | |||
| * use igraph's data structures. | |||
| * | |||
| * If you are interested in the size of the largest independent vertex set, | |||
| * use IGraph#independence_number() instead. | |||
| */ | |||
| VALUE cIGraph_maximal_independent_vertex_sets(VALUE self){ | |||
| igraph_t *graph; | |||
| igraph_vector_ptr_t res; | |||
| igraph_vector_t *vec; | |||
| int i; | |||
| int j; | |||
| VALUE independent_vertex_set; | |||
| VALUE object; | |||
| VALUE independent_vertex_sets = rb_ary_new(); | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_vector_ptr_init(&res,0); | |||
| igraph_maximal_independent_vertex_sets(graph, &res); | |||
| for(i=0; i<igraph_vector_ptr_size(&res); i++){ | |||
| independent_vertex_set = rb_ary_new(); | |||
| rb_ary_push(independent_vertex_sets,independent_vertex_set); | |||
| vec = VECTOR(res)[i]; | |||
| for(j=0; j<igraph_vector_size(vec); j++){ | |||
| vec = VECTOR(res)[i]; | |||
| object = cIGraph_get_vertex_object(self,VECTOR(*vec)[j]); | |||
| rb_ary_push(independent_vertex_set,object); | |||
| } | |||
| } | |||
| for(i=0;i<igraph_vector_ptr_size(&res);i++){ | |||
| igraph_vector_destroy(VECTOR(res)[i]); | |||
| free(VECTOR(res)[i]); | |||
| } | |||
| igraph_vector_ptr_destroy(&res); | |||
| return independent_vertex_sets; | |||
| } | |||
| /* call-seq: | |||
| * graph.independence_number() -> Integer | |||
| * | |||
| * Find the independence number of the graph | |||
| * | |||
| * The independence number of a graph is the cardinality of the largest | |||
| * independent vertex set. | |||
| */ | |||
| VALUE cIGraph_independence_number(VALUE self){ | |||
| igraph_t *graph; | |||
| igraph_integer_t res; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_independence_number(graph, &res); | |||
| return INT2NUM(res); | |||
| } | |||
| @@ -0,0 +1,137 @@ | |||
| #include "igraph.h" | |||
| #include "ruby.h" | |||
| #include "cIGraph.h" | |||
| /* call-seq: | |||
| * graph.isomorphic(graph) -> True/False | |||
| * | |||
| * Decides whether two graphs are isomorphic | |||
| * | |||
| * From Wikipedia: The graph isomorphism problem or GI problem is the graph | |||
| * theory problem of determining whether, given two graphs G1 and G2, it is | |||
| * possible to permute (or relabel) the vertices of one graph so that it is | |||
| * equal to the other. Such a permutation is called a graph isomorphism. | |||
| */ | |||
| VALUE cIGraph_isomorphic(VALUE self, VALUE g){ | |||
| igraph_bool_t res = 0; | |||
| igraph_t *graph; | |||
| igraph_t *graph2; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| Data_Get_Struct(g, igraph_t, graph2); | |||
| IGRAPH_CHECK(igraph_isomorphic(graph,graph2,&res)); | |||
| return res == 0 ? Qfalse : Qtrue; | |||
| } | |||
| /* call-seq: | |||
| * graph.isomorphic_vf2(graph) -> True/False | |||
| * | |||
| * Decides whether two graphs are isomorphic | |||
| * | |||
| * This function is an implementation of the VF2 isomorphism algorithm, | |||
| * see P. Foggia, C. Sansone, M. Vento, An Improved algorithm for matching | |||
| * large graphs, Prof. of the 3rd IAPR-TC-15 International Workshop on | |||
| * Graph-based Representations, Italy, 2001. | |||
| */ | |||
| VALUE cIGraph_isomorphic_vf2(VALUE self, VALUE g){ | |||
| igraph_bool_t res = 0; | |||
| igraph_t *graph; | |||
| igraph_t *graph2; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| Data_Get_Struct(g, igraph_t, graph2); | |||
| IGRAPH_CHECK(igraph_isomorphic_vf2(graph,graph2,&res)); | |||
| return res == 0 ? Qfalse : Qtrue; | |||
| } | |||
| /* call-seq: | |||
| * graph.isoclass() -> Integer | |||
| * | |||
| * Determine the isomorphism class of a graph | |||
| * | |||
| * All graphs with a given number of vertices belong to a number of | |||
| * isomorpism classes, with every graph in a given class being isomorphic | |||
| * to each other. | |||
| * | |||
| * This function gives the isomorphism class (a number) of a graph. Two | |||
| * graphs have the same isomorphism class if and only if they are isomorphic. | |||
| * | |||
| * The first isomorphism class is numbered zero and it is the empty graph, | |||
| * the last isomorphism class is the full graph. The number of isomorphism | |||
| * class for directed graphs with three vertices is 16 (between 0 and 15), | |||
| * for undirected graph it is only 4. For graphs with four vertices it is | |||
| * 218 (directed) and 11 (undirected). | |||
| */ | |||
| VALUE cIGraph_isoclass(VALUE self){ | |||
| int res = 0; | |||
| igraph_t *graph; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| IGRAPH_CHECK(igraph_isoclass(graph,&res)); | |||
| return INT2NUM(res); | |||
| } | |||
| /* call-seq: | |||
| * graph.isoclass_subgraph(vs) -> Integer | |||
| * | |||
| * Determine the isomorphism class of a subgraph given by the vertices given | |||
| * in the Array vs. | |||
| * | |||
| */ | |||
| VALUE cIGraph_isoclass_subgraph(VALUE self, VALUE vs){ | |||
| int res = 0; | |||
| igraph_t *graph; | |||
| igraph_vector_t vidv; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| //Convert an array of vertices to a vector of vertex ids | |||
| igraph_vector_init_int(&vidv,0); | |||
| cIGraph_vertex_arr_to_id_vec(self,vs,&vidv); | |||
| IGRAPH_CHECK(igraph_isoclass_subgraph(graph,&vidv,&res)); | |||
| igraph_vector_destroy(&vidv); | |||
| return INT2NUM(res); | |||
| } | |||
| /* call-seq: | |||
| * IGraph.isoclass_create(vn,iso,dir) -> IGraph | |||
| * | |||
| * Creates a graph with the number of vertices given by vn from the given | |||
| * isomorphism class iso and the direction boolean dir. | |||
| * | |||
| * This function is implemented only for graphs with three or four vertices. | |||
| */ | |||
| VALUE cIGraph_isoclass_create(VALUE self, VALUE vn, VALUE iso, VALUE dir){ | |||
| igraph_t *graph; | |||
| VALUE new_graph; | |||
| igraph_bool_t dir_b = 0; | |||
| if(dir) | |||
| dir_b = 1; | |||
| new_graph = cIGraph_alloc(cIGraph); | |||
| Data_Get_Struct(new_graph, igraph_t, graph); | |||
| IGRAPH_CHECK(igraph_isoclass_create(graph,NUM2INT(vn),NUM2INT(iso),dir_b)); | |||
| return new_graph; | |||
| } | |||
| @@ -0,0 +1,109 @@ | |||
| #include "igraph.h" | |||
| #include "ruby.h" | |||
| #include "cIGraph.h" | |||
| /* call-seq: | |||
| * igraph.motifs_randesu(size,cut) | |||
| * | |||
| */ | |||
| VALUE cIGraph_motifs_randesu(VALUE self, VALUE size, VALUE cuts){ | |||
| igraph_t *graph; | |||
| igraph_vector_t cutsv; | |||
| igraph_vector_t res; | |||
| int i; | |||
| VALUE hist = 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 | |||
| igraph_vector_init(&cutsv,0); | |||
| for(i=0;i<RARRAY(cuts)->len;i++){ | |||
| igraph_vector_push_back(&cutsv,NUM2DBL(RARRAY(cuts)->ptr[i])); | |||
| } | |||
| igraph_motifs_randesu(graph,&res,NUM2INT(size),&cutsv); | |||
| for(i=0; i<igraph_vector_size(&res); i++){ | |||
| rb_ary_push(hist,INT2NUM(VECTOR(res)[i])); | |||
| } | |||
| igraph_vector_destroy(&cutsv); | |||
| igraph_vector_destroy(&res); | |||
| return hist; | |||
| } | |||
| /* call-seq: | |||
| * igraph.motifs_randesu_no(size,cut) | |||
| * | |||
| */ | |||
| VALUE cIGraph_motifs_randesu_no(VALUE self, VALUE size, VALUE cuts){ | |||
| igraph_t *graph; | |||
| igraph_vector_t cutsv; | |||
| igraph_integer_t res; | |||
| int i; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| //Convert an array of vertices to a vector of vertex ids | |||
| igraph_vector_init(&cutsv,0); | |||
| for(i=0;i<RARRAY(cuts)->len;i++){ | |||
| igraph_vector_push_back(&cutsv,NUM2DBL(RARRAY(cuts)->ptr[i])); | |||
| } | |||
| igraph_motifs_randesu_no(graph,&res,NUM2INT(size),&cutsv); | |||
| igraph_vector_destroy(&cutsv); | |||
| return INT2NUM(res); | |||
| } | |||
| /* call-seq: | |||
| * igraph.motifs_randesu_estimate(size,cut,samplen,samplev) | |||
| * | |||
| */ | |||
| VALUE cIGraph_motifs_randesu_estimate(VALUE self, VALUE size, VALUE cuts, | |||
| VALUE samplen, VALUE samplev){ | |||
| igraph_t *graph; | |||
| igraph_vector_t cutsv; | |||
| igraph_vector_t vidv; | |||
| igraph_integer_t res; | |||
| int i; | |||
| if(samplev != Qnil){ | |||
| igraph_vector_init(&vidv,0); | |||
| //Convert an array of vertices to a vector of vertex ids | |||
| igraph_vector_init_int(&vidv,0); | |||
| cIGraph_vertex_arr_to_id_vec(self,samplev,&vidv); | |||
| } | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_vector_init(&cutsv,0); | |||
| for(i=0;i<RARRAY(cuts)->len;i++){ | |||
| igraph_vector_push_back(&cutsv,NUM2DBL(RARRAY(cuts)->ptr[i])); | |||
| } | |||
| if(samplev == Qnil){ | |||
| igraph_motifs_randesu_estimate(graph,&res,NUM2INT(size), | |||
| &cutsv,NUM2INT(samplen),NULL); | |||
| } else { | |||
| igraph_motifs_randesu_estimate(graph,&res,NUM2INT(size), | |||
| &cutsv,NUM2INT(samplen),&vidv); | |||
| } | |||
| igraph_vector_destroy(&cutsv); | |||
| if(samplev != Qnil){ | |||
| igraph_vector_destroy(&vidv); | |||
| } | |||
| return INT2NUM(res); | |||
| } | |||
| @@ -31,7 +31,7 @@ VALUE cIGraph_laplacian(VALUE self, VALUE mode){ | |||
| VALUE val; | |||
| VALUE matrix = rb_ary_new(); | |||
| if(mode = Qtrue) | |||
| if(mode == Qtrue) | |||
| pmode = 1; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| @@ -12,12 +12,16 @@ require 'tc_centrality' | |||
| require 'tc_components' | |||
| require 'tc_copy' | |||
| require 'tc_cores' | |||
| require 'tc_dijkstra' | |||
| require 'tc_directedness' | |||
| require 'tc_error_handling' | |||
| require 'tc_file_read_write' | |||
| require 'tc_independent_vertex_sets' | |||
| require 'tc_isomorphic' | |||
| require 'tc_iterators' | |||
| require 'tc_layout' | |||
| require 'tc_matrix' | |||
| require 'tc_motif' | |||
| require 'tc_other_ops' | |||
| require 'tc_selectors' | |||
| require 'tc_shortest_paths' | |||