123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678(**************************************************************************)(* *)(* Ocamlgraph: a generic graph library for OCaml *)(* Copyright (C) 2004-2010 *)(* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *)(* *)(* This software is free software; you can redistribute it and/or *)(* modify it under the terms of the GNU Library General Public *)(* License version 2.1, with the special exception on linking *)(* described in file LICENSE. *)(* *)(* This software is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)(* *)(**************************************************************************)openSigopenBlocksmoduletypeS=sig(** Imperative Unlabeled Graphs *)moduleConcrete(V:COMPARABLE):Sig.IwithtypeV.t=V.tandtypeV.label=V.tandtypeE.t=V.t*V.tandtypeE.label=unit(** Abstract Imperative Unlabeled Graphs *)moduleAbstract(V:sigtypetend):Sig.IMwithtypeV.label=V.tandtypeE.label=unitandtypeE.label=unit(** Imperative Labeled Graphs *)moduleConcreteLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT):Sig.IwithtypeV.t=V.tandtypeV.label=V.tandtypeE.t=V.t*E.t*V.tandtypeE.label=E.t(** Abstract Imperative Labeled Graphs *)moduleAbstractLabeled(V:sigtypetend)(E:ORDERED_TYPE_DFT):Sig.IMwithtypeV.label=V.tandtypeE.label=E.tendmoduleI=Make(Make_Hashtbl)type'aabstract_vertex={tag:int;label:'a;mutablemark:int}(* Implement module type [MARK]. *)moduleMake_Mark(X:sigtypegraphtypelabelvaliter_vertex:(labelabstract_vertex->unit)->graph->unitend)=structtypevertex=X.labelabstract_vertextypegraph=X.graphletgetv=v.markletsetvm=v.mark<-mletclearg=X.iter_vertex(funv->setv0)gend(* Vertex for abstract imperative graphs:
comparing to vertex for abstract **persistent** graphs, marks are added. *)moduleAbstractVertex(V:sigtypetend)=structtypelabel=V.ttypet=labelabstract_vertexletcomparexy=Stdlib.comparex.tagy.taglethashx=x.tagletequalxy=x.tag=y.tagletlabelx=x.labelletcreatel=if!cpt_vertex=first_value_for_cpt_vertex-1theninvalid_arg"Too much vertices";incrcpt_vertex;{tag=!cpt_vertex;label=l;mark=0}endmoduleDigraph=structmoduleConcrete(V:COMPARABLE)=structincludeI.Digraph.Concrete(V)letadd_vertexgv=ignore(add_vertexgv)letadd_edgegv1v2=ignore(add_edgegv1v2)letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)letadd_edge_ege=ignore(add_edge_ege)letremove_vertexgv=ifHM.memvgthenbeginignore(HM.removevg);HM.iter(funks->ignore(HM.addk(S.removevs)g))gendendmoduleConcreteLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT)=structincludeI.Digraph.ConcreteLabeled(V)(E)letadd_vertexgv=ignore(add_vertexgv)letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)letadd_edge_ege=ignore(add_edge_ege)letadd_edgegv1v2=ignore(add_edgegv1v2)letremove_vertexgv=ifHM.memvgthenbeginignore(HM.removevg);letremovev=S.filter(fun(v2,_)->not(V.equalvv2))inHM.iter(funks->ignore(HM.addk(removevs)g))gendendmoduleConcreteBidirectional(V:COMPARABLE)=structincludeI.Digraph.ConcreteBidirectional(V)letadd_vertexgv=ignore(add_vertexgv)letadd_edgegv1v2=ignore(add_edgegv1v2)letadd_edge_eg(v1,v2)=add_edgegv1v2letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)letremove_vertexgv=ifHM.memvgthenbeginiter_pred_e(fune->remove_edge_ege)gv;iter_succ_e(fune->remove_edge_ege)gv;ignore(HM.removevg)endendmoduleConcreteBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT)=structincludeI.Digraph.ConcreteBidirectionalLabeled(V)(E)letadd_vertexgv=ignore(add_vertexgv)letadd_edgegv1v2=ignore(add_edgegv1v2)letadd_edge_eg(v1,l,v2)=ignore(add_edge_eg(v1,l,v2))letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)letremove_vertexgv=ifHM.memvgthenbeginiter_pred_e(fune->remove_edge_ege)gv;iter_succ_e(fune->remove_edge_ege)gv;ignore(HM.removevg)endendmoduleAbstract(V:sigtypetend)=structincludeI.Digraph.Abstract(AbstractVertex(V))letadd_vertexgv=ifnot(HM.memvg.edges)thenbeging.size<-Stdlib.succg.size;ignore(G.unsafe_add_vertexg.edgesv)endletadd_edgegv1v2=add_vertexgv1;add_vertexgv2;ignore(unsafe_add_edgeg.edgesv1v2)letadd_edge_eg(v1,v2)=add_edgegv1v2letremove_vertexgv=ifHM.memvg.edgesthenlete=g.edgesinignore(HM.removeve);HM.iter(funks->ignore(HM.addk(S.removevs)e))e;g.size<-Stdlib.predg.sizemoduleMark=Make_Mark(structtypegraph=ttypelabel=V.labelletiter_vertex=iter_vertexend)letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)endmoduleAbstractLabeled(V:sigtypetend)(Edge:ORDERED_TYPE_DFT)=structincludeI.Digraph.AbstractLabeled(AbstractVertex(V))(Edge)letadd_vertexgv=ifnot(HM.memvg.edges)thenbeging.size<-Stdlib.succg.size;ignore(G.unsafe_add_vertexg.edgesv)endletadd_edge_eg(v1,l,v2)=add_vertexgv1;add_vertexgv2;ignore(unsafe_add_edgeg.edgesv1(v2,l))letadd_edgegv1v2=add_edge_eg(v1,Edge.default,v2)letremove_vertexgv=ifHM.memvg.edgesthenletremoves=S.fold(fun(v2,_ase)s->ifnot(V.equalvv2)thenS.addeselses)sS.emptyinlete=g.edgesinignore(HM.removeve);HM.iter(funks->ignore(HM.addk(removes)e))e;g.size<-Stdlib.predg.sizemoduleMark=Make_Mark(structtypegraph=ttypelabel=V.labelletiter_vertex=iter_vertexend)letremove_edgegv1v2=ignore(remove_edgegv1v2)letremove_edge_ege=ignore(remove_edge_ege)endendmoduleGraph=structmoduleConcrete(V:COMPARABLE)=structmoduleG=structincludeDigraph.Concrete(V)typereturn=unitendincludeBlocks.Graph(G)(* Redefine the [add_edge] and [remove_edge] operations *)letadd_edgegv1v2=ifnot(mem_edgegv1v2)thenbeginG.add_edgegv1v2;assert(G.HM.memv1g&&G.HM.memv2g);ignore(G.unsafe_add_edgegv2v1)endletadd_edge_eg(v1,v2)=add_edgegv1v2letremove_edgegv1v2=G.remove_edgegv1v2;assert(G.HM.memv1g&&G.HM.memv2g);ignore(G.unsafe_remove_edgegv2v1)letremove_edge_eg(v1,v2)=remove_edgegv1v2endmoduleConcreteLabeled(V:COMPARABLE)(Edge:ORDERED_TYPE_DFT)=structmoduleG=structincludeDigraph.ConcreteLabeled(V)(Edge)typereturn=unitendincludeBlocks.Graph(G)(* Redefine the [add_edge] and [remove_edge] operations *)letadd_edge_eg(v1,l,v2ase)=ifnot(mem_edge_ege)thenbeginG.add_edge_ege;assert(G.HM.memv1g&&G.HM.memv2g);ignore(G.unsafe_add_edgegv2(v1,l))endletadd_edgegv1v2=add_edge_eg(v1,Edge.default,v2)letremove_edgegv1v2=G.remove_edgegv1v2;assert(G.HM.memv1g&&G.HM.memv2g);ignore(G.unsafe_remove_edgegv2v1)letremove_edge_eg(v1,l,v2ase)=G.remove_edge_ege;assert(G.HM.memv1g&&G.HM.memv2g);ignore(G.unsafe_remove_edge_eg(v2,l,v1))endmoduleAbstract(V:sigtypetend)=structmoduleG=structincludeDigraph.Abstract(V)typereturn=unitendincludeBlocks.Graph(G)(* Export some definitions of [G] *)moduleMark=G.Mark(* Redefine the [add_edge] and [remove_edge] operations *)letadd_edgegv1v2=G.add_edgegv1v2;assert(G.HM.memv1g.G.edges&&G.HM.memv2g.G.edges);ignore(G.unsafe_add_edgeg.G.edgesv2v1)letadd_edge_eg(v1,v2)=add_edgegv1v2letremove_edgegv1v2=G.remove_edgegv1v2;assert(G.HM.memv1g.G.edges&&G.HM.memv2g.G.edges);ignore(G.unsafe_remove_edgeg.G.edgesv2v1)letremove_edge_eg(v1,v2)=remove_edgegv1v2endmoduleAbstractLabeled(V:sigtypetend)(Edge:ORDERED_TYPE_DFT)=structmoduleG=structincludeDigraph.AbstractLabeled(V)(Edge)typereturn=unitendincludeBlocks.Graph(G)(* Export some definitions of [G] *)moduleMark=G.Mark(* Redefine the [add_edge] and [remove_edge] operations *)letadd_edge_eg(v1,l,v2ase)=G.add_edge_ege;assert(G.HM.memv1g.G.edges&&G.HM.memv2g.G.edges);ignore(G.unsafe_add_edgeg.G.edgesv2(v1,l))letadd_edgegv1v2=add_edge_eg(v1,Edge.default,v2)letremove_edgegv1v2=G.remove_edgegv1v2;assert(G.HM.memv1g.G.edges&&G.HM.memv2g.G.edges);ignore(G.unsafe_remove_edgeg.G.edgesv2v1)letremove_edge_eg(v1,l,v2ase)=ignore(G.remove_edge_ege);assert(G.HM.memv1g.G.edges&&G.HM.memv2g.G.edges);ignore(G.unsafe_remove_edge_eg.G.edges(v2,l,v1))endendmoduleMatrix=structmoduletypeS=sigincludeSig.IwithtypeV.t=intandtypeV.label=intandtypeE.t=int*intvalmake:int->tendmoduleDigraph=structmoduleV=structtypet=inttypelabel=intletcompare:t->t->int=Stdlib.comparelethash=Hashtbl.hashletequal=(==)letcreatei=iletlabeli=iendmoduleE=structtypet=V.t*V.ttypevertex=V.tletcompare:t->t->int=Stdlib.comparetypelabel=unitletcreatev1_v2=(v1,v2)letsrc=fstletdst=sndletlabel_=()endtypet=Bitv.tarraytypevertex=V.ttypeedge=E.tletcreate?size:_()=failwith"[ocamlgraph] do not use Matrix.create; please use Matrix.make instead"letmaken=ifn<0theninvalid_arg"[ocamlgraph] Matrix.make";Array.initn(fun_->Bitv.createnfalse)letis_directed=trueletnb_vertex=Array.lengthletis_emptyg=nb_vertexg=0letnb_edges=Array.fold_left(Bitv.fold_left(funnb->ifbthenn+1elsen))0letmem_vertexgv=0<=v&&v<nb_vertexgletmem_edgegij=Bitv.getg.(i)jletmem_edge_eg(i,j)=Bitv.getg.(i)jletfind_edgegij=ifmem_edgegijtheni,jelseraiseNot_foundletfind_all_edgesgij=try[find_edgegij]withNot_found->[](* constructors *)letadd_edgegij=Bitv.setg.(i)jtrueletadd_edge_eg(i,j)=Bitv.setg.(i)jtrueletremove_edgegij=Bitv.setg.(i)jfalseletremove_edge_eg(i,j)=Bitv.setg.(i)jfalseletunsafe_add_edgegij=Bitv.unsafe_set(Array.unsafe_getgi)jtrueletunsafe_remove_edgegij=Bitv.unsafe_set(Array.unsafe_getgi)jfalseletremove_vertex__=()letadd_vertex__=()letclearg=Array.iter(funb->Bitv.iteri(funj_->Bitv.setbjfalse)b)gletcopyg=Array.init(nb_vertexg)(funi->Bitv.copyg.(i))(* iter/fold on all vertices/edges of a graph *)letiter_vertexfg=fori=0tonb_vertexg-1dofidoneletiter_edgesfg=fori=0tonb_vertexg-1doBitv.iteri(funjb->ifbthenfij)g.(i)doneletfold_vertexfga=letn=nb_vertexginletrecfoldia=ifi=nthenaelsefold(i+1)(fia)infold0aletfold_edgesfga=fold_vertex(funia->Bitv.foldi_right(funjba->ifbthenfijaelsea)g.(i)a)ga(* successors and predecessors of a vertex *)letsuccgi=Bitv.foldi_left(funljb->ifbthenj::lelsel)[]g.(i)letpredgi=fold_vertex(funja->ifBitv.unsafe_getg.(j)ithenj::aelsea)g[](* iter/fold on all successor/predecessor of a vertex. *)letiter_succfgi=letsi=g.(i)inforj=0tonb_vertexg-1doifBitv.unsafe_getsijthenfjdone(* optimization w.r.t.
[Bitv.iteri (fun j b -> if b then f j) g.(i)]
*)letiter_predfgi=forj=0tonb_vertexg-1doifBitv.unsafe_getg.(j)ithenfjdoneletfold_succfgia=Bitv.foldi_right(funjba->ifbthenfjaelsea)g.(i)aletfold_predfgia=fold_vertex(funja->ifBitv.unsafe_getg.(j)ithenfjaelsea)ga(* degree *)letout_degreegi=fold_succ(fun_n->n+1)gi0letin_degreegi=fold_pred(fun_n->n+1)gi0(* map iterator on vertex *)letmap_vertexfg=letn=nb_vertexginletfi=(* ensures f is applied exactly once for each vertex *)letfi=fiiniffi<0||fi>=ntheninvalid_arg"[ocamlgraph] map_vertex";fiinletv=Array.initnfinletg'=makeniniter_edges(funij->Bitv.unsafe_setg'.(v.(i))v.(j)true)g;g'(* labeled edges going from/to a vertex *)(* successors and predecessors of a vertex *)letsucc_egi=Bitv.foldi_left(funljb->ifbthen(i,j)::lelsel)[]g.(i)letpred_egi=fold_vertex(funja->ifBitv.unsafe_getg.(j)ithen(j,i)::aelsea)g[](* iter/fold on all labeled edges of a graph *)letiter_edges_efg=fori=0tonb_vertexg-1doBitv.iteri(funjb->ifbthenf(i,j))g.(i)doneletfold_edges_efga=fold_vertex(funia->Bitv.foldi_right(funjba->ifbthenf(i,j)aelsea)g.(i)a)ga(* iter/fold on all edges going from/to a vertex *)letiter_succ_efgi=letsi=g.(i)inforj=0tonb_vertexg-1doifBitv.unsafe_getsijthenf(i,j)doneletiter_pred_efgi=forj=0tonb_vertexg-1doifBitv.unsafe_getg.(j)ithenf(j,i)doneletfold_succ_efgia=Bitv.foldi_right(funjba->ifbthenf(i,j)aelsea)g.(i)aletfold_pred_efgia=fold_vertex(funja->ifBitv.unsafe_getg.(j)ithenf(j,i)aelsea)gaendmoduleGraph=structmoduleG=structincludeDigraphtypereturn=unitendincludeBlocks.Graph(G)(* Export some definitions of [G] *)letmake=G.make(* Redefine the [add_edge] and [remove_edge] operations *)letadd_edgegv1v2=G.add_edgegv1v2;ignore(G.unsafe_add_edgegv2v1)letadd_edge_eg(v1,v2)=add_edgegv1v2letremove_edgegv1v2=G.remove_edgegv1v2;ignore(G.unsafe_remove_edgegv2v1)letremove_edge_eg(v1,v2)=remove_edgegv1v2endend(* Faster implementations when vertices are not shared between graphs. *)(****
module UV = struct
let cpt_vertex = ref min_int
type ('label, 'succ) vertex = {
tag : int;
label : 'label;
mutable mark : int;
mutable succ : 'succ;
}
module Digraph = struct
module Abstract(L: ANY_TYPE) :
Sig.IM with type V.label = L.t and type E.label = unit
=
struct
module rec V :
VERTEX with type label = L.t and type t = (L.t, S.t) vertex =
struct
type label = L.t
type t = (L.t, S.t) vertex
let compare x y = compare x.tag y.tag
let hash x = Hashtbl.hash x.tag
let equal x y = x.tag = y.tag
let label x = x.label
let create l =
assert (!cpt_vertex < max_int);
incr cpt_vertex;
{ tag = !cpt_vertex; label = l; mark = 0; succ = S.empty }
end
and S : Set.S with type elt = V.t = Set.Make(V)
type vertex = V.t
module E = struct
type t = V.t * V.t
type vertex = V.t
let compare = Stdlib.compare
type label = unit
let create v1 _ v2 = (v1, v2)
let src = fst
let dst = snd
let label _ = ()
end
type edge = E.t
type t = {
mutable vertices : S.t;
}
let create ?size () = { vertices = S.empty }
let is_directed = true
let is_empty g = S.is_empty g.vertices
let nb_vertex g = S.cardinal g.vertices
let out_degree _ v = S.cardinal v.succ
let clear g = g.vertices <- S.empty
let add_vertex g v = g.vertices <- S.add v g.vertices
let mem_vertex g v = S.mem v g.vertices
let iter_vertex f g = S.iter f g.vertices
let fold_vertex f g = S.fold f g.vertices
let succ _ v = S.elements v.succ
let succ_e _ v = List.map (fun w -> (v, w)) (S.elements v.succ)
let iter_succ f _ v = S.iter f v.succ
let iter_succ_e f _ v = S.iter (fun w -> f (v, w)) v.succ
let fold_succ f _ v acc = S.fold f v.succ acc
let fold_succ_e f _ v acc = S.fold (fun w acc -> f (v, w) acc) v.succ acc
let add_edge _ v1 v2 = v1.succ <- S.add v2 v1.succ
let add_edge_e g (v1, v2) = add_edge g v1 v2
let mem_edge _ v1 v2 = S.mem v2 v1.succ
let mem_edge_e g (v1, v2) = mem_edge g v1 v2
let remove_edge _ v1 v2 = v1.succ <- S.remove v2 v1.succ
let remove_edge_e g (v1, v2) = remove_edge g v1 v2
let nb_edges g = fold_vertex (fun v n -> n + S.cardinal v.succ) g 0
let find_edge g i j = if mem_edge g i j then i, j else raise Not_found
let find_all_edges g i j = try [ find_edge g i j ] with Not_found -> []
module Mark = struct
type graph = t
type vertex = V.t
let clear g = S.iter (fun v -> v.mark <- 0) g.vertices
let get v = v.mark
let set v m = v.mark <- m
end
end
module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) :
Sig.IM with type V.label = V.t and type E.label = E.t
=
AbstractLabeled
(V)(struct type t = unit let compare _ _ = 0 let default = () end)
end
(**
module Graph = struct
module Abstract(V: ANY_TYPE) :
Sig.IM with type V.label = V.t and type E.label = unit
module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) :
Sig.IM with type V.label = V.t and type E.label = E.t
end
**)
end
****)(*
Local Variables:
compile-command: "make -C .."
End:
*)