static int igraph_i_bridges_rec(const igraph_t *graph, const igraph_inclist_t *il, igraph_integer_t u, igraph_integer_t *time, igraph_vector_t *bridges, igraph_vector_bool_t *visited, igraph_vector_int_t *disc, igraph_vector_int_t *low, igraph_vector_int_t *parent) { igraph_vector_int_t *incedges; long nc; /* neighbour count */ long i; VECTOR(*visited)[u] = 1; *time += 1; VECTOR(*disc)[u] = *time; VECTOR(*low)[u] = *time; incedges = igraph_inclist_get(il, u); nc = igraph_vector_int_size(incedges); for (i=0; i < nc; ++i) { long edge = (long) VECTOR(*incedges)[i]; igraph_integer_t v = IGRAPH_TO(graph, edge) == u ? IGRAPH_FROM(graph, edge) : IGRAPH_TO(graph, edge); if (! VECTOR(*visited)[v]) { VECTOR(*parent)[v] = u; IGRAPH_CHECK(igraph_i_bridges_rec(graph, il, v, time, bridges, visited, disc, low, parent)); VECTOR(*low)[u] = VECTOR(*low)[u] < VECTOR(*low)[v] ? VECTOR(*low)[u] : VECTOR(*low)[v]; if (VECTOR(*low)[v] > VECTOR(*disc)[u]) IGRAPH_CHECK(igraph_vector_push_back(bridges, edge)); } else if (v != VECTOR(*parent)[u]) { VECTOR(*low)[u] = VECTOR(*low)[u] < VECTOR(*disc)[v] ? VECTOR(*low)[u] : VECTOR(*disc)[v]; } } return IGRAPH_SUCCESS; }
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_i_largest_cliques_store(const igraph_vector_t* clique, void* data, igraph_bool_t* cont) { igraph_vector_ptr_t* result = (igraph_vector_ptr_t*)data; igraph_vector_t* vec; long int i, n; /* Is the current clique at least as large as the others that we have found? */ if (!igraph_vector_ptr_empty(result)) { n = igraph_vector_size(clique); if (n < igraph_vector_size(VECTOR(*result)[0])) return IGRAPH_SUCCESS; if (n > igraph_vector_size(VECTOR(*result)[0])) { for (i = 0; i < igraph_vector_ptr_size(result); i++) igraph_vector_destroy(VECTOR(*result)[i]); igraph_vector_ptr_free_all(result); igraph_vector_ptr_resize(result, 0); } } vec = igraph_Calloc(1, igraph_vector_t); if (vec == 0) IGRAPH_ERROR("cannot allocate memory for storing next clique", IGRAPH_ENOMEM); IGRAPH_CHECK(igraph_vector_copy(vec, clique)); IGRAPH_CHECK(igraph_vector_ptr_push_back(result, vec)); return IGRAPH_SUCCESS; }
/** * \ingroup interface * \function igraph_empty_attrs * \brief Creates an empty graph with some vertices, no edges and some graph attributes. * * </para><para> * Use this instead of \ref igraph_empty() if you wish to add some graph * attributes right after initialization. This function is currently * not very interesting for the ordinary user, just supply 0 here or * use \ref igraph_empty(). * \param graph Pointer to a not-yet initialized graph object. * \param n The number of vertices in the graph, a non-negative * integer number is expected. * \param directed Whether the graph is directed or not. * \param attr The attributes. * \return Error code: * \c IGRAPH_EINVAL: invalid number of vertices. * * Time complexity: O(|V|) for a graph with * |V| vertices (and no edges). */ int igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, void* attr) { if (n<0) { IGRAPH_ERROR("cannot create empty graph with negative number of vertices", IGRAPH_EINVAL); } if (!IGRAPH_FINITE(n)) { IGRAPH_ERROR("number of vertices is not finite (NA, NaN or Inf)", IGRAPH_EINVAL); } graph->n=0; graph->directed=directed; IGRAPH_VECTOR_INIT_FINALLY(&graph->from, 0); IGRAPH_VECTOR_INIT_FINALLY(&graph->to, 0); IGRAPH_VECTOR_INIT_FINALLY(&graph->oi, 0); IGRAPH_VECTOR_INIT_FINALLY(&graph->ii, 0); IGRAPH_VECTOR_INIT_FINALLY(&graph->os, 1); IGRAPH_VECTOR_INIT_FINALLY(&graph->is, 1); VECTOR(graph->os)[0]=0; VECTOR(graph->is)[0]=0; /* init attributes */ graph->attr=0; IGRAPH_CHECK(igraph_i_attribute_init(graph, attr)); /* add the vertices */ IGRAPH_CHECK(igraph_add_vertices(graph, n, 0)); IGRAPH_FINALLY_CLEAN(6); return 0; }
/** * \ingroup interface * \function igraph_add_vertices * \brief Adds vertices to a graph. * * </para><para> * This function invalidates all iterators. * * \param graph The graph object to extend. * \param nv Non-negative integer giving the number of * vertices to add. * \param attr The attributes of the new vertices, only used by * high level interfaces, you can supply 0 here. * \return Error code: * \c IGRAPH_EINVAL: invalid number of new * vertices. * * Time complexity: O(|V|) where * |V| is * the number of vertices in the \em new, extended graph. */ int igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr) { long int ec=igraph_ecount(graph); long int i; if (nv < 0) { IGRAPH_ERROR("cannot add negative number of vertices", IGRAPH_EINVAL); } IGRAPH_CHECK(igraph_vector_reserve(&graph->os, graph->n+nv+1)); IGRAPH_CHECK(igraph_vector_reserve(&graph->is, graph->n+nv+1)); igraph_vector_resize(&graph->os, graph->n+nv+1); /* reserved */ igraph_vector_resize(&graph->is, graph->n+nv+1); /* reserved */ for (i=graph->n+1; i<graph->n+nv+1; i++) { VECTOR(graph->os)[i]=ec; VECTOR(graph->is)[i]=ec; } graph->n += nv; if (graph->attr) { IGRAPH_CHECK(igraph_i_attribute_add_vertices(graph, nv, attr)); } return 0; }
int igraph_similarity_inverse_log_weighted(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode) { igraph_vector_t weights; igraph_neimode_t mode0; long int i, no_of_nodes; switch (mode) { case IGRAPH_OUT: mode0 = IGRAPH_IN; break; case IGRAPH_IN: mode0 = IGRAPH_OUT; break; default: mode0 = IGRAPH_ALL; } no_of_nodes = igraph_vcount(graph); IGRAPH_VECTOR_INIT_FINALLY(&weights, no_of_nodes); IGRAPH_CHECK(igraph_degree(graph, &weights, igraph_vss_all(), mode0, 1)); for (i=0; i < no_of_nodes; i++) { if (VECTOR(weights)[i] > 1) VECTOR(weights)[i] = 1.0 / log(VECTOR(weights)[i]); } IGRAPH_CHECK(igraph_cocitation_real(graph, res, vids, mode0, &weights)); igraph_vector_destroy(&weights); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_i_eigen_matrix_lapack_common(const igraph_matrix_t *A, const igraph_eigen_which_t *which, igraph_vector_complex_t *values, igraph_matrix_complex_t *vectors) { igraph_vector_t valuesreal, valuesimag; igraph_matrix_t vectorsright, *myvectors= vectors ? &vectorsright : 0; int n=(int) igraph_matrix_nrow(A); int info=1; IGRAPH_VECTOR_INIT_FINALLY(&valuesreal, n); IGRAPH_VECTOR_INIT_FINALLY(&valuesimag, n); if (vectors) { IGRAPH_MATRIX_INIT_FINALLY(&vectorsright, n, n); } IGRAPH_CHECK(igraph_lapack_dgeev(A, &valuesreal, &valuesimag, /*vectorsleft=*/ 0, myvectors, &info)); IGRAPH_CHECK(igraph_i_eigen_matrix_lapack_reorder(&valuesreal, &valuesimag, myvectors, which, values, vectors)); if (vectors) { igraph_matrix_destroy(&vectorsright); IGRAPH_FINALLY_CLEAN(1); } igraph_vector_destroy(&valuesimag); igraph_vector_destroy(&valuesreal); IGRAPH_FINALLY_CLEAN(2); return 0; }
int igraph_attribute_combination(igraph_attribute_combination_t *comb, ...) { va_list ap; IGRAPH_CHECK(igraph_attribute_combination_init(comb)); va_start(ap, comb); while (1) { void *func=0; igraph_attribute_combination_type_t type; const char *name; name=va_arg(ap, const char *); if (name == IGRAPH_NO_MORE_ATTRIBUTES) { break; } type=(igraph_attribute_combination_type_t)va_arg(ap, int); if (type == IGRAPH_ATTRIBUTE_COMBINE_FUNCTION) { func=va_arg(ap, void*); } if (strlen(name)==0) { name=0; } IGRAPH_CHECK(igraph_attribute_combination_add(comb, name, type, func)); }
/** * \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_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_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_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_matrix_complex_imag(const igraph_matrix_complex_t *v, igraph_matrix_t *imag) { long int nrow=igraph_matrix_complex_nrow(v); long int ncol=igraph_matrix_complex_ncol(v); IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol)); IGRAPH_CHECK(igraph_vector_complex_imag(&v->data, &imag->data)); return 0; }
int igraph_matrix_complex_real(const igraph_matrix_complex_t *v, igraph_matrix_t *real) { long int nrow=igraph_matrix_complex_nrow(v); long int ncol=igraph_matrix_complex_ncol(v); IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol)); IGRAPH_CHECK(igraph_vector_complex_real(&v->data, &real->data)); return 0; }
/* 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; }
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; }
int igraph_eigen_matrix_symmetric(const igraph_matrix_t *A, const igraph_sparsemat_t *sA, igraph_arpack_function_t *fun, int n, void *extra, igraph_eigen_algorithm_t algorithm, const igraph_eigen_which_t *which, igraph_arpack_options_t *options, igraph_arpack_storage_t *storage, igraph_vector_t *values, igraph_matrix_t *vectors) { IGRAPH_CHECK(igraph_i_eigen_checks(A, sA, fun, n)); if (which->pos != IGRAPH_EIGEN_LM && which->pos != IGRAPH_EIGEN_SM && which->pos != IGRAPH_EIGEN_LA && which->pos != IGRAPH_EIGEN_SA && which->pos != IGRAPH_EIGEN_BE && which->pos != IGRAPH_EIGEN_ALL && which->pos != IGRAPH_EIGEN_INTERVAL && which->pos != IGRAPH_EIGEN_SELECT) { IGRAPH_ERROR("Invalid 'pos' position in 'which'", IGRAPH_EINVAL); } switch (algorithm) { case IGRAPH_EIGEN_AUTO: if (which->howmany==n || n < 100) { IGRAPH_CHECK(igraph_i_eigen_matrix_symmetric_lapack(A, sA, fun, n, extra, which, values, vectors)); } else { IGRAPH_CHECK(igraph_i_eigen_matrix_symmetric_arpack(A, sA, fun, n, extra, which, options, storage, values, vectors)); } break; case IGRAPH_EIGEN_LAPACK: IGRAPH_CHECK(igraph_i_eigen_matrix_symmetric_lapack(A, sA, fun, n ,extra, which, values, vectors)); break; case IGRAPH_EIGEN_ARPACK: IGRAPH_CHECK(igraph_i_eigen_matrix_symmetric_arpack(A, sA, fun, n, extra, which, options, storage, values, vectors)); break; default: IGRAPH_ERROR("Unknown 'algorithm'", IGRAPH_EINVAL); } 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; }
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; }
/** * \function igraph_is_matching * Checks whether the given matching is valid for the given graph. * * This function checks a matching vector and verifies whether its length * matches the number of vertices in the given graph, its values are between * -1 (inclusive) and the number of vertices (exclusive), and whether there * exists a corresponding edge in the graph for every matched vertex pair. * For bipartite graphs, it also verifies whether the matched vertices are * in different parts of the graph. * * \param graph The input graph. It can be directed but the edge directions * will be ignored. * \param types If the graph is bipartite and you are interested in bipartite * matchings only, pass the vertex types here. If the graph is * non-bipartite, simply pass \c NULL. * \param matching The matching itself. It must be a vector where element i * contains the ID of the vertex that vertex i is matched to, * or -1 if vertex i is unmatched. * \param result Pointer to a boolean variable, the result will be returned * here. * * \sa \ref igraph_is_maximal_matching() if you are also interested in whether * the matching is maximal (i.e. non-extendable). * * Time complexity: O(|V|+|E|) where |V| is the number of vertices and * |E| is the number of edges. * * \example examples/simple/igraph_maximum_bipartite_matching.c */ int igraph_is_matching(const igraph_t* graph, const igraph_vector_bool_t* types, const igraph_vector_long_t* matching, igraph_bool_t* result) { long int i, j, no_of_nodes = igraph_vcount(graph); igraph_bool_t conn; /* Checking match vector length */ if (igraph_vector_long_size(matching) != no_of_nodes) { *result = 0; return IGRAPH_SUCCESS; } for (i = 0; i < no_of_nodes; i++) { j = VECTOR(*matching)[i]; /* Checking range of each element in the match vector */ if (j < -1 || j >= no_of_nodes) { *result = 0; return IGRAPH_SUCCESS; } /* When i is unmatched, we're done */ if (j == -1) continue; /* Matches must be mutual */ if (VECTOR(*matching)[j] != i) { *result = 0; return IGRAPH_SUCCESS; } /* Matched vertices must be connected */ IGRAPH_CHECK(igraph_are_connected(graph, (igraph_integer_t) i, (igraph_integer_t) j, &conn)); if (!conn) { /* Try the other direction -- for directed graphs */ IGRAPH_CHECK(igraph_are_connected(graph, (igraph_integer_t) j, (igraph_integer_t) i, &conn)); if (!conn) { *result = 0; return IGRAPH_SUCCESS; } } } if (types != 0) { /* Matched vertices must be of different types */ for (i = 0; i < no_of_nodes; i++) { j = VECTOR(*matching)[i]; if (j == -1) continue; if (VECTOR(*types)[i] == VECTOR(*types)[j]) { *result = 0; return IGRAPH_SUCCESS; } } } *result = 1; return IGRAPH_SUCCESS; }
/** * \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_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_biguint_mul_limb(igraph_biguint_t *res, igraph_biguint_t *b, limb_t l) { long int nlimb=igraph_biguint_size(b); limb_t carry; if (res!= b) { IGRAPH_CHECK(igraph_biguint_resize(res, nlimb)); } carry=bn_mul_limb( VECTOR(res->v), VECTOR(b->v), l, nlimb); if (carry) { IGRAPH_CHECK(igraph_biguint_extend(res, carry)); } return 0; }
int igraph_i_maximal_cliques_store(const igraph_vector_t* clique, void* data, igraph_bool_t* cont) { igraph_vector_ptr_t* result = (igraph_vector_ptr_t*)data; igraph_vector_t* vec; vec = igraph_Calloc(1, igraph_vector_t); if (vec == 0) IGRAPH_ERROR("cannot allocate memory for storing next clique", IGRAPH_ENOMEM); IGRAPH_CHECK(igraph_vector_copy(vec, clique)); IGRAPH_CHECK(igraph_vector_ptr_push_back(result, vec)); return IGRAPH_SUCCESS; }
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; }
int igraph_vector_complex_realimag(const igraph_vector_complex_t *v, igraph_vector_t *real, igraph_vector_t *imag) { int i, n=igraph_vector_complex_size(v); IGRAPH_CHECK(igraph_vector_resize(real, n)); IGRAPH_CHECK(igraph_vector_resize(imag, n)); for (i=0; i<n; i++) { igraph_complex_t z=VECTOR(*v)[i]; VECTOR(*real)[i] = IGRAPH_REAL(z); VECTOR(*imag)[i] = IGRAPH_IMAG(z); } return 0; }
int igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool_t *types, const igraph_vector_t *edges, igraph_bool_t directed) { igraph_integer_t no_of_nodes= (igraph_integer_t) igraph_vector_bool_size(types); long int no_of_edges=igraph_vector_size(edges); igraph_real_t min_edge=0, max_edge=0; igraph_bool_t min_type=0, max_type=0; long int i; if (no_of_edges % 2 != 0) { IGRAPH_ERROR("Invalid (odd) edges vector", IGRAPH_EINVEVECTOR); } no_of_edges /= 2; if (no_of_edges != 0) { igraph_vector_minmax(edges, &min_edge, &max_edge); } if (min_edge < 0 || max_edge >= no_of_nodes) { IGRAPH_ERROR("Invalid (negative) vertex id", IGRAPH_EINVVID); } /* Check types vector */ if (no_of_nodes != 0) { igraph_vector_bool_minmax(types, &min_type, &max_type); if (min_type < 0 || max_type > 1) { IGRAPH_WARNING("Non-binary type vector when creating a bipartite graph"); } } /* Check bipartiteness */ for (i=0; i<no_of_edges*2; i+=2) { long int from=(long int) VECTOR(*edges)[i]; long int to=(long int) VECTOR(*edges)[i+1]; long int t1=VECTOR(*types)[from]; long int t2=VECTOR(*types)[to]; if ( (t1 && t2) || (!t1 && !t2) ) { IGRAPH_ERROR("Invalid edges, not a bipartite graph", IGRAPH_EINVAL); } } IGRAPH_CHECK(igraph_empty(graph, no_of_nodes, directed)); IGRAPH_FINALLY(igraph_destroy, graph); IGRAPH_CHECK(igraph_add_edges(graph, edges, 0)); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *vecs, igraph_bool_t directed) { igraph_integer_t nrow=igraph_matrix_nrow(vecs); igraph_integer_t ncol=igraph_matrix_ncol(vecs); int i, j; igraph_vector_t edges; igraph_bool_t warned_neg=0, warned_big=0; IGRAPH_VECTOR_INIT_FINALLY(&edges, 0); RNG_BEGIN(); for (i = 0; i < ncol; i++) { int from=directed ? 0 : i+1; igraph_vector_t v1; igraph_vector_view(&v1, &MATRIX(*vecs, 0, i), nrow); for (j = from; j < ncol; j++) { igraph_real_t prob; igraph_vector_t v2; if (i==j) { continue; } igraph_vector_view(&v2, &MATRIX(*vecs, 0, j), nrow); igraph_lapack_ddot(&v1, &v2, &prob); if (prob < 0 && ! warned_neg) { warned_neg=1; IGRAPH_WARNING("Negative connection probability in " "dot-product graph"); } else if (prob > 1 && ! warned_big) { warned_big=1; IGRAPH_WARNING("Greater than 1 connection probability in " "dot-product graph"); IGRAPH_CHECK(igraph_vector_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_push_back(&edges, j)); } else if (RNG_UNIF01() < prob) { IGRAPH_CHECK(igraph_vector_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_push_back(&edges, j)); } } } RNG_END(); igraph_create(graph, &edges, ncol, directed); igraph_vector_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); return 0; }
/* * Converts a Java VertexSet to an igraph_vs_t * @return: zero if everything went fine, 1 if a null pointer was passed */ int Java_net_sf_igraph_VertexSet_to_igraph_vs(JNIEnv *env, jobject jobj, igraph_vs_t *result) { jint typeHint; jobject idArray; if (jobj == 0) { IGRAPH_CHECK(igraph_vs_all(result)); return IGRAPH_SUCCESS; } typeHint = (*env)->CallIntMethod(env, jobj, net_sf_igraph_VertexSet_getTypeHint_mid); if (typeHint != 1 && typeHint != 2) { IGRAPH_CHECK(igraph_vs_all(result)); return IGRAPH_SUCCESS; } idArray = (*env)->CallObjectMethod(env, jobj, net_sf_igraph_VertexSet_getIdArray_mid); if ((*env)->ExceptionCheck(env)) { return IGRAPH_EINVAL; } if (typeHint == 1) { /* Single vertex */ jlong id[1]; (*env)->GetLongArrayRegion(env, idArray, 0, 1, id); IGRAPH_CHECK(igraph_vs_1(result, (igraph_integer_t)id[0])); } else if (typeHint == 2) { /* List of vertices */ jlong* ids; igraph_vector_t vec; long i, n; ids = (*env)->GetLongArrayElements(env, idArray, 0); n = (*env)->GetArrayLength(env, idArray); IGRAPH_VECTOR_INIT_FINALLY(&vec, n); for (i = 0; i < n; i++) VECTOR(vec)[i] = ids[i]; IGRAPH_CHECK(igraph_vs_vector_copy(result, &vec)); igraph_vector_destroy(&vec); IGRAPH_FINALLY_CLEAN(1); (*env)->ReleaseLongArrayElements(env, idArray, ids, JNI_ABORT); } (*env)->DeleteLocalRef(env, idArray); 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; }