source: vis_dev/glu-2.3/src/graph/graph_dfs.c@ 83

Last change on this file since 83 was 13, checked in by cecile, 15 years ago

library glu 2.3

File size: 5.7 KB
Line 
1/*
2 * $Id: graph_dfs.c,v 1.9 2005/04/15 23:24:21 fabio Exp $
3 */
4
5#include "graph_int.h"
6
7static vertex_t *
8find_an_end_vertex(vertex_t *v, st_table *visit_list)
9{
10 edge_t *e;
11 vertex_t *dest;
12 lsGen gen;
13
14 if (lsLength(g_get_out_edges(v)) == 0) {
15 return(v);
16 }
17 foreach_out_edge (v,gen,e) {
18 (void) lsFinish(gen);
19 dest = g_e_dest(e);
20 if (st_insert(visit_list,(char *) dest,(char *) 0) == 1) {
21 return(NIL(vertex_t));
22 }
23 return(find_an_end_vertex(dest,visit_list));
24 /* NOTREACHED */
25 }
26 /* no free out_edges */
27 return(NIL(vertex_t));
28}
29
30static int
31dfs_recurr(vertex_t *v, st_table *dfs_list, array_t *dfs_array)
32{
33 edge_t *e;
34 lsGen gen;
35 int val;
36
37 if (st_lookup_int(dfs_list,(char *) v, &val)) {
38 return(val == 0);
39 }
40 (void) st_insert(dfs_list,(char *) v,(char *) 1);
41
42 foreach_in_edge (v,gen,e) {
43 if (!dfs_recurr(g_e_source(e),dfs_list,dfs_array)) {
44 return(0);
45 }
46 }
47 (void) st_insert(dfs_list,(char *) v,(char *) 0);
48 array_insert_last(vertex_t *,dfs_array,v);
49 return(1);
50}
51
52static array_t *
53g_dfs_int(graph_t *g)
54{
55 vertex_t *v;
56 lsGen gen;
57 array_t *dfs_array;
58 st_table *visit_list,*dfs_list;
59 int cycle = FALSE;
60
61 dfs_array = array_alloc(vertex_t *,0);
62 visit_list = st_init_table(st_ptrcmp,st_ptrhash);
63 dfs_list = st_init_table(st_ptrcmp,st_ptrhash);
64
65 foreach_vertex (g,gen,v) {
66 if (!st_is_member(dfs_list,(char *) v)) {
67 (void) st_insert(visit_list,(char *) v,(char *) 0);
68 v = find_an_end_vertex(v,visit_list);
69 if (v == NIL(vertex_t) || !dfs_recurr(v,dfs_list,dfs_array)) {
70 cycle = TRUE;
71 (void) lsFinish(gen);
72 break;
73 }
74 }
75 }
76
77 st_free_table(visit_list);
78 st_free_table(dfs_list);
79 if (cycle == TRUE) {
80 array_free(dfs_array);
81 return(NIL(array_t));
82 }
83 return(dfs_array);
84}
85
86array_t *
87g_dfs(graph_t *g)
88{
89 array_t *x;
90
91 x = g_dfs_int(g);
92 if (x == NIL(array_t)) {
93 fail("g_dfs: Graph has cycle");
94 }
95 return(x);
96}
97
98int
99g_is_acyclic(graph_t *g)
100{
101 array_t *x;
102
103 x = g_dfs_int(g);
104 if (x) {
105 array_free(x);
106 return(TRUE);
107 }
108 return(FALSE);
109}
110
111
112static int
113reachable_recurr(vertex_t *v, st_table *dfs_list)
114{
115 edge_t *e;
116 lsGen gen;
117 int val;
118
119 if (st_lookup_int(dfs_list,(char *) v, &val)) {
120 return(val == 0);
121 }
122 (void) st_insert(dfs_list,(char *) v,(char *) 1);
123
124 foreach_out_edge (v,gen,e) {
125 reachable_recurr(g_e_dest(e),dfs_list);
126 }
127 (void) st_insert(dfs_list,(char *) v,(char *) 0);
128
129 return(1);
130}
131
132/* compute reachable states from the initial states */
133st_table *
134g_reachable(graph_t *g, st_table *init)
135{
136 vertex_t *v;
137 st_table *dfs_list;
138 st_generator *stgen;
139
140 dfs_list = st_init_table(st_ptrcmp, st_ptrhash);
141
142 st_foreach_item(init, stgen, &v, NIL(char *)) {
143 reachable_recurr(v,dfs_list);
144 }
145
146 return (dfs_list);
147}
148
149
150static int
151EF_recurr(vertex_t *v, st_table *EF_list)
152{
153 edge_t *e;
154 lsGen gen;
155 int val;
156
157 if (st_lookup_int(EF_list,(char *) v, &val)) {
158 return(val == 0);
159 }
160 (void) st_insert(EF_list,(char *) v,(char *) 1);
161
162 foreach_in_edge (v,gen,e) {
163 EF_recurr(g_e_source(e),EF_list);
164 }
165 (void) st_insert(EF_list,(char *) v,(char *) 0);
166
167 return(1);
168}
169
170/* compute EF(goal) of an automaton, might include unreachable states */
171st_table *
172g_EF(graph_t *g, st_table *goal)
173{
174 vertex_t *v;
175 st_table *EF_list;
176 st_generator *stgen;
177
178 EF_list = st_init_table(st_ptrcmp, st_ptrhash);
179
180 st_foreach_item(goal, stgen, &v, NIL(char *)) {
181 EF_recurr(v,EF_list);
182 }
183
184 return (EF_list);
185}
186
187static void
188searchSCC(
189 vertex_t *v,
190 st_table *scc,
191 st_table *old /*visited*/,
192 lsList stack,
193 st_table *onstack,
194 int *countr)
195{
196 int lowlink_v, dfnumber_v, lowlink_w, dfnumber_w;
197 vertex_t *x, *w;
198 st_table *component;
199 lsGen gen;
200 edge_t *e;
201
202 lowlink_v = dfnumber_v = *countr;
203 (*countr)++;
204 st_insert(old, (char *)v, (char *)(long)dfnumber_v);
205 st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
206 lsNewBegin(stack, (lsGeneric)v, NIL(lsHandle));
207
208 foreach_out_edge (v,gen,e) {
209 w = g_e_dest(e);
210 if (!st_is_member(old, (char *)w)) {
211 searchSCC(w,scc,old,stack,onstack,countr);
212 if(st_lookup_int(onstack, (char *)w, &lowlink_w) &&
213 lowlink_w < lowlink_v) {
214 lowlink_v = lowlink_w;
215 st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
216 }
217 }else {
218 st_lookup_int(old, (char *)w, &dfnumber_w);
219 if (dfnumber_w < dfnumber_v && st_is_member(onstack, (char *)w)) {
220 if (dfnumber_w < lowlink_v) {
221 lowlink_v = dfnumber_w;
222 st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
223 }
224 }
225 }
226 }
227
228 /* put current SCC into st_table, and then insert into 'scc' */
229 if (dfnumber_v == lowlink_v) {
230 component = st_init_table(st_ptrcmp, st_ptrhash);
231 while (lsDelBegin(stack, &x) != LS_NOMORE) {
232 st_insert(component, (char *)x, NIL(char));
233 st_delete(onstack, &x, NIL(char *));
234 if (v == x) break;
235 }
236 st_insert(scc, (char *)component, NIL(char)); /* is component fair? */
237 }
238}
239
240/* compute the strongly connected components of a graph (Tarjan's alg.) */
241st_table *
242g_SCC(graph_t *g, st_table *init)
243{
244 vertex_t *v;
245 lsList stack;
246 st_table *old, *onstack, *scc;
247 st_generator *stgen;
248 int countr = 0;
249
250 scc = st_init_table(st_ptrcmp, st_ptrhash);
251
252 stack = lsCreate();
253 old = st_init_table(st_ptrcmp, st_ptrhash);
254 onstack = st_init_table(st_ptrcmp, st_ptrhash);
255 st_foreach_item(init, stgen, &v, NIL(char *)) {
256 if (!st_is_member(old, (char *)v))
257 searchSCC(v,scc,old,stack,onstack,&countr);
258 }
259 lsDestroy(stack, (void (*)(lsGeneric))0 );
260 st_free_table(old);
261 st_free_table(onstack);
262
263 return scc;
264}
Note: See TracBrowser for help on using the repository browser.