int main(int argc, char **argv) { dglGraph_s graph; int fd; int nret; /* program options */ char *pszFilein; GNO_BEGIN /* short long default variable help */ GNO_OPTION("g", "graph", NULL, &pszFilein, "Graph file to view") GNO_END if (GNO_PARSE(argc, argv) < 0) { return 1; } /* * options parsed */ if (pszFilein == NULL) { GNO_HELP("Incomplete parameters"); return 1; } fd = open(pszFilein, O_RDONLY); if (fd < 0) { perror("open"); return 1; } nret = dglRead(&graph, fd); if (nret < 0) { fprintf(stderr, "dglRead error: %s\n", dglStrerror(&graph)); return 1; } close(fd); /* print the header */ fprintf(stdout, "Version: %d\n", graph.Version); fprintf(stdout, "Byte Order: %s\n", (graph.Endian == DGL_ENDIAN_LITTLE) ? "Little Endian" : "Big Endian"); fprintf(stdout, "Node Attribute Size: %ld\n", graph.NodeAttrSize); fprintf(stdout, "Edge Attribute Size: %ld\n", graph.EdgeAttrSize); fprintf(stdout, "Counters: %ld Edges - %ld Nodes: %ld HEAD / %ld TAIL / %ld ALONE\n", graph.cEdge, graph.cNode, graph.cHead, graph.cTail, graph.cAlone); fprintf(stdout, "Opaque Settings:\n"); fprintf(stdout, "%10ld %10ld %10ld %10ld\n", graph.aOpaqueSet[0], graph.aOpaqueSet[1], graph.aOpaqueSet[2], graph.aOpaqueSet[3]); fprintf(stdout, "%10ld %10ld %10ld %10ld\n", graph.aOpaqueSet[4], graph.aOpaqueSet[5], graph.aOpaqueSet[6], graph.aOpaqueSet[7]); fprintf(stdout, "%10ld %10ld %10ld %10ld\n", graph.aOpaqueSet[8], graph.aOpaqueSet[9], graph.aOpaqueSet[10], graph.aOpaqueSet[11]); fprintf(stdout, "%10ld %10ld %10ld %10ld\n", graph.aOpaqueSet[12], graph.aOpaqueSet[13], graph.aOpaqueSet[14], graph.aOpaqueSet[15]); fprintf(stdout, "Total Cost: %lld\n", graph.nnCost); fprintf(stdout, "--\n"); { dglInt32_t *pnode; dglNodeTraverser_s traverser; dglNode_T_Initialize(&traverser, &graph); for (pnode = dglNode_T_First(&traverser); pnode; pnode = dglNode_T_Next(&traverser)) { _print_node(&graph, pnode, stdout); } dglNode_T_Release(&traverser); } printf("\n"); dglRelease(&graph); return 0; }
/*! \brief Get number of articulation points in the graph \param graph input graph \param[out] articulation_list list of articulation points \return number of points \return -1 on error */ int NetA_articulation_points(dglGraph_s * graph, struct ilist *articulation_list) { int nnodes; int points = 0; dglEdgesetTraverser_s *current; /*edge to be processed when the node is visited */ int *tin, *min_tin; /*time in, and smallest tin over all successors. 0 if not yet visited */ dglInt32_t **parent; /*parents of the nodes */ dglInt32_t **stack; /*stack of nodes */ dglInt32_t **current_edge; /*current edge for each node */ int *mark; /*marked articulation points */ dglNodeTraverser_s nt; dglInt32_t *current_node; int stack_size; int i, time; nnodes = dglGet_NodeCount(graph); current = (dglEdgesetTraverser_s *) G_calloc(nnodes + 1, sizeof(dglEdgesetTraverser_s)); tin = (int *)G_calloc(nnodes + 1, sizeof(int)); min_tin = (int *)G_calloc(nnodes + 1, sizeof(int)); parent = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); mark = (int *)G_calloc(nnodes + 1, sizeof(int)); if (!tin || !min_tin || !parent || !stack || !current || !mark) { G_fatal_error(_("Out of memory")); return -1; } for (i = 1; i <= nnodes; i++) { dglEdgeset_T_Initialize(¤t[i], graph, dglNodeGet_OutEdgeset(graph, dglGetNode(graph, i))); current_edge[i] = dglEdgeset_T_First(¤t[i]); tin[i] = mark[i] = 0; } dglNode_T_Initialize(&nt, graph); time = 0; for (current_node = dglNode_T_First(&nt); current_node; current_node = dglNode_T_Next(&nt)) { dglInt32_t current_id = dglNodeGet_Id(graph, current_node); if (tin[current_id] == 0) { int children = 0; /*number of subtrees rooted at the root/current_node */ stack[0] = current_node; stack_size = 1; parent[current_id] = NULL; while (stack_size) { dglInt32_t *node = stack[stack_size - 1]; dglInt32_t node_id = dglNodeGet_Id(graph, node); if (tin[node_id] == 0) /*vertex visited for the first time */ min_tin[node_id] = tin[node_id] = ++time; else { /*return from the recursion */ dglInt32_t to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, current_edge [node_id])); if (min_tin[to] >= tin[node_id]) /*no path from the subtree above the current node */ mark[node_id] = 1; /*so the current node must be an articulation point */ if (min_tin[to] < min_tin[node_id]) min_tin[node_id] = min_tin[to]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id]); /*proceed to the next edge */ } /*try next edges */ for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id])) { dglInt32_t *to = dglEdgeGet_Tail(graph, current_edge[node_id]); if (to == parent[node_id]) continue; /*skip parent */ int to_id = dglNodeGet_Id(graph, to); if (tin[to_id]) { /*back edge, cannot be a bridge/articualtion point */ if (tin[to_id] < min_tin[node_id]) min_tin[node_id] = tin[to_id]; } else { /*forward edge */ if (node_id == current_id) children++; /*if root, increase number of children */ parent[to_id] = node; stack[stack_size++] = to; break; } } if (!current_edge[node_id]) stack_size--; /*current node completely processed */ } if (children > 1) mark[current_id] = 1; /*if the root has more than 1 subtrees rooted at it, then it is an * articulation point */ } } for (i = 1; i <= nnodes; i++) if (mark[i]) { points++; Vect_list_append(articulation_list, i); } dglNode_T_Release(&nt); for (i = 1; i <= nnodes; i++) dglEdgeset_T_Release(¤t[i]); G_free(current); G_free(tin); G_free(min_tin); G_free(parent); G_free(stack); G_free(current_edge); return points; }
/*! \brief Computes weakly connected components \param graph input graph \param[out] component array of component ids \return number of components \return -1 on failure */ int NetA_weakly_connected_components(dglGraph_s * graph, int *component) { int nnodes, i; dglInt32_t *stack; int stack_size, components; dglInt32_t *cur_node; dglNodeTraverser_s nt; int have_node_costs; dglInt32_t ncost; if (graph->Version < 2) { G_warning("Directed graph must be version 2 or 3 for NetA_weakly_connected_components()"); return -1; } components = 0; nnodes = dglGet_NodeCount(graph); stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t)); if (!stack) { G_fatal_error(_("Out of memory")); return -1; } for (i = 1; i <= nnodes; i++) component[i] = 0; ncost = 0; have_node_costs = dglGet_NodeAttrSize(graph); dglNode_T_Initialize(&nt, graph); for (cur_node = dglNode_T_First(&nt); cur_node; cur_node = dglNode_T_Next(&nt)) { dglInt32_t cur_node_id = dglNodeGet_Id(graph, cur_node); if (!component[cur_node_id]) { stack[0] = cur_node_id; stack_size = 1; component[cur_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 (!component[to]) { component[to] = components; /* do not go through closed nodes */ if (have_node_costs) { memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Tail(graph, edge)), sizeof(ncost)); } if (ncost >= 0) stack[stack_size++] = to; } } dglEdgeset_T_Release(&et); edgeset = dglNodeGet_InEdgeset(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_Head(graph, edge)); if (!component[to]) { component[to] = components; /* do not go through closed nodes */ if (have_node_costs) { memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Tail(graph, edge)), sizeof(ncost)); } if (ncost >= 0) stack[stack_size++] = to; } } dglEdgeset_T_Release(&et); } } } dglNode_T_Release(&nt); G_free(stack); return components; }
/*! \brief Get number of bridges in the graph. Bridge is an array containing the indices of the bridges. \param graph input graph \param[out] bridge_list list of bridges \return number of bridges, -1 on error */ int NetA_compute_bridges(dglGraph_s * graph, struct ilist *bridge_list) { int nnodes; int bridges = 0; dglEdgesetTraverser_s *current; /*edge to be processed when the node is visited */ int *tin, *min_tin; /*time in, and smallest tin over all successors. 0 if not yet visited */ dglInt32_t *parent; /*edge from parent to the node */ dglInt32_t **stack; /*stack of nodes */ dglInt32_t **current_edge; /*current edge for each node */ dglNodeTraverser_s nt; dglInt32_t *current_node; int stack_size; int i, time; nnodes = dglGet_NodeCount(graph); current = (dglEdgesetTraverser_s *) G_calloc(nnodes + 1, sizeof(dglEdgesetTraverser_s)); tin = (int *)G_calloc(nnodes + 1, sizeof(int)); min_tin = (int *)G_calloc(nnodes + 1, sizeof(int)); parent = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t)); stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); if (!tin || !min_tin || !parent || !stack || !current) { G_fatal_error(_("Out of memory")); return -1; } for (i = 1; i <= nnodes; i++) { dglEdgeset_T_Initialize(¤t[i], graph, dglNodeGet_OutEdgeset(graph, dglGetNode(graph, i))); current_edge[i] = dglEdgeset_T_First(¤t[i]); tin[i] = 0; } dglNode_T_Initialize(&nt, graph); time = 0; for (current_node = dglNode_T_First(&nt); current_node; current_node = dglNode_T_Next(&nt)) { dglInt32_t current_id = dglNodeGet_Id(graph, current_node); if (tin[current_id] == 0) { stack[0] = current_node; stack_size = 1; parent[current_id] = 0; while (stack_size) { dglInt32_t *node = stack[stack_size - 1]; dglInt32_t node_id = dglNodeGet_Id(graph, node); if (tin[node_id] == 0) /*vertex visited for the first time */ min_tin[node_id] = tin[node_id] = ++time; else { /*return from the recursion */ dglInt32_t to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, current_edge [node_id])); if (min_tin[to] > tin[node_id]) { /*no path from the subtree above the current node */ Vect_list_append(bridge_list, dglEdgeGet_Id(graph, current_edge[node_id])); /*so it must be a bridge */ bridges++; } if (min_tin[to] < min_tin[node_id]) min_tin[node_id] = min_tin[to]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id]); /*proceed to the next edge */ } for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id])) { /*try next edges */ dglInt32_t *to = dglEdgeGet_Tail(graph, current_edge[node_id]); dglInt32_t edge_id = dglEdgeGet_Id(graph, current_edge[node_id]); if (abs(edge_id) == parent[node_id]) continue; /*skip edge we used to travel to this node */ int to_id = dglNodeGet_Id(graph, to); if (tin[to_id]) { /*back edge, cannot be a bridge/articualtion point */ if (tin[to_id] < min_tin[node_id]) min_tin[node_id] = tin[to_id]; } else { /*forward edge */ parent[to_id] = abs(edge_id); stack[stack_size++] = to; break; } } if (!current_edge[node_id]) stack_size--; /*current node completely processed */ } } } dglNode_T_Release(&nt); for (i = 1; i <= nnodes; i++) dglEdgeset_T_Release(¤t[i]); G_free(current); G_free(tin); G_free(min_tin); G_free(parent); G_free(stack); G_free(current_edge); return bridges; }
/*! \brief Computes strongly connected components with Kosaraju's two-pass algorithm \param graph input graph \param[out] component array of component ids \return number of components \return -1 on failure */ int NetA_strongly_connected_components(dglGraph_s * graph, int *component) { int nnodes, i; dglInt32_t *stack, *order; int *processed; int stack_size, order_size, components; dglInt32_t *cur_node; dglNodeTraverser_s nt; int have_node_costs; dglInt32_t ncost; if (graph->Version < 2) { G_warning("Directed graph must be version 2 or 3 for NetA_strongly_connected_components()"); return -1; } 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)); processed = (int *)G_calloc(nnodes + 1, sizeof(int)); if (!stack || !order || !processed) { G_fatal_error(_("Out of memory")); return -1; } for (i = 1; i <= nnodes; i++) { component[i] = 0; } ncost = 0; have_node_costs = dglGet_NodeAttrSize(graph); order_size = 0; dglNode_T_Initialize(&nt, graph); for (cur_node = dglNode_T_First(&nt); cur_node; cur_node = dglNode_T_Next(&nt)) { dglInt32_t cur_node_id = dglNodeGet_Id(graph, cur_node); if (!component[cur_node_id]) { component[cur_node_id] = --components; stack[0] = cur_node_id; stack_size = 1; while (stack_size) { dglInt32_t *node, *edgeset, *edge; dglEdgesetTraverser_s et; dglInt32_t node_id = stack[stack_size - 1]; if (processed[node_id]) { stack_size--; order[order_size++] = node_id; continue; } processed[node_id] = 1; node = dglGetNode(graph, 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; to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge)); if (!component[to]) { component[to] = components; /* do not go through closed nodes */ if (have_node_costs) { memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Tail(graph, edge)), sizeof(ncost)); } if (ncost < 0) processed[to] = 1; stack[stack_size++] = to; } } dglEdgeset_T_Release(&et); } } } dglNode_T_Release(&nt); components = 0; dglNode_T_Initialize(&nt, graph); while (order_size) { dglInt32_t cur_node_id = order[--order_size]; int cur_comp = component[cur_node_id]; if (cur_comp < 1) { component[cur_node_id] = ++components; stack[0] = cur_node_id; stack_size = 1; while (stack_size) { dglInt32_t *node, *edgeset, *edge; dglEdgesetTraverser_s et; dglInt32_t node_id = stack[--stack_size]; node = dglGetNode(graph, node_id); edgeset = dglNodeGet_InEdgeset(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_Head(graph, edge)); if (component[to] == cur_comp) { component[to] = components; /* do not go through closed nodes */ if (have_node_costs) { memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Head(graph, edge)), sizeof(ncost)); } if (ncost >= 0) stack[stack_size++] = to; } } dglEdgeset_T_Release(&et); } } } dglNode_T_Release(&nt); G_free(stack); G_free(order); G_free(processed); return components; }