コード例 #1
0
ファイル: igraph_vs_vector.c プロジェクト: AlessiaWent/igraph
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;
}
コード例 #2
0
ファイル: cocitation.c プロジェクト: AlessiaWent/igraph
/**
 * \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;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: separators.c プロジェクト: dacapo1142/igraph
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;
}
コード例 #5
0
ファイル: separators.c プロジェクト: dacapo1142/igraph
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;
}
コード例 #6
0
ファイル: cocitation.c プロジェクト: AlessiaWent/igraph
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;
}
コード例 #7
0
ファイル: shd-tgen-graph.c プロジェクト: MileB/shadow
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;
}
コード例 #8
0
/**
 * \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;
}
コード例 #9
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;
}
コード例 #10
0
ファイル: cIGraph_dijkstra.c プロジェクト: honschi/igraph
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;
}
コード例 #11
0
ファイル: centrality.c プロジェクト: Cecko/3dsoftviz
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;
}
コード例 #12
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;

}
コード例 #13
0
ファイル: LayoutBuilder.cpp プロジェクト: primotom/PeTe
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();
}
コード例 #14
0
ファイル: centrality.c プロジェクト: Cecko/3dsoftviz
/**
 * \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;
}
コード例 #15
0
ファイル: graph-analysis.c プロジェクト: lccanon/ggen
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;
}
コード例 #16
0
/**
 * \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;
}
コード例 #17
0
ファイル: graph-analysis.c プロジェクト: lccanon/ggen
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;
}
コード例 #18
0
ファイル: centrality.c プロジェクト: Cecko/3dsoftviz
/**
 * \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;
}