123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)(** Common implementation to persistent and imperative graphs. *)openSigopenUtilletfirst_value_for_cpt_vertex=0letcpt_vertex=reffirst_value_for_cpt_vertex(* global counter for abstract vertex *)(* [max_cpt t1 t2] returns the maximum of [t1] and [t2] wrt the total ordering
induced by tags creation. This ordering is defined as follow:
forall tags t1 t2,
t1 <= t2 iff
t1 is before t2 in the finite sequence
[0; 1; ..; max_int; min_int; min_int-1; -1] *)letmax_cptc1c2=max(c1+min_int)(c2+min_int)-min_int(* This function must be called after the unserialisation of any abstract
vertex if you want to create new vertices. *)letafter_unserializationserialized_cpt_vertex=cpt_vertex:=max_cptserialized_cpt_vertex!cpt_vertex(* ************************************************************************* *)(** {2 Association table builder} *)(* ************************************************************************* *)(** Common signature to an imperative/persistent association table *)moduletypeHM=sigtype'areturntype'attypekeyvalcreate:?size:int->unit->'atvalcreate_from:'at->'atvalempty:'areturnvalclear:'at->unitvalis_empty:'at->boolvaladd:key->'a->'at->'atvalremove:key->'at->'atvalmem:key->'at->boolvalfind:key->'at->'avalfind_and_raise:key->'at->string->'a(** [find_and_raise k t s] is equivalent to [find k t] but
raises [Invalid_argument s] when [find k t] raises [Not_found] *)valiter:(key->'a->unit)->'at->unitvalmap:(key->'a->key*'a)->'at->'atvalfold:(key->'a->'b->'b)->'at->'b->'bvalcopy:'at->'atendmoduletypeTBL_BUILDER=functor(X:COMPARABLE)->HMwithtypekey=X.t(** [HM] implementation using hashtbl. *)moduleMake_Hashtbl(X:COMPARABLE)=structincludeHashtbl.Make(X)type'areturn=unitletempty=()(* never call and not visible for the user thank's to signature
constraints *)letcreate_fromh=create(lengthh)letcreate?(size=97)()=createsizeletis_emptyh=(lengthh=0)letfind_and_raisekhs=tryfindhkwithNot_found->invalid_argsletmapfh=leth'=create_fromhiniter(funkv->letk,v=fkvinaddh'kv)h;h'letaddkvh=replacehkv;hletremovekh=removehk;hletmemkh=memhkletfindkh=findhkend(** [HM] implementation using map *)moduleMake_Map(X:COMPARABLE)=structincludeMap.Make(X)type'areturn='atletcreate?size:_()=assertfalse(* never call and not visible for the user thank's to
signature constraints *)letcreate_from_=emptyletcopym=mletmapfm=fold(funkvm->letk,v=fkvinaddkvm)memptyletfind_and_raisekhs=tryfindkhwithNot_found->invalid_argsletclear_=assertfalse(* never call and not visible for the user thank's to
signature constraints *)end(* ************************************************************************* *)(** {2 Blocks builder} *)(* ************************************************************************* *)(** Common implementation to all (directed) graph implementations. *)moduleMinimal(S:Set.S)(HM:HM)=structtypevertex=HM.keyletis_directed=trueletempty=HM.emptyletcreate=HM.createletis_empty=HM.is_emptyletcopy=HM.copyletclear=HM.clearletnb_vertexg=HM.fold(fun__->succ)g0letnb_edgesg=HM.fold(fun_sn->n+S.cardinals)g0letout_degreegv=S.cardinal(tryHM.findvgwithNot_found->invalid_arg"[ocamlgraph] out_degree")letmem_vertexgv=HM.memvgletunsafe_add_vertexgv=HM.addvS.emptygletunsafe_add_edgegv1v2=HM.addv1(S.addv2(HM.findv1g))gletadd_vertexgv=ifHM.memvgthengelseunsafe_add_vertexgvletiter_vertexf=HM.iter(funv_->fv)letfold_vertexf=HM.fold(funv_->fv)end(** All the predecessor operations from the iterators on the edges *)modulePred(S:sigmodulePV:COMPARABLEmodulePE:EDGEwithtypevertex=PV.ttypetvalmem_vertex:PV.t->t->boolvaliter_edges:(PV.t->PV.t->unit)->t->unitvalfold_edges:(PV.t->PV.t->'a->'a)->t->'a->'avaliter_edges_e:(PE.t->unit)->t->unitvalfold_edges_e:(PE.t->'a->'a)->t->'a->'aend)=structopenSletiter_predfgv=ifnot(mem_vertexvg)theninvalid_arg"[ocamlgraph] iter_pred";iter_edges(funv1v2->ifPV.equalvv2thenfv1)gletfold_predfgv=ifnot(mem_vertexvg)theninvalid_arg"[ocamlgraph] fold_pred";fold_edges(funv1v2a->ifPV.equalvv2thenfv1aelsea)gletpredgv=fold_pred(funvl->v::l)gv[]letin_degreegv=ifnot(mem_vertexvg)theninvalid_arg"[ocamlgraph] in_degree";fold_pred(fun_n->n+1)gv0letiter_pred_efgv=ifnot(mem_vertexvg)theninvalid_arg"[ocamlgraph] iter_pred_e";iter_edges_e(fune->ifPV.equalv(PE.dste)thenfe)gletfold_pred_efgv=ifnot(mem_vertexvg)theninvalid_arg"[ocamlgraph] fold_pred_e";fold_edges_e(funea->ifPV.equalv(PE.dste)thenfeaelsea)gletpred_egv=fold_pred_e(funvl->v::l)gv[]end(** Common implementation to all the unlabeled (directed) graphs. *)moduleUnlabeled(V:COMPARABLE)(HM:HMwithtypekey=V.t)=structmoduleS=Set.Make(V)moduleE=structtypevertex=V.tincludeOTProduct(V)(V)letsrc=fstletdst=sndtypelabel=unitletlabel_=()letcreatev1()v2=v1,v2endtypeedge=E.tletmem_edgegv1v2=tryS.memv2(HM.findv1g)withNot_found->falseletmem_edge_eg(v1,v2)=mem_edgegv1v2letfind_edgegv1v2=ifmem_edgegv1v2thenv1,v2elseraiseNot_foundletfind_all_edgesgv1v2=try[find_edgegv1v2]withNot_found->[]letunsafe_remove_edgegv1v2=HM.addv1(S.removev2(HM.findv1g))gletunsafe_remove_edge_eg(v1,v2)=unsafe_remove_edgegv1v2letremove_edgegv1v2=ifnot(HM.memv2g)theninvalid_arg"[ocamlgraph] remove_edge";HM.addv1(S.removev2(HM.find_and_raisev1g"[ocamlgraph] remove_edge"))gletremove_edge_eg(v1,v2)=remove_edgegv1v2letiter_succfgv=S.iterf(HM.find_and_raisevg"[ocamlgraph] iter_succ")letfold_succfgv=S.foldf(HM.find_and_raisevg"[ocamlgraph] fold_succ")letiter_succ_efgv=iter_succ(funv2->f(v,v2))gvletfold_succ_efgv=fold_succ(funv2->f(v,v2))gvletsuccgv=S.elements(HM.find_and_raisevg"[ocamlgraph] succ")letsucc_egv=fold_succ_e(funel->e::l)gv[]letmap_vertexfg=letmoduleMV=Util.Memo(V)inletf=MV.memofinHM.map(funvs->fv,S.fold(funvs->S.add(fv)s)sS.empty)gmoduleI=structtypet=S.tHM.tmodulePV=VmodulePE=Eletiter_edgesf=HM.iter(funv->S.iter(fv))letfold_edgesf=HM.fold(funv->S.fold(fv))letiter_edges_ef=iter_edges(funv1v2->f(v1,v2))letfold_edges_ef=fold_edges(funv1v2a->f(v1,v2)a)endincludeIincludePred(structincludeIletmem_vertex=HM.memend)end(** Common implementation to all the labeled (directed) graphs. *)moduleLabeled(V:COMPARABLE)(E:ORDERED_TYPE)(HM:HMwithtypekey=V.t)=structmoduleVE=OTProduct(V)(E)moduleS=Set.Make(VE)moduleE=structtypevertex=V.ttypelabel=E.ttypet=vertex*label*vertexletsrc(v,_,_)=vletdst(_,_,v)=vletlabel(_,l,_)=lletcreatev1lv2=v1,l,v2moduleC=OTProduct(V)(VE)letcompare(x1,x2,x3)(y1,y2,y3)=C.compare(x1,(x3,x2))(y1,(y3,y2))endtypeedge=E.tletmem_edgegv1v2=tryS.exists(fun(v2',_)->V.equalv2v2')(HM.findv1g)withNot_found->falseletmem_edge_eg(v1,l,v2)=tryletve=v2,linS.exists(funve'->VE.compareveve'=0)(HM.findv1g)withNot_found->falseexceptionFoundofedgeletfind_edgegv1v2=tryS.iter(fun(v2',l)->ifV.equalv2v2'thenraise(Found(v1,l,v2')))(HM.findv1g);raiseNot_foundwithFounde->eletfind_all_edgesgv1v2=tryS.fold(fun(v2',l)acc->ifV.equalv2v2'then(v1,l,v2')::accelseacc)(HM.findv1g)[]withNot_found->[]letunsafe_remove_edgegv1v2=HM.addv1(S.filter(fun(v2',_)->not(V.equalv2v2'))(HM.findv1g))gletunsafe_remove_edge_eg(v1,l,v2)=HM.addv1(S.remove(v2,l)(HM.findv1g))gletremove_edgegv1v2=ifnot(HM.memv2g)theninvalid_arg"[ocamlgraph] remove_edge";HM.addv1(S.filter(fun(v2',_)->not(V.equalv2v2'))(HM.find_and_raisev1g"[ocamlgraph] remove_edge"))gletremove_edge_eg(v1,l,v2)=ifnot(HM.memv2g)theninvalid_arg"[ocamlgraph] remove_edge_e";HM.addv1(S.remove(v2,l)(HM.find_and_raisev1g"[ocamlgraph] remove_edge_e"))gletiter_succfgv=S.iter(fun(w,_)->fw)(HM.find_and_raisevg"[ocamlgraph] iter_succ")letfold_succfgv=S.fold(fun(w,_)->fw)(HM.find_and_raisevg"[ocamlgraph] fold_succ")letiter_succ_efgv=S.iter(fun(w,l)->f(v,l,w))(HM.find_and_raisevg"[ocamlgraph] iter_succ_e")letfold_succ_efgv=S.fold(fun(w,l)->f(v,l,w))(HM.find_and_raisevg"[ocamlgraph] fold_succ_e")letsuccgv=fold_succ(funwl->w::l)gv[]letsucc_egv=fold_succ_e(funel->e::l)gv[]letmap_vertexfg=letmoduleMV=Util.Memo(V)inletf=MV.memofinHM.map(funvs->fv,S.fold(fun(v,l)s->S.add(fv,l)s)sS.empty)gmoduleI=structtypet=S.tHM.tmodulePV=VmodulePE=Eletiter_edgesf=HM.iter(funv->S.iter(fun(w,_)->fvw))letfold_edgesf=HM.fold(funv->S.fold(fun(w,_)->fvw))letiter_edges_ef=HM.iter(funv->S.iter(fun(w,l)->f(v,l,w)))letfold_edges_ef=HM.fold(funv->S.fold(fun(w,l)->f(v,l,w)))endincludeIincludePred(structincludeIletmem_vertex=HM.memend)end(** The vertex module and the vertex table for the concrete graphs. *)moduleConcreteVertex(F:TBL_BUILDER)(V:COMPARABLE)=structmoduleV=structincludeVtypelabel=tletlabelv=vletcreatev=vendmoduleHM=F(V)endmoduleMake_Abstract(G:sigmoduleHM:HMmoduleS:Set.SincludeGwithtypet=S.tHM.tandtypeV.t=HM.keyvalremove_edge:t->vertex->vertex->tvalremove_edge_e:t->edge->t(* val unsafe_add_vertex: t -> vertex -> t *)(* Was unused *)valunsafe_add_edge:t->vertex->S.elt->tvalunsafe_remove_edge:t->vertex->vertex->tvalunsafe_remove_edge_e:t->edge->tvalcreate:?size:int->unit->tvalclear:t->unitend)=structmoduleI=structtypet={edges:G.t;mutablesize:int}(* BE CAREFUL: [size] is only mutable in the imperative version. As
there is no extensible records in current ocaml version, and for
genericity purpose, [size] is mutable in both imperative and
persistent implementations.
Do not modify size in the persistent implementation! *)typevertex=G.vertextypeedge=G.edgemodulePV=G.VmodulePE=G.Eletiter_edgesfg=G.iter_edgesfg.edgesletfold_edgesfg=G.fold_edgesfg.edgesletiter_edges_efg=G.iter_edges_efg.edgesletfold_edges_efg=G.fold_edges_efg.edgesletmem_vertexvg=G.mem_vertexg.edgesvletcreate?size()={edges=G.create?size();size=0}letclearg=G.clearg.edges;g.size<-0endincludeIincludePred(I)(* optimisations *)letis_emptyg=g.size=0letnb_vertexg=g.size(* redefinitions *)moduleV=G.VmoduleE=G.EmoduleHM=G.HMmoduleS=G.Sletunsafe_add_edge=G.unsafe_add_edgeletunsafe_remove_edge=G.unsafe_remove_edgeletunsafe_remove_edge_e=G.unsafe_remove_edge_eletis_directed=G.is_directedletremove_edgeg=G.remove_edgeg.edgesletremove_edge_eg=G.remove_edge_eg.edgesletout_degreeg=G.out_degreeg.edgesletin_degreeg=G.in_degreeg.edgesletnb_edgesg=G.nb_edgesg.edgesletsuccg=G.succg.edgesletmem_vertexg=G.mem_vertexg.edgesletmem_edgeg=G.mem_edgeg.edgesletmem_edge_eg=G.mem_edge_eg.edgesletfind_edgeg=G.find_edgeg.edgesletfind_all_edgesg=G.find_all_edgesg.edgesletiter_vertexfg=G.iter_vertexfg.edgesletfold_vertexfg=G.fold_vertexfg.edgesletiter_succfg=G.iter_succfg.edgesletfold_succfg=G.fold_succfg.edgesletsucc_eg=G.succ_eg.edgesletiter_succ_efg=G.iter_succ_efg.edgesletfold_succ_efg=G.fold_succ_efg.edgesletmap_vertexfg={gwithedges=G.map_vertexfg.edges}(* reimplementation *)letcopyg=leth=HM.create()inletvertexv=tryHM.findvhwithNot_found->letv'=V.create(V.labelv)inleth'=HM.addvv'hinassert(h==h');v'inmap_vertexvertexgend(** Support for explicitly maintaining edge set of
predecessors. Crucial for algorithms that do a lot of backwards
traversal. *)moduleBidirectionalMinimal(S:Set.S)(HM:HM)=structtypevertex=HM.keyletis_directed=trueletempty=HM.emptyletcreate=HM.createletclear=HM.clearletis_empty=HM.is_emptyletcopy=HM.copyletnb_vertexg=HM.fold(fun__->succ)g0letnb_edgesg=HM.fold(fun_(_,s)n->n+S.cardinals)g0letout_degreegv=S.cardinal(snd(tryHM.findvgwithNot_found->invalid_arg"[ocamlgraph] out_degree"))letmem_vertexgv=HM.memvgletunsafe_add_vertexgv=HM.addv(S.empty,S.empty)gletadd_vertexgv=ifHM.memvgthengelseunsafe_add_vertexgvletiter_vertexf=HM.iter(funv_->fv)letfold_vertexf=HM.fold(funv_->fv)endmoduleBidirectionalUnlabeled(V:COMPARABLE)(HM:HMwithtypekey=V.t)=structmoduleS=Set.Make(V)moduleE=structtypevertex=V.tincludeOTProduct(V)(V)letsrc=fstletdst=sndtypelabel=unitletlabel_=()letcreatev1()v2=v1,v2endtypeedge=E.tletmem_edgegv1v2=tryS.memv2(snd(HM.findv1g))withNot_found->falseletmem_edge_eg(v1,v2)=mem_edgegv1v2letfind_edgegv1v2=ifmem_edgegv1v2thenv1,v2elseraiseNot_foundletfind_all_edgesgv1v2=try[find_edgegv1v2]withNot_found->[]letunsafe_remove_edgegv1v2=letin_set,out_set=HM.findv1ginletg=HM.addv1(in_set,S.removev2out_set)ginletin_set,out_set=HM.findv2ginHM.addv2(S.removev1in_set,out_set)gletunsafe_remove_edge_eg(v1,v2)=unsafe_remove_edgegv1v2letremove_edgegv1v2=ifnot(HM.memv2g&&HM.memv1g)theninvalid_arg"[ocamlgraph] remove_edge";unsafe_remove_edgegv1v2letremove_edge_eg(v1,v2)=remove_edgegv1v2letiter_succfgv=S.iterf(snd(HM.find_and_raisevg"[ocamlgraph] iter_succ"))letfold_succfgv=S.foldf(snd(HM.find_and_raisevg"[ocamlgraph] fold_succ"))letiter_succ_efgv=iter_succ(funv2->f(v,v2))gvletfold_succ_efgv=fold_succ(funv2->f(v,v2))gvletsuccgv=S.elements(snd(HM.find_and_raisevg"[ocamlgraph] succ"))letsucc_egv=fold_succ_e(funel->e::l)gv[]letmap_vertexfg=letmoduleMV=Util.Memo(V)inletf=MV.memofinHM.map(funv(s1,s2)->fv,(S.fold(funvs->S.add(fv)s)s1S.empty,S.fold(funvs->S.add(fv)s)s2S.empty))gmoduleI=struct(* we keep sets for both incoming and outgoing edges *)typet=(S.t(* incoming *)*S.t(* outgoing *))HM.tmodulePV=VmodulePE=Eletiter_edgesf=HM.iter(funv(_,outset)->S.iter(fv)outset)letfold_edgesf=HM.fold(funv(_,outset)->S.fold(fv)outset)letiter_edges_ef=iter_edges(funv1v2->f(v1,v2))letfold_edges_ef=fold_edges(funv1v2a->f(v1,v2)a)endincludeIletiter_predfgv=S.iterf(fst(HM.find_and_raisevg"[ocamlgraph] iter_pred"))letfold_predfgv=S.foldf(fst(HM.find_and_raisevg"[ocamlgraph] fold_pred"))letpredgv=S.elements(fst(HM.find_and_raisevg"[ocamlgraph] pred"))letin_degreegv=S.cardinal(fst(tryHM.findvgwithNot_found->invalid_arg"[ocamlgraph] in_degree"))letiter_pred_efgv=iter_pred(funv2->f(v2,v))gvletfold_pred_efgv=fold_pred(funv2->f(v2,v))gvletpred_egv=fold_pred_e(funel->e::l)gv[]endmoduleBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE)(HM:HMwithtypekey=V.t)=structmoduleVE=OTProduct(V)(E)moduleS=Set.Make(VE)moduleE=structtypevertex=V.ttypelabel=E.ttypet=vertex*label*vertexletsrc(v,_,_)=vletdst(_,_,v)=vletlabel(_,l,_)=lletcreatev1lv2=v1,l,v2moduleC=OTProduct(V)(VE)letcompare(x1,x2,x3)(y1,y2,y3)=C.compare(x1,(x3,x2))(y1,(y3,y2))endtypeedge=E.tletmem_edgegv1v2=tryS.exists(fun(v2',_)->V.equalv2v2')(snd(HM.findv1g))withNot_found->falseletmem_edge_eg(v1,l,v2)=tryletve=v2,linS.exists(funve'->VE.compareveve'=0)(snd(HM.findv1g))withNot_found->falseexceptionFoundofedgeletfind_edgegv1v2=tryS.iter(fun(v2',l)->ifV.equalv2v2'thenraise(Found(v1,l,v2')))(snd(HM.findv1g));raiseNot_foundwithFounde->eletfind_all_edgesgv1v2=tryS.fold(fun(v2',l)acc->ifV.equalv2v2'then(v1,l,v2')::accelseacc)(snd(HM.findv1g))[]withNot_found->[]letunsafe_remove_edgegv1v2=letin_set,out_set=HM.findv1ginletdelvset=S.filter(fun(v',_)->not(V.equalvv'))setinletg=HM.addv1(in_set,delv2out_set)ginletin_set,out_set=HM.findv2ginHM.addv2(delv1in_set,out_set)gletunsafe_remove_edge_eg(v1,l,v2)=letin_set,out_set=HM.findv1ginletg=HM.addv1(in_set,S.remove(v2,l)out_set)ginletin_set,out_set=HM.findv2ginHM.addv2(S.remove(v1,l)in_set,out_set)gletremove_edgegv1v2=(* if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge";*)letin_set,out_set=HM.find_and_raisev1g"[ocamlgraph] remove_edge"inletdelvset=S.filter(fun(v',_)->not(V.equalvv'))setinletg=HM.addv1(in_set,delv2out_set)ginletin_set,out_set=HM.find_and_raisev2g"[ocamlgraph] remove_edge"inHM.addv2(delv1in_set,out_set)gletremove_edge_eg(v1,l,v2)=(* if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge_e";*)letin_set,out_set=HM.find_and_raisev1g"[ocamlgraph] remove_edge_e"inletg=HM.addv1(in_set,S.remove(v2,l)out_set)ginletin_set,out_set=HM.find_and_raisev2g"[ocamlgraph] remove_edge_e"inHM.addv2(S.remove(v1,l)in_set,out_set)gletiter_succfgv=S.iter(fun(w,_)->fw)(snd(HM.find_and_raisevg"[ocamlgraph] iter_succ"))letfold_succfgv=S.fold(fun(w,_)->fw)(snd(HM.find_and_raisevg"[ocamlgraph] fold_succ"))letiter_succ_efgv=S.iter(fun(w,l)->f(v,l,w))(snd(HM.find_and_raisevg"[ocamlgraph] iter_succ_e"))letfold_succ_efgv=S.fold(fun(w,l)->f(v,l,w))(snd(HM.find_and_raisevg"[ocamlgraph] fold_succ_e"))letsuccgv=fold_succ(funwl->w::l)gv[]letsucc_egv=fold_succ_e(funel->e::l)gv[]letmap_vertexfg=letmoduleMV=Util.Memo(V)inletf=MV.memofinHM.map(funv(s1,s2)->fv,(S.fold(fun(v,l)s->S.add(fv,l)s)s1S.empty,S.fold(fun(v,l)s->S.add(fv,l)s)s2S.empty))gmoduleI=structtypet=(S.t*S.t)HM.tmodulePV=VmodulePE=Eletiter_edgesf=HM.iter(funv(_,outset)->S.iter(fun(w,_)->fvw)outset)letfold_edgesf=HM.fold(funv(_,outset)->S.fold(fun(w,_)->fvw)outset)letiter_edges_ef=HM.iter(funv(_,outset)->S.iter(fun(w,l)->f(v,l,w))outset)letfold_edges_ef=HM.fold(funv(_,outset)->S.fold(fun(w,l)->f(v,l,w))outset)endincludeIletiter_predfgv=S.iter(fun(w,_)->fw)(fst(HM.find_and_raisevg"[ocamlgraph] iter_pred"))letfold_predfgv=S.fold(fun(w,_)->fw)(fst(HM.find_and_raisevg"[ocamlgraph] fold_pred"))letin_degreegv=S.cardinal(fst(tryHM.findvgwithNot_found->invalid_arg"[ocamlgraph] in_degree"))letiter_pred_efgv=S.iter(fun(w,l)->f(w,l,v))(fst(HM.find_and_raisevg"[ocamlgraph] iter_pred_e"))letfold_pred_efgv=S.fold(fun(w,l)->f(w,l,v))(fst(HM.find_and_raisevg"[ocamlgraph] fold_pred_e"))letpredgv=fold_pred(funwl->w::l)gv[]letpred_egv=fold_pred_e(funel->e::l)gv[]end(** Build persistent (resp. imperative) graphs from a persistent (resp.
imperative) association table *)moduleMake(F:TBL_BUILDER)=structmoduleDigraph=structmoduleConcrete(V:COMPARABLE)=structincludeConcreteVertex(F)(V)includeUnlabeled(V)(HM)includeMinimal(S)(HM)letadd_edgegv1v2=ifmem_edgegv1v2thengelseletg=add_vertexgv1inletg=add_vertexgv2inunsafe_add_edgegv1v2letadd_edge_eg(v1,v2)=add_edgegv1v2endmoduleConcreteBidirectional(V:COMPARABLE)=structincludeConcreteVertex(F)(V)includeBidirectionalUnlabeled(V)(HM)includeBidirectionalMinimal(S)(HM)letunsafe_add_edgegv1v2=letfindvg=tryHM.findvgwithNot_found->S.empty,S.emptyinletin_set,out_set=findv1ginletg=HM.addv1(in_set,S.addv2out_set)ginletin_set,out_set=findv2ginHM.addv2(S.addv1in_set,out_set)gletadd_edgegv1v2=ifmem_edgegv1v2thengelseunsafe_add_edgegv1v2letadd_edge_eg(v1,v2)=add_edgegv1v2endmoduleConcreteLabeled(V:COMPARABLE)(Edge:ORDERED_TYPE_DFT)=structincludeConcreteVertex(F)(V)includeLabeled(V)(Edge)(HM)includeMinimal(S)(HM)letadd_edge_eg(v1,l,v2ase)=ifmem_edge_egethengelseletg=add_vertexgv1inletg=add_vertexgv2inunsafe_add_edgegv1(v2,l)letadd_edgegv1v2=add_edge_eg(v1,Edge.default,v2)endmoduleConcreteBidirectionalLabeled(V:COMPARABLE)(Edge:ORDERED_TYPE_DFT)=structincludeConcreteVertex(F)(V)includeBidirectionalLabeled(V)(Edge)(HM)includeBidirectionalMinimal(S)(HM)letunsafe_add_edge_eg(v1,l,v2)=letfindvg=tryHM.findvgwithNot_found->S.empty,S.emptyinletin_set,out_set=findv1ginletg=HM.addv1(in_set,S.add(v2,l)out_set)ginletin_set,out_set=findv2ginHM.addv2(S.add(v1,l)in_set,out_set)gletadd_edge_ege=ifmem_edge_egethengelseunsafe_add_edge_egeletadd_edgegv1v2=add_edge_eg(v1,Edge.default,v2)endmoduleAbstract(V:VERTEX)=structmoduleG=structmoduleV=VmoduleHM=F(V)includeUnlabeled(V)(HM)includeMinimal(S)(HM)endincludeMake_Abstract(G)endmoduleAbstractLabeled(V:VERTEX)(E:ORDERED_TYPE_DFT)=structmoduleG=structmoduleV=VmoduleHM=F(V)includeLabeled(V)(E)(HM)includeMinimal(S)(HM)endincludeMake_Abstract(G)endendend(** Implementation of undirected graphs from implementation of directed
graphs. *)moduleGraph(G:sigincludeSig.Gvalcreate:?size:int->unit->tvalclear:t->unitvalcopy:t->ttypereturnvaladd_vertex:t->vertex->returnvalremove_vertex:t->vertex->returnend)=structincludeGletis_directed=false(* Redefine iterators and [nb_edges]. *)letiter_edgesf=iter_edges(funv1v2->ifV.comparev1v2>=0thenfv1v2)letfold_edgesf=fold_edges(funv1v2acc->ifV.comparev1v2>=0thenfv1v2accelseacc)letiter_edges_ef=iter_edges_e(fune->ifV.compare(E.srce)(E.dste)>=0thenfe)letfold_edges_ef=fold_edges_e(funeacc->ifV.compare(E.srce)(E.dste)>=0thenfeaccelseacc)letnb_edgesg=fold_edges_e(fun_->(+)1)g0(* Redefine operations on predecessors:
predecessors are successors in an undirected graph. *)letpred=succletin_degree=out_degreeletiter_pred=iter_succletfold_pred=fold_succletpred_e=succ_eletiter_pred_e=iter_succ_eletfold_pred_e=fold_succ_eend(*
Local Variables:
compile-command: "make -C .."
End:
*)