123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /*!
- \file vector/neta/components.c
- \brief Network Analysis library - graph componets
- Computes strongly and weakly connected components.
- (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- \author Daniel Bundala (Google Summer of Code 2009)
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include <grass/dgl/graph.h>
- /*!
- \brief Computes weekly connected components
- \param graph input graph
- \param[out] component list of components
- \return number of components
- \return -1 on failure
- */
- int NetA_weakly_connected_components(dglGraph_s * graph, int *component)
- {
- int nnodes;
- dglInt32_t *stack;
- int *visited;
- int stack_size, components;
- dglInt32_t *cur_node;
- dglNodeTraverser_s nt;
- components = 0;
- nnodes = dglGet_NodeCount(graph);
- stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
- visited = (int *)G_calloc(nnodes + 1, sizeof(int));
- if (!stack || !visited) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- dglNode_T_Initialize(&nt, graph);
- for (cur_node = dglNode_T_First(&nt); cur_node;
- cur_node = dglNode_T_Next(&nt)) {
- dglInt32_t node_id = dglNodeGet_Id(graph, cur_node);
- if (!visited[node_id]) {
- visited[node_id] = 1;
- stack[0] = node_id;
- stack_size = 1;
- component[node_id] = ++components;
- while (stack_size) {
- dglInt32_t *node, *edgeset, *edge;
- dglEdgesetTraverser_s et;
- node = dglGetNode(graph, stack[--stack_size]);
- edgeset = dglNodeGet_OutEdgeset(graph, node);
- dglEdgeset_T_Initialize(&et, graph, edgeset);
- for (edge = dglEdgeset_T_First(&et); edge;
- edge = dglEdgeset_T_Next(&et)) {
- dglInt32_t to;
- to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
- if (!visited[to]) {
- visited[to] = 1;
- component[to] = components;
- stack[stack_size++] = to;
- }
- }
- dglEdgeset_T_Release(&et);
- }
- }
- }
- dglNode_T_Release(&nt);
- G_free(visited);
- return components;
- }
- /*!
- \brief Computes strongly connected components
- \param graph input graph
- \param[out] component list of components
- \return number of components
- \return -1 on failure
- */
- int NetA_strongly_connected_components(dglGraph_s * graph, int *component)
- {
- int nnodes;
- dglInt32_t *stack, *order;
- int *visited, *processed;
- int stack_size, order_size, components;
- dglInt32_t *node;
- dglNodeTraverser_s nt;
- components = 0;
- nnodes = dglGet_NodeCount(graph);
- stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
- order = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
- visited = (int *)G_calloc(nnodes + 1, sizeof(int));
- processed = (int *)G_calloc(nnodes + 1, sizeof(int));
- if (!stack || !visited || !order || !processed) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- order_size = 0;
- dglNode_T_Initialize(&nt, graph);
- for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
- dglInt32_t node_id = dglNodeGet_Id(graph, node);
- component[node_id] = 0;
- if (!visited[node_id]) {
- visited[node_id] = 1;
- stack[0] = node_id;
- stack_size = 1;
- while (stack_size) {
- dglInt32_t *node, *edgeset, *edge;
- dglEdgesetTraverser_s et;
- dglInt32_t cur_node_id = stack[stack_size - 1];
- if (processed[cur_node_id]) {
- stack_size--;
- order[order_size++] = cur_node_id;
- continue;
- }
- processed[cur_node_id] = 1;
- node = dglGetNode(graph, cur_node_id);
- edgeset = dglNodeGet_OutEdgeset(graph, node);
- dglEdgeset_T_Initialize(&et, graph, edgeset);
- for (edge = dglEdgeset_T_First(&et); edge;
- edge = dglEdgeset_T_Next(&et)) {
- dglInt32_t to;
- if (dglEdgeGet_Id(graph, edge) < 0)
- continue; /*ignore backward edges */
- to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
- if (!visited[to]) {
- visited[to] = 1;
- stack[stack_size++] = to;
- }
- }
- dglEdgeset_T_Release(&et);
- }
- }
- }
- dglNode_T_Release(&nt);
- while (order_size) {
- dglInt32_t node_id = order[--order_size];
- if (component[node_id])
- continue;
- components++;
- component[node_id] = components;
- stack[0] = node_id;
- stack_size = 1;
- while (stack_size) {
- dglInt32_t *node, *edgeset, *edge;
- dglEdgesetTraverser_s et;
- dglInt32_t cur_node_id = stack[--stack_size];
- node = dglGetNode(graph, cur_node_id);
- edgeset = dglNodeGet_OutEdgeset(graph, node);
- dglEdgeset_T_Initialize(&et, graph, edgeset);
- for (edge = dglEdgeset_T_First(&et); edge;
- edge = dglEdgeset_T_Next(&et)) {
- dglInt32_t to;
- if (dglEdgeGet_Id(graph, edge) > 0)
- continue; /*ignore forward edges */
- to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
- if (!component[to]) {
- component[to] = components;
- stack[stack_size++] = to;
- }
- }
- dglEdgeset_T_Release(&et);
- }
- }
- G_free(stack);
- G_free(visited);
- G_free(order);
- G_free(processed);
- return components;
- }
|