int igraph_is_separator(const igraph_t *graph, const igraph_vs_t candidate, igraph_bool_t *res) { long int no_of_nodes=igraph_vcount(graph); igraph_vector_bool_t removed; igraph_dqueue_t Q; igraph_vector_t neis; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, candidate, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); IGRAPH_CHECK(igraph_vector_bool_init(&removed, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &removed); IGRAPH_CHECK(igraph_dqueue_init(&Q, 100)); IGRAPH_FINALLY(igraph_dqueue_destroy, &Q); IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); IGRAPH_CHECK(igraph_i_is_separator(graph, &vit, -1, res, &removed, &Q, &neis, no_of_nodes)); igraph_vector_destroy(&neis); igraph_dqueue_destroy(&Q); igraph_vector_bool_destroy(&removed); igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(4); return 0; }
int igraph_i_largest_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_ptr_t *res) { graph_t *g; igraph_integer_t vcount = igraph_vcount(graph); if (vcount == 0) { igraph_vector_ptr_clear(res); return IGRAPH_SUCCESS; } igraph_to_cliquer(graph, &g); IGRAPH_FINALLY(graph_free, g); IGRAPH_CHECK(set_weights(vertex_weights, g)); igraph_vector_ptr_clear(res); igraph_cliquer_opt.user_data = res; igraph_cliquer_opt.user_function = &collect_cliques_callback; IGRAPH_FINALLY(free_clique_list, res); CLIQUER_INTERRUPTABLE(clique_find_all(g, 0, 0, FALSE, &igraph_cliquer_opt)); IGRAPH_FINALLY_CLEAN(1); graph_free(g); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_i_cliquer_cliques(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_integer_t min_size, igraph_integer_t max_size) { graph_t *g; igraph_integer_t vcount = igraph_vcount(graph); if (vcount == 0) { igraph_vector_ptr_clear(res); return IGRAPH_SUCCESS; } if (min_size <= 0) min_size = 1; if (max_size <= 0) max_size = 0; if (max_size > 0 && max_size < min_size) IGRAPH_ERROR("max_size must not be smaller than min_size", IGRAPH_EINVAL); igraph_to_cliquer(graph, &g); IGRAPH_FINALLY(graph_free, g); igraph_vector_ptr_clear(res); igraph_cliquer_opt.user_data = res; igraph_cliquer_opt.user_function = &collect_cliques_callback; IGRAPH_FINALLY(free_clique_list, res); CLIQUER_INTERRUPTABLE(clique_unweighted_find_all(g, min_size, max_size, /* maximal= */ FALSE, &igraph_cliquer_opt)); IGRAPH_FINALLY_CLEAN(1); graph_free(g); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_i_local_scan_1_directed(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode) { int no_of_nodes=igraph_vcount(graph); igraph_inclist_t incs; int i, node; igraph_vector_int_t neis; IGRAPH_CHECK(igraph_inclist_init(graph, &incs, mode)); IGRAPH_FINALLY(igraph_inclist_destroy, &incs); igraph_vector_int_init(&neis, no_of_nodes); IGRAPH_FINALLY(igraph_vector_int_destroy, &neis); igraph_vector_resize(res, no_of_nodes); igraph_vector_null(res); for (node=0; node < no_of_nodes; node++) { igraph_vector_int_t *edges1=igraph_inclist_get(&incs, node); int edgeslen1=igraph_vector_int_size(edges1); IGRAPH_ALLOW_INTERRUPTION(); /* Mark neighbors and self*/ VECTOR(neis)[node] = node+1; for (i=0; i<edgeslen1; i++) { int e=VECTOR(*edges1)[i]; int nei=IGRAPH_OTHER(graph, e, node); igraph_real_t w= weights ? VECTOR(*weights)[e] : 1; VECTOR(neis)[nei] = node+1; VECTOR(*res)[node] += w; } /* Crawl neighbors */ for (i=0; i<edgeslen1; i++) { int e2=VECTOR(*edges1)[i]; int nei=IGRAPH_OTHER(graph, e2, node); igraph_vector_int_t *edges2=igraph_inclist_get(&incs, nei); int j, edgeslen2=igraph_vector_int_size(edges2); for (j=0; j<edgeslen2; j++) { int e2=VECTOR(*edges2)[j]; int nei2=IGRAPH_OTHER(graph, e2, nei); igraph_real_t w2= weights ? VECTOR(*weights)[e2] : 1; if (VECTOR(neis)[nei2] == node+1) { VECTOR(*res)[node] += w2; } } } } /* node < no_of_nodes */ igraph_vector_int_destroy(&neis); igraph_inclist_destroy(&incs); IGRAPH_FINALLY_CLEAN(2); return 0; }
int igraph_adjlist_init_complementer(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_bool_t loops) { long int i, j, k, n; igraph_bool_t* seen; igraph_vector_t vec; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_EINVMODE); } if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; } al->length=igraph_vcount(graph); al->adjs=igraph_Calloc(al->length, igraph_vector_t); if (al->adjs == 0) { IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_adjlist_destroy, al); n=al->length; seen=igraph_Calloc(n, igraph_bool_t); if (seen==0) { IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, seen); IGRAPH_VECTOR_INIT_FINALLY(&vec, 0); for (i=0; i<al->length; i++) { IGRAPH_ALLOW_INTERRUPTION(); igraph_neighbors(graph, &vec, i, mode); memset(seen, 0, sizeof(igraph_bool_t)*al->length); n=al->length; if (!loops) { seen[i] = 1; n--; } for (j=0; j<igraph_vector_size(&vec); j++) { if (! seen [ (long int) VECTOR(vec)[j] ] ) { n--; seen[ (long int) VECTOR(vec)[j] ] = 1; } } IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], n)); for (j=0, k=0; k<n; j++) { if (!seen[j]) { VECTOR(al->adjs[i])[k++] = j; } } } igraph_Free(seen); igraph_vector_destroy(&vec); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_i_separators_store(igraph_vector_ptr_t *separators, const igraph_adjlist_t *adjlist, igraph_vector_t *components, igraph_vector_t *leaveout, unsigned long int *mark, igraph_vector_t *sorter) { /* We need to stote N(C), the neighborhood of C, but only if it is * not already stored among the separators. */ long int cptr=0, next, complen=igraph_vector_size(components); while (cptr < complen) { long int saved=cptr; igraph_vector_clear(sorter); /* Calculate N(C) for the next C */ while ( (next=(long int) VECTOR(*components)[cptr++]) != -1) { VECTOR(*leaveout)[next] = *mark; } cptr=saved; while ( (next=(long int) VECTOR(*components)[cptr++]) != -1) { igraph_vector_int_t *neis=igraph_adjlist_get(adjlist, next); long int j, nn=igraph_vector_int_size(neis); for (j=0; j<nn; j++) { long int nei=(long int) VECTOR(*neis)[j]; if (VECTOR(*leaveout)[nei] != *mark) { igraph_vector_push_back(sorter, nei); VECTOR(*leaveout)[nei] = *mark; } } } igraph_vector_sort(sorter); UPDATEMARK(); /* Add it to the list of separators, if it is new */ if (igraph_i_separators_newsep(separators, sorter)) { igraph_vector_t *newc=igraph_Calloc(1, igraph_vector_t); if (!newc) { IGRAPH_ERROR("Cannot calculate minimal separators", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, newc); igraph_vector_copy(newc, sorter); IGRAPH_FINALLY(igraph_vector_destroy, newc); IGRAPH_CHECK(igraph_vector_ptr_push_back(separators, newc)); IGRAPH_FINALLY_CLEAN(2); } } /* while cptr < complen */ return 0; }
int igraph_i_maximal_or_largest_cliques_or_indsets(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_integer_t *clique_number, igraph_bool_t keep_only_largest, igraph_bool_t complementer) { igraph_i_max_ind_vsets_data_t clqdata; long int no_of_nodes = igraph_vcount(graph), i; if (igraph_is_directed(graph)) IGRAPH_WARNING("directionality of edges is ignored for directed graphs"); clqdata.matrix_size=no_of_nodes; clqdata.keep_only_largest=keep_only_largest; if (complementer) IGRAPH_CHECK(igraph_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, 0)); else IGRAPH_CHECK(igraph_adjlist_init(graph, &clqdata.adj_list, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjlist_destroy, &clqdata.adj_list); clqdata.IS = igraph_Calloc(no_of_nodes, igraph_integer_t); if (clqdata.IS == 0) IGRAPH_ERROR("igraph_i_maximal_or_largest_cliques_or_indsets failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes); for (i=0; i<no_of_nodes; i++) VECTOR(clqdata.deg)[i] = igraph_vector_size(igraph_adjlist_get(&clqdata.adj_list, i)); clqdata.buckets = igraph_Calloc(no_of_nodes+1, igraph_set_t); if (clqdata.buckets == 0) IGRAPH_ERROR("igraph_maximal_or_largest_cliques_or_indsets failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_i_free_set_array, clqdata.buckets); for (i=0; i<no_of_nodes; i++) IGRAPH_CHECK(igraph_set_init(&clqdata.buckets[i], 0)); if (res) igraph_vector_ptr_clear(res); /* Do the show */ clqdata.largest_set_size=0; IGRAPH_CHECK(igraph_i_maximal_independent_vertex_sets_backtrack(graph, res, &clqdata, 0)); /* Cleanup */ for (i=0; i<no_of_nodes; i++) igraph_set_destroy(&clqdata.buckets[i]); igraph_adjlist_destroy(&clqdata.adj_list); igraph_vector_destroy(&clqdata.deg); igraph_free(clqdata.IS); igraph_free(clqdata.buckets); IGRAPH_FINALLY_CLEAN(4); if (clique_number) *clique_number = clqdata.largest_set_size; return 0; }
/** * \ingroup structural * \function igraph_similarity_jaccard * \brief Jaccard similarity coefficient for the given vertices. * * </para><para> * The Jaccard similarity coefficient of two vertices is the number of common * neighbors divided by the number of vertices that are neighbors of at * least one of the two vertices being considered. This function calculates * the pairwise Jaccard similarities for some (or all) of the vertices. * * \param graph The graph object to analyze * \param res Pointer to a matrix, the result of the calculation will * be stored here. The number of its rows and columns is the same * as the number of vertex ids in \p vids. * \param vids The vertex ids of the vertices for which the * calculation will be done. * \param mode The type of neighbors to be used for the calculation in * directed graphs. Possible values: * \clist * \cli IGRAPH_OUT * the outgoing edges will be considered for each node. * \cli IGRAPH_IN * the incoming edges will be considered for each node. * \cli IGRAPH_ALL * the directed graph is considered as an undirected one for the * computation. * \endclist * \param loops Whether to include the vertices themselves in the neighbor * sets. * \return Error code: * \clist * \cli IGRAPH_ENOMEM * not enough memory for temporary data. * \cli IGRAPH_EINVVID * invalid vertex id passed. * \cli IGRAPH_EINVMODE * invalid mode argument. * \endclist * * Time complexity: O(|V|^2 d), * |V| is the number of vertices in the vertex iterator given, d is the * (maximum) degree of the vertices in the graph. * * \sa \ref igraph_similarity_dice(), a measure very similar to the Jaccard * coefficient * * \example examples/simple/igraph_similarity.c */ int igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops) { igraph_lazy_adjlist_t al; igraph_vit_t vit, vit2; long int i, j, k; long int len_union, len_intersection; igraph_vector_t *v1, *v2; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit2)); IGRAPH_FINALLY(igraph_vit_destroy, &vit2); IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &al, mode, IGRAPH_SIMPLIFY)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &al); IGRAPH_CHECK(igraph_matrix_resize(res, IGRAPH_VIT_SIZE(vit), IGRAPH_VIT_SIZE(vit))); if (loops) { for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { i=IGRAPH_VIT_GET(vit); v1=igraph_lazy_adjlist_get(&al, (igraph_integer_t) i); if (!igraph_vector_binsearch(v1, i, &k)) igraph_vector_insert(v1, k, i); } } for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { MATRIX(*res, i, i) = 1.0; for (IGRAPH_VIT_RESET(vit2), j=0; !IGRAPH_VIT_END(vit2); IGRAPH_VIT_NEXT(vit2), j++) { if (j <= i) continue; v1=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit)); v2=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit2)); igraph_i_neisets_intersect(v1, v2, &len_union, &len_intersection); if (len_union > 0) MATRIX(*res, i, j) = ((igraph_real_t)len_intersection)/len_union; else MATRIX(*res, i, j) = 0.0; MATRIX(*res, j, i) = MATRIX(*res, i, j); } } igraph_lazy_adjlist_destroy(&al); igraph_vit_destroy(&vit); igraph_vit_destroy(&vit2); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_is_minimal_separator(const igraph_t *graph, const igraph_vs_t candidate, igraph_bool_t *res) { long int no_of_nodes=igraph_vcount(graph); igraph_vector_bool_t removed; igraph_dqueue_t Q; igraph_vector_t neis; long int candsize; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, candidate, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); candsize=IGRAPH_VIT_SIZE(vit); IGRAPH_CHECK(igraph_vector_bool_init(&removed, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &removed); IGRAPH_CHECK(igraph_dqueue_init(&Q, 100)); IGRAPH_FINALLY(igraph_dqueue_destroy, &Q); IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); /* Is it a separator at all? */ IGRAPH_CHECK(igraph_i_is_separator(graph, &vit, -1, res, &removed, &Q, &neis, no_of_nodes)); if (!(*res)) { /* Not a separator at all, nothing to do, *res is already set */ } else if (candsize == 0) { /* Nothing to do, minimal, *res is already set */ } else { /* General case, we need to remove each vertex from 'candidate' * and check whether the remainder is a separator. If this is * false for all vertices, then 'candidate' is a minimal * separator. */ long int i; for (i=0, *res=0; i<candsize && (!*res); i++) { igraph_vector_bool_null(&removed); IGRAPH_CHECK(igraph_i_is_separator(graph, &vit, i, res, &removed, &Q, &neis, no_of_nodes)); } (*res) = (*res) ? 0 : 1; /* opposite */ } igraph_vector_destroy(&neis); igraph_dqueue_destroy(&Q); igraph_vector_bool_destroy(&removed); igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(4); return 0; }
/* 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; }
int igraph_get_edgelist(const igraph_t *graph, igraph_vector_t *res, igraph_bool_t bycol) { igraph_eit_t edgeit; long int no_of_edges=igraph_ecount(graph); long int vptr=0; igraph_integer_t from, to; IGRAPH_CHECK(igraph_vector_resize(res, no_of_edges*2)); IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &edgeit)); IGRAPH_FINALLY(igraph_eit_destroy, &edgeit); if (bycol) { while (!IGRAPH_EIT_END(edgeit)) { igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &from, &to); VECTOR(*res)[vptr]=from; VECTOR(*res)[vptr+no_of_edges]=to; vptr++; IGRAPH_EIT_NEXT(edgeit); } } else { while (!IGRAPH_EIT_END(edgeit)) { igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &from, &to); VECTOR(*res)[vptr++]=from; VECTOR(*res)[vptr++]=to; IGRAPH_EIT_NEXT(edgeit); } } igraph_eit_destroy(&edgeit); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_i_weighted_clique_number(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_real_t *res) { graph_t *g; igraph_integer_t vcount = igraph_vcount(graph); if (vcount == 0) { *res = 0; return IGRAPH_SUCCESS; } igraph_to_cliquer(graph, &g); IGRAPH_FINALLY(graph_free, g); IGRAPH_CHECK(set_weights(vertex_weights, g)); igraph_cliquer_opt.user_function = NULL; /* we are not using a callback function, thus this is not interruptable */ *res = clique_max_weight(g, &igraph_cliquer_opt); graph_free(g); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_i_cliquer_callback(const igraph_t *graph, igraph_integer_t min_size, igraph_integer_t max_size, igraph_clique_handler_t *cliquehandler_fn, void *arg) { graph_t *g; struct callback_data cd; igraph_integer_t vcount = igraph_vcount(graph); if (vcount == 0) return IGRAPH_SUCCESS; if (min_size <= 0) min_size = 1; if (max_size <= 0) max_size = 0; if (max_size > 0 && max_size < min_size) IGRAPH_ERROR("max_size must not be smaller than min_size", IGRAPH_EINVAL); igraph_to_cliquer(graph, &g); IGRAPH_FINALLY(graph_free, g); cd.handler = cliquehandler_fn; cd.arg = arg; igraph_cliquer_opt.user_data = &cd; igraph_cliquer_opt.user_function = &callback_callback; CLIQUER_INTERRUPTABLE(clique_unweighted_find_all(g, min_size, max_size, /* maximal= */ FALSE, &igraph_cliquer_opt)); graph_free(g); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_inclist_init(const igraph_t *graph, igraph_inclist_t *il, igraph_neimode_t mode) { long int i; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create incidence list view", IGRAPH_EINVMODE); } if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; } il->length=igraph_vcount(graph); il->incs=igraph_Calloc(il->length, igraph_vector_t); if (il->incs == 0) { IGRAPH_ERROR("Cannot create incidence list view", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_inclist_destroy, il); for (i=0; i<il->length; i++) { IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_vector_init(&il->incs[i], 0)); IGRAPH_CHECK(igraph_incident(graph, &il->incs[i], i, mode)); } IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_i_trans4_il_simplify(const igraph_t *graph, igraph_inclist_t *il, const igraph_vector_int_t *rank) { long int i; long int n=il->length; igraph_vector_int_t mark; igraph_vector_int_init(&mark, n); IGRAPH_FINALLY(igraph_vector_int_destroy, &mark); for (i=0; i<n; i++) { igraph_vector_int_t *v=&il->incs[i]; int j, l=igraph_vector_int_size(v); int irank=VECTOR(*rank)[i]; VECTOR(mark)[i] = i+1; for (j=0; j<l; /* nothing */) { long int edge=(long int) VECTOR(*v)[j]; long int e=IGRAPH_OTHER(graph, edge, i); if (VECTOR(*rank)[e] > irank && VECTOR(mark)[e] != i+1) { VECTOR(mark)[e]=i+1; j++; } else { VECTOR(*v)[j] = igraph_vector_int_tail(v); igraph_vector_int_pop_back(v); l--; } } } igraph_vector_int_destroy(&mark); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_local_scan_0_them(const igraph_t *us, const igraph_t *them, igraph_vector_t *res, const igraph_vector_t *weights_them, igraph_neimode_t mode) { igraph_t is; if (igraph_vcount(us) != igraph_vcount(them)) { IGRAPH_ERROR("Number of vertices don't match in scan-0", IGRAPH_EINVAL); } if (igraph_is_directed(us) != igraph_is_directed(them)) { IGRAPH_ERROR("Directedness don't match in scan-0", IGRAPH_EINVAL); } if (weights_them) { return igraph_i_local_scan_0_them_w(us, them, res, weights_them, mode); } igraph_intersection(&is, us, them, /*edgemap1=*/ 0, /*edgemap2=*/ 0); IGRAPH_FINALLY(igraph_destroy, &is); igraph_degree(&is, res, igraph_vss_all(), mode, IGRAPH_LOOPS); igraph_destroy(&is); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode) { long int i; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_EINVMODE); } if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; } al->length=igraph_vcount(graph); al->adjs=igraph_Calloc(al->length, igraph_vector_t); if (al->adjs == 0) { IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_adjlist_destroy, al); for (i=0; i<al->length; i++) { IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], 0)); IGRAPH_CHECK(igraph_neighbors(graph, &al->adjs[i], i, mode)); } IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_largest_cliques(const igraph_t *graph, igraph_vector_ptr_t *res) { igraph_vector_ptr_clear(res); IGRAPH_FINALLY(igraph_i_cliques_free_res, res); IGRAPH_CHECK(igraph_i_maximal_cliques(graph, &igraph_i_largest_cliques_store, (void*)res)); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_2dgrid_init(igraph_2dgrid_t *grid, igraph_matrix_t *coords, igraph_real_t minx, igraph_real_t maxx, igraph_real_t deltax, igraph_real_t miny, igraph_real_t maxy, igraph_real_t deltay) { long int i; grid->coords=coords; grid->minx=minx; grid->maxx=maxx; grid->deltax=deltax; grid->miny=miny; grid->maxy=maxy; grid->deltay=deltay; grid->stepsx=(long int) ceil((maxx-minx)/deltax); grid->stepsy=(long int) ceil((maxy-miny)/deltay); IGRAPH_CHECK(igraph_matrix_init(&grid->startidx, grid->stepsx, grid->stepsy)); IGRAPH_FINALLY(igraph_matrix_destroy, &grid->startidx); IGRAPH_VECTOR_INIT_FINALLY(&grid->next, igraph_matrix_nrow(coords)); IGRAPH_VECTOR_INIT_FINALLY(&grid->prev, igraph_matrix_nrow(coords)); for (i=0; i<igraph_vector_size(&grid->next); i++) { VECTOR(grid->next)[i]=-1; } grid->massx=0; grid->massy=0; grid->vertices=0; IGRAPH_FINALLY_CLEAN(3); return 0; }
/** * \ingroup structural * \function igraph_similarity_jaccard_es * \brief Jaccard similarity coefficient for a given edge selector. * * </para><para> * The Jaccard similarity coefficient of two vertices is the number of common * neighbors divided by the number of vertices that are neighbors of at * least one of the two vertices being considered. This function calculates * the pairwise Jaccard similarities for the endpoints of edges in a given edge * selector. * * \param graph The graph object to analyze * \param res Pointer to a vector, the result of the calculation will * be stored here. The number of elements is the same as the number * of edges in \p es. * \param es An edge selector that specifies the edges to be included in the * result. * \param mode The type of neighbors to be used for the calculation in * directed graphs. Possible values: * \clist * \cli IGRAPH_OUT * the outgoing edges will be considered for each node. * \cli IGRAPH_IN * the incoming edges will be considered for each node. * \cli IGRAPH_ALL * the directed graph is considered as an undirected one for the * computation. * \endclist * \param loops Whether to include the vertices themselves in the neighbor * sets. * \return Error code: * \clist * \cli IGRAPH_ENOMEM * not enough memory for temporary data. * \cli IGRAPH_EINVVID * invalid vertex id passed. * \cli IGRAPH_EINVMODE * invalid mode argument. * \endclist * * Time complexity: O(nd), n is the number of edges in the edge selector, d is * the (maximum) degree of the vertices in the graph. * * \sa \ref igraph_similarity_jaccard() and \ref igraph_similarity_jaccard_pairs() * to calculate the Jaccard similarity between all pairs of a vertex set or * some selected vertex pairs, or \ref igraph_similarity_dice(), * \ref igraph_similarity_dice_pairs() and \ref igraph_similarity_dice_es() for a * measure very similar to the Jaccard coefficient * * \example examples/simple/igraph_similarity.c */ int igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector_t *res, const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops) { igraph_vector_t v; igraph_eit_t eit; IGRAPH_VECTOR_INIT_FINALLY(&v, 0); IGRAPH_CHECK(igraph_eit_create(graph, es, &eit)); IGRAPH_FINALLY(igraph_eit_destroy, &eit); while (!IGRAPH_EIT_END(eit)) { long int eid = IGRAPH_EIT_GET(eit); igraph_vector_push_back(&v, IGRAPH_FROM(graph, eid)); igraph_vector_push_back(&v, IGRAPH_TO(graph, eid)); IGRAPH_EIT_NEXT(eit); } igraph_eit_destroy(&eit); IGRAPH_FINALLY_CLEAN(1); IGRAPH_CHECK(igraph_similarity_jaccard_pairs(graph, res, &v, mode, loops)); igraph_vector_destroy(&v); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_i_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_ptr_t *res, igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal) { graph_t *g; igraph_integer_t vcount = igraph_vcount(graph); if (vcount == 0) { igraph_vector_ptr_clear(res); return IGRAPH_SUCCESS; } if (min_weight != (int) min_weight) { IGRAPH_WARNING("Only integer vertex weights are supported; the minimum weight will be truncated to its integer part"); min_weight = (int) min_weight; } if (max_weight != (int) max_weight) { IGRAPH_WARNING("Only integer vertex weights are supported; the maximum weight will be truncated to its integer part"); max_weight = (int) max_weight; } if (min_weight <= 0) min_weight = 1; if (max_weight <= 0) max_weight = 0; if (max_weight > 0 && max_weight < min_weight) IGRAPH_ERROR("max_weight must not be smaller than min_weight", IGRAPH_EINVAL); igraph_to_cliquer(graph, &g); IGRAPH_FINALLY(graph_free, g); IGRAPH_CHECK(set_weights(vertex_weights, g)); igraph_vector_ptr_clear(res); igraph_cliquer_opt.user_data = res; igraph_cliquer_opt.user_function = &collect_cliques_callback; IGRAPH_FINALLY(free_clique_list, res); CLIQUER_INTERRUPTABLE(clique_find_all(g, min_weight, max_weight, maximal, &igraph_cliquer_opt)); IGRAPH_FINALLY_CLEAN(1); graph_free(g); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; }
int igraph_bridges(const igraph_t *graph, igraph_vector_t *bridges) { igraph_inclist_t il; igraph_vector_bool_t visited; igraph_vector_int_t disc, low; igraph_vector_int_t parent; long n; long i; igraph_integer_t time; n = igraph_vcount(graph); IGRAPH_CHECK(igraph_inclist_init(graph, &il, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_inclist_destroy, &il); IGRAPH_CHECK(igraph_vector_bool_init(&visited, n)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &visited); IGRAPH_CHECK(igraph_vector_int_init(&disc, n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &disc); IGRAPH_CHECK(igraph_vector_int_init(&low, n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &low); IGRAPH_CHECK(igraph_vector_int_init(&parent, n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &parent); for (i=0; i < n; ++i) VECTOR(parent)[i] = -1; igraph_vector_clear(bridges); time = 0; for (i=0; i < n; ++i) if (! VECTOR(visited)[i]) IGRAPH_CHECK(igraph_i_bridges_rec(graph, &il, i, &time, bridges, &visited, &disc, &low, &parent)); igraph_vector_int_destroy(&parent); igraph_vector_int_destroy(&low); igraph_vector_int_destroy(&disc); igraph_vector_bool_destroy(&visited); igraph_inclist_destroy(&il); IGRAPH_FINALLY_CLEAN(5); return IGRAPH_SUCCESS; }
/* call-seq: * graph.eigenvector_centrality(scale, weights) -> Array * * Returns a two-element arrar, the first element of which is an Array of * eigenvector centrality scores for graph, and the second of which is the * eigenvalue. * * scale is a boolean value. If true, the scores will be weighted so that the * absolute value of the maximum centrality is one. * * weights is an Array giving the weights of the edges. If nil, the edges are unweighted. */ VALUE cIGraph_eigenvector_centrality(VALUE self, VALUE scale, VALUE weights) { int i; igraph_t *graph; igraph_vector_t vec; igraph_real_t val; igraph_vector_t wgts; igraph_arpack_options_t arpack_opt; igraph_bool_t sc = 0; VALUE eigenvector = rb_ary_new(); VALUE rb_res = rb_ary_new(); IGRAPH_FINALLY(igraph_vector_destroy, &vec); IGRAPH_FINALLY(igraph_vector_destroy, &wgts); IGRAPH_CHECK(igraph_vector_init(&vec,0)); IGRAPH_CHECK(igraph_vector_init(&wgts,0)); igraph_arpack_options_init(&arpack_opt); if (scale == Qtrue) sc = 1; Data_Get_Struct(self, igraph_t, graph); if (weights == Qnil) { IGRAPH_CHECK(igraph_eigenvector_centrality(graph, &vec, &val, sc, NULL, &arpack_opt)); } else { for(i = 0; i < RARRAY_LEN(weights); i++) IGRAPH_CHECK(igraph_vector_push_back(&wgts, NUM2DBL(RARRAY_PTR(weights)[i]))); IGRAPH_CHECK(igraph_eigenvector_centrality(graph, &vec, &val, sc, &wgts, &arpack_opt)); } for(i = 0; i < igraph_vector_size(&vec); i++) rb_ary_push(eigenvector, rb_float_new(VECTOR(vec)[i])); igraph_vector_destroy(&vec); igraph_vector_destroy(&wgts); rb_ary_push(rb_res, eigenvector); rb_ary_push(rb_res, rb_float_new(val)); IGRAPH_FINALLY_CLEAN(2); return rb_res; }
int igraph_i_maximum_bipartite_matching_unweighted_relabel(const igraph_t* graph, const igraph_vector_bool_t* types, igraph_vector_t* labels, igraph_vector_long_t* match, igraph_bool_t smaller_set) { long int i, j, n, no_of_nodes = igraph_vcount(graph), matched_to; igraph_dqueue_long_t q; igraph_vector_t neis; debug("Running global relabeling.\n"); /* Set all the labels to no_of_nodes first */ igraph_vector_fill(labels, no_of_nodes); /* Allocate vector for neighbors */ IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); /* Create a FIFO for the BFS and initialize it with the unmatched rows * (i.e. members of the larger set) */ IGRAPH_CHECK(igraph_dqueue_long_init(&q, 0)); IGRAPH_FINALLY(igraph_dqueue_long_destroy, &q); for (i = 0; i < no_of_nodes; i++) { if (VECTOR(*types)[i] != smaller_set && VECTOR(*match)[i] == -1) { IGRAPH_CHECK(igraph_dqueue_long_push(&q, i)); VECTOR(*labels)[i] = 0; } } /* Run the BFS */ while (!igraph_dqueue_long_empty(&q)) { long int v = igraph_dqueue_long_pop(&q); long int w; IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) v, IGRAPH_ALL)); n = igraph_vector_size(&neis); //igraph_vector_shuffle(&neis); for (j = 0; j < n; j++) { w = (long int) VECTOR(neis)[j]; if (VECTOR(*labels)[w] == no_of_nodes) { VECTOR(*labels)[w] = VECTOR(*labels)[v] + 1; matched_to = VECTOR(*match)[w]; if (matched_to != -1 && VECTOR(*labels)[matched_to] == no_of_nodes) { IGRAPH_CHECK(igraph_dqueue_long_push(&q, matched_to)); VECTOR(*labels)[matched_to] = VECTOR(*labels)[w] + 1; } } } } printf("Inside relabel : "); igraph_vector_print(labels); igraph_dqueue_long_destroy(&q); igraph_vector_destroy(&neis); IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; }
/* removes multiple edges and returns new edge id's for each edge in |E|log|E| */ int igraph_i_multilevel_simplify_multiple(igraph_t *graph, igraph_vector_t *eids) { long int ecount = igraph_ecount(graph); long int i, l = -1, last_from = -1, last_to = -1; igraph_bool_t directed = igraph_is_directed(graph); igraph_integer_t from, to; igraph_vector_t edges; igraph_i_multilevel_link *links; /* Make sure there's enough space in eids to store the new edge IDs */ IGRAPH_CHECK(igraph_vector_resize(eids, ecount)); links = igraph_Calloc(ecount, igraph_i_multilevel_link); if (links == 0) { IGRAPH_ERROR("multi-level community structure detection failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, links); for (i = 0; i < ecount; i++) { igraph_edge(graph, (igraph_integer_t) i, &from, &to); links[i].from = from; links[i].to = to; links[i].id = i; } qsort((void*)links, (size_t) ecount, sizeof(igraph_i_multilevel_link), igraph_i_multilevel_link_cmp); IGRAPH_VECTOR_INIT_FINALLY(&edges, 0); for (i = 0; i < ecount; i++) { if (links[i].from == last_from && links[i].to == last_to) { VECTOR(*eids)[links[i].id] = l; continue; } last_from = links[i].from; last_to = links[i].to; igraph_vector_push_back(&edges, last_from); igraph_vector_push_back(&edges, last_to); l++; VECTOR(*eids)[links[i].id] = l; } free(links); IGRAPH_FINALLY_CLEAN(1); igraph_destroy(graph); IGRAPH_CHECK(igraph_create(graph, &edges, igraph_vcount(graph), directed)); igraph_vector_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); return 0; }
/* 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; }
int igraph_random_walk(const igraph_t *graph, igraph_vector_t *walk, igraph_integer_t start, igraph_neimode_t mode, igraph_integer_t steps, igraph_random_walk_stuck_t stuck) { /* TODO: - multiple walks potentially from multiple start vertices - weights */ igraph_lazy_adjlist_t adj; igraph_integer_t vc = igraph_vcount(graph); igraph_integer_t i; if (start < 0 || start >= vc) { IGRAPH_ERROR("Invalid start vertex", IGRAPH_EINVAL); } if (steps < 0) { IGRAPH_ERROR("Invalid number of steps", IGRAPH_EINVAL); } IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adj, mode, IGRAPH_DONT_SIMPLIFY)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adj); IGRAPH_CHECK(igraph_vector_resize(walk, steps)); RNG_BEGIN(); VECTOR(*walk)[0] = start; for (i = 1; i < steps; i++) { igraph_vector_t *neis; igraph_integer_t nn; neis = igraph_lazy_adjlist_get(&adj, start); nn = igraph_vector_size(neis); if (IGRAPH_UNLIKELY(nn == 0)) { igraph_vector_resize(walk, i); if (stuck == IGRAPH_RANDOM_WALK_STUCK_RETURN) { break; } else { IGRAPH_ERROR("Random walk got stuck", IGRAPH_ERWSTUCK); } } start = VECTOR(*walk)[i] = VECTOR(*neis)[ RNG_INTEGER(0, nn - 1) ]; } RNG_END(); igraph_lazy_adjlist_destroy(&adj); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_biguint_fprint(igraph_biguint_t *b, FILE *file) { /* It is hard to control memory allocation for the bn2d function, so we do our own version */ long int n=igraph_biguint_size(b); long int size=12*n+1; igraph_biguint_t tmp; char *dst; limb_t r; /* Zero? */ if (!bn_cmp_limb(VECTOR(b->v), 0, n)) { fputs("0", file); return 0; } IGRAPH_CHECK(igraph_biguint_copy(&tmp, b)); IGRAPH_FINALLY(igraph_biguint_destroy, &tmp); dst=igraph_Calloc(size, char); if (!dst) { IGRAPH_ERROR("Cannot print big number", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, dst); size--; dst[size]='\0'; while (0 != bn_cmp_limb(VECTOR(tmp.v), 0, n)) { r=bn_div_limb(VECTOR(tmp.v), VECTOR(tmp.v), 10, n); dst[--size] = '0' + r; } fputs(&dst[size], file); igraph_Free(dst); igraph_biguint_destroy(&tmp); IGRAPH_FINALLY_CLEAN(2); return 0; }
int igraph_is_connected_weak(const igraph_t *graph, igraph_bool_t *res) { long int no_of_nodes=igraph_vcount(graph); char *already_added; igraph_vector_t neis=IGRAPH_VECTOR_NULL; igraph_dqueue_t q=IGRAPH_DQUEUE_NULL; long int i, j; if (no_of_nodes == 0) { *res = 1; return IGRAPH_SUCCESS; } already_added=igraph_Calloc(no_of_nodes, char); if (already_added==0) { IGRAPH_ERROR("is connected (weak) failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, already_added); /* TODO: hack */ IGRAPH_DQUEUE_INIT_FINALLY(&q, 10); IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); /* Try to find at least two clusters */ already_added[0]=1; IGRAPH_CHECK(igraph_dqueue_push(&q, 0)); j=1; while ( !igraph_dqueue_empty(&q)) { long int actnode=(long int) igraph_dqueue_pop(&q); IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) actnode, IGRAPH_ALL)); for (i=0; i <igraph_vector_size(&neis); i++) { long int neighbor=(long int) VECTOR(neis)[i]; if (already_added[neighbor] != 0) { continue; } IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor)); j++; already_added[neighbor]++; } } /* Connected? */ *res = (j == no_of_nodes); igraph_Free(already_added); igraph_dqueue_destroy(&q); igraph_vector_destroy(&neis); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_lapack_dgetrf(igraph_matrix_t *a, igraph_vector_int_t *ipiv, int *info) { int m=(int) igraph_matrix_nrow(a); int n=(int) igraph_matrix_ncol(a); int lda=m > 0 ? m : 1; igraph_vector_int_t *myipiv=ipiv, vipiv; if (!ipiv) { IGRAPH_CHECK(igraph_vector_int_init(&vipiv, m<n ? m : n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &vipiv); myipiv=&vipiv; } igraphdgetrf_(&m, &n, VECTOR(a->data), &lda, VECTOR(*myipiv), info); if (*info > 0) { IGRAPH_WARNING("LU: factor is exactly singular"); } else if (*info < 0) { switch(*info) { case -1: IGRAPH_ERROR("Invalid number of rows", IGRAPH_ELAPACK); break; case -2: IGRAPH_ERROR("Invalid number of columns", IGRAPH_ELAPACK); break; case -3: IGRAPH_ERROR("Invalid input matrix", IGRAPH_ELAPACK); break; case -4: IGRAPH_ERROR("Invalid LDA parameter", IGRAPH_ELAPACK); break; case -5: IGRAPH_ERROR("Invalid pivot vector", IGRAPH_ELAPACK); break; case -6: IGRAPH_ERROR("Invalid info argument", IGRAPH_ELAPACK); break; default: IGRAPH_ERROR("Unknown LAPACK error", IGRAPH_ELAPACK); break; } } if (!ipiv) { igraph_vector_int_destroy(&vipiv); IGRAPH_FINALLY_CLEAN(1); } return 0; }