int main() { igraph_t g; igraph_vector_t v=IGRAPH_VECTOR_NULL; igraph_real_t edges[] = { 0,1, 1,2, 2,2, 2,3, 2,4, 3,4 }; igraph_vector_t v2; long int i; igraph_vit_t vit; igraph_vs_t vs; igraph_integer_t size; igraph_vector_view(&v, edges, sizeof(edges)/sizeof(igraph_real_t)); igraph_create(&g, &v, 0, IGRAPH_DIRECTED); /* Create iterator based on a vector (view) */ igraph_vector_init(&v2, 6); VECTOR(v2)[0]=0; VECTOR(v2)[1]=2; VECTOR(v2)[2]=4; VECTOR(v2)[3]=0; VECTOR(v2)[4]=2; VECTOR(v2)[5]=4; igraph_vit_create(&g, igraph_vss_vector(&v2), &vit); i=0; while (!IGRAPH_VIT_END(vit)) { if (IGRAPH_VIT_GET(vit) != VECTOR(v2)[i]) { return 1; } IGRAPH_VIT_NEXT(vit); i++; } if (i != igraph_vector_size(&v2)) { return 2; } igraph_vit_destroy(&vit); igraph_vector_destroy(&v2); /* Create small vector iterator */ igraph_vs_vector_small(&vs, 0, 2, 4, 0, 2, 4, 2, -1); igraph_vit_create(&g, vs, &vit); igraph_vs_size(&g, &vs, &size); printf("%li ", (long int) size); for (; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { printf("%li ", (long int) IGRAPH_VIT_GET(vit)); } printf("\n"); igraph_vit_destroy(&vit); igraph_vs_destroy(&vs); /* Clean up */ igraph_destroy(&g); return 0; }
/** * \ingroup structural * \function igraph_similarity_jaccard * \brief Jaccard similarity coefficient for the given vertices. * * </para><para> * The Jaccard similarity coefficient of two vertices is the number of common * neighbors divided by the number of vertices that are neighbors of at * least one of the two vertices being considered. This function calculates * the pairwise Jaccard similarities for some (or all) of the vertices. * * \param graph The graph object to analyze * \param res Pointer to a matrix, the result of the calculation will * be stored here. The number of its rows and columns is the same * as the number of vertex ids in \p vids. * \param vids The vertex ids of the vertices for which the * calculation will be done. * \param mode The type of neighbors to be used for the calculation in * directed graphs. Possible values: * \clist * \cli IGRAPH_OUT * the outgoing edges will be considered for each node. * \cli IGRAPH_IN * the incoming edges will be considered for each node. * \cli IGRAPH_ALL * the directed graph is considered as an undirected one for the * computation. * \endclist * \param loops Whether to include the vertices themselves in the neighbor * sets. * \return Error code: * \clist * \cli IGRAPH_ENOMEM * not enough memory for temporary data. * \cli IGRAPH_EINVVID * invalid vertex id passed. * \cli IGRAPH_EINVMODE * invalid mode argument. * \endclist * * Time complexity: O(|V|^2 d), * |V| is the number of vertices in the vertex iterator given, d is the * (maximum) degree of the vertices in the graph. * * \sa \ref igraph_similarity_dice(), a measure very similar to the Jaccard * coefficient * * \example examples/simple/igraph_similarity.c */ int igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops) { igraph_lazy_adjlist_t al; igraph_vit_t vit, vit2; long int i, j, k; long int len_union, len_intersection; igraph_vector_t *v1, *v2; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit2)); IGRAPH_FINALLY(igraph_vit_destroy, &vit2); IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &al, mode, IGRAPH_SIMPLIFY)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &al); IGRAPH_CHECK(igraph_matrix_resize(res, IGRAPH_VIT_SIZE(vit), IGRAPH_VIT_SIZE(vit))); if (loops) { for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { i=IGRAPH_VIT_GET(vit); v1=igraph_lazy_adjlist_get(&al, (igraph_integer_t) i); if (!igraph_vector_binsearch(v1, i, &k)) igraph_vector_insert(v1, k, i); } } for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { MATRIX(*res, i, i) = 1.0; for (IGRAPH_VIT_RESET(vit2), j=0; !IGRAPH_VIT_END(vit2); IGRAPH_VIT_NEXT(vit2), j++) { if (j <= i) continue; v1=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit)); v2=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit2)); igraph_i_neisets_intersect(v1, v2, &len_union, &len_intersection); if (len_union > 0) MATRIX(*res, i, j) = ((igraph_real_t)len_intersection)/len_union; else MATRIX(*res, i, j) = 0.0; MATRIX(*res, j, i) = MATRIX(*res, i, j); } } igraph_lazy_adjlist_destroy(&al); igraph_vit_destroy(&vit); igraph_vit_destroy(&vit2); IGRAPH_FINALLY_CLEAN(3); return 0; }
int main() { igraph_vs_t vs; igraph_vit_t vit; igraph_t g; igraph_integer_t size; igraph_ring(&g, 10, IGRAPH_UNDIRECTED, 0, 1); igraph_vs_seq(&vs, 0, 9); igraph_vit_create(&g, vs, &vit); igraph_vs_size(&g, &vs, &size); printf("%li", (long int) size); while (!IGRAPH_VIT_END(vit)) { printf(" %li", (long int)IGRAPH_VIT_GET(vit)); IGRAPH_VIT_NEXT(vit); } printf("\n"); igraph_vit_destroy(&vit); igraph_vs_destroy(&vs); igraph_destroy(&g); 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_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_cocitation_real(const igraph_t *graph, igraph_matrix_t *res, igraph_vs_t vids, igraph_neimode_t mode, igraph_vector_t *weights) { long int no_of_nodes=igraph_vcount(graph); long int no_of_vids; long int from, i, j, k, l, u, v; igraph_vector_t neis=IGRAPH_VECTOR_NULL; igraph_vector_t vid_reverse_index; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); no_of_vids = IGRAPH_VIT_SIZE(vit); /* Create a mapping from vertex IDs to the row of the matrix where * the result for this vertex will appear */ IGRAPH_VECTOR_INIT_FINALLY(&vid_reverse_index, no_of_nodes); igraph_vector_fill(&vid_reverse_index, -1); for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { v = IGRAPH_VIT_GET(vit); if (v < 0 || v >= no_of_nodes) IGRAPH_ERROR("invalid vertex ID in vertex selector", IGRAPH_EINVAL); VECTOR(vid_reverse_index)[v] = i; } IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); IGRAPH_CHECK(igraph_matrix_resize(res, no_of_vids, no_of_nodes)); igraph_matrix_null(res); /* The result */ for (from=0; from<no_of_nodes; from++) { igraph_real_t weight = 1; IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) from, mode)); if (weights) weight = VECTOR(*weights)[from]; for (i=0; i < igraph_vector_size(&neis)-1; i++) { u = (long int) VECTOR(neis)[i]; k = (long int) VECTOR(vid_reverse_index)[u]; for (j=i+1; j<igraph_vector_size(&neis); j++) { v = (long int) VECTOR(neis)[j]; l = (long int) VECTOR(vid_reverse_index)[v]; if (k != -1) MATRIX(*res, k, v) += weight; if (l != -1) MATRIX(*res, l, u) += weight; } } } /* Clean up */ igraph_vector_destroy(&neis); igraph_vector_destroy(&vid_reverse_index); igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(3); return 0; }
static GError* _tgengraph_parseGraphVertices(TGenGraph* g) { TGEN_ASSERT(g); tgen_debug("checking graph vertices..."); /* we will iterate through the vertices */ igraph_vit_t vertexIterator; gint result = igraph_vit_create(g->graph, igraph_vss_all(), &vertexIterator); if(result != IGRAPH_SUCCESS) { return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "igraph_vit_create return non-success code %i", result); } /* count the vertices as we iterate */ igraph_integer_t vertexCount = 0; GError* error = NULL; while (!IGRAPH_VIT_END(vertexIterator)) { igraph_integer_t vertexIndex = (igraph_integer_t)IGRAPH_VIT_GET(vertexIterator); /* get vertex attributes: S for string and N for numeric */ const gchar* idStr = (g->knownAttributes&TGEN_VA_ID) ? VAS(g->graph, "id", vertexIndex) : NULL; if(!idStr) { error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE, "found vertex %li with missing action 'id' attribute", (glong)vertexIndex); break; } if(g_strstr_len(idStr, (gssize)-1, "start")) { error = _tgengraph_parseStartVertex(g, idStr, vertexIndex); } else if(g_strstr_len(idStr, (gssize)-1, "end")) { error = _tgengraph_parseEndVertex(g, idStr, vertexIndex); } else if(g_strstr_len(idStr, (gssize)-1, "pause")) { error = _tgengraph_parsePauseVertex(g, idStr, vertexIndex); } else if(g_strstr_len(idStr, (gssize)-1, "synchronize")) { error = _tgengraph_parseSynchronizeVertex(g, idStr, vertexIndex); } else if(g_strstr_len(idStr, (gssize)-1, "transfer")) { error = _tgengraph_parseTransferVertex(g, idStr, vertexIndex); } else if(g_strstr_len(idStr, (gssize)-1, "choose")) { error = _tgengraph_parseChooseVertex(g, idStr, vertexIndex); } else { error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "found vertex %li (%s) with an unknown action id '%s'", (glong)vertexIndex, idStr, idStr); } if(error) { break; } vertexCount++; IGRAPH_VIT_NEXT(vertexIterator); } /* clean up */ igraph_vit_destroy(&vertexIterator); if(!g->startHasPeers && g->transferMissingPeers) { error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "peers required in either the 'start' action, or *every* 'transfer' action"); } if(!error) { g->vertexCount = igraph_vcount(g->graph); if(g->vertexCount != vertexCount) { tgen_warning("igraph_vcount %f does not match iterator count %f", g->vertexCount, vertexCount); } tgen_info("%u graph vertices ok", (guint) g->vertexCount); } return error; }
/** * \ingroup interface * \function igraph_degree * \brief The degree of some vertices in a graph. * * </para><para> * This function calculates the in-, out- or total degree of the * specified vertices. * \param graph The graph. * \param res Vector, this will contain the result. It should be * initialized and will be resized to be the appropriate size. * \param vids Vector, giving the vertex ids of which the degree will * be calculated. * \param mode Defines the type of the degree. * \c IGRAPH_OUT, out-degree, * \c IGRAPH_IN, in-degree, * \c IGRAPH_ALL, total degree (sum of the * in- and out-degree). * This parameter is ignored for undirected graphs. * \param loops Boolean, gives whether the self-loops should be * counted. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex id. * \c IGRAPH_EINVMODE: invalid mode argument. * * Time complexity: O(v) if * loops is * TRUE, and * O(v*d) * otherwise. v is the number * vertices for which the degree will be calculated, and * d is their (average) degree. * * \sa \ref igraph_strength() for the version that takes into account * edge weigths. */ int igraph_degree(const igraph_t *graph, igraph_vector_t *res, const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops) { long int nodes_to_calc; long int i, j; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { IGRAPH_ERROR("degree calculation failed", IGRAPH_EINVMODE); } nodes_to_calc=IGRAPH_VIT_SIZE(vit); if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; } IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc)); igraph_vector_null(res); if (loops) { if (mode & IGRAPH_OUT) { for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { long int vid=IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid+1]-VECTOR(graph->os)[vid]); } } if (mode & IGRAPH_IN) { for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { long int vid=IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid+1]-VECTOR(graph->is)[vid]); } } } else { /* no loops */ if (mode & IGRAPH_OUT) { for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { long int vid=IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid+1]-VECTOR(graph->os)[vid]); for (j=VECTOR(graph->os)[vid]; j<VECTOR(graph->os)[vid+1]; j++) { if (VECTOR(graph->to)[ (long int)VECTOR(graph->oi)[j] ]==vid) { VECTOR(*res)[i] -= 1; } } } } if (mode & IGRAPH_IN) { for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { long int vid=IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid+1]-VECTOR(graph->is)[vid]); for (j=VECTOR(graph->is)[vid]; j<VECTOR(graph->is)[vid+1]; j++) { if (VECTOR(graph->from)[ (long int)VECTOR(graph->ii)[j] ]==vid) { VECTOR(*res)[i] -= 1; } } } } } /* loops */ igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(1); return 0; }
/** * \ingroup interface * \function igraph_delete_vertices * \brief Removes vertices (with all their edges) from the graph. * * </para><para> * This function changes the ids of the vertices (except in some very * special cases, but these should not be relied on anyway). * * </para><para> * This function invalidates all iterators. * * \param graph The graph to work on. * \param vertices The ids of the vertices to remove in a * vector. The vector may contain the same id more * than once. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex id. * * Time complexity: O(|V|+|E|), * |V| and * |E| are the number of vertices and * edges in the original graph. */ int igraph_delete_vertices(igraph_t *graph, const igraph_vs_t vertices) { long int no_of_edges=igraph_ecount(graph); long int no_of_nodes=igraph_vcount(graph); igraph_vector_t edge_recoding, vertex_recoding; igraph_vit_t vit; igraph_t newgraph; long int i, j; long int remaining_vertices, remaining_edges; IGRAPH_VECTOR_INIT_FINALLY(&vertex_recoding, no_of_nodes); IGRAPH_VECTOR_INIT_FINALLY(&edge_recoding, no_of_edges); IGRAPH_CHECK(igraph_vit_create(graph, vertices, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); /* mark the vertices to delete */ for (; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit) ) { long int vertex=IGRAPH_VIT_GET(vit); if (vertex < 0 || vertex >= no_of_nodes) { IGRAPH_ERROR("Cannot delete vertices", IGRAPH_EINVVID); } VECTOR(vertex_recoding)[vertex]=1; } /* create vertex recoding vector */ for (remaining_vertices=0, i=0; i<no_of_nodes; i++) { if (VECTOR(vertex_recoding)[i]==0) { VECTOR(vertex_recoding)[i]=remaining_vertices+1; remaining_vertices++; } else { VECTOR(vertex_recoding)[i]=0; } } /* create edge recoding vector */ for (remaining_edges=0, i=0; i<no_of_edges; i++) { long int from=VECTOR(graph->from)[i]; long int to=VECTOR(graph->to)[i]; if (VECTOR(vertex_recoding)[from] != 0 && VECTOR(vertex_recoding)[to ] != 0) { VECTOR(edge_recoding)[i]=remaining_edges+1; remaining_edges++; } } /* start creating the graph */ newgraph.n=remaining_vertices; newgraph.directed=graph->directed; /* allocate vectors */ IGRAPH_VECTOR_INIT_FINALLY(&newgraph.from, remaining_edges); IGRAPH_VECTOR_INIT_FINALLY(&newgraph.to, remaining_edges); IGRAPH_VECTOR_INIT_FINALLY(&newgraph.oi, remaining_edges); IGRAPH_VECTOR_INIT_FINALLY(&newgraph.ii, remaining_edges); IGRAPH_VECTOR_INIT_FINALLY(&newgraph.os, remaining_vertices+1); IGRAPH_VECTOR_INIT_FINALLY(&newgraph.is, remaining_vertices+1); /* Add the edges */ for (i=0, j=0; j<remaining_edges; i++) { if (VECTOR(edge_recoding)[i]>0) { long int from=VECTOR(graph->from)[i]; long int to=VECTOR(graph->to )[i]; VECTOR(newgraph.from)[j]=VECTOR(vertex_recoding)[from]-1; VECTOR(newgraph.to )[j]=VECTOR(vertex_recoding)[to]-1; j++; } } /* update oi & ii */ IGRAPH_CHECK(igraph_vector_order(&newgraph.from, &newgraph.to, &newgraph.oi, remaining_vertices)); IGRAPH_CHECK(igraph_vector_order(&newgraph.to, &newgraph.from, &newgraph.ii, remaining_vertices)); IGRAPH_CHECK(igraph_i_create_start(&newgraph.os, &newgraph.from, &newgraph.oi, remaining_vertices)); IGRAPH_CHECK(igraph_i_create_start(&newgraph.is, &newgraph.to, &newgraph.ii, remaining_vertices)); /* attributes */ IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1,1,1); IGRAPH_FINALLY_CLEAN(6); IGRAPH_FINALLY(igraph_destroy, &newgraph); IGRAPH_I_ATTRIBUTE_DELETE_VERTICES(&newgraph, &edge_recoding, &vertex_recoding); igraph_vit_destroy(&vit); igraph_vector_destroy(&edge_recoding); igraph_vector_destroy(&vertex_recoding); igraph_destroy(graph); *graph=newgraph; IGRAPH_FINALLY_CLEAN(4); return 0; }
int igraph_dijkstra_shortest_paths(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t from, const igraph_vector_t *wghts, igraph_neimode_t mode) { long int no_of_nodes=igraph_vcount(graph); long int no_of_from; igraph_real_t *shortest; igraph_real_t min,alt; int i, j, uj, included; igraph_integer_t eid, u,v; igraph_vector_t q; igraph_vit_t fromvit; igraph_vector_t neis; IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit)); IGRAPH_FINALLY(igraph_vit_destroy, &fromvit); no_of_from=IGRAPH_VIT_SIZE(fromvit); if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE); } shortest=calloc(no_of_nodes, sizeof(igraph_real_t)); if (shortest==0) { IGRAPH_ERROR("shortest paths failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, shortest); IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_nodes)); igraph_matrix_null(res); for (IGRAPH_VIT_RESET(fromvit), i=0; !IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { //Start shortest and previous for(j=0;j<no_of_nodes;j++){ shortest[j] = INFINITY; //memset(previous,NAN, no_of_nodes); } shortest[(int)IGRAPH_VIT_GET(fromvit)] = 0; igraph_vector_init_seq(&q,0,no_of_nodes-1); while(igraph_vector_size(&q) != 0){ min = INFINITY; u = no_of_nodes; uj = igraph_vector_size(&q); for(j=0;j<igraph_vector_size(&q);j++){ v = VECTOR(q)[j]; if(shortest[(int)v] < min){ min = shortest[(int)v]; u = v; uj = j; } } if(min == INFINITY) break; igraph_vector_remove(&q,uj); igraph_vector_init(&neis,0); igraph_neighbors(graph,&neis,u,mode); for(j=0;j<igraph_vector_size(&neis);j++){ v = VECTOR(neis)[j]; //v must be in Q included = 0; for(j=0;j<igraph_vector_size(&q);j++){ if(v == VECTOR(q)[j]){ included = 1; break; } } if(!included) continue; igraph_get_eid(graph,&eid,u,v,1); alt = shortest[(int)u] + VECTOR(*wghts)[(int)eid]; if(alt < shortest[(int)v]){ shortest[(int)v] = alt; } } igraph_vector_destroy(&neis); } for(j=0;j<no_of_nodes;j++){ MATRIX(*res,i,j) = shortest[j]; } igraph_vector_destroy(&q); } /* Clean */ free(shortest); igraph_vit_destroy(&fromvit); IGRAPH_FINALLY_CLEAN(2); return 0; }
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; }
static PyObject *ignp_fun_propagate(PyObject *self, PyObject *args) { long int num_active = 0; long int num_susc = 1; long int limit = 30; long int i; float lrAct; PyObject* mem_addr_o; long int mem_addr; /* StateTracker Vars */ PyArrayObject *py_trkr; // 'i64' /* By EdgeID */ PyArrayObject *py_tie_r; // 'f32' /* By NodeID */ PyArrayObject *py_act_n; // 'i8' PyArrayObject *py_thr_n; // 'f32' PyArrayObject *py_exp_n; // 'i64' /* By Infection Order*/ PyArrayObject *py_deg; // i64 PyArrayObject *py_nSuc; // i64 PyArrayObject *py_nAct; // i64 PyArrayObject *py_lrAct; // f32 PyArrayObject *py_hom; // i64 PyArrayObject *py_eComp; // i64 PyArrayObject *py_iComp; // i64 PyArrayObject *py_eTri; // i64 PyArrayObject *py_iTri; // i64 PyArrayObject *py_thr; // i32 PyArrayObject *py_exp; // i64 PyArrayObject *py_cTime; // i64 PyObject *g_obj; igraph_t *g; igraph_t gc; long int randID; long int low = 0; long int high = -1; long int ctime = 0; igraph_rng_t *rGen; igraph_vit_t nbr_iter; igraph_vs_t nbr_sel; igraph_integer_t eid; igraph_integer_t vdeg; igraph_integer_t e_comp = 0; igraph_integer_t i_comp = 0; igraph_integer_t e_tri = 0; igraph_integer_t i_tri = 0; int actv_nbr_count; //int res, j; igraph_vector_t temp; //igraph_vector_t actv_nbrs; //PySys_WriteStdout("Parse Started\n"); if (!PyArg_ParseTuple(args, "OO!O!O!O!O!O!O!O!O!O!O!O!O!O!O!O!O!", &g_obj, &PyArray_Type, &py_trkr, // i64 &PyArray_Type, &py_tie_r, // 'f32' &PyArray_Type, &py_act_n, // 'i8' &PyArray_Type, &py_thr_n, // 'i32' &PyArray_Type, &py_exp_n, // 'i64' &PyArray_Type, &py_deg, // i64 &PyArray_Type, &py_nSuc, // i64 &PyArray_Type, &py_nAct, // i64 &PyArray_Type, &py_lrAct, // f32 &PyArray_Type, &py_hom, // i64 &PyArray_Type, &py_eComp, // i64 &PyArray_Type, &py_iComp, // i64 &PyArray_Type, &py_eTri, // i64 &PyArray_Type, &py_iTri, // i64 &PyArray_Type, &py_thr, // i64 &PyArray_Type, &py_exp, // i64 &PyArray_Type, &py_cTime // i64 )) { printf("Parse Failed\n"); Py_RETURN_NONE; } //PySys_WriteStdout("Getting Tracker Vars\n"); num_active = (long) ax_i64(py_trkr, 0); num_susc = (long) ax_i64(py_trkr, 1); limit = (long) ax_i64(py_trkr, 2); mem_addr_o = PyObject_CallMethod(g_obj, "_raw_pointer", "()"); mem_addr = PyInt_AsLong(mem_addr_o); Py_DECREF(mem_addr_o); if (mem_addr == -1) { printf("PyInt to Long Failed"); return NULL; } g = (igraph_t*) mem_addr; //Setup Vars rGen = igraph_rng_default(); //igraph_rng_init(rGen, time(NULL)); high += (long) igraph_vcount(g); //PySys_WriteStdout("Propagate Starting with %li active of target %li with %li open\n", // num_active, limit, num_susc); //Propagate do { // get random node ctime += 1; randID = igraph_rng_get_integer(rGen, low, high); if ( ax_i8(py_act_n, randID) != 1 && ax_i64(py_exp_n, randID)>=ax_i32(py_thr_n, randID) ){ //activate ax_i8(py_act_n,randID) = 1; lrAct = 0; //update nbrs actv_nbr_count = 0; igraph_vs_adj( &nbr_sel, randID, IGRAPH_ALL); igraph_vit_create(g, nbr_sel, &nbr_iter); igraph_vs_size(g, &nbr_sel, &vdeg); igraph_vector_init(&temp, vdeg); while( !IGRAPH_VIT_END(nbr_iter) ){ i = (long int) IGRAPH_VIT_GET(nbr_iter); ax_i64( py_exp_n, i ) += 1; /* update active nbr count and collect id of active */ if ( ax_i8(py_act_n, i) == i ) { VECTOR(temp)[actv_nbr_count]=i; actv_nbr_count += 1; } /* update num_susc */ if ( ax_i8(py_act_n, i) == 0 && \ ax_i32(py_thr_n, i) > (float) (ax_i64(py_exp_n, i)-1) && \ ax_i32(py_thr_n, i) <= (float) ax_i64(py_exp_n, i) ){ /*PySys_WriteStdout("%li < %i <= %li\n", (ax_i64(py_exp_n, i)-1), ax_i32(py_thr_n, i), ax_i64(py_exp_n, i) );*/ num_susc += 1; } /* Get #active long ties */ if ( ax_i8(py_act_n, i) == 1 ){ igraph_get_eid(g, &eid, randID, i, 0, 1); lrAct += ax_f32( py_tie_r, eid )>2 ; } IGRAPH_VIT_NEXT(nbr_iter); } igraph_vit_destroy(&nbr_iter); igraph_vs_destroy(&nbr_sel); //Compute Components (among all and active nbrs) igraph_vs_adj( &nbr_sel, randID, IGRAPH_ALL); igraph_induced_subgraph(g, &gc, nbr_sel, IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH); igraph_clusters(&gc, NULL, NULL, &e_comp, IGRAPH_WEAK); e_tri = igraph_vcount(&gc); igraph_destroy(&gc); igraph_vs_destroy(&nbr_sel); igraph_induced_subgraph(g, &gc, igraph_vss_vector(&temp), \ IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH); igraph_clusters(&gc, NULL, NULL, &i_comp, IGRAPH_WEAK); i_tri = igraph_vcount(&gc); //Clean up igraph_destroy(&gc); igraph_vector_destroy(&temp); //PySys_WriteStdout("e_comp: %i, i_comp: %i\n", e_comp, i_comp); //PySys_WriteStdout("e_tri: %i, i_tri: %i\n", e_tri, i_tri); //update tracking vars ax_f32( py_lrAct, num_active ) = (npy_float32) lrAct; ax_i32( py_thr, num_active) = ax_i32(py_thr_n, randID); ax_i64( py_deg, num_active) = (npy_int64) vdeg; ax_i64( py_nSuc, num_active) = (npy_int64) num_susc; ax_i64( py_nAct, num_active) = (npy_int64) num_active; //ax_i64( py_hom, num_active) = (npy_int64) num_susc; ax_i64( py_eComp, num_active) = (npy_int64) e_comp; ax_i64( py_iComp, num_active) = (npy_int64) i_comp; ax_i64( py_eTri, num_active) = (npy_int64) e_tri; ax_i64( py_iTri, num_active) = (npy_int64) i_tri; ax_i64( py_exp, num_active) = ax_i64(py_exp_n, randID); ax_i64( py_cTime, num_active) = (npy_int64) ctime; num_active += 1; } } while( num_susc > num_active && num_active < limit); //PySys_WriteStdout("Propagate Finished with %li active of target %li with %li open\n", // num_active, limit, num_susc); //igraph_rng_destroy(rGen); ax_i64(py_trkr, 0) = (npy_int64) num_active; ax_i64(py_trkr, 1) = (npy_int64) num_susc ; ax_i64(py_trkr, 2) = (npy_int64) limit ; Py_RETURN_NONE; }
void LayoutBuilder::produce(AbstractPetriNetBuilder *builder){ if(!attrTableAttached){ igraph_i_set_attribute_table(&igraph_cattribute_table); attrTableAttached = true; } size_t V = places.size() + transitions.size(); size_t E = inArcs.size() + outArcs.size(); igraph_t graph; // Create a directed graph igraph_empty(&graph, V, true); // Create vector with all edges igraph_vector_t edges; igraph_vector_init(&edges, E * 2); // Add edges to vector int i = 0; for(ArcIter it = inArcs.begin(); it != inArcs.end(); it++){ VECTOR(edges)[i++] = numberFromName(it->start); VECTOR(edges)[i++] = numberFromName(it->end); } for(ArcIter it = outArcs.begin(); it != outArcs.end(); it++){ VECTOR(edges)[i++] = numberFromName(it->start); VECTOR(edges)[i++] = numberFromName(it->end); } // Add the edges to graph igraph_add_edges(&graph, &edges, 0); // Delete the vector with edges igraph_vector_destroy(&edges); // Arrays to store result in double posx[V]; double posy[V]; // Provide current positions, if they're used at all if(startFromCurrentPositions){ int i = 0; for(PlaceIter it = places.begin(); it != places.end(); it++){ posx[i] = it->x; posy[i] = it->y; igraph_cattribute_VAN_set(&graph, "id", i, i); i++; } for(TransitionIter it = transitions.begin(); it != transitions.end(); it++){ posx[i] = it->x; posy[i] = it->y; igraph_cattribute_VAN_set(&graph, "id", i, i); i++; } } // Decompose the graph, and layout subgraphs induvidually igraph_vector_ptr_t subgraphs; igraph_vector_ptr_init(&subgraphs, 0); igraph_decompose(&graph, &subgraphs, IGRAPH_WEAK, -1, 0); // Offset for places subgraphs double offsetx = 0; double offsety = 0; // Layout, translate and extract results for each subgraph for(int i = 0; i < igraph_vector_ptr_size(&subgraphs); i++){ //Get the subgraph igraph_t* subgraph = (igraph_t*)VECTOR(subgraphs)[i]; // Allocate result matrix igraph_matrix_t sublayout; igraph_matrix_init(&sublayout, 0, 0); // Vertex selector and iterator igraph_vs_t vs; igraph_vit_t vit; // Select all and create iterator igraph_vs_all(&vs); igraph_vit_create(subgraph, vs, &vit); // Initialize sublayout, using original positions if(startFromCurrentPositions){ // Count vertices int vertices = 0; // Iterator over vertices to count them, hacked but it works while(!IGRAPH_VIT_END(vit)){ vertices++; IGRAPH_VIT_NEXT(vit); } //Reset vertex iterator IGRAPH_VIT_RESET(vit); // Resize sublayout igraph_matrix_resize(&sublayout, vertices, 2); // Iterator over vertices while(!IGRAPH_VIT_END(vit)){ int subindex = (int)IGRAPH_VIT_GET(vit); int index = (int)igraph_cattribute_VAN(subgraph, "id", subindex); MATRIX(sublayout, subindex, 0) = posx[index]; MATRIX(sublayout, subindex, 1) = posy[index]; IGRAPH_VIT_NEXT(vit); } //Reset vertex iterator IGRAPH_VIT_RESET(vit); } igraph_layout_kamada_kawai(subgraph, &sublayout, 1000, ((double)V)/4.0, 10, 0.99, V*V, startFromCurrentPositions); // Other layout algorithms with reasonable parameters //igraph_layout_kamada_kawai(subgraph, &sublayout, 1000, ((double)V)/4.0, 10, 0.99, V*V, startFromCurrentPositions); //igraph_layout_grid_fruchterman_reingold(subgraph, &sublayout, 500, V, V*V, 1.5, V*V*V, V*V/4, startFromCurrentPositions); //igraph_layout_fruchterman_reingold(subgraph, &sublayout, 500, V, V*V, 1.5, V*V*V, startFromCurrentPositions, NULL); //igraph_layout_lgl(subgraph, &sublayout, 150, V, V*V, 1.5, V*V*V, sqrt(V), -1); //Find min and max values: double minx = DBL_MAX, miny = DBL_MAX, maxx = -DBL_MAX, maxy = -DBL_MAX; //Iterator over all vertices while(!IGRAPH_VIT_END(vit)){ int subindex = (int)IGRAPH_VIT_GET(vit); double x = MATRIX(sublayout, subindex, 0) * factor; double y = MATRIX(sublayout, subindex, 1) * factor; minx = minx < x ? minx : x; miny = miny < y ? miny : y; maxx = maxx > x ? maxx : x; maxy = maxy > y ? maxy : y; IGRAPH_VIT_NEXT(vit); } //Reset vertex iterator IGRAPH_VIT_RESET(vit); // Compute translation double tx = margin - minx; double ty = margin - miny; // Decide whether to put it below or left of current content if(maxx - minx + offsetx < maxy - miny + offsety){ tx += offsetx; offsetx += maxx - minx + margin; if(offsety < maxy - miny + margin) offsety = maxy - miny + margin; }else{ ty += offsety; offsety += maxy - miny + margin; if(offsetx < maxx - minx + margin) offsetx = maxx - minx + margin; } // Translate and extract results while(!IGRAPH_VIT_END(vit)){ int subindex = (int)IGRAPH_VIT_GET(vit); int index = (int)igraph_cattribute_VAN(subgraph, "id", subindex); double x = MATRIX(sublayout, subindex, 0) * factor; double y = MATRIX(sublayout, subindex, 1) * factor; posx[index] = x + tx; posy[index] = y + ty; IGRAPH_VIT_NEXT(vit); } // Destroy iterator and selector igraph_vit_destroy(&vit); igraph_vs_destroy(&vs); // Destroy the sublayout igraph_matrix_destroy(&sublayout); // Destroy subgraph igraph_destroy(subgraph); free(VECTOR(subgraphs)[i]); } // Remove the attributes igraph_cattribute_remove_v(&graph, "id"); // Destroy the graph igraph_destroy(&graph); // Insert results i = 0; for(PlaceIter it = places.begin(); it != places.end(); it++){ it->x = posx[i]; it->y = posy[i]; i++; } for(TransitionIter it = transitions.begin(); it != transitions.end(); it++){ it->x = posx[i]; it->y = posy[i]; i++; } // Produce variables for(VarIter it = vars.begin(); it != vars.end(); it++) builder->addVariable(it->name, it->initialValue, it->range); for(BoolVarIter it = boolVars.begin(); it != boolVars.end(); it++) builder->addBoolVariable(it->name, it->initialValue); for(PlaceIter it = places.begin(); it != places.end(); it++) builder->addPlace(it->name, it->tokens, it->x, it->y); for(TransitionIter it = transitions.begin(); it != transitions.end(); it++) builder->addTransition(it->name, it->conditions, it->assignments, it->x, it->y); for(ArcIter it = inArcs.begin(); it != inArcs.end(); it++) builder->addInputArc(it->start, it->end, it->weight); for(ArcIter it = outArcs.begin(); it != outArcs.end(); it++) builder->addInputArc(it->start, it->end, it->weight); //Reset builder state (just in case some idoit decides to reuse it! vars.clear(); boolVars.clear(); places.clear(); transitions.clear(); inArcs.clear(); outArcs.clear(); }
/** * \ingroup structural * \function igraph_betweenness_estimate * \brief Estimated betweenness centrality of some vertices. * * </para><para> * The betweenness centrality of a vertex is the number of geodesics * going through it. If there are more than one geodesic between two * vertices, the value of these geodesics are weighted by one over the * number of geodesics. When estimating betweenness centrality, igraph * takes into consideration only those paths that are shorter than or * equal to a prescribed length. Note that the estimated centrality * will always be less than the real one. * * \param graph The graph object. * \param res The result of the computation, a vector containing the * estimated betweenness scores for the specified vertices. * \param vids The vertices of which the betweenness centrality scores * will be estimated. * \param directed Logical, if true directed paths will be considered * for directed graphs. It is ignored for undirected graphs. * \param cutoff The maximal length of paths that will be considered. * If zero or negative, the exact betweenness will be calculated * (no upper limit on path lengths). * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for * temporary data. * \c IGRAPH_EINVVID, invalid vertex id passed in * \p vids. * * Time complexity: O(|V||E|), * |V| and * |E| are the number of vertices and * edges in the graph. * Note that the time complexity is independent of the number of * vertices for which the score is calculated. * * \sa Other centrality types: \ref igraph_degree(), \ref igraph_closeness(). * See \ref igraph_edge_betweenness() for calculating the betweenness score * of the edges in a graph. */ int igraph_betweenness_estimate(const igraph_t *graph, igraph_vector_t *res, const igraph_vs_t vids, igraph_bool_t directed, igraph_integer_t cutoff) { long int no_of_nodes=igraph_vcount(graph); igraph_dqueue_t q=IGRAPH_DQUEUE_NULL; long int *distance; long int *nrgeo; double *tmpscore; igraph_stack_t stack=IGRAPH_STACK_NULL; long int source; long int j, k; igraph_integer_t modein, modeout; igraph_vit_t vit; igraph_vector_t *neis; igraph_adjlist_t adjlist_out, adjlist_in; igraph_adjlist_t *adjlist_out_p, *adjlist_in_p; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); directed=directed && igraph_is_directed(graph); if (directed) { modeout=IGRAPH_OUT; modein=IGRAPH_IN; IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist_out, IGRAPH_OUT)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist_out); IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist_in, IGRAPH_IN)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist_in); adjlist_out_p=&adjlist_out; adjlist_in_p=&adjlist_in; } else { modeout=modein=IGRAPH_ALL; IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist_out, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist_out); adjlist_out_p=adjlist_in_p=&adjlist_out; } distance=igraph_Calloc(no_of_nodes, long int); if (distance==0) { IGRAPH_ERROR("betweenness failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, distance); nrgeo=igraph_Calloc(no_of_nodes, long int); if (nrgeo==0) { IGRAPH_ERROR("betweenness failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, nrgeo); tmpscore=igraph_Calloc(no_of_nodes, double); if (tmpscore==0) { IGRAPH_ERROR("betweenness failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, tmpscore); IGRAPH_DQUEUE_INIT_FINALLY(&q, 100); igraph_stack_init(&stack, no_of_nodes); IGRAPH_FINALLY(igraph_stack_destroy, &stack); IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_VIT_SIZE(vit))); igraph_vector_null(res); /* here we go */ for (source=0; source<no_of_nodes; source++) { IGRAPH_PROGRESS("Betweenness centrality: ", 100.0*source/no_of_nodes, 0); IGRAPH_ALLOW_INTERRUPTION(); memset(distance, 0, no_of_nodes*sizeof(long int)); memset(nrgeo, 0, no_of_nodes*sizeof(long int)); memset(tmpscore, 0, no_of_nodes*sizeof(double)); igraph_stack_clear(&stack); /* it should be empty anyway... */ IGRAPH_CHECK(igraph_dqueue_push(&q, source)); nrgeo[source]=1; distance[source]=0; while (!igraph_dqueue_empty(&q)) { long int actnode=igraph_dqueue_pop(&q); if (cutoff > 0 && distance[actnode] >= cutoff) continue; neis = igraph_adjlist_get(adjlist_out_p, actnode); for (j=0; j<igraph_vector_size(neis); j++) { long int neighbor=VECTOR(*neis)[j]; if (nrgeo[neighbor] != 0) { /* we've already seen this node, another shortest path? */ if (distance[neighbor]==distance[actnode]+1) { nrgeo[neighbor]+=nrgeo[actnode]; } } else { /* we haven't seen this node yet */ nrgeo[neighbor]+=nrgeo[actnode]; distance[neighbor]=distance[actnode]+1; IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor)); IGRAPH_CHECK(igraph_stack_push(&stack, neighbor)); } } } /* while !igraph_dqueue_empty */ /* Ok, we've the distance of each node and also the number of shortest paths to them. Now we do an inverse search, starting with the farthest nodes. */ while (!igraph_stack_empty(&stack)) { long int actnode=igraph_stack_pop(&stack); if (distance[actnode]<=1) { continue; } /* skip source node */ /* set the temporary score of the friends */ neis = igraph_adjlist_get(adjlist_in_p, actnode); for (j=0; j<igraph_vector_size(neis); j++) { long int neighbor=VECTOR(*neis)[j]; if (distance[neighbor]==distance[actnode]-1 && nrgeo[neighbor] != 0) { tmpscore[neighbor] += (tmpscore[actnode]+1)*nrgeo[neighbor]/nrgeo[actnode]; } } } /* Ok, we've the scores for this source */ for (k=0, IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), k++) { long int node=IGRAPH_VIT_GET(vit); VECTOR(*res)[k] += tmpscore[node]; tmpscore[node] = 0.0; /* in case a node is in vids multiple times */ } } /* for source < no_of_nodes */ /* divide by 2 for undirected graph */ if (!directed) { for (j=0; j<igraph_vector_size(res); j++) { VECTOR(*res)[j] /= 2.0; } } /* clean */ igraph_Free(distance); igraph_Free(nrgeo); igraph_Free(tmpscore); igraph_dqueue_destroy(&q); igraph_stack_destroy(&stack); igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(6); if (directed) { igraph_adjlist_destroy(&adjlist_out); igraph_adjlist_destroy(&adjlist_in); IGRAPH_FINALLY_CLEAN(2); } else { igraph_adjlist_destroy(&adjlist_out); IGRAPH_FINALLY_CLEAN(1); } return 0; }
igraph_vector_t *ggen_analyze_lowest_single_ancestor(igraph_t *g) { unsigned long i,v,l,vid,r; int err = 0; igraph_vector_t toposort,itopo; igraph_vector_t *lsa; igraph_t tree; igraph_vs_t vs; igraph_vit_t vit; lca_metadata md; if(g == NULL) return NULL; err = igraph_vector_init(&toposort,igraph_vcount(g)); if(err) return NULL; err = igraph_topological_sorting(g,&toposort,IGRAPH_OUT); if(err) goto d_tp; /* build a reverse index of the toposort */ err = igraph_vector_init(&itopo,igraph_vcount(g)); if(err) goto d_tp; for(i = 0; i < igraph_vcount(g); i++) { v = VECTOR(toposort)[i]; VECTOR(itopo)[v] = i; } err = igraph_empty(&tree,1,IGRAPH_DIRECTED); if(err) goto d_i; lsa = calloc(1,sizeof(igraph_vector_t*)); if(lsa == NULL) goto cleanup; err = igraph_vector_init(lsa,igraph_vcount(g)); if(err) goto f_l; for(v = 1; v < igraph_vcount(g); v++) { vid = VECTOR(toposort)[v]; tree_lca_metadata_init(&tree,&md); tree_lca_preprocessing(&tree,0,&md); /* iterate over parents of v in g * The lsa of a node is the LCA of all its parents in our * special tree. */ igraph_vs_adj(&vs, vid, IGRAPH_IN); igraph_vit_create(g,vs,&vit); l = VECTOR(itopo)[IGRAPH_VIT_GET(vit)]; IGRAPH_VIT_NEXT(vit); for(vit;!IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { tree_lca_query(&tree,l,VECTOR(itopo)[IGRAPH_VIT_GET(vit)],&r,&md); l = r; } igraph_vit_destroy(&vit); igraph_vs_destroy(&vs); tree_lca_metadata_free(&tree,&md); // update tree err = igraph_add_vertices(&tree,1,NULL); if(err) goto d_l; err = igraph_add_edge(&tree,l,v); if(err) goto d_l; VECTOR(*lsa)[vid] = VECTOR(toposort)[l]; } goto cleanup; d_l: igraph_vector_destroy(lsa); f_l: free(lsa); lsa = NULL; cleanup: igraph_destroy(&tree); d_i: igraph_vector_destroy(&itopo); d_tp: igraph_vector_destroy(&toposort); return lsa; }
/** * \ingroup python_interface_vertexseq * \brief Selects a single vertex from the vertex sequence based on some criteria */ PyObject* igraphmodule_VertexSeq_find(igraphmodule_VertexSeqObject *self, PyObject *args) { PyObject *item; igraph_integer_t i; Py_ssize_t n; igraph_vit_t vit; if (!PyArg_ParseTuple(args, "O", &item)) return NULL; if (PyCallable_Check(item)) { /* Call the callable for every vertex in the current sequence and return * the first one for which it evaluates to True */ n = PySequence_Size((PyObject*)self); for (i=0; i<n; i++) { PyObject *vertex = PySequence_GetItem((PyObject*)self, i); PyObject *call_result; if (vertex == 0) return NULL; call_result = PyObject_CallFunctionObjArgs(item, vertex, NULL); if (call_result == 0) { Py_DECREF(vertex); return NULL; } if (PyObject_IsTrue(call_result)) { Py_DECREF(call_result); return vertex; /* reference passed to caller */ } Py_DECREF(call_result); Py_DECREF(vertex); } } else if (PyInt_Check(item)) { /* Integers are interpreted as indices on the vertex set and NOT on the * original, untouched vertex sequence of the graph */ return PySequence_GetItem((PyObject*)self, PyInt_AsLong(item)); } else if (PyBaseString_Check(item)) { /* Strings are interpreted as vertex names */ if (igraphmodule_get_vertex_id_by_name(&self->gref->g, item, &i)) return NULL; /* We now have the ID of the vertex in the graph. If the vertex sequence * itself represents the full vertex sequence of the graph, we can return * here. If not, we have to check whether the vertex sequence contains this * ID or not. */ if (igraph_vs_is_all(&self->vs)) return PySequence_GetItem((PyObject*)self, i); if (igraph_vit_create(&self->gref->g, self->vs, &vit)) { igraphmodule_handle_igraph_error(); return NULL; } for (n = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), n++) { if (IGRAPH_VIT_GET(vit) == i) { igraph_vit_destroy(&vit); return PySequence_GetItem((PyObject*)self, n); } } igraph_vit_destroy(&vit); PyErr_SetString(PyExc_ValueError, "vertex with the given name exists but not in the current sequence"); return NULL; } PyErr_SetString(PyExc_IndexError, "no such vertex"); return NULL; }
igraph_vector_t * ggen_analyze_longest_path(igraph_t *g) { igraph_vector_t topology; igraph_vector_t lengths; igraph_vector_t preds; igraph_vs_t vs; igraph_vit_t vit; igraph_vector_t *res = NULL; int err; unsigned long v,i,f,t; long maxv; if(g == NULL) return NULL; v = igraph_vcount(g); err = igraph_vector_init(&topology,v); if(err) return NULL; err = igraph_vector_init(&lengths,v); if(err) goto error_il; err = igraph_vector_init(&preds,v); if(err) goto error_ip; res = malloc(sizeof(igraph_vector_t)); if(res == NULL) goto cleanup; err = igraph_vector_init(res,v); if(err) goto error_ir; // sort topologically the vertices err = igraph_topological_sorting(g,&topology,IGRAPH_OUT); if(err) goto error; // igraph is stupid, it returns 0 even if the graph isn't a dag if(igraph_vector_size(&topology) != v) goto error; // find the best path incomming from every node igraph_vector_null(&lengths); igraph_vector_fill(&preds,-1); maxv = -1; for(i = 0; i < v; i++) { f = VECTOR(topology)[i]; err = igraph_vs_adj(&vs,f,IGRAPH_OUT); if(err) goto error; err = igraph_vit_create(g,vs,&vit); if(err) { igraph_vs_destroy(&vs); goto error; } for(vit; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { t = IGRAPH_VIT_GET(vit); if(VECTOR(lengths)[t] < VECTOR(lengths)[f] + 1) { VECTOR(lengths)[t] = VECTOR(lengths)[f] +1; VECTOR(preds)[t] = f; } if(maxv == -1 || VECTOR(lengths)[t] > VECTOR(lengths)[maxv]) maxv = t; } igraph_vs_destroy(&vs); igraph_vit_destroy(&vit); } // build the path, using preds and maxv f = 0; while(maxv != -1) { VECTOR(*res)[f++] = maxv; maxv = VECTOR(preds)[maxv]; } // finish the path correctly, resizing and reversing the array err = igraph_vector_resize(res,f); if(err) goto error; err = igraph_vector_reverse(res); if(err) goto error; goto cleanup; error: igraph_vector_destroy(res); error_ir: free(res); res = NULL; cleanup: igraph_vector_destroy(&preds); error_ip: igraph_vector_destroy(&lengths); error_il: igraph_vector_destroy(&topology); return res; }
/** * \ingroup structural * \function igraph_closeness_estimate * \brief Closeness centrality estimations for some vertices. * * </para><para> * The closeness centrality of a vertex measures how easily other * vertices can be reached from it (or the other way: how easily it * can be reached from the other vertices). It is defined as the * number of the number of vertices minus one divided by the sum of the * lengths of all geodesics from/to the given vertex. When estimating * closeness centrality, igraph considers paths having a length less than * or equal to a prescribed cutoff value. * * </para><para> * If the graph is not connected, and there is no such path between two * vertices, the number of vertices is used instead the length of the * geodesic. This is always longer than the longest possible geodesic. * * </para><para> * Since the estimation considers vertex pairs with a distance greater than * the given value as disconnected, the resulting estimation will always be * lower than the actual closeness centrality. * * \param graph The graph object. * \param res The result of the computation, a vector containing the * closeness centrality scores for the given vertices. * \param vids Vector giving the vertices for which the closeness * centrality scores will be computed. * \param mode The type of shortest paths to be used for the * calculation in directed graphs. Possible values: * \clist * \cli IGRAPH_OUT * the lengths of the outgoing paths are calculated. * \cli IGRAPH_IN * the lengths of the incoming paths are calculated. * \cli IGRAPH_ALL * the directed graph is considered as an * undirected one for the computation. * \endclist * \param cutoff The maximal length of paths that will be considered. * If zero or negative, the exact closeness will be calculated * (no upper limit on path lengths). * \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(n|E|), * n is the number * of vertices for which the calculation is done and * |E| is the number * of edges in the graph. * * \sa Other centrality types: \ref igraph_degree(), \ref igraph_betweenness(). */ int igraph_closeness_estimate(const igraph_t *graph, igraph_vector_t *res, const igraph_vs_t vids, igraph_neimode_t mode, igraph_integer_t cutoff) { long int no_of_nodes=igraph_vcount(graph); igraph_vector_t already_counted, *neis; long int i, j; long int nodes_reached; igraph_adjlist_t allneis; igraph_dqueue_t q; long int nodes_to_calc; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); nodes_to_calc=IGRAPH_VIT_SIZE(vit); if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { IGRAPH_ERROR("calculating closeness", IGRAPH_EINVMODE); } IGRAPH_VECTOR_INIT_FINALLY(&already_counted, no_of_nodes); IGRAPH_DQUEUE_INIT_FINALLY(&q, 100); IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, mode)); IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis); IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc)); igraph_vector_null(res); for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { IGRAPH_CHECK(igraph_dqueue_push(&q, IGRAPH_VIT_GET(vit))); IGRAPH_CHECK(igraph_dqueue_push(&q, 0)); nodes_reached=1; VECTOR(already_counted)[(long int)IGRAPH_VIT_GET(vit)]=i+1; IGRAPH_PROGRESS("Closeness: ", 100.0*i/no_of_nodes, NULL); IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_empty(&q)) { long int act=igraph_dqueue_pop(&q); long int actdist=igraph_dqueue_pop(&q); VECTOR(*res)[i] += actdist; if (cutoff>0 && actdist>=cutoff) continue; neis=igraph_adjlist_get(&allneis, act); for (j=0; j<igraph_vector_size(neis); j++) { long int neighbor=VECTOR(*neis)[j]; if (VECTOR(already_counted)[neighbor] == i+1) { continue; } VECTOR(already_counted)[neighbor] = i+1; nodes_reached++; IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor)); IGRAPH_CHECK(igraph_dqueue_push(&q, actdist+1)); } } VECTOR(*res)[i] += ((igraph_integer_t)no_of_nodes * (no_of_nodes-nodes_reached)); VECTOR(*res)[i] = (no_of_nodes-1) / VECTOR(*res)[i]; } IGRAPH_PROGRESS("Closeness: ", 100.0, NULL); /* Clean */ igraph_dqueue_destroy(&q); igraph_vector_destroy(&already_counted); igraph_vit_destroy(&vit); igraph_adjlist_destroy(&allneis); IGRAPH_FINALLY_CLEAN(4); return 0; }