Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file merge.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249(**************************************************************************)(* *)(* Ocamlgraph: a generic graph library for OCaml *)(* Copyright (C) 2004-2012 *)(* 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. *)(* *)(**************************************************************************)moduletypeS=sigtypegraphtypevertextypeedgetypeedge_labelvalmerge_vertex:graph->vertexlist->graphvalmerge_edges_e:?src:vertex->?dst:vertex->graph->edgelist->graphvalmerge_edges_with_label:?src:vertex->?dst:vertex->?label:edge_label->graph->edge_label->graphvalmerge_isolabelled_edges:graph->graphvalmerge_ends:?strict:bool->?specified_vertex:vertex->graph->graphvalmerge_starts:?strict:bool->?specified_vertex:vertex->graph->graphvalmerge_scc:?loop_killer:bool->?specified_vertex:(vertexlist->vertex)->graph->graphendmoduleB(B:Builder.S)=structtypegraph=B.G.ttypevertex=B.G.vertextypeedge=B.G.edgetypeedge_label=B.G.E.labelletmemxec=List.exists(funy->B.G.V.equalxy)ecletidentifyxec=matchecwith|[]->false,x|y::ec->ifmemxecthentrue,yelsefalse,xletidentify_extremitiesgvl=letfeaccu=letsx,x=identify(B.G.E.srce)vlinletsy,y=identify(B.G.E.dste)vlinifsx||sythenB.G.E.(createx(labele)y)::accuelseaccuinB.G.fold_edges_efg[](* – former buggy version – the case where v is neither the source nor the
destination of some arrow was not taken into account, so that vertices were
just removed
let merge_vertex g vl = match vl with
| [] -> g
| _ :: vl' ->
let to_be_added = identify_extremities g vl in
let g = List.fold_left B.remove_vertex g vl' in
List.fold_left B.add_edge_e g to_be_added
*)letmerge_vertexgvl=matchvlwith|[]->g|v::vl'->letto_be_added=identify_extremitiesgvlinletg=List.fold_leftB.remove_vertexgvl'inifto_be_added=[]thenB.add_vertexgvelseList.fold_leftB.add_edge_egto_be_addedletmerge_edges_e?src?dstgel=matchelwith|e::el'->letel'=List.filter(B.G.mem_edge_eg)el'inifel'<>[]then(letel=e::el'inletextremitiese=B.G.E.(srce,dste)inletsources,destinations=List.split(List.mapextremitiesel)inletremoveaccue=tryB.remove_edge_eaccuewithInvalid_argument_->ginletg=List.fold_leftremovegelinifList.exists(funv->memvdestinations)sourcesthenletv=matchsrcwith|None->(matchdstwith|None->List.hdsources|Somew->w)|Somev->vinletg=merge_vertexg(v::sources@destinations)inB.add_edge_egB.G.E.(createv(labele)v)elseletv=matchsrcwithNone->List.hdsources|Somev->vinletw=matchsrcwith|None->List.hddestinations|Somew->winletg=merge_vertexgsourcesinletg=merge_vertexgdestinationsinB.add_edge_egB.G.E.(createv(labele)w))elseg|[]->gletmerge_edges_with_label?src?dst?labelgl=letupdate_labele=matchlabelwith|None->e|Somel->B.G.E.(create(srce)l(dste))inletcollect_edgeeaccu=ifB.G.E.labele=lthen(update_labele)::accuelseaccuinletedges_to_be_merged=B.G.fold_edges_ecollect_edgeg[]inmerge_edges_e?src?dstgedges_to_be_merged(* To deduce a comparison function on labels from a comparison function on
edges *)letcompare_labelg=tryletdefault_vertex=leta_vertex_of_g=refNonein(tryB.G.iter_vertex(funv->a_vertex_of_g:=Somev;raiseExit)gwithExit->());match!a_vertex_of_gwith|Somev->v|None->raiseExit(*hence g is empty*)infunl1l2->lete1=B.G.E.createdefault_vertexl1default_vertexinlete2=B.G.E.createdefault_vertexl2default_vertexinB.G.E.comparee1e2withExit->(fun__->0)letmerge_isolabelled_edgesg=letmoduleS=Set.Make(B.G.V)inletdo_meets1s2=S.exists(funx->S.memxs2)s1inletmoduleM=(* TODO: using [compare] here is really suspicious ...
DONE – yet not so clean *)Map.Make(structtypet=B.G.E.labelletcompare=compare_labelgend)inletaccumulatingeaccu=letl=B.G.E.labeleintrylets,d=M.findlaccuinlets,d=B.G.E.(S.add(srce)s,S.add(dste)d)inM.addl(s,d)accuwithNot_found->M.addlB.G.E.(S.singleton(srce),S.singleton(dste))accuinletto_be_identified=B.G.fold_edges_eaccumulatinggM.emptyinletgathering_(s,d)accu=letto_be_gathered,others=List.partition(do_meets)accuinletaccu=List.fold_left(funaccux->S.unionaccux)sto_be_gathered::othersinletto_be_gathered,others=List.partition(do_meetd)accuinList.fold_left(funaccux->S.unionaccux)dto_be_gathered::othersinletto_be_identified=M.foldgatheringto_be_identified[]inList.fold_left(funaccus->merge_vertexaccu(S.elementss))gto_be_identifiedletmerge_ends?(strict=false)?specified_vertexg=letaccumulatorvaccu=ifletout_d=B.G.out_degreegvinout_d=0||((notstrict)&&out_d=List.length(B.G.find_all_edgesgvv))thenv::accuelseaccuinletends=B.G.(fold_vertexaccumulatorg[])inletto_be_merged=matchspecified_vertexwith|Somev->v::ends|None->endsinmerge_vertexgto_be_mergedletmerge_starts?(strict=false)?specified_vertexg=letaccumulatorvaccu=ifletin_d=B.G.in_degreegvinin_d=0||((notstrict)&&in_d=List.length(B.G.find_all_edgesgvv))thenv::accuelseaccuinletstarts=B.G.(fold_vertexaccumulatorg[])inletto_be_merged=matchspecified_vertexwith|Somev->v::starts|None->startsinmerge_vertexgto_be_mergedletmerge_scc?(loop_killer=false)?specified_vertexg=letmoduleC=Components.Make(B.G)inletcomponents=C.scc_listginletalteraccuto_be_identified=letto_be_identified=matchspecified_vertexwith|None->to_be_identified|Somef->(fto_be_identified)::to_be_identifiedinletv=List.hdto_be_identifiedinletaccu=merge_vertexaccuto_be_identifiedinifloop_killerthenB.remove_edgeaccuvvelseaccuinList.fold_leftaltergcomponentsendmoduleP(G:Sig.P)=B(Builder.P(G))moduleI(G:Sig.I)=structincludeB(Builder.I(G))letmerge_vertexgvl=ignore(merge_vertexgvl)letmerge_edges_e?src?dstgel=ignore(merge_edges_e?src?dstgel)letmerge_edges_with_label?src?dst?labelgl=ignore(merge_edges_with_label?src?dst?labelgl)letmerge_isolabelled_edgesg=ignore(merge_isolabelled_edgesg)letmerge_ends?strict?specified_vertexg=ignore(merge_ends?strict?specified_vertexg)letmerge_starts?strict?specified_vertexg=ignore(merge_starts?strict?specified_vertexg)letmerge_scc?loop_killer?specified_vertexg=ignore(merge_scc?loop_killer?specified_vertexg)end(*
Local Variables:
compile-command: "make -C .."
End:
*)