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; }
/** * \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; }
void print_edges(const igraph_t *graph) { long ecount = igraph_ecount(graph); long i; for (i=0; i < ecount; ++i) printf("%d %d\n", IGRAPH_FROM(graph, i), IGRAPH_TO(graph, i)); printf("\n"); }
int check_evecs(const igraph_t *graph, const igraph_vector_ptr_t *vecs, const igraph_vector_ptr_t *evecs, int error_code) { igraph_bool_t directed=igraph_is_directed(graph); long int i, n=igraph_vector_ptr_size(vecs); if (igraph_vector_ptr_size(evecs) != n) { exit(error_code+1); } for (i=0; i<n; i++) { igraph_vector_t *vvec=VECTOR(*vecs)[i]; igraph_vector_t *evec=VECTOR(*evecs)[i]; long int j, n2=igraph_vector_size(evec); if (igraph_vector_size(vvec) == 0 && n2==0) { continue; } if (igraph_vector_size(vvec) != n2+1) { exit(error_code+2); } for (j=0; j<n2; j++) { long int edge=VECTOR(*evec)[j]; long int from=VECTOR(*vvec)[j]; long int to=VECTOR(*vvec)[j+1]; if (directed) { if (from != IGRAPH_FROM(graph, edge) || to != IGRAPH_TO (graph, edge)) { exit(error_code); } } else { long int from2=IGRAPH_FROM(graph, edge); long int to2=IGRAPH_TO(graph, edge); long int min1= from < to ? from : to; long int max1= from < to ? to : from; long int min2= from2 < to2 ? from2 : to2; long int max2= from2 < to2 ? to2 : from2; if (min1 != min2 || max1 != max2) { exit(error_code+3); } } } } return 0; }
/* Convert an igraph graph to a Cliquer graph */ static void igraph_to_cliquer(const igraph_t *ig, graph_t **cg) { igraph_integer_t vcount, ecount; int i; if (igraph_is_directed(ig)) IGRAPH_WARNING("Edge directions are ignored for clique calculations"); vcount = igraph_vcount(ig); ecount = igraph_ecount(ig); *cg = graph_new(vcount); for (i=0; i < ecount; ++i) { long s, t; s = IGRAPH_FROM(ig, i); t = IGRAPH_TO(ig, i); if (s != t) GRAPH_ADD_EDGE(*cg, s, t); } }
int igraph_edges(const igraph_t *graph, igraph_es_t eids, igraph_vector_t *edges) { igraph_eit_t eit; long int n, ptr=0; IGRAPH_CHECK(igraph_eit_create(graph, eids, &eit)); IGRAPH_FINALLY(igraph_eit_destroy, &eit); n=IGRAPH_EIT_SIZE(eit); IGRAPH_CHECK(igraph_vector_resize(edges, n*2)); for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { long int e=IGRAPH_EIT_GET(eit); VECTOR(*edges)[ptr++]=IGRAPH_FROM(graph, e); VECTOR(*edges)[ptr++]=IGRAPH_TO(graph, e); } igraph_eit_destroy(&eit); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_inclist_remove_duplicate(const igraph_t *graph, igraph_inclist_t *al) { long int i; long int n=al->length; for (i=0; i<n; i++) { igraph_vector_t *v=&al->incs[i]; long int j, p=1, l=igraph_vector_size(v); for (j=1; j<l; j++) { long int e=VECTOR(*v)[j]; /* Non-loop edges and one end of loop edges are fine. */ /* We use here, that the vector is sorted and we also keep it sorted */ if (IGRAPH_FROM(graph, e) != IGRAPH_TO(graph, e) || VECTOR(*v)[j-1] != e) { VECTOR(*v)[p++] = e; } } igraph_vector_resize(v, p); } return 0; }
int igraph_revolver_mes_p_p(const igraph_t *graph, igraph_lazy_inclist_t *inclist, igraph_matrix_t *kernel, igraph_matrix_t *sd, igraph_matrix_t *norm, igraph_matrix_t *cites, const igraph_matrix_t *debug, igraph_vector_ptr_t *debugres, const igraph_vector_t *st, const igraph_vector_t *vtime, const igraph_vector_t *vtimeidx, const igraph_vector_t *etime, const igraph_vector_t *etimeidx, igraph_integer_t pno_of_events, const igraph_vector_t *authors, const igraph_vector_t *eventsizes, igraph_integer_t pmaxpapers) { long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); long int no_of_events=pno_of_events; long int maxpapers=pmaxpapers; igraph_vector_long_t papers; igraph_vector_char_t added; igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull; igraph_matrix_t ch; igraph_vector_long_t ntk; igraph_matrix_t ntkk; igraph_vector_t *adjedges; long int timestep, i; long int nptr=0, eptr=0, aptr=0; long int nptr_save, eptr_save, eptr_new; IGRAPH_CHECK(igraph_vector_long_init(&papers, no_of_nodes)); IGRAPH_FINALLY(&igraph_vector_long_destroy, &papers); IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges)); IGRAPH_FINALLY(igraph_vector_char_destroy, &added); IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxpapers+1)); IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk); IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxpapers+1, maxpapers+1); IGRAPH_MATRIX_INIT_FINALLY(&ch, maxpapers+1, maxpapers+1); if (norm) { normfact=norm; IGRAPH_CHECK(igraph_matrix_resize(normfact, maxpapers+1, maxpapers+1)); igraph_matrix_null(normfact); } else { normfact=&v_normfact; IGRAPH_MATRIX_INIT_FINALLY(normfact, maxpapers+1, maxpapers+1); } if (cites) { notnull=cites; IGRAPH_CHECK(igraph_matrix_resize(notnull, maxpapers+1, maxpapers+1)); igraph_matrix_null(notnull); } else { notnull=&v_notnull; IGRAPH_MATRIX_INIT_FINALLY(notnull, maxpapers+1, maxpapers+1); } IGRAPH_CHECK(igraph_matrix_resize(kernel, maxpapers+1, maxpapers+1)); igraph_matrix_null(kernel); if (sd) { IGRAPH_CHECK(igraph_matrix_resize(sd, maxpapers+1, maxpapers+1)); igraph_matrix_null(sd); } for (timestep=0; timestep<no_of_events; timestep++) { IGRAPH_ALLOW_INTERRUPTION(); nptr_save=nptr; while (nptr < no_of_nodes && VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) { nptr++; } /* If it is a new author then she has no papers yet */ VECTOR(ntk)[0] += (nptr-nptr_save); /* Update ch accordingly, could be done later as well */ if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) { if (nptr-nptr_save >= 2) { MATRIX(ch, 0, 0) = eptr; } for (i=1; i<maxpapers+1; i++) { if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) { MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr; } } } /* print_ntkk(&ntkk, &ntk); */ /* Estimate Akk */ eptr_save=eptr; while (eptr < no_of_edges && VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(papers)[from]; long int yidx=VECTOR(papers)[to]; double xk, oldakk; MATRIX(*notnull, xidx, yidx) += 1; MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx); xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx); oldakk=MATRIX(*kernel, xidx, yidx); MATRIX(*kernel, xidx, yidx) += (xk-oldakk)/MATRIX(*notnull, xidx, yidx); MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx); if (sd) { MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx)); MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx); } /* TODO: debug */ eptr++; } /* update ntkk, the new papers change the type of their authors */ eptr_new=eptr; for (i=aptr; i<aptr+VECTOR(*eventsizes)[timestep]; i++) { long int aut=(long int) VECTOR(*authors)[i]; long int pap=VECTOR(papers)[aut]; long int j, n; adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) aut); n=igraph_vector_size(adjedges); for (j=0; j<n; j++) { long int edge=(long int) VECTOR(*adjedges)[j]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, aut); long int otherpap=VECTOR(papers)[otherv]; MATRIX(ntkk, pap, otherpap) -= 1; MATRIX(ntkk, otherpap, pap) = MATRIX(ntkk, pap, otherpap); if (NTKK(pap, otherpap)==1) { MATRIX(ch, pap, otherpap) = eptr_new; MATRIX(ch, otherpap, pap) = MATRIX(ch, pap, otherpap); } MATRIX(ntkk, pap+1, otherpap) += 1; MATRIX(ntkk, otherpap, pap+1) = MATRIX(ntkk, pap+1, otherpap); if (NTKK(pap+1, otherpap)==0) { MATRIX(*normfact, pap+1, otherpap) += eptr_new-MATRIX(ch, pap+1, otherpap); MATRIX(*normfact, otherpap, pap+1) = MATRIX(*normfact, pap+1, otherpap); } } } /* update ntk too */ for (j=0; j<maxpapers+1; j++) { long int before, after; before=(long int) NTKK(pap, j); VECTOR(ntk)[pap]-=1; after=(long int) NTKK(pap, j); VECTOR(ntk)[pap]+=1; if (before > 0 && after==0) { MATRIX(*normfact, pap, j) += eptr_new-MATRIX(ch, pap, j); MATRIX(*normfact, j, pap) = MATRIX(*normfact, pap, j); } } VECTOR(ntk)[pap]-=1; for (j=0; j<maxpapers+1; j++) { long int before, after; before=(long int) NTKK(pap+1, j); VECTOR(ntk)[pap+1] += 1; after=(long int) NTKK(pap+1, j); VECTOR(ntk)[pap+1] -= 1; if (before == 0 && after > 0) { MATRIX(ch, pap+1, j) = eptr_new; MATRIX(ch, j, pap+1) = MATRIX(ch, pap+1, j); } } VECTOR(ntk)[pap+1]+=1; VECTOR(papers)[aut] += 1; } aptr += VECTOR(*eventsizes)[timestep]; /* For every new edge, we lose one connection possibility, also add the edges*/ eptr=eptr_save; while (eptr < no_of_edges && VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(papers)[from]; long int yidx=VECTOR(papers)[to]; MATRIX(ntkk, xidx, yidx) += 1; MATRIX(ntkk, yidx, xidx) = MATRIX(ntkk, xidx, yidx); if (NTKK(xidx, yidx)==0) { MATRIX(*normfact, xidx, yidx) += eptr_new-MATRIX(ch, xidx, yidx); MATRIX(*normfact, yidx, xidx) = MATRIX(*normfact, xidx, yidx); } VECTOR(added)[edge]=1; eptr++; } } for (i=0; i<maxpapers+1; i++) { igraph_real_t oldakk; long int j; for (j=0; j<=i; j++) { if (NTKK(i, j) != 0) { MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j)); MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j); } if (MATRIX(*normfact, i, j)==0) { MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0; MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1; } oldakk=MATRIX(*kernel, i, j); MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j); MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j); if (sd) { MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) * (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j)); MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1)); MATRIX(*sd, j, i) = MATRIX(*sd, i, j); } } } if (!cites) { igraph_matrix_destroy(notnull); IGRAPH_FINALLY_CLEAN(1); } if (!norm) { igraph_matrix_destroy(normfact); IGRAPH_FINALLY_CLEAN(1); } igraph_matrix_destroy(&ch); igraph_matrix_destroy(&ntkk); igraph_vector_long_destroy(&ntk); igraph_vector_char_destroy(&added); igraph_vector_long_destroy(&papers); IGRAPH_FINALLY_CLEAN(5); return 0; }
int igraph_biconnected_components(const igraph_t *graph, igraph_integer_t *no, igraph_vector_ptr_t *components, igraph_vector_t *articulation_points) { long int no_of_nodes=igraph_vcount(graph); igraph_vector_long_t nextptr; igraph_vector_long_t num, low; igraph_vector_bool_t found; igraph_vector_t *adjedges; igraph_stack_t path; igraph_vector_t edgestack; igraph_adjedgelist_t adjedgelist; long int i, counter, rootdfs=0; IGRAPH_CHECK(igraph_vector_long_init(&nextptr, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &nextptr); IGRAPH_CHECK(igraph_vector_long_init(&num, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &num); IGRAPH_CHECK(igraph_vector_long_init(&low, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &low); IGRAPH_CHECK(igraph_vector_bool_init(&found, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &found); IGRAPH_CHECK(igraph_stack_init(&path, 100)); IGRAPH_FINALLY(igraph_stack_destroy, &path); IGRAPH_VECTOR_INIT_FINALLY(&edgestack, 0); IGRAPH_CHECK(igraph_vector_reserve(&edgestack, 100)); IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist); if (no) { *no=0; } if (components) { igraph_vector_ptr_clear(components); } if (articulation_points) { igraph_vector_clear(articulation_points); } for (i=0; i<no_of_nodes; i++) { if (VECTOR(low)[i] != 0) { continue; /* already visited */ } IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_stack_push(&path, i)); counter=1; rootdfs=0; VECTOR(low)[i]=VECTOR(num)[i]=counter++; while (!igraph_stack_empty(&path)) { long int n; long int act=igraph_stack_top(&path); long int actnext=VECTOR(nextptr)[act]; adjedges=igraph_adjedgelist_get(&adjedgelist, act); n=igraph_vector_size(adjedges); if (actnext < n) { /* Step down (maybe) */ long int edge=VECTOR(*adjedges)[actnext]; long int nei=IGRAPH_OTHER(graph, edge, act); if (VECTOR(low)[nei] == 0) { if (act==i) { rootdfs++; } IGRAPH_CHECK(igraph_vector_push_back(&edgestack, edge)); IGRAPH_CHECK(igraph_stack_push(&path, nei)); VECTOR(low)[nei] = VECTOR(num)[nei]=counter++; } else { /* Update low value if needed */ if (VECTOR(num)[nei] < VECTOR(low)[act]) { VECTOR(low)[act]=VECTOR(num)[nei]; } } VECTOR(nextptr)[act] += 1; } else { /* Step up */ igraph_stack_pop(&path); if (!igraph_stack_empty(&path)) { long int prev=igraph_stack_top(&path); /* Update LOW value if needed */ if (VECTOR(low)[act] < VECTOR(low)[prev]) { VECTOR(low)[prev] = VECTOR(low)[act]; } /* Check for articulation point */ if (VECTOR(low)[act] >= VECTOR(num)[prev]) { if (articulation_points && !VECTOR(found)[prev] && prev != i /* the root */) { IGRAPH_CHECK(igraph_vector_push_back(articulation_points, prev)); VECTOR(found)[prev] = 1; } if (no) { *no += 1; } if (components) { igraph_vector_t *v=igraph_Calloc(1, igraph_vector_t); IGRAPH_CHECK(igraph_vector_init(v, 0)); while (!igraph_vector_empty(&edgestack)) { long int e=igraph_vector_pop_back(&edgestack); IGRAPH_CHECK(igraph_vector_push_back(v, e)); if (IGRAPH_FROM(graph,e)==prev || IGRAPH_TO(graph,e)==prev) { break; } } IGRAPH_CHECK(igraph_vector_ptr_push_back(components, v)); } } } /* !igraph_stack_empty(&path) */ } } /* !igraph_stack_empty(&path) */ if (articulation_points && rootdfs >= 2) { IGRAPH_CHECK(igraph_vector_push_back(articulation_points, i)); } } /* i < no_of_nodes */ igraph_adjedgelist_destroy(&adjedgelist); igraph_vector_destroy(&edgestack); igraph_stack_destroy(&path); igraph_vector_bool_destroy(&found); igraph_vector_long_destroy(&low); igraph_vector_long_destroy(&num); igraph_vector_long_destroy(&nextptr); IGRAPH_FINALLY_CLEAN(7); return 0; }
int igraph_revolver_st_d_d(const igraph_t *graph, igraph_lazy_inclist_t *inclist, igraph_vector_t *st, const igraph_matrix_t *kernel, const igraph_vector_t *vtime, const igraph_vector_t *vtimeidx, const igraph_vector_t *etime, const igraph_vector_t *etimeidx, igraph_integer_t pno_of_events) { long int no_of_events=pno_of_events; long int maxdegree=igraph_matrix_nrow(kernel)-1; long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); long int timestep=0; igraph_vector_long_t degree; igraph_vector_long_t ntk; igraph_vector_char_t added; igraph_vector_t *adjedges; long int i; long int nptr=0, eptr=0; IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxdegree+1)); IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk); IGRAPH_CHECK(igraph_vector_long_init(°ree, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, °ree); IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges)); IGRAPH_FINALLY(igraph_vector_char_destroy, &added); IGRAPH_CHECK(igraph_vector_resize(st, no_of_events)); VECTOR(*st)[0]=0; for (timestep=0; timestep<no_of_events-1; timestep++) { IGRAPH_ALLOW_INTERRUPTION(); /* add the new nodes */ while (nptr < no_of_nodes && VECTOR(*vtime)[ (long int) VECTOR(*vtimeidx)[nptr] ] == timestep) { for (i=0; i<maxdegree+1; i++) { VECTOR(*st)[timestep] += VECTOR(ntk)[i]*MATRIX(*kernel, i, 0); } VECTOR(ntk)[0]++; nptr++; } /* add the new edges as well, but this is for the next timestep already */ VECTOR(*st)[timestep+1] = VECTOR(*st)[timestep]; while (eptr < no_of_edges && VECTOR(*etime)[ (long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge); long int to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(degree)[from]; long int yidx=VECTOR(degree)[to]; igraph_real_t inc=0; long int n; inc -= MATRIX(*kernel, xidx, yidx); for (i=0; i<maxdegree+1; i++) { inc += VECTOR(ntk)[i] * (MATRIX(*kernel, i, xidx+1) - MATRIX(*kernel, i, xidx) + MATRIX(*kernel, i, yidx+1) - MATRIX(*kernel, i, yidx)); } inc -= MATRIX(*kernel, xidx+1, xidx+1); inc -= MATRIX(*kernel, yidx+1, yidx+1); inc += MATRIX(*kernel, xidx, xidx); inc += MATRIX(*kernel, yidx, yidx); VECTOR(ntk)[xidx]--; VECTOR(ntk)[yidx]--; VECTOR(ntk)[xidx+1]++; VECTOR(ntk)[yidx+1]++; adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) from); n=igraph_vector_size(adjedges); for (i=0; i<n; i++) { long int edge=(long int) VECTOR(*adjedges)[i]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, from); long int deg=VECTOR(degree)[otherv]; inc += MATRIX(*kernel, xidx, deg); inc -= MATRIX(*kernel, xidx+1, deg); } } adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) to); n=igraph_vector_size(adjedges); for (i=0; i<n; i++) { long int edge=(long int) VECTOR(*adjedges)[i]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, to); long int deg=VECTOR(degree)[otherv]; inc += MATRIX(*kernel, yidx, deg); inc -= MATRIX(*kernel, yidx+1, deg); } } VECTOR(degree)[from] += 1; VECTOR(degree)[to] += 1; VECTOR(added)[edge]=1; VECTOR(*st)[timestep+1] += inc; eptr++; } } igraph_vector_char_destroy(&added); igraph_vector_long_destroy(°ree); igraph_vector_long_destroy(&ntk); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_revolver_error_d_d(const igraph_t *graph, igraph_lazy_inclist_t *inclist, const igraph_matrix_t *kernel, const igraph_vector_t *st, const igraph_vector_t *vtime, const igraph_vector_t *vtimeidx, const igraph_vector_t *etime, const igraph_vector_t *etimeidx, igraph_integer_t pno_of_events, igraph_integer_t pmaxdegree, igraph_real_t *logprob, igraph_real_t *lognull) { long int no_of_events=pno_of_events; long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); igraph_vector_long_t degree; long int timestep, nptr=0, eptr=0, eptr_save; long int edges=0, vertices=0; igraph_real_t rlogprob, rlognull, *mylogprob=logprob, *mylognull=lognull; IGRAPH_CHECK(igraph_vector_long_init(°ree, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, °ree); if (!logprob) { mylogprob=&rlogprob; } if (!lognull) { mylognull=&rlognull; } *mylogprob=0; *mylognull=0; for (timestep=0; timestep<no_of_events; timestep++) { IGRAPH_ALLOW_INTERRUPTION(); while (nptr < no_of_nodes && VECTOR(*vtime)[ (long int) VECTOR(*vtimeidx)[nptr] ] == timestep) { vertices++; nptr++; } eptr_save=eptr; while (eptr < no_of_edges && VECTOR(*etime)[ (long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge); long int to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(degree)[from]; long int yidx=VECTOR(degree)[to]; igraph_real_t prob=MATRIX(*kernel, xidx, yidx)/VECTOR(*st)[timestep]; igraph_real_t nullprob=1.0/(vertices*(vertices-1)/2-eptr_save); *mylogprob += log(prob); *mylognull += log(nullprob); edges++; eptr++; } eptr=eptr_save; while (eptr < no_of_edges && VECTOR(*etime)[ (long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge); long int to=IGRAPH_TO(graph, edge); VECTOR(degree)[from] += 1; VECTOR(degree)[to] += 1; eptr++; } } igraph_vector_long_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_revolver_st_p_p(const igraph_t *graph, igraph_lazy_inclist_t *inclist, igraph_vector_t *st, const igraph_matrix_t *kernel, const igraph_vector_t *vtime, const igraph_vector_t *vtimeidx, const igraph_vector_t *etime, const igraph_vector_t *etimeidx, igraph_integer_t pno_of_events, const igraph_vector_t *authors, const igraph_vector_t *eventsizes, igraph_integer_t pmaxpapers) { long int no_of_events=pno_of_events; long int maxpapers=igraph_matrix_nrow(kernel)-1; long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); long int timestep=0; igraph_vector_long_t papers; igraph_vector_long_t ntk; igraph_vector_char_t added; igraph_vector_t *adjedges; long int i; long int nptr=0, eptr=0, aptr=0, nptr_save; IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxpapers+1)); IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk); IGRAPH_CHECK(igraph_vector_long_init(&papers, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &papers); IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges)); IGRAPH_FINALLY(igraph_vector_char_destroy, &added); IGRAPH_CHECK(igraph_vector_resize(st, no_of_events)); VECTOR(*st)[0]=0; for (timestep=0; timestep<no_of_events-1; timestep++) { IGRAPH_ALLOW_INTERRUPTION(); /* add the new nodes */ nptr_save=nptr; while (nptr < no_of_nodes && VECTOR(*vtime)[ (long int) VECTOR(*vtimeidx)[nptr] ] == timestep) { nptr++; } nptr_save=nptr-nptr_save; if (nptr_save != 0) { for (i=0; i<maxpapers+1; i++) { VECTOR(*st)[timestep] += VECTOR(ntk)[i]*MATRIX(*kernel, i, 0)*nptr_save; } VECTOR(*st)[timestep] += nptr_save*(nptr_save-1)/2 * MATRIX(*kernel, 0, 0); VECTOR(ntk)[0]+=nptr_save; } VECTOR(*st)[timestep+1] = VECTOR(*st)[timestep]; for (i=aptr; i<aptr+VECTOR(*eventsizes)[timestep]; i++) { long int aut=(long int) VECTOR(*authors)[i]; long int pap=VECTOR(papers)[aut]; long int j, n; for (j=0; j<maxpapers+1; j++) { VECTOR(*st)[timestep+1] += VECTOR(ntk)[j] * (MATRIX(*kernel, j, pap+1)- MATRIX(*kernel, j, pap)); } VECTOR(*st)[timestep+1] += MATRIX(*kernel, pap, pap); VECTOR(*st)[timestep+1] -= MATRIX(*kernel, pap+1, pap+1); VECTOR(ntk)[pap]--; VECTOR(ntk)[pap+1]++; adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) aut); n=igraph_vector_size(adjedges); for (j=0; j<n; j++) { long int edge=(long int) VECTOR(*adjedges)[j]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, aut); long int otherpap=VECTOR(papers)[otherv]; VECTOR(*st)[timestep+1] += MATRIX(*kernel, pap, otherpap); VECTOR(*st)[timestep+1] -= MATRIX(*kernel, pap+1, otherpap); } } VECTOR(papers)[aut] += 1; } aptr += VECTOR(*eventsizes)[timestep]; while (eptr < no_of_edges && VECTOR(*etime)[ (long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge); long int to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(papers)[from]; long int yidx=VECTOR(papers)[to]; VECTOR(*st)[timestep+1] -= MATRIX(*kernel, xidx, yidx); VECTOR(added)[edge]=1; eptr++; } } igraph_vector_char_destroy(&added); igraph_vector_long_destroy(&papers); igraph_vector_long_destroy(&ntk); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_revolver_mes_d_d(const igraph_t *graph, igraph_lazy_inclist_t *inclist, igraph_matrix_t *kernel, igraph_matrix_t *sd, igraph_matrix_t *norm, igraph_matrix_t *cites, const igraph_matrix_t *debug, igraph_vector_ptr_t *debugres, const igraph_vector_t *st, const igraph_vector_t *vtime, const igraph_vector_t *vtimeidx, const igraph_vector_t *etime, const igraph_vector_t *etimeidx, igraph_integer_t pno_of_events, igraph_integer_t pmaxdegree) { long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); long int no_of_events=pno_of_events; long int maxdegree=pmaxdegree; igraph_vector_long_t degree; igraph_vector_char_t added; /* is this edge already in the network? */ igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull; igraph_matrix_t ch; igraph_vector_long_t ntk; /* # of type x vertices */ igraph_matrix_t ntkk; /* # of connections between type x1, x2 vert. */ igraph_vector_t *adjedges; long int timestep, i; long int nptr=0, eptr=0; long int nptr_save, eptr_save, eptr_new; IGRAPH_CHECK(igraph_vector_long_init(°ree, no_of_nodes)); IGRAPH_FINALLY(&igraph_vector_long_destroy, °ree); IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges)); IGRAPH_FINALLY(igraph_vector_char_destroy, &added); IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxdegree+1)); IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk); IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxdegree+1, maxdegree+1); IGRAPH_MATRIX_INIT_FINALLY(&ch, maxdegree+1, maxdegree+1); if (norm) { normfact=norm; IGRAPH_CHECK(igraph_matrix_resize(normfact, maxdegree+1, maxdegree+1)); igraph_matrix_null(normfact); } else { normfact=&v_normfact; IGRAPH_MATRIX_INIT_FINALLY(normfact, maxdegree+1, maxdegree+1); } if (cites) { notnull=cites; IGRAPH_CHECK(igraph_matrix_resize(notnull, maxdegree+1, maxdegree+1)); igraph_matrix_null(notnull); } else { notnull=&v_notnull; IGRAPH_MATRIX_INIT_FINALLY(notnull, maxdegree+1, maxdegree+1); } IGRAPH_CHECK(igraph_matrix_resize(kernel, maxdegree+1, maxdegree+1)); igraph_matrix_null(kernel); if (sd) { IGRAPH_CHECK(igraph_matrix_resize(sd, maxdegree+1, maxdegree+1)); igraph_matrix_null(sd); } for (timestep=0; timestep<no_of_events; timestep++) { IGRAPH_ALLOW_INTERRUPTION(); /* Add the vertices in the first */ nptr_save=nptr; while (nptr < no_of_nodes && VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) { nptr++; } VECTOR(ntk)[0] += (nptr-nptr_save); /* Update ch accordingly, could be done later as well */ if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) { if (nptr-nptr_save >= 2) { MATRIX(ch, 0, 0) = eptr; } for (i=1; i<maxdegree+1; i++) { if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) { MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr; } } } /* Estimate Akk */ eptr_save=eptr; while (eptr < no_of_edges && VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(degree)[from]; long int yidx=VECTOR(degree)[to]; double xk, oldakk; MATRIX(*notnull, xidx, yidx) += 1; MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx); xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx); oldakk=MATRIX(*kernel, xidx, yidx); MATRIX(*kernel, xidx, yidx) += (xk-oldakk)/MATRIX(*notnull, xidx, yidx); MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx); if (sd) { MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx)); MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx); } /* TODO: debug */ eptr++; } /* Update ntkk, ntk, ch, normfact, add the edges */ eptr_new=eptr; eptr=eptr_save; while (eptr < no_of_edges && VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) { long int edge=(long int) VECTOR(*etimeidx)[eptr]; long int from=IGRAPH_FROM(graph, edge); long int to=IGRAPH_TO(graph, edge); long int xidx=VECTOR(degree)[from]; long int yidx=VECTOR(degree)[to]; long int n; adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) from); n=igraph_vector_size(adjedges); for (i=0; i<n; i++) { long int edge=(long int) VECTOR(*adjedges)[i]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, from); /* other than from */ long int deg=VECTOR(degree)[otherv]; MATRIX(ntkk, xidx, deg) -= 1; MATRIX(ntkk, deg, xidx) = MATRIX(ntkk, xidx, deg); if (NTKK(xidx, deg)==1) { MATRIX(ch, deg, xidx) = eptr_new; MATRIX(ch, xidx, deg) = MATRIX(ch, deg, xidx); } MATRIX(ntkk, xidx+1, deg) += 1; MATRIX(ntkk, deg, xidx+1) = MATRIX(ntkk, xidx+1, deg); if (NTKK(xidx+1, deg)==0) { MATRIX(*normfact, xidx+1, deg) += eptr_new-MATRIX(ch, xidx+1, deg); MATRIX(*normfact, deg, xidx+1) = MATRIX(*normfact, xidx+1, deg); } } } adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) to); n=igraph_vector_size(adjedges); for (i=0; i<n; i++) { long int edge=(long int) VECTOR(*adjedges)[i]; if (VECTOR(added)[edge]) { long int otherv=IGRAPH_OTHER(graph, edge, to); /* other than to */ long int deg=VECTOR(degree)[otherv]; MATRIX(ntkk, yidx, deg) -= 1; MATRIX(ntkk, deg, yidx) = MATRIX(ntkk, yidx, deg); if (NTKK(yidx, deg)==1) { MATRIX(ch, deg, yidx) = eptr_new; MATRIX(ch, yidx, deg) = MATRIX(ch, deg, yidx); } MATRIX(ntkk, yidx+1, deg) += 1; MATRIX(ntkk, deg, yidx+1) = MATRIX(ntkk, yidx+1, deg); if (NTKK(yidx+1, deg)==0) { MATRIX(*normfact, yidx+1, deg) += eptr_new-MATRIX(ch, yidx+1, deg); MATRIX(*normfact, deg, yidx+1) = MATRIX(*normfact, yidx+1, deg); } } } VECTOR(added)[edge]=1; MATRIX(ntkk, xidx+1, yidx+1) += 1; MATRIX(ntkk, yidx+1, xidx+1) = MATRIX(ntkk, xidx+1, yidx+1); if (NTKK(xidx+1, yidx+1)==0) { MATRIX(*normfact, xidx+1, yidx+1) = eptr_new-MATRIX(ch, xidx+1, yidx+1); MATRIX(*normfact, yidx+1, xidx+1) = MATRIX(*normfact, xidx+1, yidx+1); } for (i=0; i<maxdegree+1; i++) { long int before, after; before=(long int) NTKK(xidx,i); VECTOR(ntk)[xidx] -= 1; after=(long int) NTKK(xidx,i); VECTOR(ntk)[xidx] += 1; if (before > 0 && after==0) { MATRIX(*normfact, xidx, i) += eptr_new-MATRIX(ch, xidx, i); MATRIX(*normfact, i, xidx) = MATRIX(*normfact, xidx, i); } } VECTOR(ntk)[xidx]--; for (i=0; i<maxdegree+1; i++) { long int before, after; before=(long int) NTKK(yidx, i); VECTOR(ntk)[yidx] -= 1; after=(long int) NTKK(yidx, i); VECTOR(ntk)[yidx] += 1; if (before > 0 && after==0) { MATRIX(*normfact, yidx, i) += eptr_new-MATRIX(ch, yidx, i); MATRIX(*normfact, i, yidx) = MATRIX(*normfact, yidx, i); } } VECTOR(ntk)[yidx]--; for (i=0; i<maxdegree+1; i++) { long int before, after; before=(long int) NTKK(xidx+1, i); VECTOR(ntk)[xidx+1] += 1; after=(long int) NTKK(xidx+1, i); VECTOR(ntk)[xidx+1] -= 1; if (before==0 && after > 0) { MATRIX(ch, xidx+1, i) = eptr_new; MATRIX(ch, i, xidx+1) = MATRIX(ch, xidx+1, i); } } VECTOR(ntk)[xidx+1]++; for (i=0; i<maxdegree+1; i++) { long int before, after; before=(long int) NTKK(yidx+1, i); VECTOR(ntk)[yidx+1] += 1; after=(long int) NTKK(yidx+1, i); VECTOR(ntk)[yidx+1] -= 1; if (before == 0 && after == 0) { MATRIX(ch, yidx+1, i) = eptr_new; MATRIX(ch, i, yidx+1) = MATRIX(ch, yidx+1, i); } } VECTOR(ntk)[yidx+1]++; VECTOR(degree)[from]++; VECTOR(degree)[to]++; eptr++; } } for (i=0; i<maxdegree+1; i++) { igraph_real_t oldakk; long int j; for (j=0; j<=i; j++) { if (NTKK(i, j) != 0) { MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j)); MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j); } if (MATRIX(*normfact, i, j)==0) { MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0; MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1; } oldakk=MATRIX(*kernel, i, j); MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j); MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j); if (sd) { MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) * (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j)); MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1)); MATRIX(*sd, j, i) = MATRIX(*sd, i, j); } } } if (!cites) { igraph_matrix_destroy(notnull); IGRAPH_FINALLY_CLEAN(1); } if (!norm) { igraph_matrix_destroy(normfact); IGRAPH_FINALLY_CLEAN(1); } igraph_matrix_destroy(&ch); igraph_matrix_destroy(&ntkk); igraph_vector_long_destroy(&ntk); igraph_vector_char_destroy(&added); igraph_vector_long_destroy(°ree); IGRAPH_FINALLY_CLEAN(5); return 0; }
int check_multi() { igraph_t g; igraph_vector_t vec; igraph_vector_t eids, eids2; int ret; long int i; igraph_real_t q1[] = { 0,1, 0,1 }; igraph_real_t q2[] = { 0,1, 0,1, 0,1 }; igraph_real_t q3[] = { 1,0, 3,4, 1,0, 0,1, 3,4, 0,1 }; igraph_vector_init(&eids, 0); /*********************************/ igraph_small(&g, /*n=*/ 10, /*directed=*/ 1, 0,1, 0,1, 1,0, 1,2, 3,4, 3,4, 3,4, 3,5, 3,7, 9,8, -1); igraph_vector_view(&vec, q1, sizeof(q1) / sizeof(igraph_real_t)); igraph_get_eids_multi(&g, &eids, &vec, 0, /*directed=*/ 1, /*error=*/ 1); igraph_vector_sort(&eids); print_vector(&eids, stdout); igraph_vector_view(&vec, q2, sizeof(q2) / sizeof(igraph_real_t)); igraph_get_eids_multi(&g, &eids, &vec, 0, /*directed=*/ 0, /*error=*/ 1); igraph_vector_sort(&eids); print_vector(&eids, stdout); igraph_vector_view(&vec, q2, sizeof(q2) / sizeof(igraph_real_t)); igraph_set_error_handler(igraph_error_handler_ignore); ret=igraph_get_eids_multi(&g, &eids, &vec, 0, /*directed=*/ 1, /*error=*/1); if (ret != IGRAPH_EINVAL) { return 1; } igraph_set_error_handler(igraph_error_handler_abort); igraph_destroy(&g); /*********************************/ /*********************************/ igraph_small(&g, /*n=*/10, /*directed=*/0, 0,1, 1,0, 0,1, 3,4, 3,4, 5,4, 9,8, -1); igraph_vector_view(&vec, q1, sizeof(q1) / sizeof(igraph_real_t)); igraph_get_eids_multi(&g, &eids, &vec, 0, /*directed=*/1, /*error=*/ 1); igraph_vector_sort(&eids); print_vector(&eids, stdout); igraph_vector_view(&vec, q3, sizeof(q3) / sizeof(igraph_real_t)); igraph_set_error_handler(igraph_error_handler_ignore); ret=igraph_get_eids_multi(&g, &eids, &vec, 0, /*directed=*/0, /*error=*/ 1); if (ret != IGRAPH_EINVAL) { return 2; } igraph_set_error_handler(igraph_error_handler_abort); igraph_destroy(&g); /*********************************/ igraph_vector_destroy(&eids); /*********************************/ /* Speed tests */ #define NODES 10000 igraph_barabasi_game(&g, /*n=*/ NODES, /*power=*/ 1.0, /*m=*/ 3, /*outseq=*/ 0, /*outpref=*/ 0, /*A=*/ 1, /*directed=*/ 1, IGRAPH_BARABASI_BAG, /*start_from=*/ 0); igraph_simplify(&g, /*multiple=*/ 1, /*loops=*/ 0, /*edge_comb=*/ 0); igraph_vector_init(&eids, NODES/2); igraph_random_sample(&eids, 0, igraph_ecount(&g)-1, NODES/2); igraph_vector_init(&vec, NODES); for (i=0; i<NODES/2; i++) { VECTOR(vec)[2*i] = IGRAPH_FROM(&g, VECTOR(eids)[i]); VECTOR(vec)[2*i+1] = IGRAPH_TO(&g, VECTOR(eids)[i]); } igraph_vector_init(&eids2, 0); igraph_get_eids_multi(&g, &eids2, &vec, 0, /*directed=*/ 1, /*error=*/ 1); if (!igraph_vector_all_e(&eids, &eids2)) { return 3; } /**/ for (i=0; i<NODES/2; i++) { VECTOR(vec)[2*i] = IGRAPH_TO(&g, VECTOR(eids)[i]); VECTOR(vec)[2*i+1] = IGRAPH_FROM(&g, VECTOR(eids)[i]); } igraph_get_eids_multi(&g, &eids2, &vec, 0, /*directed=*/ 0, /*error=*/ 1); if (!igraph_vector_all_e(&eids, &eids2)) { return 4; } igraph_vector_destroy(&eids); igraph_vector_destroy(&eids2); igraph_vector_destroy(&vec); igraph_destroy(&g); /*********************************/ return 0; }
/** * \function igraph_community_fastgreedy * \brief Finding community structure by greedy optimization of modularity * * This function implements the fast greedy modularity optimization * algorithm for finding community structure, see * A Clauset, MEJ Newman, C Moore: Finding community structure in very * large networks, http://www.arxiv.org/abs/cond-mat/0408187 for the * details. * * </para><para> * Some improvements proposed in K Wakita, T Tsurumi: Finding community * structure in mega-scale social networks, * http://www.arxiv.org/abs/cs.CY/0702048v1 have also been implemented. * * \param graph The input graph. It must be a simple graph, i.e. a graph * without multiple and without loop edges. This is checked and an * error message is given for non-simple graphs. * \param weights Potentially a numeric vector containing edge * weights. Supply a null pointer here for unweighted graphs. The * weights are expected to be non-negative. * \param merges Pointer to an initialized matrix or NULL, the result of the * computation is stored here. The matrix has two columns and each * merge corresponds to one merge, the ids of the two merged * components are stored. The component ids are numbered from zero and * the first \c n components are the individual vertices, \c n is * the number of vertices in the graph. Component \c n is created * in the first merge, component \c n+1 in the second merge, etc. * The matrix will be resized as needed. If this argument is NULL * then it is ignored completely. * \param modularity Pointer to an initialized matrix or NULL pointer, * in the former case the modularity scores along the stages of the * computation are recorded here. The vector will be resized as * needed. * \return Error code. * * \sa \ref igraph_community_walktrap(), \ref * igraph_community_edge_betweenness() for other community detection * algorithms, \ref igraph_community_to_membership() to convert the * dendrogram to a membership vector. * * Time complexity: O(|E||V|log|V|) in the worst case, * O(|E|+|V|log^2|V|) typically, |V| is the number of vertices, |E| is * the number of edges. */ int igraph_community_fastgreedy(const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *merges, igraph_vector_t *modularity) { long int no_of_edges, no_of_nodes, no_of_joins, total_joins; long int i, j, k, n, m, from, to, dummy; igraph_integer_t ffrom, fto; igraph_eit_t edgeit; igraph_i_fastgreedy_commpair *pairs, *p1, *p2; igraph_i_fastgreedy_community_list communities; igraph_vector_t a; igraph_real_t q, maxq, *dq, weight_sum; igraph_bool_t simple; /*long int join_order[] = { 16,5, 5,6, 6,0, 4,0, 10,0, 26,29, 29,33, 23,33, 27,33, 25,24, 24,31, 12,3, 21,1, 30,8, 8,32, 9,2, 17,1, 11,0, 7,3, 3,2, 13,2, 1,2, 28,31, 31,33, 22,32, 18,32, 20,32, 32,33, 15,33, 14,33, 0,19, 19,2, -1,-1 };*/ /*long int join_order[] = { 43,42, 42,41, 44,41, 41,36, 35,36, 37,36, 36,29, 38,29, 34,29, 39,29, 33,29, 40,29, 32,29, 14,29, 30,29, 31,29, 6,18, 18,4, 23,4, 21,4, 19,4, 27,4, 20,4, 22,4, 26,4, 25,4, 24,4, 17,4, 0,13, 13,2, 1,2, 11,2, 8,2, 5,2, 3,2, 10,2, 9,2, 7,2, 2,28, 28,15, 12,15, 29,16, 4,15, -1,-1 };*/ no_of_nodes = igraph_vcount(graph); no_of_edges = igraph_ecount(graph); if (igraph_is_directed(graph)) { IGRAPH_ERROR("fast greedy community detection works for undirected graphs only", IGRAPH_UNIMPLEMENTED); } total_joins=no_of_nodes-1; if (weights != 0) { if (igraph_vector_size(weights) < igraph_ecount(graph)) IGRAPH_ERROR("fast greedy community detection: weight vector too short", IGRAPH_EINVAL); if (igraph_vector_any_smaller(weights, 0)) IGRAPH_ERROR("weights must be positive", IGRAPH_EINVAL); weight_sum = igraph_vector_sum(weights); } else weight_sum = no_of_edges; IGRAPH_CHECK(igraph_is_simple(graph, &simple)); if (!simple) { IGRAPH_ERROR("fast-greedy community finding works only on simple graphs", IGRAPH_EINVAL); } if (merges != 0) { IGRAPH_CHECK(igraph_matrix_resize(merges, total_joins, 2)); igraph_matrix_null(merges); } if (modularity != 0) { IGRAPH_CHECK(igraph_vector_resize(modularity, total_joins+1)); } /* Create degree vector */ IGRAPH_VECTOR_INIT_FINALLY(&a, no_of_nodes); if (weights) { debug("Calculating weighted degrees\n"); for (i=0; i < no_of_edges; i++) { VECTOR(a)[(long int)IGRAPH_FROM(graph, i)] += VECTOR(*weights)[i]; VECTOR(a)[(long int)IGRAPH_TO(graph, i)] += VECTOR(*weights)[i]; } } else { debug("Calculating degrees\n"); IGRAPH_CHECK(igraph_degree(graph, &a, igraph_vss_all(), IGRAPH_ALL, 0)); } /* Create list of communities */ debug("Creating community list\n"); communities.n = no_of_nodes; communities.no_of_communities = no_of_nodes; communities.e = (igraph_i_fastgreedy_community*)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community)); if (communities.e == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, communities.e); communities.heap = (igraph_i_fastgreedy_community**)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community*)); if (communities.heap == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, communities.heap); communities.heapindex = (igraph_integer_t*)calloc(no_of_nodes, sizeof(igraph_integer_t)); if (communities.heapindex == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY_CLEAN(2); IGRAPH_FINALLY(igraph_i_fastgreedy_community_list_destroy, &communities); for (i=0; i<no_of_nodes; i++) { igraph_vector_ptr_init(&communities.e[i].neis, 0); communities.e[i].id = i; communities.e[i].size = 1; } /* Create list of community pairs from edges */ debug("Allocating dq vector\n"); dq = (igraph_real_t*)calloc(no_of_edges, sizeof(igraph_real_t)); if (dq == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, dq); debug("Creating community pair list\n"); IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit)); IGRAPH_FINALLY(igraph_eit_destroy, &edgeit); pairs = (igraph_i_fastgreedy_commpair*)calloc(2*no_of_edges, sizeof(igraph_i_fastgreedy_commpair)); if (pairs == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, pairs); i=j=0; while (!IGRAPH_EIT_END(edgeit)) { long int eidx = IGRAPH_EIT_GET(edgeit); igraph_edge(graph, eidx, &ffrom, &fto); /* Create the pairs themselves */ from = (long int)ffrom; to = (long int)fto; if (from == to) { IGRAPH_ERROR("loop edge detected, simplify the graph before starting community detection", IGRAPH_EINVAL); } if (from>to) { dummy=from; from=to; to=dummy; } if (weights) { dq[j]=2*(VECTOR(*weights)[eidx]/(weight_sum*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*weight_sum*weight_sum)); } else { dq[j]=2*(1.0/(no_of_edges*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*no_of_edges*no_of_edges)); } pairs[i].first = from; pairs[i].second = to; pairs[i].dq = &dq[j]; pairs[i].opposite = &pairs[i+1]; pairs[i+1].first = to; pairs[i+1].second = from; pairs[i+1].dq = pairs[i].dq; pairs[i+1].opposite = &pairs[i]; /* Link the pair to the communities */ igraph_vector_ptr_push_back(&communities.e[from].neis, &pairs[i]); igraph_vector_ptr_push_back(&communities.e[to].neis, &pairs[i+1]); /* Update maximums */ if (communities.e[from].maxdq==0 || *communities.e[from].maxdq->dq < *pairs[i].dq) communities.e[from].maxdq = &pairs[i]; if (communities.e[to].maxdq==0 || *communities.e[to].maxdq->dq < *pairs[i+1].dq) communities.e[to].maxdq = &pairs[i+1]; /* Iterate */ i+=2; j++; IGRAPH_EIT_NEXT(edgeit); } igraph_eit_destroy(&edgeit); IGRAPH_FINALLY_CLEAN(1); /* Sorting community neighbor lists by community IDs */ debug("Sorting community neighbor lists\n"); for (i=0, j=0; i<no_of_nodes; i++) { igraph_vector_ptr_sort(&communities.e[i].neis, igraph_i_fastgreedy_commpair_cmp); /* Isolated vertices won't be stored in the heap (to avoid maxdq == 0) */ if (VECTOR(a)[i] > 0) { communities.heap[j] = &communities.e[i]; communities.heapindex[i] = j; j++; } else { communities.heapindex[i] = -1; } } communities.no_of_communities = j; /* Calculate proper vector a (see paper) and initial modularity */ q=0; igraph_vector_scale(&a, 1.0/(2.0 * (weights ? weight_sum : no_of_edges))); for (i=0; i<no_of_nodes; i++) q -= VECTOR(a)[i]*VECTOR(a)[i]; maxq=q; /* Initializing community heap */ debug("Initializing community heap\n"); igraph_i_fastgreedy_community_list_build_heap(&communities); debug("Initial modularity: %.4f\n", q); /* Let's rock ;) */ no_of_joins=0; while (no_of_joins<total_joins) { IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_PROGRESS("fast greedy community detection", no_of_joins*100.0/total_joins, 0); /* Store the modularity */ if (modularity) VECTOR(*modularity)[no_of_joins] = q; /* Some debug info if needed */ /* igraph_i_fastgreedy_community_list_check_heap(&communities); */ #ifdef DEBUG debug("===========================================\n"); for (i=0; i<communities.n; i++) { if (communities.e[i].maxdq == 0) { debug("Community #%ld: PASSIVE\n", i); continue; } debug("Community #%ld\n ", i); for (j=0; j<igraph_vector_ptr_size(&communities.e[i].neis); j++) { p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[i].neis)[j]; debug(" (%ld,%ld,%.4f)", p1->first, p1->second, *p1->dq); } p1=communities.e[i].maxdq; debug("\n Maxdq: (%ld,%ld,%.4f)\n", p1->first, p1->second, *p1->dq); } debug("Global maxdq is: (%ld,%ld,%.4f)\n", communities.heap[0]->maxdq->first, communities.heap[0]->maxdq->second, *communities.heap[0]->maxdq->dq); for (i=0; i<communities.no_of_communities; i++) debug("(%ld,%ld,%.4f) ", communities.heap[i]->maxdq->first, communities.heap[i]->maxdq->second, *communities.heap[0]->maxdq->dq); debug("\n"); #endif if (communities.heap[0] == 0) break; /* no more communities */ if (communities.heap[0]->maxdq == 0) break; /* there are only isolated comms */ to=communities.heap[0]->maxdq->second; from=communities.heap[0]->maxdq->first; debug("Q[%ld] = %.7f\tdQ = %.7f\t |H| = %ld\n", no_of_joins, q, *communities.heap[0]->maxdq->dq, no_of_nodes-no_of_joins-1); /* DEBUG */ /* from=join_order[no_of_joins*2]; to=join_order[no_of_joins*2+1]; if (to == -1) break; for (i=0; i<igraph_vector_ptr_size(&communities.e[to].neis); i++) { p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; if (p1->second == from) communities.maxdq = p1; } */ n = igraph_vector_ptr_size(&communities.e[to].neis); m = igraph_vector_ptr_size(&communities.e[from].neis); /*if (n>m) { dummy=n; n=m; m=dummy; dummy=to; to=from; from=dummy; }*/ debug(" joining: %ld <- %ld\n", to, from); q += *communities.heap[0]->maxdq->dq; /* Merge the second community into the first */ i = j = 0; while (i<n && j<m) { p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j]; debug("Pairs: %ld-%ld and %ld-%ld\n", p1->first, p1->second, p2->first, p2->second); if (p1->second < p2->second) { /* Considering p1 from now on */ debug(" Considering: %ld-%ld\n", p1->first, p1->second); if (p1->second == from) { debug(" WILL REMOVE: %ld-%ld\n", to, from); } else { /* chain, case 1 */ debug(" CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]); } i++; } else if (p1->second == p2->second) { /* p1->first, p1->second and p2->first form a triangle */ debug(" Considering: %ld-%ld and %ld-%ld\n", p1->first, p1->second, p2->first, p2->second); /* Update dq value */ debug(" TRIANGLE: %ld-%ld-%ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, *p2->dq, p1->first, p1->second, *p1->dq+*p2->dq); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq + *p2->dq); igraph_i_fastgreedy_community_remove_nei(&communities, p1->second, from); i++; j++; } else { debug(" Considering: %ld-%ld\n", p2->first, p2->second); if (p2->second == to) { debug(" WILL REMOVE: %ld-%ld\n", p2->second, p2->first); } else { /* chain, case 2 */ debug(" CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n", to, p2->second, from, to, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); p2->opposite->second=to; /* need to re-sort community nei list `p2->second` */ /* TODO: quicksort is O(n*logn), although we could do a deletion and * insertion which can be done in O(logn) if deletion is O(1) */ debug(" Re-sorting community %ld\n", p2->second); igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp); /* link from.neis[j] to the current place in to.neis if * from.neis[j] != to */ p2->first=to; IGRAPH_CHECK(igraph_vector_ptr_insert(&communities.e[to].neis,i,p2)); n++; i++; if (*p2->dq > *communities.e[to].maxdq->dq) { communities.e[to].maxdq = p2; k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to); igraph_i_fastgreedy_community_list_sift_up(&communities, k); } igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq - 2*VECTOR(a)[to]*VECTOR(a)[p2->second]); } j++; } } while (i<n) { p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; if (p1->second == from) { debug(" WILL REMOVE: %ld-%ld\n", p1->first, from); } else { /* chain, case 1 */ debug(" CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]); } i++; } while (j<m) { p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j]; if (to == p2->second) { j++; continue; } /* chain, case 2 */ debug(" CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n", to, p2->second, from, p1->first, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); p2->opposite->second=to; /* need to re-sort community nei list `p2->second` */ /* TODO: quicksort is O(n*logn), although we could do a deletion and * insertion which can be done in O(logn) if deletion is O(1) */ debug(" Re-sorting community %ld\n", p2->second); igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp); /* link from.neis[j] to the current place in to.neis if * from.neis[j] != to */ p2->first=to; IGRAPH_CHECK(igraph_vector_ptr_push_back(&communities.e[to].neis,p2)); if (*p2->dq > *communities.e[to].maxdq->dq) { communities.e[to].maxdq = p2; k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to); igraph_i_fastgreedy_community_list_sift_up(&communities, k); } igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); j++; } /* Now, remove community `from` from the neighbors of community `to` */ if (communities.no_of_communities > 2) { debug(" REMOVING: %ld-%ld\n", to, from); igraph_i_fastgreedy_community_remove_nei(&communities, to, from); i=igraph_i_fastgreedy_community_list_find_in_heap(&communities, from); igraph_i_fastgreedy_community_list_remove(&communities, i); } communities.e[from].maxdq=0; /* Update community sizes */ communities.e[to].size += communities.e[from].size; communities.e[from].size = 0; /* record what has been merged */ /* igraph_vector_ptr_clear is not enough here as it won't free * the memory consumed by communities.e[from].neis. Thanks * to Tom Gregorovic for pointing that out. */ igraph_vector_ptr_destroy(&communities.e[from].neis); if (merges) { MATRIX(*merges, no_of_joins, 0) = communities.e[to].id; MATRIX(*merges, no_of_joins, 1) = communities.e[from].id; communities.e[to].id = no_of_nodes+no_of_joins; } /* Update vector a */ VECTOR(a)[to] += VECTOR(a)[from]; VECTOR(a)[from] = 0.0; no_of_joins++; } /* TODO: continue merging when some isolated communities remained. Always * joining the communities with the least number of nodes results in the * smallest decrease in modularity every step. Now we're simply deleting * the excess rows from the merge matrix */ if (no_of_joins < total_joins) { long int *ivec; ivec=igraph_Calloc(igraph_matrix_nrow(merges), long int); if (ivec == 0) IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); IGRAPH_FINALLY(free, ivec); for (i=0; i<no_of_joins; i++) ivec[i] = i+1; igraph_matrix_permdelete_rows(merges, ivec, total_joins-no_of_joins); free(ivec); IGRAPH_FINALLY_CLEAN(1); }
int check_simple() { igraph_t g; long int nodes=100; long int edges=1000; igraph_real_t p=3.0/nodes; long int runs=10; long int r, e, ecount; igraph_vector_t eids, pairs, path; srand(time(0)); igraph_vector_init(&pairs, edges*2); igraph_vector_init(&path, 0); igraph_vector_init(&eids, 0); for (r=0; r<runs; r++) { igraph_erdos_renyi_game(&g, IGRAPH_ERDOS_RENYI_GNP, nodes, p, /*directed=*/ 0, /*loops=*/ 0); ecount=igraph_ecount(&g); for (e=0; e<edges; e++) { long int edge=RNG_INTEGER(0, ecount-1); VECTOR(pairs)[2*e] = IGRAPH_FROM(&g, edge); VECTOR(pairs)[2*e+1] = IGRAPH_TO(&g, edge); } igraph_get_eids(&g, &eids, &pairs, /*path=*/ 0, 0, /*error=*/ 1); for (e=0; e<edges; e++) { long int edge=VECTOR(eids)[e]; long int from1=VECTOR(pairs)[2*e]; long int to1=VECTOR(pairs)[2*e+1]; long int from2=IGRAPH_FROM(&g, edge); long int to2=IGRAPH_TO(&g, edge); long int min1= from1 < to1 ? from1 : to1; long int max1= from1 < to1 ? to1 : from1; long int min2= from2 < to2 ? from2 : to2; long int max2= from2 < to2 ? to2 : from2; if (min1 != min2 || max1 != max2) { return 11; } } igraph_diameter(&g, /*res=*/ 0, /*from=*/ 0, /*to=*/ 0, &path, IGRAPH_UNDIRECTED, /*unconn=*/ 1); igraph_get_eids(&g, &eids, /*pairs=*/ 0, &path, 0, /*error=*/ 1); for (e=0; e<igraph_vector_size(&path)-1; e++) { long int edge=VECTOR(eids)[e]; long int from1=VECTOR(path)[e]; long int to1=VECTOR(path)[e+1]; long int from2=IGRAPH_FROM(&g, edge); long int to2=IGRAPH_TO(&g, edge); long int min1= from1 < to1 ? from1 : to1; long int max1= from1 < to1 ? to1 : from1; long int min2= from2 < to2 ? from2 : to2; long int max2= from2 < to2 ? to2 : from2; if (min1 != min2 || max1 != max2) { return 12; } } igraph_destroy(&g); } igraph_vector_destroy(&path); igraph_vector_destroy(&pairs); igraph_vector_destroy(&eids); return 0; }
int igraph_layout_i_grid_fr(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); float width=sqrtf(no_nodes), height=width; igraph_2dgrid_t grid; igraph_vector_float_t dispx, dispy; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; igraph_2dgrid_iterator_t vidit; igraph_integer_t i; const float cellsize=2.0; RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; } if (!igraph_finite(x2)) { x2 = sqrt(no_nodes)/2; } if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; } if (!igraph_finite(y2)) { y2 = sqrt(no_nodes)/2; } MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); } } /* make grid */ IGRAPH_CHECK(igraph_2dgrid_init(&grid, res, -width/2, width/2, cellsize, -height/2, height/2, cellsize)); IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid); /* place vertices on grid */ for (i=0; i<no_nodes; i++) { igraph_2dgrid_add2(&grid, i); } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); /* repulsion */ igraph_2dgrid_reset(&grid, &vidit); while ( (v=igraph_2dgrid_next(&grid, &vidit)-1) != -1) { while ( (u=igraph_2dgrid_next_nei(&grid, &vidit)-1) != -1) { float dx=MATRIX(*res, v, 0)-MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1)-MATRIX(*res, u, 1); float dlen=dx * dx + dy * dy; if (dlen < cellsize * cellsize) { VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; } } } /* attraction */ for (e=0; e<no_edges; e++) { igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); } /* update */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } } temp -= difftemp; } igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); igraph_2dgrid_destroy(&grid); IGRAPH_FINALLY_CLEAN(3); return 0; }
int print_attributes(const igraph_t *g) { igraph_vector_t gtypes, vtypes, etypes; igraph_strvector_t gnames, vnames, enames; long int i; igraph_vector_t vec; igraph_strvector_t svec; long int j; igraph_vector_init(>ypes, 0); igraph_vector_init(&vtypes, 0); igraph_vector_init(&etypes, 0); igraph_strvector_init(&gnames, 0); igraph_strvector_init(&vnames, 0); igraph_strvector_init(&enames, 0); igraph_cattribute_list(g, &gnames, >ypes, &vnames, &vtypes, &enames, &etypes); /* Graph attributes */ for (i=0; i<igraph_strvector_size(&gnames); i++) { printf("%s=", STR(gnames, i)); if (VECTOR(gtypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) { igraph_real_printf(GAN(g, STR(gnames,i))); putchar(' '); } else { printf("\"%s\" ", GAS(g, STR(gnames,i))); } } printf("\n"); for (i=0; i<igraph_vcount(g); i++) { long int j; printf("Vertex %li: ", i); for (j=0; j<igraph_strvector_size(&vnames); j++) { printf("%s=", STR(vnames, j)); if (VECTOR(vtypes)[j]==IGRAPH_ATTRIBUTE_NUMERIC) { igraph_real_printf(VAN(g, STR(vnames,j), i)); putchar(' '); } else { printf("\"%s\" ", VAS(g, STR(vnames,j), i)); } } printf("\n"); } for (i=0; i<igraph_ecount(g); i++) { long int j; printf("Edge %li (%i-%i): ", i, (int)IGRAPH_FROM(g,i), (int)IGRAPH_TO(g,i)); for (j=0; j<igraph_strvector_size(&enames); j++) { printf("%s=", STR(enames, j)); if (VECTOR(etypes)[j]==IGRAPH_ATTRIBUTE_NUMERIC) { igraph_real_printf(EAN(g, STR(enames, j), i)); putchar(' '); } else { printf("\"%s\" ", EAS(g, STR(enames, j), i)); } } printf("\n"); } /* Check vector-based query functions */ igraph_vector_init(&vec, 0); igraph_strvector_init(&svec, 0); for (j=0; j<igraph_strvector_size(&vnames); j++) { if (VECTOR(vtypes)[j]==IGRAPH_ATTRIBUTE_NUMERIC) { igraph_cattribute_VANV(g, STR(vnames, j), igraph_vss_all(), &vec); for (i=0; i<igraph_vcount(g); i++) { igraph_real_t num=VAN(g, STR(vnames, j), i); if (num != VECTOR(vec)[i] && (!isnan(num) || !isnan(VECTOR(vec)[i]))) { exit(51); } } } else { igraph_cattribute_VASV(g, STR(vnames, j), igraph_vss_all(), &svec); for (i=0; i<igraph_vcount(g); i++) { const char *str=VAS(g, STR(vnames, j), i); if (strcmp(str,STR(svec, i))) { exit(52); } } } } for (j=0; j<igraph_strvector_size(&enames); j++) { if (VECTOR(etypes)[j]==IGRAPH_ATTRIBUTE_NUMERIC) { igraph_cattribute_EANV(g, STR(enames, j), igraph_ess_all(IGRAPH_EDGEORDER_ID), &vec); for (i=0; i<igraph_ecount(g); i++) { igraph_real_t num=EAN(g, STR(enames, j), i); if (num != VECTOR(vec)[i] && (!isnan(num) || !isnan(VECTOR(vec)[i]))) { exit(53); } } } else { igraph_cattribute_EASV(g, STR(enames, j), igraph_ess_all(IGRAPH_EDGEORDER_ID), &svec); for (i=0; i<igraph_ecount(g); i++) { const char *str=EAS(g, STR(enames, j), i); if (strcmp(str,STR(svec, i))) { exit(54); } } } } igraph_strvector_destroy(&svec); igraph_vector_destroy(&vec); igraph_strvector_destroy(&enames); igraph_strvector_destroy(&vnames); igraph_strvector_destroy(&gnames); igraph_vector_destroy(&etypes); igraph_vector_destroy(&vtypes); igraph_vector_destroy(>ypes); return 0; }
int igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy, const igraph_vector_t *minz, const igraph_vector_t *maxz) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); igraph_integer_t i; igraph_vector_float_t dispx, dispy, dispz; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; float width=sqrtf(no_nodes), height=width, depth=width; igraph_bool_t conn=1; float C; if (niter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in " "Fruchterman-Reingold layout", IGRAPH_EINVAL); } if (use_seed && (igraph_matrix_nrow(res) != no_nodes || igraph_matrix_ncol(res) != 3)) { IGRAPH_ERROR("Invalid start position matrix size in " "Fruchterman-Reingold layout", IGRAPH_EINVAL); } if (weight && igraph_vector_size(weight) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL); } if (minx && igraph_vector_size(minx) != no_nodes) { IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL); } if (maxx && igraph_vector_size(maxx) != no_nodes) { IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL); } if (minx && maxx && !igraph_vector_all_le(minx, maxx)) { IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL); } if (miny && igraph_vector_size(miny) != no_nodes) { IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL); } if (maxy && igraph_vector_size(maxy) != no_nodes) { IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL); } if (miny && maxy && !igraph_vector_all_le(miny, maxy)) { IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL); } if (minz && igraph_vector_size(minz) != no_nodes) { IGRAPH_ERROR("Invalid minz vector length", IGRAPH_EINVAL); } if (maxz && igraph_vector_size(maxz) != no_nodes) { IGRAPH_ERROR("Invalid maxz vector length", IGRAPH_EINVAL); } if (minz && maxz && !igraph_vector_all_le(minz, maxz)) { IGRAPH_ERROR("minz must not be greater than maxz", IGRAPH_EINVAL); } igraph_is_connected(graph, &conn, IGRAPH_WEAK); if (!conn) { C = no_nodes * sqrtf(no_nodes); } RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; igraph_real_t z1=minz ? VECTOR(*minz)[i] : -depth/2; igraph_real_t z2=maxz ? VECTOR(*maxz)[i] : depth/2; MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); MATRIX(*res, i, 2) = RNG_UNIF(z1, z2); } } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); IGRAPH_CHECK(igraph_vector_float_init(&dispz, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispz); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; /* calculate repulsive forces, we have a special version for unconnected graphs */ igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); igraph_vector_float_null(&dispz); if (conn) { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); float dlen=dx * dx + dy * dy + dz * dz; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dz = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy + dz * dz; } VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispz)[v] += dz/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; VECTOR(dispz)[u] -= dz/dlen; } } } else { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); float dlen, rdlen; dlen=dx * dx + dy * dy + dz * dz; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dz = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy + dz * dz; } rdlen=sqrt(dlen); VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dz * (C-dlen * rdlen) / (dlen*C); VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispz)[u] -= dz * (C-dlen * rdlen) / (dlen*C); } } } /* calculate attractive forces */ for (e=0; e<no_edges; e++) { /* each edges is an ordered pair of vertices v and u */ igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy + dz * dz) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispz)[v] -= (dz * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); VECTOR(dispz)[u] += (dz * dlen); } /* limit max displacement to temperature t and prevent from displacement outside frame */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dz=VECTOR(dispz)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy + dz * dz); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; igraph_real_t mz=fabs(dz) < temp ? dz : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; MATRIX(*res, v, 2) += (dz / displen) * mz; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } if (minz && MATRIX(*res, v, 2) < VECTOR(*minz)[v]) { MATRIX(*res, v, 2) = VECTOR(*minz)[v]; } if (maxz && MATRIX(*res, v, 2) > VECTOR(*maxz)[v]) { MATRIX(*res, v, 2) = VECTOR(*maxz)[v]; } } temp -= difftemp; } RNG_END(); igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); igraph_vector_float_destroy(&dispz); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_layout_i_fr(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); igraph_integer_t i; igraph_vector_float_t dispx, dispy; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; float width=sqrtf(no_nodes), height=width; igraph_bool_t conn=1; float C; igraph_is_connected(graph, &conn, IGRAPH_WEAK); if (!conn) { C = no_nodes * sqrtf(no_nodes); } RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; } if (!igraph_finite(x2)) { x2 = sqrt(no_nodes)/2; } if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; } if (!igraph_finite(y2)) { y2 = sqrt(no_nodes)/2; } MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); } } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; /* calculate repulsive forces, we have a special version for unconnected graphs */ igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); if (conn) { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dlen=dx * dx + dy * dy; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy; } VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; } } } else { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dlen, rdlen; dlen=dx * dx + dy * dy; if (dlen == 0) { dx = RNG_UNIF(0, 1e-6); dy = RNG_UNIF(0, 1e-6); dlen = dx * dx + dy * dy; } rdlen=sqrt(dlen); VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C); } } } /* calculate attractive forces */ for (e=0; e<no_edges; e++) { /* each edges is an ordered pair of vertices v and u */ igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); } /* limit max displacement to temperature t and prevent from displacement outside frame */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } } temp -= difftemp; } RNG_END(); igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); IGRAPH_FINALLY_CLEAN(2); return 0; }
integer_t Edge::destination() { return IGRAPH_TO(m_pGraph->c_graph(), m_index); }
int igraph_get_incidence(const igraph_t *graph, const igraph_vector_bool_t *types, igraph_matrix_t *res, igraph_vector_t *row_ids, igraph_vector_t *col_ids) { long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); long int n1=0, n2=0, i; igraph_vector_t perm; long int p1, p2; if (igraph_vector_bool_size(types) != no_of_nodes) { IGRAPH_ERROR("Invalid vertex type vector for bipartite graph", IGRAPH_EINVAL); } for (i=0; i<no_of_nodes; i++) { n1 += VECTOR(*types)[i] == 0 ? 1 : 0; } n2 = no_of_nodes-n1; IGRAPH_VECTOR_INIT_FINALLY(&perm, no_of_nodes); for (i=0, p1=0, p2=n1; i<no_of_nodes; i++) { VECTOR(perm)[i] = VECTOR(*types)[i] ? p2++ : p1++; } IGRAPH_CHECK(igraph_matrix_resize(res, n1, n2)); igraph_matrix_null(res); for (i=0; i<no_of_edges; i++) { long int from=IGRAPH_FROM(graph, i); long int to=IGRAPH_TO(graph, i); long int from2=(long int) VECTOR(perm)[from]; long int to2=(long int) VECTOR(perm)[to]; if (! VECTOR(*types)[from]) { MATRIX(*res, from2, to2-n1) += 1; } else { MATRIX(*res, to2, from2-n1) += 1; } } if (row_ids) { IGRAPH_CHECK(igraph_vector_resize(row_ids, n1)); } if (col_ids) { IGRAPH_CHECK(igraph_vector_resize(col_ids, n2)); } if (row_ids || col_ids) { for (i=0; i<no_of_nodes; i++) { if (! VECTOR(*types)[i]) { if (row_ids) { long int i2=(long int) VECTOR(perm)[i]; VECTOR(*row_ids)[i2] = i; } } else { if (col_ids) { long int i2=(long int) VECTOR(perm)[i]; VECTOR(*col_ids)[i2-n1] = i; } } } } igraph_vector_destroy(&perm); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_biconnected_components(const igraph_t *graph, igraph_integer_t *no, igraph_vector_ptr_t *tree_edges, igraph_vector_ptr_t *component_edges, igraph_vector_ptr_t *components, igraph_vector_t *articulation_points) { long int no_of_nodes=igraph_vcount(graph); igraph_vector_long_t nextptr; igraph_vector_long_t num, low; igraph_vector_bool_t found; igraph_vector_int_t *adjedges; igraph_stack_t path; igraph_vector_t edgestack; igraph_inclist_t inclist; long int i, counter, rootdfs=0; igraph_vector_long_t vertex_added; long int comps=0; igraph_vector_ptr_t *mycomponents=components, vcomponents; IGRAPH_CHECK(igraph_vector_long_init(&nextptr, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &nextptr); IGRAPH_CHECK(igraph_vector_long_init(&num, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &num); IGRAPH_CHECK(igraph_vector_long_init(&low, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &low); IGRAPH_CHECK(igraph_vector_bool_init(&found, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &found); IGRAPH_CHECK(igraph_stack_init(&path, 100)); IGRAPH_FINALLY(igraph_stack_destroy, &path); IGRAPH_VECTOR_INIT_FINALLY(&edgestack, 0); IGRAPH_CHECK(igraph_vector_reserve(&edgestack, 100)); IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_inclist_destroy, &inclist); IGRAPH_CHECK(igraph_vector_long_init(&vertex_added, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &vertex_added); if (no) { *no=0; } if (tree_edges) { igraph_vector_ptr_clear(tree_edges); } if (components) { igraph_vector_ptr_clear(components); } if (component_edges) { igraph_vector_ptr_clear(component_edges); } if (articulation_points) { igraph_vector_clear(articulation_points); } if (component_edges && !components) { mycomponents=&vcomponents; IGRAPH_CHECK(igraph_vector_ptr_init(mycomponents, 0)); IGRAPH_FINALLY(igraph_i_free_vectorlist, mycomponents); } for (i=0; i<no_of_nodes; i++) { if (VECTOR(low)[i] != 0) { continue; } /* already visited */ IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_stack_push(&path, i)); counter=1; rootdfs=0; VECTOR(low)[i]=VECTOR(num)[i]=counter++; while (!igraph_stack_empty(&path)) { long int n; long int act=(long int) igraph_stack_top(&path); long int actnext=VECTOR(nextptr)[act]; adjedges=igraph_inclist_get(&inclist, act); n=igraph_vector_int_size(adjedges); if (actnext < n) { /* Step down (maybe) */ long int edge=(long int) VECTOR(*adjedges)[actnext]; long int nei=IGRAPH_OTHER(graph, edge, act); if (VECTOR(low)[nei] == 0) { if (act==i) { rootdfs++; } IGRAPH_CHECK(igraph_vector_push_back(&edgestack, edge)); IGRAPH_CHECK(igraph_stack_push(&path, nei)); VECTOR(low)[nei] = VECTOR(num)[nei]=counter++; } else { /* Update low value if needed */ if (VECTOR(num)[nei] < VECTOR(low)[act]) { VECTOR(low)[act]=VECTOR(num)[nei]; } } VECTOR(nextptr)[act] += 1; } else { /* Step up */ igraph_stack_pop(&path); if (!igraph_stack_empty(&path)) { long int prev=(long int) igraph_stack_top(&path); /* Update LOW value if needed */ if (VECTOR(low)[act] < VECTOR(low)[prev]) { VECTOR(low)[prev] = VECTOR(low)[act]; } /* Check for articulation point */ if (VECTOR(low)[act] >= VECTOR(num)[prev]) { if (articulation_points && !VECTOR(found)[prev] && prev != i /* the root */) { IGRAPH_CHECK(igraph_vector_push_back(articulation_points, prev)); VECTOR(found)[prev] = 1; } if (no) { *no += 1; } /*------------------------------------*/ /* Record the biconnected component just found */ if (tree_edges || mycomponents) { igraph_vector_t *v = 0, *v2 = 0; comps++; if (tree_edges) { v=igraph_Calloc(1, igraph_vector_t); if (!v) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); } IGRAPH_CHECK(igraph_vector_init(v, 0)); IGRAPH_FINALLY(igraph_vector_destroy, v); } if (mycomponents) { v2=igraph_Calloc(1, igraph_vector_t); if (!v2) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); } IGRAPH_CHECK(igraph_vector_init(v2, 0)); IGRAPH_FINALLY(igraph_vector_destroy, v2); } while (!igraph_vector_empty(&edgestack)) { long int e=(long int) igraph_vector_pop_back(&edgestack); long int from=IGRAPH_FROM(graph,e); long int to=IGRAPH_TO(graph,e); if (tree_edges) { IGRAPH_CHECK(igraph_vector_push_back(v, e)); } if (mycomponents) { if (VECTOR(vertex_added)[from] != comps) { VECTOR(vertex_added)[from] = comps; IGRAPH_CHECK(igraph_vector_push_back(v2, from)); } if (VECTOR(vertex_added)[to] != comps) { VECTOR(vertex_added)[to] = comps; IGRAPH_CHECK(igraph_vector_push_back(v2, to)); } } if (from==prev || to==prev) { break; } } if (mycomponents) { IGRAPH_CHECK(igraph_vector_ptr_push_back(mycomponents, v2)); IGRAPH_FINALLY_CLEAN(1); } if (tree_edges) { IGRAPH_CHECK(igraph_vector_ptr_push_back(tree_edges, v)); IGRAPH_FINALLY_CLEAN(1); } if (component_edges) { igraph_vector_t *nodes=VECTOR(*mycomponents)[comps-1]; igraph_vector_t *vv=igraph_Calloc(1, igraph_vector_t); long int ii, no_vert=igraph_vector_size(nodes); if (!vv) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); } IGRAPH_CHECK(igraph_vector_init(vv, 0)); IGRAPH_FINALLY(igraph_vector_destroy, vv); for (ii=0; ii<no_vert; ii++) { long int vert=(long int) VECTOR(*nodes)[ii]; igraph_vector_int_t *edges=igraph_inclist_get(&inclist, vert); long int j, nn=igraph_vector_int_size(edges); for (j=0; j<nn; j++) { long int e=(long int) VECTOR(*edges)[j]; long int nei=IGRAPH_OTHER(graph, e, vert); if (VECTOR(vertex_added)[nei] == comps && nei<vert) { IGRAPH_CHECK(igraph_vector_push_back(vv, e)); } } } IGRAPH_CHECK(igraph_vector_ptr_push_back(component_edges, vv)); IGRAPH_FINALLY_CLEAN(1); } } /* record component if requested */ /*------------------------------------*/ } } /* !igraph_stack_empty(&path) */ } } /* !igraph_stack_empty(&path) */ if (articulation_points && rootdfs >= 2) { IGRAPH_CHECK(igraph_vector_push_back(articulation_points, i)); } } /* i < no_of_nodes */ if (mycomponents != components) { igraph_i_free_vectorlist(mycomponents); IGRAPH_FINALLY_CLEAN(1); } igraph_vector_long_destroy(&vertex_added); igraph_inclist_destroy(&inclist); igraph_vector_destroy(&edgestack); igraph_stack_destroy(&path); igraph_vector_bool_destroy(&found); igraph_vector_long_destroy(&low); igraph_vector_long_destroy(&num); igraph_vector_long_destroy(&nextptr); IGRAPH_FINALLY_CLEAN(8); return 0; }
int igraph_pagerank(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, const igraph_vs_t vids, igraph_bool_t directed, igraph_real_t damping, const igraph_vector_t *weights, igraph_arpack_options_t *options) { igraph_matrix_t values; igraph_matrix_t vectors; igraph_integer_t dirmode; igraph_vector_t outdegree; igraph_vector_t tmp; long int i; long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); options->n = igraph_vcount(graph); options->nev = 1; options->ncv = 3; options->which[0]='L'; options->which[1]='M'; options->start=1; /* no random start vector */ directed = directed && igraph_is_directed(graph); if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid length of weights vector when calculating " "PageRank scores", IGRAPH_EINVAL); } IGRAPH_MATRIX_INIT_FINALLY(&values, 0, 0); IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1); if (directed) { dirmode=IGRAPH_IN; } else { dirmode=IGRAPH_ALL; } IGRAPH_VECTOR_INIT_FINALLY(&outdegree, options->n); IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n); RNG_BEGIN(); if (!weights) { igraph_adjlist_t adjlist; igraph_i_pagerank_data_t data = { graph, &adjlist, damping, &outdegree, &tmp }; IGRAPH_CHECK(igraph_degree(graph, &outdegree, igraph_vss_all(), directed ? IGRAPH_OUT : IGRAPH_ALL, /*loops=*/ 0)); /* Avoid division by zero */ for (i=0; i<options->n; i++) { if (VECTOR(outdegree)[i]==0) { VECTOR(outdegree)[i]=1; } MATRIX(vectors, i, 0) = VECTOR(outdegree)[i]; } IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, dirmode)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank, &data, options, 0, &values, &vectors)); igraph_adjlist_destroy(&adjlist); IGRAPH_FINALLY_CLEAN(1); } else { igraph_adjedgelist_t adjedgelist; igraph_i_pagerank_data2_t data = { graph, &adjedgelist, weights, damping, &outdegree, &tmp }; IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, dirmode)); IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist); /* Weighted degree */ for (i=0; i<no_of_edges; i++) { long int from=IGRAPH_FROM(graph, i); long int to=IGRAPH_TO(graph, i); igraph_real_t weight=VECTOR(*weights)[i]; VECTOR(outdegree)[from] += weight; if (!directed) { VECTOR(outdegree)[to] += weight; } } /* Avoid division by zero */ for (i=0; i<options->n; i++) { if (VECTOR(outdegree)[i]==0) { VECTOR(outdegree)[i]=1; } MATRIX(vectors, i, 0) = VECTOR(outdegree)[i]; } IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank2, &data, options, 0, &values, &vectors)); igraph_adjedgelist_destroy(&adjedgelist); IGRAPH_FINALLY_CLEAN(1); } RNG_END(); igraph_vector_destroy(&tmp); igraph_vector_destroy(&outdegree); IGRAPH_FINALLY_CLEAN(2); if (value) { *value=MATRIX(values, 0, 0); } if (vector) { long int i; igraph_vit_t vit; long int nodes_to_calc; igraph_real_t sum=0; for (i=0; i<no_of_nodes; i++) { sum += MATRIX(vectors, i, 0); } IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); nodes_to_calc=IGRAPH_VIT_SIZE(vit); IGRAPH_CHECK(igraph_vector_resize(vector, nodes_to_calc)); for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { VECTOR(*vector)[i] = MATRIX(vectors, (long int)IGRAPH_VIT_GET(vit), 0); VECTOR(*vector)[i] /= sum; } igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(1); } if (options->info) { IGRAPH_WARNING("Non-zero return code from ARPACK routine!"); } igraph_matrix_destroy(&vectors); igraph_matrix_destroy(&values); IGRAPH_FINALLY_CLEAN(2); return 0; }