Source file pb_typing_graph.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module Int_map = Pb_util.Int_map
type id = int
type node = {
id: id;
sub: id list;
}
let create_node id sub = { id; sub }
type graph = node Int_map.t
let empty_graph = Int_map.empty
let add_node ({ id; _ } as n) g = Int_map.add id n g
module Tarjan = struct
type tnode = {
core: node;
mutable index: int option;
mutable lowlink: int option;
mutable on_stack: bool;
}
type tgraph = tnode Int_map.t
let new_tgraph (g : graph) : tgraph =
Int_map.map
(fun core -> { core; index = None; lowlink = None; on_stack = false })
g
let rec strong_connect (g : tgraph) sccs stack (index : int) (v : tnode) =
Pb_logger.log "[Graph] processing v [%i], index: %i\n" v.core.id index;
v.index <- Some index;
v.lowlink <- Some index;
let stack = v :: stack in
v.on_stack <- true;
let sccs, stack, index =
List.fold_left
(fun (sccs, stack, index) id ->
let (w : tnode) = Int_map.find id g in
Pb_logger.log "[Graph] sub w [%i], w.index: %s\n" w.core.id
(Pb_util.Option.string_of_option string_of_int w.index);
match w.index with
| Some _ ->
if w.on_stack then
v.lowlink <- Pb_util.Option.min_value v.lowlink w.index;
sccs, stack, index
| None ->
let sccs, stack, index =
strong_connect g sccs stack (index + 1) w
in
v.lowlink <- Pb_util.Option.min_value v.lowlink w.lowlink;
sccs, stack, index)
(sccs, stack, index) v.core.sub
in
Pb_logger.log "[Graph] after sub for v [%i], lowlink: %s, index: %s\n"
v.core.id
(Pb_util.Option.string_of_option string_of_int v.lowlink)
(Pb_util.Option.string_of_option string_of_int v.index);
Pb_logger.log "[Graph] -> stack : %s\n"
("["
^ String.concat ";"
(List.map (fun { core = { id; _ }; _ } -> string_of_int id) stack)
^ "]");
if Pb_util.Option.eq_value v.lowlink v.index then (
let scc, stack, _ =
List.fold_left
(fun (scc, stack, splitted) n ->
if splitted then
scc, n :: stack, splitted
else (
n.on_stack <- false;
if n.core.id = v.core.id then
n.core.id :: scc, stack, true
else
n.core.id :: scc, stack, false
))
([], [], false) stack
in
scc :: sccs, List.rev stack, index
) else
sccs, stack, index
let tarjan g : id list list =
let g = new_tgraph g in
let sccs, _, _ =
Int_map.fold
(fun _ n (sccs, stack, index) ->
match n.index with
| Some _ -> sccs, stack, index
| None -> strong_connect g sccs stack index n)
g ([], [], 0)
in
sccs
end
let tarjan = Tarjan.tarjan