mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
cleanup of LazyGraph
This commit is contained in:
parent
5553ed4699
commit
974df85321
3 changed files with 130 additions and 140 deletions
|
|
@ -713,7 +713,6 @@ module Timer = struct
|
||||||
Mutex.unlock timer.mutex
|
Mutex.unlock timer.mutex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module Infix = struct
|
module Infix = struct
|
||||||
let (>>=) x f = flatMap f x
|
let (>>=) x f = flatMap f x
|
||||||
let (>>) a f = andThen a f
|
let (>>) a f = andThen a f
|
||||||
|
|
|
||||||
216
lazyGraph.ml
216
lazyGraph.ml
|
|
@ -72,71 +72,27 @@ let from_fun ?(eq=(=)) ?(hash=Hashtbl.hash) f =
|
||||||
| Some (l, edges) -> Node (v, l, Gen.of_list edges) in
|
| Some (l, edges) -> Node (v, l, Gen.of_list edges) in
|
||||||
{ eq; hash; force; }
|
{ eq; hash; force; }
|
||||||
|
|
||||||
(** {2 Polymorphic utils} *)
|
(** {2 Polymorphic map} *)
|
||||||
|
|
||||||
(** A set of vertices *)
|
type ('id, 'a) map = {
|
||||||
type 'id set =
|
map_is_empty : unit -> bool;
|
||||||
<
|
map_mem : 'id -> bool;
|
||||||
mem : 'id -> bool;
|
map_add : 'id -> 'a -> unit;
|
||||||
add : 'id -> unit;
|
map_get : 'id -> 'a;
|
||||||
remove : 'id -> unit;
|
}
|
||||||
iter : ('id -> unit) -> unit;
|
|
||||||
>
|
|
||||||
|
|
||||||
(** Make a set based on hashtables *)
|
let mk_map (type id) ~eq ~hash =
|
||||||
let rec mk_hset (type id) ?(eq=(=)) ~hash =
|
let module H = Hashtbl.Make(struct
|
||||||
let module H = Hashtbl.Make(struct type t = id let equal = eq let hash = hash end) in
|
type t = id
|
||||||
let set = H.create 5 in
|
let equal = eq
|
||||||
object
|
let hash = hash
|
||||||
method mem x = H.mem set x
|
end) in
|
||||||
method add x = H.replace set x ()
|
let h = H.create 3 in
|
||||||
method remove x = H.remove set x
|
{ map_is_empty = (fun () -> H.length h = 0);
|
||||||
method iter f = H.iter (fun x () -> f x) set
|
map_mem = (fun k -> H.mem h k);
|
||||||
end
|
map_add = (fun k v -> H.replace h k v);
|
||||||
|
map_get = (fun k -> H.find h k);
|
||||||
(** Make a set based on balanced trees *)
|
}
|
||||||
let rec mk_tset (type id) ~cmp =
|
|
||||||
let module S = Set.Make(struct type t = id let compare = cmp end) in
|
|
||||||
let set = ref S.empty in
|
|
||||||
object
|
|
||||||
method mem x = S.mem x !set
|
|
||||||
method add x = set := S.add x !set
|
|
||||||
method remove x = set := S.remove x !set
|
|
||||||
method iter f = S.iter f !set
|
|
||||||
end
|
|
||||||
|
|
||||||
type ('id,'a) map =
|
|
||||||
<
|
|
||||||
mem : 'id -> bool;
|
|
||||||
get : 'id -> 'a; (* or Not_found *)
|
|
||||||
add : 'id -> 'a -> unit;
|
|
||||||
remove : 'id -> unit;
|
|
||||||
iter : ('id -> 'a -> unit) -> unit;
|
|
||||||
>
|
|
||||||
|
|
||||||
(** Make a map based on hashtables *)
|
|
||||||
let rec mk_hmap (type id) ?(eq=(=)) ~hash =
|
|
||||||
let module H = Hashtbl.Make(struct type t = id let equal = eq let hash = hash end) in
|
|
||||||
let m = H.create 5 in
|
|
||||||
object
|
|
||||||
method mem k = H.mem m k
|
|
||||||
method add k v = H.replace m k v
|
|
||||||
method remove k = H.remove m k
|
|
||||||
method get k = H.find m k
|
|
||||||
method iter f = H.iter f m
|
|
||||||
end
|
|
||||||
|
|
||||||
(** Make a map based on balanced trees *)
|
|
||||||
let rec mk_tmap (type id) ~cmp =
|
|
||||||
let module M = Map.Make(struct type t = id let compare = cmp end) in
|
|
||||||
let m = ref M.empty in
|
|
||||||
object
|
|
||||||
method mem k = M.mem k !m
|
|
||||||
method add k v = m := M.add k v !m
|
|
||||||
method remove k = m := M.remove k !m
|
|
||||||
method get k = M.find k !m
|
|
||||||
method iter f = M.iter f !m
|
|
||||||
end
|
|
||||||
|
|
||||||
(** {2 Mutable concrete implementation} *)
|
(** {2 Mutable concrete implementation} *)
|
||||||
|
|
||||||
|
|
@ -154,22 +110,22 @@ module Mutable = struct
|
||||||
}
|
}
|
||||||
|
|
||||||
let create ?(eq=(=)) ~hash =
|
let create ?(eq=(=)) ~hash =
|
||||||
let map = mk_hmap ~eq ~hash in
|
let map = mk_map ~eq ~hash in
|
||||||
let force v =
|
let force v =
|
||||||
try let node = map#get v in
|
try let node = map.map_get v in
|
||||||
Node (v, node.mut_v, Gen.of_list node.mut_outgoing)
|
Node (v, node.mut_v, Gen.of_list node.mut_outgoing)
|
||||||
with Not_found -> Empty in
|
with Not_found -> Empty in
|
||||||
let graph = { eq; hash; force; } in
|
let graph = { eq; hash; force; } in
|
||||||
map, graph
|
map, graph
|
||||||
|
|
||||||
let add_vertex map id v =
|
let add_vertex map id v =
|
||||||
if not (map#mem id)
|
if not (map.map_mem id)
|
||||||
then
|
then
|
||||||
let node = { mut_id=id; mut_v=v; mut_outgoing=[]; } in
|
let node = { mut_id=id; mut_v=v; mut_outgoing=[]; } in
|
||||||
map#add id node
|
map.map_add id node
|
||||||
|
|
||||||
let add_edge map v1 e v2 =
|
let add_edge map v1 e v2 =
|
||||||
let n1 = map#get v1 in
|
let n1 = map.map_get v1 in
|
||||||
n1.mut_outgoing <- (e, v2) :: n1.mut_outgoing;
|
n1.mut_outgoing <- (e, v2) :: n1.mut_outgoing;
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
|
|
@ -200,24 +156,21 @@ module Full = struct
|
||||||
(eq v v') || (eq v v'') || (mem_path ~eq path' v)
|
(eq v v') || (eq v v'') || (mem_path ~eq path' v)
|
||||||
| [] -> false
|
| [] -> false
|
||||||
|
|
||||||
let bfs_full ?(id=0) ?explored graph vertices =
|
let bfs_full graph vertices =
|
||||||
let explored = match explored with
|
|
||||||
| Some e -> e
|
|
||||||
| None -> fun () -> mk_hset ~eq:graph.eq ~hash:graph.hash in
|
|
||||||
fun () ->
|
fun () ->
|
||||||
let explored = explored () in
|
let explored = mk_map ~eq:graph.eq ~hash:graph.hash in
|
||||||
let id = ref id in
|
let id = ref 0 in
|
||||||
let q = Queue.create () in (* queue of nodes to explore *)
|
let q = Queue.create () in (* queue of nodes to explore *)
|
||||||
Gen.iter (fun v -> Queue.push (FullEnter (v,[])) q) vertices;
|
Gen.iter (fun v -> Queue.push (FullEnter (v,[])) q) vertices;
|
||||||
let rec next () =
|
let rec next () =
|
||||||
if Queue.is_empty q then raise Gen.EOG else
|
if Queue.is_empty q then raise Gen.EOG else
|
||||||
match Queue.pop q with
|
match Queue.pop q with
|
||||||
| FullEnter (v', path) ->
|
| FullEnter (v', path) ->
|
||||||
if explored#mem v' then next ()
|
if explored.map_mem v' then next ()
|
||||||
else begin match graph.force v' with
|
else begin match graph.force v' with
|
||||||
| Empty -> next ()
|
| Empty -> next ()
|
||||||
| Node (_, label, edges) ->
|
| Node (_, label, edges) ->
|
||||||
explored#add v';
|
explored.map_add v' ();
|
||||||
(* explore neighbors *)
|
(* explore neighbors *)
|
||||||
Gen.iter
|
Gen.iter
|
||||||
(fun (e,v'') ->
|
(fun (e,v'') ->
|
||||||
|
|
@ -235,7 +188,7 @@ module Full = struct
|
||||||
| FullFollowEdge [] -> assert false
|
| FullFollowEdge [] -> assert false
|
||||||
| FullFollowEdge (((v'', e, v') :: path) as path') ->
|
| FullFollowEdge (((v'', e, v') :: path) as path') ->
|
||||||
(* edge path .... v' --e--> v'' *)
|
(* edge path .... v' --e--> v'' *)
|
||||||
if explored#mem v''
|
if explored.map_mem v''
|
||||||
then if mem_path ~eq:graph.eq path v''
|
then if mem_path ~eq:graph.eq path v''
|
||||||
then MeetEdge (v'', e, v', EdgeBackward)
|
then MeetEdge (v'', e, v', EdgeBackward)
|
||||||
else MeetEdge (v'', e, v', EdgeTransverse)
|
else MeetEdge (v'', e, v', EdgeTransverse)
|
||||||
|
|
@ -246,13 +199,10 @@ module Full = struct
|
||||||
end
|
end
|
||||||
in next
|
in next
|
||||||
|
|
||||||
let dfs_full ?(id=0) ?explored graph vertices =
|
let dfs_full graph vertices =
|
||||||
let explored = match explored with
|
|
||||||
| Some e -> e
|
|
||||||
| None -> (fun () -> mk_hset ~eq:graph.eq ~hash:graph.hash) in
|
|
||||||
fun () ->
|
fun () ->
|
||||||
let explored = explored () in
|
let explored = mk_map ~eq:graph.eq ~hash:graph.hash in
|
||||||
let id = ref id in
|
let id = ref 0 in
|
||||||
let s = Stack.create () in (* stack of nodes to explore *)
|
let s = Stack.create () in (* stack of nodes to explore *)
|
||||||
Gen.iter (fun v -> Stack.push (FullEnter (v,[])) s) vertices;
|
Gen.iter (fun v -> Stack.push (FullEnter (v,[])) s) vertices;
|
||||||
let rec next () =
|
let rec next () =
|
||||||
|
|
@ -260,12 +210,12 @@ module Full = struct
|
||||||
match Stack.pop s with
|
match Stack.pop s with
|
||||||
| FullExit v' -> ExitVertex v'
|
| FullExit v' -> ExitVertex v'
|
||||||
| FullEnter (v', path) ->
|
| FullEnter (v', path) ->
|
||||||
if explored#mem v' then next ()
|
if explored.map_mem v' then next ()
|
||||||
(* explore the node now *)
|
(* explore the node now *)
|
||||||
else begin match graph.force v' with
|
else begin match graph.force v' with
|
||||||
| Empty -> next ()
|
| Empty -> next ()
|
||||||
| Node (_, label, edges) ->
|
| Node (_, label, edges) ->
|
||||||
explored#add v';
|
explored.map_add v' ();
|
||||||
(* prepare to exit later *)
|
(* prepare to exit later *)
|
||||||
Stack.push (FullExit v') s;
|
Stack.push (FullExit v') s;
|
||||||
(* explore neighbors *)
|
(* explore neighbors *)
|
||||||
|
|
@ -281,7 +231,7 @@ module Full = struct
|
||||||
| FullFollowEdge [] -> assert false
|
| FullFollowEdge [] -> assert false
|
||||||
| FullFollowEdge (((v'', e, v') :: path) as path') ->
|
| FullFollowEdge (((v'', e, v') :: path) as path') ->
|
||||||
(* edge path .... v' --e--> v'' *)
|
(* edge path .... v' --e--> v'' *)
|
||||||
if explored#mem v''
|
if explored.map_mem v''
|
||||||
then if mem_path ~eq:graph.eq path v''
|
then if mem_path ~eq:graph.eq path v''
|
||||||
then MeetEdge (v'', e, v', EdgeBackward)
|
then MeetEdge (v'', e, v', EdgeBackward)
|
||||||
else MeetEdge (v'', e, v', EdgeTransverse)
|
else MeetEdge (v'', e, v', EdgeTransverse)
|
||||||
|
|
@ -293,28 +243,102 @@ module Full = struct
|
||||||
in next
|
in next
|
||||||
end
|
end
|
||||||
|
|
||||||
let bfs ?id ?explored graph v =
|
let bfs graph v =
|
||||||
Gen.filterMap
|
Gen.filterMap
|
||||||
(function
|
(function
|
||||||
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
|
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
(Full.bfs_full ?id ?explored graph (Gen.singleton v))
|
(Full.bfs_full graph (Gen.singleton v))
|
||||||
|
|
||||||
let dfs ?id ?explored graph v =
|
let dfs graph v =
|
||||||
Gen.filterMap
|
Gen.filterMap
|
||||||
(function
|
(function
|
||||||
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
|
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
(Full.dfs_full ?id ?explored graph (Gen.singleton v))
|
(Full.dfs_full graph (Gen.singleton v))
|
||||||
|
|
||||||
let enum graph v = (Gen.empty, Gen.empty) (* TODO *)
|
let enum graph v = (Gen.empty, Gen.empty) (* TODO *)
|
||||||
|
|
||||||
let depth graph v =
|
let depth graph v =
|
||||||
failwith "not implemented" (* TODO *)
|
failwith "not implemented" (* TODO *)
|
||||||
|
|
||||||
(** Minimal path from the given Graph from the first vertex to
|
(** {3 Mutable heap (taken from heap.ml to avoid dependencies)} *)
|
||||||
the second. It returns both the distance and the path *)
|
module Heap = struct
|
||||||
let min_path ?(distance=fun v1 e v2 -> 1) ?explored graph v1 v2 =
|
type 'a t = {
|
||||||
|
mutable tree : 'a tree;
|
||||||
|
cmp : 'a -> 'a -> int;
|
||||||
|
} (** A splay tree heap with the given comparison function *)
|
||||||
|
and 'a tree =
|
||||||
|
| Empty
|
||||||
|
| Node of ('a tree * 'a * 'a tree)
|
||||||
|
(** A splay tree containing values of type 'a *)
|
||||||
|
|
||||||
|
let empty ~cmp = {
|
||||||
|
tree = Empty;
|
||||||
|
cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_empty h =
|
||||||
|
match h.tree with
|
||||||
|
| Empty -> true
|
||||||
|
| Node _ -> false
|
||||||
|
|
||||||
|
(** Partition the tree into (elements <= pivot, elements > pivot) *)
|
||||||
|
let rec partition ~cmp pivot tree =
|
||||||
|
match tree with
|
||||||
|
| Empty -> Empty, Empty
|
||||||
|
| Node (a, x, b) ->
|
||||||
|
if cmp x pivot <= 0
|
||||||
|
then begin
|
||||||
|
match b with
|
||||||
|
| Empty -> (tree, Empty)
|
||||||
|
| Node (b1, y, b2) ->
|
||||||
|
if cmp y pivot <= 0
|
||||||
|
then
|
||||||
|
let small, big = partition ~cmp pivot b2 in
|
||||||
|
Node (Node (a, x, b1), y, small), big
|
||||||
|
else
|
||||||
|
let small, big = partition ~cmp pivot b1 in
|
||||||
|
Node (a, x, small), Node (big, y, b2)
|
||||||
|
end else begin
|
||||||
|
match a with
|
||||||
|
| Empty -> (Empty, tree)
|
||||||
|
| Node (a1, y, a2) ->
|
||||||
|
if cmp y pivot <= 0
|
||||||
|
then
|
||||||
|
let small, big = partition ~cmp pivot a2 in
|
||||||
|
Node (a1, y, small), Node (big, x, b)
|
||||||
|
else
|
||||||
|
let small, big = partition ~cmp pivot a1 in
|
||||||
|
small, Node (big, y, Node (a2, x, b))
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Insert the element in the tree *)
|
||||||
|
let insert h x =
|
||||||
|
let small, big = partition ~cmp:h.cmp x h.tree in
|
||||||
|
let tree' = Node (small, x, big) in
|
||||||
|
h.tree <- tree'
|
||||||
|
|
||||||
|
(** Get minimum value and remove it from the tree *)
|
||||||
|
let pop h =
|
||||||
|
let rec delete_min tree = match tree with
|
||||||
|
| Empty -> raise Not_found
|
||||||
|
| Node (Empty, x, b) -> x, b
|
||||||
|
| Node (Node (Empty, x, b), y, c) ->
|
||||||
|
x, Node (b, y, c) (* rebalance *)
|
||||||
|
| Node (Node (a, x, b), y, c) ->
|
||||||
|
let m, a' = delete_min a in
|
||||||
|
m, Node (a', x, Node (b, y, c))
|
||||||
|
in
|
||||||
|
let m, tree' = delete_min h.tree in
|
||||||
|
h.tree <- tree';
|
||||||
|
m
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Shortest path from the first node to the second one, according
|
||||||
|
to the given (positive!) distance function. The path is reversed,
|
||||||
|
ie, from the destination to the source. The int is the distance. *)
|
||||||
|
let disjktra graph ?(distance=fun v1 e v2 -> 1) v1 v2 =
|
||||||
failwith "not implemented"
|
failwith "not implemented"
|
||||||
|
|
||||||
(** {2 Lazy transformations} *)
|
(** {2 Lazy transformations} *)
|
||||||
|
|
@ -397,13 +421,13 @@ module Dot = struct
|
||||||
(* map from vertices to integers *)
|
(* map from vertices to integers *)
|
||||||
and get_id =
|
and get_id =
|
||||||
let count = ref 0 in
|
let count = ref 0 in
|
||||||
let m = mk_hmap ~eq ~hash in
|
let m = mk_map ~eq ~hash in
|
||||||
fun vertex ->
|
fun vertex ->
|
||||||
try m#get vertex
|
try m.map_get vertex
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
let n = !count in
|
let n = !count in
|
||||||
incr count;
|
incr count;
|
||||||
m#add vertex n;
|
m.map_add vertex n;
|
||||||
n
|
n
|
||||||
in
|
in
|
||||||
(* the unique name of a vertex *)
|
(* the unique name of a vertex *)
|
||||||
|
|
|
||||||
|
|
@ -79,36 +79,6 @@ val from_fun : ?eq:('id -> 'id -> bool) -> ?hash:('id -> int) ->
|
||||||
('id -> ('v * ('e * 'id) list) option) -> ('id, 'v, 'e) t
|
('id -> ('v * ('e * 'id) list) option) -> ('id, 'v, 'e) t
|
||||||
(** Convenient semi-lazy implementation of graphs *)
|
(** Convenient semi-lazy implementation of graphs *)
|
||||||
|
|
||||||
(** {2 Polymorphic utils} *)
|
|
||||||
|
|
||||||
(** A set of vertices *)
|
|
||||||
type 'id set =
|
|
||||||
<
|
|
||||||
mem : 'id -> bool;
|
|
||||||
add : 'id -> unit;
|
|
||||||
remove : 'id -> unit;
|
|
||||||
iter : ('id -> unit) -> unit;
|
|
||||||
>
|
|
||||||
|
|
||||||
val mk_hset : ?eq:('id -> 'id -> bool) -> hash:('id -> int) -> 'id set
|
|
||||||
(** Make a set based on hashtables *)
|
|
||||||
|
|
||||||
val mk_tset : cmp:('id -> 'id -> int) -> 'id set
|
|
||||||
(** Make a set based on balanced trees *)
|
|
||||||
|
|
||||||
type ('id,'a) map =
|
|
||||||
<
|
|
||||||
mem : 'id -> bool;
|
|
||||||
get : 'id -> 'a; (* or Not_found *)
|
|
||||||
add : 'id -> 'a -> unit;
|
|
||||||
remove : 'id -> unit;
|
|
||||||
iter : ('id -> 'a -> unit) -> unit;
|
|
||||||
>
|
|
||||||
|
|
||||||
val mk_hmap : ?eq:('id -> 'id -> bool) -> hash:('id -> int) -> ('id,'a) map
|
|
||||||
|
|
||||||
val mk_tmap : cmp:('id -> 'id -> int) -> ('id,'a) map
|
|
||||||
|
|
||||||
(** {2 Mutable concrete implementation} *)
|
(** {2 Mutable concrete implementation} *)
|
||||||
|
|
||||||
type ('id, 'v, 'e) graph = ('id, 'v, 'e) t (* alias *)
|
type ('id, 'v, 'e) graph = ('id, 'v, 'e) t (* alias *)
|
||||||
|
|
@ -142,25 +112,21 @@ module Full : sig
|
||||||
| EdgeBackward (* toward the current trail *)
|
| EdgeBackward (* toward the current trail *)
|
||||||
| EdgeTransverse (* toward a totally explored part of the graph *)
|
| EdgeTransverse (* toward a totally explored part of the graph *)
|
||||||
|
|
||||||
val bfs_full : ?id:int -> ?explored:(unit -> 'id set) ->
|
val bfs_full : ('id, 'v, 'e) t -> 'id Gen.t ->
|
||||||
('id, 'v, 'e) t -> 'id Gen.t ->
|
|
||||||
('id, 'v, 'e) traverse_event Gen.t
|
('id, 'v, 'e) traverse_event Gen.t
|
||||||
(** Lazy traversal in breadth first from a finite set of vertices *)
|
(** Lazy traversal in breadth first from a finite set of vertices *)
|
||||||
|
|
||||||
val dfs_full : ?id:int -> ?explored:(unit -> 'id set) ->
|
val dfs_full : ('id, 'v, 'e) t -> 'id Gen.t ->
|
||||||
('id, 'v, 'e) t -> 'id Gen.t ->
|
|
||||||
('id, 'v, 'e) traverse_event Gen.t
|
('id, 'v, 'e) traverse_event Gen.t
|
||||||
(** Lazy traversal in depth first from a finite set of vertices *)
|
(** Lazy traversal in depth first from a finite set of vertices *)
|
||||||
end
|
end
|
||||||
|
|
||||||
(** The traversal functions assign a unique ID to every traversed node *)
|
(** The traversal functions assign a unique ID to every traversed node *)
|
||||||
|
|
||||||
val bfs : ?id:int -> ?explored:(unit -> 'id set) ->
|
val bfs : ('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
|
||||||
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
|
|
||||||
(** Lazy traversal in breadth first *)
|
(** Lazy traversal in breadth first *)
|
||||||
|
|
||||||
val dfs : ?id:int -> ?explored:(unit -> 'id set) ->
|
val dfs : ('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
|
||||||
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
|
|
||||||
(** Lazy traversal in depth first *)
|
(** Lazy traversal in depth first *)
|
||||||
|
|
||||||
val enum : ('id, 'v, 'e) t -> 'id -> ('id * 'v) Gen.t * ('id * 'e * 'id) Gen.t
|
val enum : ('id, 'v, 'e) t -> 'id -> ('id * 'v) Gen.t * ('id * 'e * 'id) Gen.t
|
||||||
|
|
@ -169,12 +135,13 @@ val enum : ('id, 'v, 'e) t -> 'id -> ('id * 'v) Gen.t * ('id * 'e * 'id) Gen.t
|
||||||
val depth : ('id, _, 'e) t -> 'id -> ('id, int, 'e) t
|
val depth : ('id, _, 'e) t -> 'id -> ('id, int, 'e) t
|
||||||
(** Map vertices to their depth, ie their distance from the initial point *)
|
(** Map vertices to their depth, ie their distance from the initial point *)
|
||||||
|
|
||||||
val min_path : ?distance:('id -> 'e -> 'id -> int) ->
|
val disjktra : ('id, 'v, 'e) t ->
|
||||||
?explored:(unit -> ('id, int * ('id,'e) path) map) ->
|
?distance:('id -> 'e -> 'id -> int) ->
|
||||||
('id, 'v, 'e) t -> 'id -> 'id ->
|
'id -> 'id ->
|
||||||
int * ('id, 'e) path
|
int * ('id, 'e) path
|
||||||
(** Minimal path from the given Graph from the first vertex to
|
(** Shortest path from the first node to the second one, according
|
||||||
the second. It returns both the distance and the path *)
|
to the given (positive!) distance function. The path is reversed,
|
||||||
|
ie, from the destination to the source. The int is the distance. *)
|
||||||
|
|
||||||
(** {2 Lazy transformations} *)
|
(** {2 Lazy transformations} *)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue