Graphviz 16.1.1~dev.20260906.1627
Loading...
Searching...
No Matches
comp.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13/* comp.c:
14 * Written by Emden R. Gansner
15 *
16 * Support for "connected components". Components are either connected
17 * or have a port node or have a pinned node.
18 *
19 */
20
21/* use PRIVATE interface */
22#define FDP_PRIVATE 1
23
24#include <cgraph/cgraph.h>
25#include <fdpgen/fdp.h>
26#include <fdpgen/comp.h>
27#include <pack/pack.h>
28#include <assert.h>
29#include <stdbool.h>
30#include <stddef.h>
31#include <util/agxbuf.h>
32#include <util/alloc.h>
33#include <util/bitarray.h>
34#include <util/list.h>
35#include <util/prisize_t.h>
36
37static void dfs(Agraph_t *g, Agnode_t *n, Agraph_t *out, bitarray_t *marks) {
38 Agedge_t *e;
39 Agnode_t *other;
40
41 bitarray_set(marks, ND_id(n), true);
42 agsubnode(out,n,1);
43 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
44 if ((other = agtail(e)) == n)
45 other = aghead(e);
46 if (!bitarray_get(*marks, ND_id(other)))
47 dfs(g, other, out, marks);
48 }
49}
50
51/* findCComp:
52 * Finds generalized connected components of graph g.
53 * This merges all components containing a port node or a pinned node.
54 * Assumes nodes have unique id's in range [0,agnnodes(g)-1].
55 * Components are stored as subgraphs of g, with name sg_<i>.
56 * Returns 0-terminated array of components.
57 * If cnt is non-0, count of components is stored there.
58 * If pinned is non-0, *pinned is set to 1 if there are pinned nodes.
59 * Note that if ports and/or pinned nodes exists, they will all be
60 * in the first component returned by findCComp.
61 */
62graphs_t findCComp(graph_t *g, int *pinned, size_t *counter) {
63 node_t *n;
64 graph_t *subg;
65 agxbuf name = {0};
66 size_t c_cnt = 0;
67 bport_t *pp;
68 int pinflag = 0;
69
71
72 /* Create component based on port nodes */
73 subg = 0;
74 if ((pp = PORTS(g))) {
75 agxbprint(&name, "cc%s_%" PRISIZE_T, agnameof(g), c_cnt++ + *counter);
76 subg = agsubg(g, agxbuse(&name), 1);
77 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
78 GD_alg(subg) = gv_alloc(sizeof(gdata));
79 PORTS(subg) = pp;
80 NPORTS(subg) = NPORTS(g);
81 for (; pp->n; pp++) {
82 if (bitarray_get(marks, ND_id(pp->n)))
83 continue;
84 dfs(g, pp->n, subg, &marks);
85 }
86 }
87
88 /* Create/extend component based on pinned nodes */
89 /* Note that ports cannot be pinned */
90 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
91 if (bitarray_get(marks, ND_id(n)))
92 continue;
93 if (ND_pinned(n) != P_PIN)
94 continue;
95 if (!subg) {
96 agxbprint(&name, "cc%s_%" PRISIZE_T, agnameof(g), c_cnt++ + *counter);
97 subg = agsubg(g, agxbuse(&name), 1);
98 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
99 GD_alg(subg) = gv_alloc(sizeof(gdata));
100 }
101 pinflag = 1;
102 dfs(g, n, subg, &marks);
103 }
104 if (subg)
105 (void)graphviz_node_induce(subg, NULL);
106
107 /* Pick up remaining components */
108 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
109 if (bitarray_get(marks, ND_id(n)))
110 continue;
111 agxbprint(&name, "cc%s+%" PRISIZE_T, agnameof(g), c_cnt++ + *counter);
112 subg = agsubg(g, agxbuse(&name), 1);
113 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), true); //node custom data
114 GD_alg(subg) = gv_alloc(sizeof(gdata));
115 dfs(g, n, subg, &marks);
116 (void)graphviz_node_induce(subg, NULL);
117 }
118 bitarray_reset(&marks);
119 agxbfree(&name);
120 *counter += c_cnt;
121
122 if (pinned)
123 *pinned = pinflag;
124 /* freed in layout */
125 graphs_t comps = {0};
126 LIST_RESERVE(&comps, c_cnt);
127 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
128 LIST_APPEND(&comps, subg);
129 c_cnt--;
130 }
131 assert(c_cnt == 0);
132
133 return comps;
134}
static void out(agerrlevel_t level, const char *fmt, va_list args)
Report messages using a user-supplied or default write function.
Definition agerror.c:86
Dynamically expanding string buffers.
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:97
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:252
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:325
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
API for compacted arrays of booleans.
static bitarray_t bitarray_new(size_t size_bits)
create an array of the given element length
Definition bitarray.h:47
static bool bitarray_get(bitarray_t self, size_t index)
get the value of the given element
Definition bitarray.h:65
static void bitarray_set(bitarray_t *self, size_t index, bool value)
set or clear the value of the given element
Definition bitarray.h:80
static void bitarray_reset(bitarray_t *self)
free underlying resources and leave a bit array empty
Definition bitarray.h:114
abstract graph C library, Cgraph API
graphs_t findCComp(graph_t *g, int *pinned, size_t *counter)
Definition comp.c:62
static void dfs(Agraph_t *g, Agnode_t *n, Agraph_t *out, bitarray_t *marks)
Definition comp.c:37
#define P_PIN
Definition const.h:249
node NULL
Definition grammar.y:181
size_t agnnodes_z(const Agraph_t *g)
Definition graph.c:161
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
Definition node_induce.c:12
#define agtail(e)
Definition cgraph.h:982
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:98
#define aghead(e)
Definition cgraph.h:983
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:89
#define GD_alg(g)
Definition types.h:358
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:50
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:43
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
Definition node.c:254
#define ND_pinned(n)
Definition types.h:519
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:145
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Definition rec.c:91
Agraph_t * agfstsubg(Agraph_t *g)
Definition subg.c:72
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:77
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:52
type-generic dynamically expanding list
#define LIST_APPEND(list,...)
Definition list.h:124
#define LIST_RESERVE(list, capacity)
Definition list.h:261
#define ND_id(n)
Definition mm2gv.c:41
support for connected components
#define PRISIZE_T
Definition prisize_t.h:25
graph or subgraph
Definition cgraph.h:424