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

Last change on this file since 76 was 13, checked in by cecile, 13 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.