···1122+ - [Path]: new module [Bfs01] to implement 0-1 BFS
23 - [Classic] new functions [kneser] and [petersen] to build Kneser's
34 graphs and the Petersen graph
45 - [Oper] fixed transitive reduction (#145, reported by sim642)
+108
src/lib/deque.ml
···11+(**************************************************************************)
22+(* *)
33+(* Ocamlgraph: a generic graph library for OCaml *)
44+(* Copyright (C) 2004-2010 *)
55+(* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *)
66+(* *)
77+(* This software is free software; you can redistribute it and/or *)
88+(* modify it under the terms of the GNU Library General Public *)
99+(* License version 2.1, with the special exception on linking *)
1010+(* described in file LICENSE. *)
1111+(* *)
1212+(* This software is distributed in the hope that it will be useful, *)
1313+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
1414+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
1515+(* *)
1616+(**************************************************************************)
1717+1818+(** Double-ended queue implemented with doubly-linked lists *)
1919+2020+type 'a cell =
2121+ | Null
2222+ | Cell of { value: 'a; mutable prev: 'a cell; mutable next: 'a cell; }
2323+2424+type 'a t = {
2525+ mutable front: 'a cell;
2626+ mutable back : 'a cell;
2727+ mutable size : int;
2828+}
2929+ (* invariant: size=0 && front=back == Null
3030+ || size>0 && front,back != Null
3131+3232+ ----next--->
3333+ front back
3434+ <---prev----
3535+ *)
3636+3737+let create () =
3838+ { front = Null; back = Null; size = 0 }
3939+4040+let length dq =
4141+ dq.size
4242+4343+let clear dq =
4444+ dq.front <- Null;
4545+ dq.back <- Null;
4646+ dq.size <- 0
4747+4848+let add_first dq x =
4949+ let c = Cell { value = x; prev = Null; next = Null } in
5050+ dq.front <- c;
5151+ dq.back <- c;
5252+ dq.size <- 1
5353+5454+let push_front dq x =
5555+ match dq.front with
5656+ | Null ->
5757+ add_first dq x
5858+ | Cell f as cf ->
5959+ let c = Cell { value = x; prev = Null; next = cf } in
6060+ f.prev <- c;
6161+ dq.front <- c;
6262+ dq.size <- dq.size + 1
6363+6464+let peek_front dq =
6565+ match dq.front with
6666+ | Null -> invalid_arg "peek_front"
6767+ | Cell { value=v; _ } -> v
6868+6969+let pop_front dq =
7070+ match dq.front with
7171+ | Null ->
7272+ invalid_arg "pop_front"
7373+ | Cell { value=v; next=Null; _} ->
7474+ clear dq;
7575+ v
7676+ | Cell { value=v; next=Cell c as n; _} ->
7777+ dq.front <- n;
7878+ c.prev <- Null;
7979+ dq.size <- dq.size - 1;
8080+ v
8181+8282+let push_back dq x =
8383+ match dq.back with
8484+ | Null ->
8585+ add_first dq x
8686+ | Cell b as cb ->
8787+ let c = Cell { value = x; prev = cb; next = Null } in
8888+ b.next <- c;
8989+ dq.back <- c;
9090+ dq.size <- dq.size + 1
9191+9292+let peek_back dq =
9393+ match dq.back with
9494+ | Null -> invalid_arg "peek_back"
9595+ | Cell { value=v; _ } -> v
9696+9797+let pop_back dq =
9898+ match dq.back with
9999+ | Null ->
100100+ invalid_arg "pop_back"
101101+ | Cell { value=v; prev=Null; _} ->
102102+ clear dq;
103103+ v
104104+ | Cell { value=v; prev=Cell c as p; _} ->
105105+ dq.back <- p;
106106+ c.next <- Null;
107107+ dq.size <- dq.size - 1;
108108+ v
+33
src/lib/deque.mli
···11+(**************************************************************************)
22+(* *)
33+(* Ocamlgraph: a generic graph library for OCaml *)
44+(* Copyright (C) 2004-2010 *)
55+(* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *)
66+(* *)
77+(* This software is free software; you can redistribute it and/or *)
88+(* modify it under the terms of the GNU Library General Public *)
99+(* License version 2.1, with the special exception on linking *)
1010+(* described in file LICENSE. *)
1111+(* *)
1212+(* This software is distributed in the hope that it will be useful, *)
1313+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
1414+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
1515+(* *)
1616+(**************************************************************************)
1717+1818+(** Double-ended queue *)
1919+2020+type 'a t
2121+2222+val create: unit -> 'a t
2323+val length: 'a t -> int
2424+2525+val clear: 'a t -> unit
2626+2727+val push_front: 'a t -> 'a -> unit
2828+val peek_front: 'a t -> 'a
2929+val pop_front: 'a t -> 'a
3030+3131+val push_back: 'a t -> 'a -> unit
3232+val peek_back: 'a t -> 'a
3333+val pop_back: 'a t -> 'a
+3
src/pack.ml
···5959 module BF = Path.BellmanFord(G)(W)
6060 let bellman_ford = BF.find_negative_cycle_from
61616262+ module Bfs01 = Path.Bfs01(G)
6363+ let bfs_0_1 = Bfs01.iter
6464+6265 module F = struct
6366 type label = int
6467 type t = int
+33
src/path.ml
···347347 loop ()
348348349349end
350350+351351+(** 0-1 BFS
352352+353353+ When edge weights are limited to 0 or 1, this is more efficient than
354354+ running Dijkstra's algorithm. *)
355355+356356+module Bfs01(G: sig
357357+ type t
358358+ module V: Sig.COMPARABLE
359359+ module E: sig type t val dst : t -> V.t end
360360+ val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit
361361+end) = struct
362362+363363+ module H = Hashtbl.Make(G.V)
364364+365365+ let iter f g ~zero s =
366366+ let visited = H.create 16 in
367367+ let d = Deque.create () in
368368+ Deque.push_front d (s, 0); H.add visited s ();
369369+ while Deque.length d > 0 do
370370+ let v, n = Deque.pop_front d in
371371+ f v n;
372372+ G.iter_succ_e (fun e ->
373373+ let w = G.E.dst e in
374374+ if not (H.mem visited w) then (
375375+ H.add visited w ();
376376+ if zero e then Deque.push_front d (w, n )
377377+ else Deque.push_back d (w, n+1)
378378+ )
379379+ ) g v
380380+ done
381381+382382+end
+23-2
src/path.mli
···1515(* *)
1616(**************************************************************************)
17171818-(* $Id: path.mli,v 1.9 2005-07-18 07:10:35 filliatr Exp $ *)
1919-2018(** Paths *)
21192220(** Minimal graph signature for Dijkstra's algorithm.
···152150 *)
153151154152end
153153+154154+(** 0-1 BFS
155155+156156+ When edge weights are limited to 0 or 1, this is more efficient than
157157+ running Dijkstra's algorithm. It runs in time and space O(E) in
158158+ the worst case. *)
159159+160160+module Bfs01(G: sig
161161+ type t
162162+ module V: Sig.COMPARABLE
163163+ module E: sig type t val dst : t -> V.t end
164164+ val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit
165165+end) : sig
166166+167167+ val iter: (G.V.t -> int -> unit) ->
168168+ G.t -> zero:(G.E.t -> bool) -> G.V.t -> unit
169169+ (** [iter f g zero s] performs a 0-1 BFS on graph [g], from the
170170+ source vertex [s], and applies [f] to each visited vertex and
171171+ its distance from the source. Function [zero] indicates 0-edges.
172172+ All reachable vertices are visited, in increasing order of
173173+ distance to the source. *)
174174+175175+end
+3
src/sig_pack.mli
···419419 (** [bellman_ford g v] finds a negative cycle from [v], and returns it,
420420 or raises [Not_found] if there is no such cycle *)
421421422422+ val bfs_0_1: (V.t -> int -> unit) -> t -> zero:(E.t -> bool) -> V.t -> unit
423423+ (** 0-1 BFS from a given source. Function [zero] indicates 0-edges. *)
424424+422425 (** Path checking *)
423426 module PathCheck : sig
424427 type path_checker
···11+22+(* Test file for Path.Bfs01 *)
33+44+open Graph
55+open Pack.Digraph
66+77+let zero e =
88+ E.label e = 0
99+1010+let test n =
1111+ let g = create () in
1212+ let nv = 2*n+2 in
1313+ let v = Array.init nv V.create in
1414+ Array.iter (add_vertex g) v;
1515+ let edge i d j = add_edge_e g (E.create v.(i) d v.(j)) in
1616+ for i = 1 to n do let i = 2*i in edge (i-2) 0 i done; edge (2*n) 1 (2*n+1);
1717+ edge 0 1 1; for i = 0 to n-1 do let i = 2*i+1 in edge i 1 (i+2) done;
1818+ let check v d =
1919+ let i = V.label v in
2020+ assert (d = if i mod 2 = 0 then 0
2121+ else if i = 2*n+1 then 1
2222+ else (i+1) / 2) in
2323+ bfs_0_1 check g ~zero v.(0)
2424+2525+let () =
2626+ for n = 0 to 10 do test n done
2727+2828+2929+