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
130
131
module Int_map = Map.Make (struct
type t = int
let compare (x : int) (y : int) = Stdlib.compare x y
end)
type node = {
id: int;
sub: int 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 reset g =
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 =
let g = reset 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