2
Clique tree of a graph.
4
@author Matthieu Sozeau
7
(*i $Id: cliquetree.ml,v 1.5 2004/10/20 09:59:56 signoles Exp $ i*)
9
module CliqueTree(Gr : Sig.G) = struct
11
(* Original vertex set (of Gr) *)
12
module OVSet = Set.Make(Gr.V)
14
(* Vertex signature *)
18
val compare : t -> t -> int
20
val equal : t -> t -> bool
22
val create : Gr.V.t -> t
23
val vertex : t -> Gr.V.t
25
val set_number : t -> int -> unit
27
val set_clique : t -> int -> unit
29
val incr_mark : t -> unit
31
val set_m : t -> CVS.t -> unit
33
val set_last : t -> t -> unit
40
mutable last: t option;
45
let compare x y = Gr.V.compare x.orig y.orig
46
let hash x = Gr.V.hash x.orig
47
let equal x y = Gr.V.equal x.orig y.orig
63
let clique x = x.clique
64
let set_clique x v = x.clique <- v
66
let number x = x.number
67
let set_number x v = x.number <- v
71
(*Printf.printf "Increasing mark of %s to %i\n%!"
72
(Gr.v_to_string x.orig) (succ x.mark);*)
76
let set_m x v = x.m <- v
81
| None -> failwith "last not set"
83
let set_last x v = x.last <- Some v
86
(* Clique tree vertex set *)
87
and CVS : Set.S with type elt = CliqueV.t = Set.Make(CliqueV)
89
(* The final clique tree vertex type:
90
- set of original vertexes ordered by mark.
95
(struct type t = CliqueV.t list * CVS.t end)
99
let compare x y = Pervasives.compare x y
100
let hash = Hashtbl.hash
101
let equal x y = x = y
106
module CliqueTreeE = struct
109
let compare (x, _) (y, _) = Pervasives.compare x y
111
let default = (0, CVS.empty)
113
let create n s = (n, s)
117
let width g tri (_, x) =
118
let vertices = List.map CliqueV.vertex (CVS.elements x) in
125
if not (Gr.mem_edge g v v') && Gr.mem_edge tri v v'
136
(* The returned tree *)
138
Persistent.Digraph.ConcreteLabeled(CliqueTreeV)(CliqueTreeE)
140
(* Intermediate graph *)
141
module G = Persistent.Graph.Concrete(CliqueV)
143
(* Convenient types *)
144
module EdgeSet = Set.Make(G.E)
145
module H = Hashtbl.Make(CliqueV)
147
(* Used to choose some vertex in the intermediate graph *)
148
module Choose = Oper.Choose(G)
150
(* Creates the intermediate graph from the original *)
151
module Copy = Gmap.Vertex(Gr)(struct include G include Builder.P(G) end)
155
let vertices_list x =
156
let l = CVS.elements x in
159
let markx = mark x and marky = mark y in
160
- Pervasives.compare (number x) (number y))
164
(* initializations *)
165
let n = Gr.nb_vertex g in
166
let f = EdgeSet.empty in
167
let g' = Copy.map CliqueV.create g in
168
let unnumbered = ref (G.fold_vertex CVS.add g' CVS.empty) in
169
let pmark = ref (-1) in
170
let order = ref [] in
171
let cliques = Array.make n ([], CVS.empty) in
174
(* loop, taking each unnumbered vertex in turn *)
175
for i = n downto 1 do
176
(* Find greatest unnumbered vertex
177
if CVS.is_empty !unnumbered then
178
Printf.printf "No more unnumbered vertices\n%!"
180
Printf.printf "%i unnumbered vertices remaining\n%!"
181
(CVS.cardinal !unnumbered);
184
let choosed = CVS.choose !unnumbered in
186
(fun x ((maxx, maxv) as max) ->
188
if v > maxv then (x, v) else max)
189
!unnumbered (choosed, mark choosed)
191
(* peo construction *)
192
order := x :: !order;
194
unnumbered := CVS.remove x !unnumbered;
195
if mark <= !pmark then begin
196
(* Create a new clique (lemma 8) *)
198
(* m x is the neighborhoud of x in the previous clique *)
199
cliques.(!j) <- ([x], CVS.add x (m x));
200
(* Use reverse map of cliques to find what clique
201
we're connected to. m x is the width of the ties *)
202
let clast = clique (last x) in
203
ties := (clast, m x, !j) :: !ties;
205
let l, c = cliques.(!j) in
206
cliques.(!j) <- (x::l, CVS.add x c);
210
if number y == 0 then begin
212
set_m y (CVS.add x (m y));
222
(fun i (l, c) -> CliqueTreeV.create (List.rev l, c) i)
223
(Array.sub cliques 0 (succ !j))
226
Array.fold_left CliqueTree.add_vertex CliqueTree.empty cliques
230
(fun (g, n) (i, verts, j) ->
231
let label = CliqueTreeE.create n verts in
232
let edge = CliqueTree.E.create cliques.(i) label cliques.(j) in
233
(CliqueTree.add_edge_e g edge, succ n))
236
List.map CliqueV.vertex !order, tree, cliques.(0)
238
let sons g x = CliqueTree.fold_succ (fun x y -> x :: y) g x []
242
let rec drop_while p l =
245
if p x then drop_while p tl
249
let test_simpliciality_first l sons =
250
let takeOne l = match !l with
251
| x :: xs -> l := xs; Some x
254
let put l x = l := x :: !l in
255
let vertices = ref l in
256
let sons = ref sons in
258
while !vertices <> [] && not (List.for_all (fun c -> !c = []) !sons) do
259
(match takeOne vertices with
261
let mark = CliqueV.mark v in
266
let ymark = CliqueV.mark y in
269
else if ymark = mark then
271
(fun y -> CliqueV.mark y = mark) tl
275
| None -> assert false);
278
with NotClique -> false
280
let test_simpliciality_first' l sons =
290
let test_simpliciality_next vertices sons =
298
let vm' = CliqueV.m v' in
299
if CVS.equal vm' vm then
301
else raise NotClique)
302
(CVS.add x (m x)) tl);
304
with NotClique -> false
309
let order, tree, root = mcs_clique g in
311
let csons = sons tree c in
312
let s = List.map CliqueTreeV.data csons in
313
let l = CliqueTreeV.data c in
314
let sons () = List.map (fun (x,y) -> ref x) s in
315
let first = test_simpliciality_first' (snd l) (sons ()) in
316
let next = test_simpliciality_next (fst l) (sons ()) in
317
first && next && (List.for_all aux csons)
321
let maxwidth g tri tree =
322
CliqueTree.fold_edges_e
324
let w = CliqueTreeE.width g tri (CliqueTree.E.label e) in