123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)moduletypeG=sigtypetmoduleV:Sig.COMPARABLEvaliter_vertex:(V.t->unit)->t->unitvaliter_succ:(V.t->unit)->t->V.t->unitendmoduleMake(G:G)=structmoduleH=Hashtbl.Make(G.V)(* iterative code using a stack (variable [cont] below) *)typeaction=|FinishofG.V.t*int|VisitofG.V.t*G.V.t|TestofG.V.t*G.V.tletsccg=letroot=H.create997inlethashcomp=H.create997inletstack=ref[]inletnumdfs=ref0inletnumcomp=ref0inletrecpopx=function|((y:int),w)::lwheny>x->H.addhashcompw!numcomp;popxl|l->linletcont=ref[]inletvisitv=ifnot(H.memrootv)thenbeginletn=incrnumdfs;!numdfsinH.addrootvn;cont:=Finish(v,n)::!cont;G.iter_succ(funw->cont:=Visit(v,w)::Test(v,w)::!cont)gv;endinletrecfinish()=match!contwith|[]->()|action::tail->cont:=tail;beginmatchactionwith|Finish(v,n)->ifH.findrootv=nthenbeginH.addhashcompv!numcomp;lets=popn!stackinstack:=s;incrnumcompendelsestack:=(n,v)::!stack;|Visit(_,w)->visitw|Test(v,w)->ifnot(H.memhashcompw)thenH.replacerootv(min(H.findrootv)(H.findrootw))end;finish()inletvisit_and_finishv=visitv;finish()inG.iter_vertexvisit_and_finishg;!numcomp,(funv->H.findhashcompv)letscc_arrayg=letn,f=sccginlett=Array.maken[]inG.iter_vertex(funv->leti=fvint.(i)<-v::t.(i))g;tletscc_listg=leta=scc_arrayginArray.fold_right(funlacc->l::acc)a[]end(** Connectivity in strongly connected directed graphs *)moduleConnectivity(GB:Builder.S)=structmoduleMOper=Oper.Make(GB)moduleChoose=Oper.Choose(GB.G)moduleDom=Dominator.Make(GB.G)moduleS=Dom.Sletsstrong_articulation_pointsg=lets=Choose.choose_vertexginletmoduleSCC=Make(structincludeGB.Gletiter_vertexf=GB.G.iter_vertex(funv->ifnot(V.equalsv)thenfv)letiter_succf=GB.G.iter_succ(funv->ifnot(V.equalsv)thenfv)end)inlets_is_sap=fst(SCC.sccg)>1inletdt_s=Dom.(idom_to_dom_treeg(compute_idomgs))inletd_s=Dom.dom_tree_to_snontrivial_domsdt_sinletg_r=MOper.mirrorginletdtr_s=Dom.(idom_to_dom_treeg_r(compute_idomg_rs))inletdr_s=Dom.dom_tree_to_snontrivial_domsdtr_sinletd=Dom.S.uniond_sdr_sinifs_is_sapthenDom.S.addsdelsedletstrong_articulation_pointsg=S.elements(sstrong_articulation_pointsg)endmoduleBiConnectivity(G:Sig.G)=structmoduleChoose=Oper.Choose(G)moduleDom=Dominator.Make(G)moduleRDom=Dominator.Make(structtypet=G.tmoduleV=G.Vletpred=G.succletsucc=G.predletfold_vertex=G.fold_vertexletiter_vertex=G.iter_vertexletiter_succ=G.iter_predletnb_vertex=G.nb_vertexend)moduleS=Dom.Sletsstrong_articulation_pointsg=lets=Choose.choose_vertexginletmoduleSCC=Make(structincludeGletiter_vertexf=G.iter_vertex(funv->ifnot(V.equalsv)thenfv)letiter_succf=G.iter_succ(funv->ifnot(V.equalsv)thenfv)end)inlets_is_sap=fst(SCC.sccg)>1inletdt_s=Dom.(idom_to_dom_treeg(compute_idomgs))inletd_s=Dom.dom_tree_to_snontrivial_domsdt_sinletdtr_s=RDom.(idom_to_dom_treeg(compute_idomgs))inletdr_s=Dom.dom_tree_to_snontrivial_domsdtr_sinletd=Dom.S.uniond_sdr_sinifs_is_sapthenDom.S.addsdelsedletstrong_articulation_pointsg=S.elements(sstrong_articulation_pointsg)end(** Connected components (for undirected graphs) *)moduletypeU=sigtypetmoduleV:Sig.COMPARABLEvaliter_vertex:(V.t->unit)->t->unitvaliter_edges:(V.t->V.t->unit)->t->unitendmoduleUndirected(G:U)=structmoduleUF=Unionfind.Make(G.V)moduleH=Hashtbl.Make(G.V)letcomponentsg=letvertices=ref[]inG.iter_vertex(funv->vertices:=v::!vertices)g;letuf=UF.init!verticesinletvisituv=UF.unionuvufinG.iter_edgesvisitg;letcount=ref0inletcomp=H.create5003inletvisitv=letv=UF.findvufinifnot(H.memcompv)thenbeginH.addcompv!count;incrcountendinG.iter_vertexvisitg;!count,(funv->H.findcomp(UF.findvuf))letcomponents_arrayg=letn,f=componentsginlett=Array.maken[]inG.iter_vertex(funv->leti=fvint.(i)<-v::t.(i))g;tletcomponents_listg=leta=components_arrayginArray.fold_right(funlacc->l::acc)a[]end