123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)moduleCliqueTree(Gr:Sig.G)=struct(* Vertex signature *)modulerecCliqueV:sigtypetvalcompare:t->t->intvalhash:t->intvalequal:t->t->boolvallabel:t->tvalcreate:Gr.V.t->tvalvertex:t->Gr.V.tvalnumber:t->intvalset_number:t->int->unitvalclique:t->intvalset_clique:t->int->unitvalmark:t->intvalincr_mark:t->unitvalm:t->CVS.tvalset_m:t->CVS.t->unitvallast:t->tvalset_last:t->t->unitend=structtypet={mutablemark:int;orig:Gr.V.t;mutablem:CVS.t;mutablelast:toption;mutablenumber:int;mutableclique:int;}letcomparexy=Gr.V.comparex.origy.origlethashx=Gr.V.hashx.origletequalxy=Gr.V.equalx.origy.origletlabelx=xletcreateo={mark=0;orig=o;m=CVS.empty;last=None;number=0;clique=-1;}letvertexx=x.origletcliquex=x.cliqueletset_cliquexv=x.clique<-vletnumberx=x.numberletset_numberxv=x.number<-vletmarkx=x.markletincr_markx=(*Printf.printf "Increasing mark of %s to %i\n%!"
(Gr.v_to_string x.orig) (succ x.mark);*)x.mark<-succx.markletmx=x.mletset_mxv=x.m<-vletlastx=matchx.lastwithSomev->v|None->failwith"last not set"letset_lastxv=x.last<-Somevend(* Clique tree vertex set *)andCVS:Set.Swithtypeelt=CliqueV.t=Set.Make(CliqueV)(* The final clique tree vertex type:
- set of original vertexes ordered by mark.
- clique number.
*)moduleCliqueTreeV=Util.DataV(structtypet=CliqueV.tlist*CVS.tend)(structtypet=intletcompare:t->t->int=Stdlib.comparelethash(x:t)=Hashtbl.hashxletequal(x:int)(y:int)=x=yend)moduleCliqueTreeE=structtypet=int*CVS.tletcompare(x,_:t)(y,_:t)=Stdlib.comparexyletdefault=(0,CVS.empty)letcreatens=(n,s)letvertices=sndletwidthgtri(_,x)=letvertices=List.mapCliqueV.vertex(CVS.elementsx)inletw=List.fold_left(funwv->List.fold_left(funwv'->ifv<>v'thenifnot(Gr.mem_edgegvv')&&Gr.mem_edgetrivv'thensuccwelsewelsew)wvertices)0verticesinassert(wmod2=0);w/2end(* The returned tree *)moduleCliqueTree=Persistent.Digraph.ConcreteLabeled(CliqueTreeV)(CliqueTreeE)(* Intermediate graph *)moduleG=Persistent.Graph.Concrete(CliqueV)(* Creates the intermediate graph from the original *)moduleCopy=Gmap.Vertex(Gr)(structincludeGincludeBuilder.P(G)end)openCliqueVletmcs_cliqueg=(* initializations *)letn=Gr.nb_vertexginletg'=Copy.mapCliqueV.createginletunnumbered=ref(G.fold_vertexCVS.addg'CVS.empty)inletpmark=ref(-1)inletorder=ref[]inletcliques=Array.maken([],CVS.empty)inletties=ref[]inletj=ref0in(* loop, taking each unnumbered vertex in turn *)fori=ndownto1do(* Find greatest unnumbered vertex
if CVS.is_empty !unnumbered then
Printf.printf "No more unnumbered vertices\n%!"
else
Printf.printf "%i unnumbered vertices remaining\n%!"
(CVS.cardinal !unnumbered);
*)letx,mark=letchoosed=CVS.choose!unnumberedinCVS.fold(funx((_maxx,maxv)asmax)->letv=markxinifv>maxvthen(x,v)elsemax)!unnumbered(choosed,markchoosed)in(* peo construction *)order:=x::!order;(* now numbered *)unnumbered:=CVS.removex!unnumbered;ifmark<=!pmarkthenbegin(* Create a new clique (lemma 8) *)incrj;(* m x is the neighborhoud of x in the previous clique *)cliques.(!j)<-([x],CVS.addx(mx));(* Use reverse map of cliques to find what clique
we're connected to. m x is the width of the ties *)letclast=clique(lastx)inties:=(clast,mx,!j)::!ties;endelsebeginletl,c=cliques.(!j)incliques.(!j)<-(x::l,CVS.addxc);end;G.iter_succ(funy->ifnumbery==0thenbeginincr_marky;set_my(CVS.addx(my));end;set_lastyx)g'x;pmark:=mark;set_numberxi;set_cliquex!j;done;letcliques=Array.mapi(funi(l,c)->CliqueTreeV.create(List.revl,c)i)(Array.subcliques0(succ!j))inlettree=Array.fold_leftCliqueTree.add_vertexCliqueTree.emptycliquesinlettree,_=List.fold_left(fun(g,n)(i,verts,j)->letlabel=CliqueTreeE.createnvertsinletedge=CliqueTree.E.createcliques.(i)labelcliques.(j)in(CliqueTree.add_edge_egedge,succn))(tree,1)!tiesinList.mapCliqueV.vertex!order,tree,cliques.(0)letsonsgx=CliqueTree.fold_succ(funxy->x::y)gx[]exceptionNotCliquelettest_simpliciality_first'lsons=List.for_all(funson->match!sonwith|[]->false|xi::_->letother=mxiinCVS.subsetotherl)sonslettest_simpliciality_nextvertices_sons=matchverticeswith|x::tl->begintryignore(List.fold_left(funvmv'->letvm'=CliqueV.mv'inifCVS.equalvm'vmthenCVS.addv'vm'elseraiseNotClique)(CVS.addx(mx))tl);truewithNotClique->falseend|_->trueletis_chordalg=let_order,tree,root=mcs_cliqueginletrecauxc=letcsons=sonstreecinlets=List.mapCliqueTreeV.datacsonsinletl=CliqueTreeV.datacinletsons()=List.map(fun(x,_)->refx)sinletfirst=test_simpliciality_first'(sndl)(sons())inletnext=test_simpliciality_next(fstl)(sons())infirst&&next&&(List.for_allauxcsons)inauxrootletmaxwidthgtritree=CliqueTree.fold_edges_e(funeres->letw=CliqueTreeE.widthgtri(CliqueTree.E.labele)inmaxresw)tree0end