/* call-seq: * graph.transitivity() -> Float * * Calculates the transitivity (clustering coefficient) of a graph. * * The transitivity measures the probability that two neighbors of a vertex * are connected. More precisely this is the ratio of the triangles and * connected triples in the graph, the result is a single real number or * NaN (0/0) if there are no connected triples in the graph. Directed graphs * are considered as undirected ones. */ VALUE cIGraph_transitivity_local(VALUE self, VALUE vs){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_vector_t res; VALUE trans = rb_ary_new(); int i; //vector to hold the results of the calculations igraph_vector_init_int(&res,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,vs,&vidv); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); Data_Get_Struct(self, igraph_t, graph); igraph_transitivity_local_undirected(graph,&res,vids); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(trans,rb_float_new(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); return trans; }
/* call-seq: * graph.closeness(vs,mode) -> Array * * Returns an Array of closeness centrality measures for the vertices given in * the vs Array. mode defines the type of shortest paths used for the * calculation */ VALUE cIGraph_closeness(VALUE self, VALUE vs, 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 closeness = rb_ary_new(); //vector to hold the results of the degree calculations igraph_vector_init_int(&res,0); 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); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_closeness(graph,&res,vids,pmode); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(closeness,rb_float_new(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); return closeness; }
/* call-seq: * graph.degree(vs,mode,loops) -> Array * * Returns an Array of Integers specifying the degree of each of the * vertices specified in the vs Array. mode defines the type of the degree. * IGraph::OUT, out-degree, IGraph::IN, in-degree, IGraph::ALL, total degree * (sum of the in- and out-degree). This parameter is ignored for undirected * graphs. * * Example: * * g = IGraph.new([1,2,3,4],true) * g.is_directed? #returns true * */ VALUE cIGraph_degree(VALUE self, VALUE v, VALUE mode, VALUE loops){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_neimode_t pmode = NUM2INT(mode); igraph_bool_t loop_mode = loops ? 1 : 0; igraph_vector_t res; int i; VALUE degree_r = rb_ary_new(); //vector to hold the results of the degree calculations igraph_vector_init_int(&res,0); 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,v,&vidv); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_degree(graph,&res,vids,pmode,loop_mode); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(degree_r,INT2NUM(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); return degree_r; }
/* call-seq: * graph.adjacent(vertex,mode) -> Array * * Returns an Array of the adjacent edge ids to vertex. mode defines * the way adjacent edges are searched for directed graphs. It can have * the following values: IGraph::OUT means only outgoing edges, IGraph::IN * only incoming edges, IGraph::ALL both. This parameter is ignored for * undirected graphs. * * Example: * * g = IGraph.new([1,2,3,4],true) * g.adjacent(1,IGraph::ALL) # returns [1] * */ VALUE cIGraph_adjacent(VALUE self, VALUE v, VALUE mode){ igraph_t *graph; igraph_integer_t pnode; igraph_neimode_t pmode = NUM2INT(mode); igraph_vector_t eids; int i; VALUE eids_r = rb_ary_new(); igraph_vector_init_int(&eids,0); Data_Get_Struct(self, igraph_t, graph); pnode = cIGraph_get_vertex_id(self,v); igraph_adjacent(graph,&eids,pnode,pmode); for(i=0;i<igraph_vector_size(&eids);i++){ rb_ary_push(eids_r,INT2NUM(VECTOR(eids)[i])); } igraph_vector_destroy(&eids); return eids_r; }
/* call-seq: * graph.neighbours(vertex,mode) -> Array * * Returns an Array of the neighbouring vertices to vertex. mode defines * the way adjacent vertices are searched for directed graphs. It can have * the following values: IGraph::OUT, vertices reachable by an edge from the * specified vertex are searched, IGraph::IN, vertices from which the * specified vertex is reachable are searched. IGraph::ALL, both kind of * vertices are searched. This parameter is ignored for undirected graphs. * * Example: * * g = IGraph.new([1,2,3,4],true) * g.neighbours(1,IGraph::ALL) # returns [2] * */ VALUE cIGraph_neighbors(VALUE self, VALUE v, VALUE mode){ igraph_t *graph; igraph_integer_t pnode; igraph_neimode_t pmode = NUM2INT(mode); igraph_vector_t neis; int i; VALUE neighbors = rb_ary_new(); igraph_vector_init_int(&neis,0); Data_Get_Struct(self, igraph_t, graph); pnode = cIGraph_get_vertex_id(self,v); igraph_neighbors(graph,&neis,pnode,pmode); for(i=0;i<igraph_vector_size(&neis);i++){ rb_ary_push(neighbors,cIGraph_get_vertex_object(self,VECTOR(neis)[i])); } igraph_vector_destroy(&neis); return neighbors; }
/* call-seq: * graph.subgraph(vs) -> IGraph * * Returns an IGraph object containing the vertices defined in the Array vs. */ VALUE cIGraph_subgraph(VALUE self, VALUE vs){ igraph_t *graph; igraph_t *n_graph = malloc(sizeof(igraph_t)); igraph_vs_t vids; igraph_vector_t vidv; VALUE n_graph_obj; 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); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_subgraph(graph,n_graph,vids); n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph); igraph_vector_destroy(&vidv); igraph_vs_destroy(&vids); return n_graph_obj; }
/* call-seq: * graph.maxdegree(vs,mode,loops) -> Vertex * * Returns the vertex Object in the vs Array with the largest degree. * mode defines the type * of the degree. IGRAPH_OUT, out-degree, IGRAPH_IN, in-degree, IGRAPH_ALL, * total degree (sum of the in- and out-degree). This parameter is ignored * for undirected graphs. loops is a boolean gives whether the self-loops * should be counted. */ VALUE cIGraph_maxdegree(VALUE self, VALUE vs, VALUE mode, VALUE loops){ igraph_t *graph; igraph_bool_t loop = 0; igraph_integer_t res; igraph_neimode_t pmode = NUM2INT(mode); igraph_vs_t vids; igraph_vector_t vidv; if(loops == Qtrue) loop = 1; 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); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_maxdegree(graph,&res,vids,pmode,loop); igraph_vector_destroy(&vidv); igraph_vs_destroy(&vids); return INT2NUM(res); }
/* call-seq: * graph.edge_betweenness(mode) -> Array * * Returns an Array of betweenness centrality measures for the edges * in the graph. mode defines whether directed paths or considered for * directed graphs. */ VALUE cIGraph_edge_betweenness(VALUE self, VALUE directed){ igraph_t *graph; igraph_bool_t dir = 0; igraph_vector_t res; int i; VALUE betweenness = rb_ary_new(); if(directed == Qtrue) dir = 1; //vector to hold the results of the degree calculations igraph_vector_init_int(&res,0); Data_Get_Struct(self, igraph_t, graph); igraph_edge_betweenness(graph,&res,dir); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(betweenness,INT2NUM((int)VECTOR(res)[i])); } igraph_vector_destroy(&res); return betweenness; }
/* call-seq: * graph.clusters(mode) -> Array * * Calculates the (weakly or strongly) connected components in a graph. * Returns an Array of Arrays of vertices. Each sub-Array is a graph component */ VALUE cIGraph_clusters(VALUE self, VALUE mode){ igraph_t *graph; igraph_vector_t membership; igraph_integer_t no; VALUE components; VALUE v,c; int i; igraph_vector_init_int(&membership,0); Data_Get_Struct(self, igraph_t, graph); igraph_clusters(graph, &membership, NULL, &no, NUM2INT(mode)); components = rb_ary_new(); for(i=0;i<no;i++){ rb_ary_push(components,rb_ary_new()); } for(i=0;i<igraph_vector_size(&membership);i++){ v = cIGraph_get_vertex_object(self, i); c = rb_ary_entry(components,VECTOR(membership)[i]); rb_ary_push(c,v); } igraph_vector_destroy(&membership); return components; }
/* 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_LEN(weights)); for(i=0;i<RARRAY_LEN(weights);i++){ VECTOR(wghts)[i] = NUM2DBL(RARRAY_PTR(weights)[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); igraph_vector_destroy(&wghts); return matrix; }
/* call-seq: * graph.constraint(vs,weights) -> Array * * Returns an Array of constraint measures for the vertices * in the graph. Weights is an Array of weight measures for each edge. */ VALUE cIGraph_constraint(int argc, VALUE *argv, VALUE self){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_vector_t res; igraph_vector_t wght; int i; VALUE constraints = rb_ary_new(); VALUE vs, weights; rb_scan_args(argc,argv,"11",&vs, &weights); //vector to hold the results of the degree calculations IGRAPH_FINALLY(igraph_vector_destroy, &res); IGRAPH_FINALLY(igraph_vector_destroy, &wght); IGRAPH_FINALLY(igraph_vector_destroy, &vidv); IGRAPH_CHECK(igraph_vector_init(&res,0)); IGRAPH_CHECK(igraph_vector_init(&wght,0)); Data_Get_Struct(self, igraph_t, graph); //Convert an array of vertices to a vector of vertex ids IGRAPH_CHECK(igraph_vector_init_int(&vidv,0)); cIGraph_vertex_arr_to_id_vec(self,vs,&vidv); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); if(weights == Qnil){ IGRAPH_CHECK(igraph_constraint(graph,&res,vids,NULL)); } else { for(i=0;i<RARRAY_LEN(weights);i++){ IGRAPH_CHECK(igraph_vector_push_back(&wght,NUM2DBL(RARRAY_PTR(weights)[i]))); } IGRAPH_CHECK(igraph_constraint(graph,&res,vids,&wght)); } for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(constraints,rb_float_new(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vector_destroy(&wght); igraph_vs_destroy(&vids); IGRAPH_FINALLY_CLEAN(3); return constraints; }
/* call-seq: * graph.pagerank(vs,mode,niter,eps,damping) -> Array * * Returns an Array of PageRank measures for the vertices * in the graph. mode defines whether directed paths or considered for * directed graphs. */ VALUE cIGraph_pagerank(VALUE self, VALUE vs, VALUE directed, VALUE niter, VALUE eps, VALUE damping){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_vector_t res; int i; VALUE pagerank = rb_ary_new(); igraph_bool_t dir = 0; if(directed == Qtrue) dir = 1; //vector to hold the results of the degree calculations igraph_vector_init_int(&res,0); 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); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_pagerank_old(graph,&res,vids,dir, NUM2INT(niter),NUM2DBL(eps),NUM2DBL(damping),0); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(pagerank,rb_float_new(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); return pagerank; }
/* call-seq: * graph.cocitation(varray) -> Array * * Cocitation coupling. * * Two vertices are cocited if there is another vertex citing both of them. * igraph_cocitation() simply counts how many types two vertices are cocited. * The cocitation score for each given vertex and all other vertices in the * graph will be calculated. * */ VALUE cIGraph_cocitation(VALUE self, VALUE vs){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; 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(vs,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); //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); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_cocitation(graph,&res,vids); 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 = INT2NUM(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.betweenness(vs,mode) -> Array * * Returns an Array of betweenness centrality measures for the vertices given * in the vs Array. mode defines whether directed paths or considered for * directed graphs. */ VALUE cIGraph_betweenness(VALUE self, VALUE vs, VALUE directed){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_bool_t dir = 0; igraph_vector_t res; int i; VALUE betweenness = rb_ary_new(); if(directed == Qtrue) dir = 1; //vector to hold the results of the degree calculations IGRAPH_FINALLY(igraph_vector_destroy, &res); IGRAPH_FINALLY(igraph_vector_destroy, &vidv); IGRAPH_FINALLY(igraph_vs_destroy,&vids); IGRAPH_CHECK(igraph_vector_init(&res,0)); Data_Get_Struct(self, igraph_t, graph); //Convert an array of vertices to a vector of vertex ids IGRAPH_CHECK(igraph_vector_init_int(&vidv,0)); cIGraph_vertex_arr_to_id_vec(self,vs,&vidv); //create vertex selector from the vecotr of ids IGRAPH_CHECK(igraph_vs_vector(&vids,&vidv)); IGRAPH_CHECK(igraph_betweenness(graph,&res,vids,dir)); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(betweenness,rb_float_new((float)VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); IGRAPH_FINALLY_CLEAN(3); return betweenness; }
/* 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_LEN(cuts);i++){ igraph_vector_push_back(&cutsv,NUM2DBL(RARRAY_PTR(cuts)[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); }
/* call-seq: * graph.subcomponent(v,mode) -> Array * * Returns an Array of vertices that are in the same component as the vertex v. * mode defines the type of the component for directed graphs, possible * values: IGraph::OUT: the set of vertices reachable from the vertex, * IGraph::IN the set of vertices from which the vertex is reachable, * IGraph::ALL the graph is considered as an undirected graph. Note that * this is not the same as the union of the previous two. */ VALUE cIGraph_subcomponent(VALUE self, VALUE v, VALUE mode){ igraph_t *graph; igraph_neimode_t pmode = NUM2INT(mode); igraph_vector_t neis; int i; VALUE component = rb_ary_new(); igraph_vector_init_int(&neis,0); Data_Get_Struct(self, igraph_t, graph); igraph_subcomponent(graph, &neis, cIGraph_get_vertex_id(self,v), pmode); for(i=0;i<igraph_vector_size(&neis);i++){ rb_ary_push(component,cIGraph_get_vertex_object(self,VECTOR(neis)[i])); } igraph_vector_destroy(&neis); return component; }
/* call-seq: * graph.topological_sorting(mode) -> Array * * Calculate a possible topological sorting of the graph. A topological * sorting of a directed acyclic graph is a linear ordering of its nodes * where each node comes before all nodes to which it has edges. Every DAG * has at least one topological sort, and may have many. This function * returns a possible topological sort among them. If the graph is not * acyclic (it has at least one cycle), a partial topological sort is * returned and a warning is issued. mode specifies how to use the direction * of the edges. For IGRAPH_OUT, the sorting order ensures that each node * comes before all nodes to which it has edges, so nodes with no incoming * edges go first. For IGRAPH_IN, it is quite the opposite: each node comes * before all nodes from which it receives edges. Nodes with no outgoing * edges go first. */ VALUE cIGraph_topological_sorting(VALUE self, VALUE mode){ igraph_t *graph; igraph_vector_t res; igraph_neimode_t pmode = NUM2INT(mode); VALUE result = rb_ary_new(); int i; igraph_vector_init_int(&res,0); Data_Get_Struct(self, igraph_t, graph); igraph_topological_sorting(graph, &res, pmode); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(result,cIGraph_get_vertex_object(self,VECTOR(res)[i])); } igraph_vector_destroy(&res); return result; }
/* 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 weights, VALUE mode){ igraph_t *graph; igraph_integer_t from_vid; igraph_vs_t to_vids; igraph_vector_t to_vidv; igraph_vector_t wghts; 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_LEN(to); //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); } igraph_vector_init(&wghts,RARRAY_LEN(weights)); for(i=0;i<RARRAY_LEN(weights);i++){ VECTOR(wghts)[i] = NUM2DBL(RARRAY_PTR(weights)[i]); } //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); igraph_get_shortest_paths_dijkstra(graph,&res,from_vid,to_vids,igraph_vector_size(&wghts) > 0 ? &wghts : NULL,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); igraph_vector_destroy(&wghts); return matrix; /* igraph_t *graph; igraph_integer_t from_vid; igraph_vs_t to_vids; igraph_vector_t to_vidv; igraph_vector_t wghts; 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 = 0; Data_Get_Struct(self, igraph_t, graph); n_paths = RARRAY_LEN(to); //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); } igraph_vector_init(&wghts,RARRAY_LEN(weights)); for(i=0;i<RARRAY_LEN(weights);i++){ VECTOR(wghts)[i] = NUM2DBL(RARRAY_PTR(weights)[i]); } //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); //igraph_get_shortest_paths_dijkstra(graph,&res,from_vid,to_vids,igraph_vector_size(&wghts) > 0 ? &wghts : NULL,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); igraph_vector_destroy(&wghts); return matrix; */ }
VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){ igraph_t *graph; igraph_vector_t edge_v; VALUE vertex; VALUE directed; VALUE edges; VALUE attrs; VALUE v_ary; int vertex_n = 0; int current_vertex_id; int i; 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 IGRAPH_FINALLY(igraph_vector_destroy,&edge_v); IGRAPH_FINALLY(igraph_vector_ptr_destroy,&vertex_attr); IGRAPH_FINALLY(igraph_vector_ptr_destroy,&edge_attr); IGRAPH_CHECK(igraph_vector_init_int(&edge_v,0)); IGRAPH_CHECK(igraph_vector_ptr_init(&vertex_attr,0)); IGRAPH_CHECK(igraph_vector_ptr_init(&edge_attr,0)); Data_Get_Struct(self, igraph_t, graph); v_ary = rb_ary_new(); if(!directed) IGRAPH_CHECK(igraph_to_undirected(graph,IGRAPH_TO_UNDIRECTED_COLLAPSE)); //Loop through objects in edge Array for (i=0; i<RARRAY_LEN(edges); i++) { vertex = RARRAY_PTR(edges)[i]; if(rb_ary_includes(v_ary,vertex)){ //If @vertices includes this vertex then look up the vertex number current_vertex_id = NUM2INT(rb_funcall(v_ary,rb_intern("index"),1,vertex)); } else { //Otherwise add to the list of vertices rb_ary_push(v_ary,vertex); current_vertex_id = vertex_n; vertex_n++; //Add object to list of vertex attributes rb_ary_push((VALUE)v_attr_rec.value,vertex); } IGRAPH_CHECK(igraph_vector_push_back(&edge_v,current_vertex_id)); if (i % 2){ if (attrs != Qnil){ rb_ary_push((VALUE)e_attr_rec.value,RARRAY_PTR(attrs)[i/2]); } else { rb_ary_push((VALUE)e_attr_rec.value,Qnil); } } } IGRAPH_CHECK(igraph_vector_ptr_push_back(&vertex_attr, &v_attr_rec)); IGRAPH_CHECK(igraph_vector_ptr_push_back(&edge_attr, &e_attr_rec)); if(igraph_vector_size(&edge_v) > 0){ IGRAPH_CHECK(igraph_add_vertices(graph,vertex_n,&vertex_attr)); IGRAPH_CHECK(igraph_add_edges(graph,&edge_v,&edge_attr)); } igraph_vector_destroy(&edge_v); igraph_vector_ptr_destroy(&vertex_attr); igraph_vector_ptr_destroy(&edge_attr); IGRAPH_FINALLY_CLEAN(3); return self; }