Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file CCKTree.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Lazy Tree Structure}
This structure can be used to represent trees and directed
graphs (as infinite trees) in a lazy fashion. Like {!CCKList}, it
is a structural type. *)type'asequence=('a->unit)->unittype'agen=unit->'aoptiontype'aklist=unit->[`Nil|`Consof'a*'aklist]type'aprinter=Format.formatter->'a->unittype+'at=unit->[`Nil|`Nodeof'a*'atlist]letempty()=`Nilletis_emptyt=matcht()with|`Nil->true|`Node_->falseletsingletonx()=`Node(x,[])letnodexl()=`Node(x,l)letnode1xt()=`Node(x,[t])letnode2xt1t2()=`Node(x,[t1;t2])letrecfoldfacct=matcht()with|`Nil->acc|`Node(x,l)->letacc=faccxinList.fold_left(foldf)acclletreciterft=matcht()with|`Nil->()|`Node(x,l)->fx;List.iter(iterf)lletsizet=fold(funn_->n+1)0tletheightt=letrecauxtk=matcht()with|`Nil->k0|`Node(_,l)->aux_l0lkandaux_lacclk=matchlwith|[]->kacc|t'::l'->auxt'(funn->aux_l(maxaccn)l'k)inauxt(funx->x)letrecmapft()=matcht()with|`Nil->`Nil|`Node(x,l)->`Node(fx,List.map(mapf)l)let(>|=)tf=mapftletreccut_depthnt()=matcht()with|`Nil->`Nil|`Node_whenn=0->`Nil|`Node(x,l)->`Node(x,List.map(cut_depth(n-1))l)(** {2 Graph Traversals} *)(** Abstract Set structure *)classtype['a]pset=objectmethodadd:'a->'apsetmethodmem:'a->boolendletset_of_cmp(typeelt)~cmp()=letmoduleS=Set.Make(structtypet=eltletcompare=cmpend)inobjectvals=S.emptymethodaddx={<s=S.addxs>}methodmemx=S.memxsendlet_nil()=`Nillet_consxl=`Cons(x,l)letdfs~psett=letrecdfspsetstack()=matchstackwith|[]->`Nil|`Exploret::stack'->beginmatcht()with|`Nil->dfspsetstack'()|`Node(x,_)whenpset#memx->dfspsetstack'()(* loop *)|`Node(x,l)->letpset'=pset#addxinletstack'=List.rev_append(List.rev_map(funx->`Explorex)l)(`Exitx::stack')in_cons(`Enterx)(dfspset'stack')end|`Exitx::stack'->_cons(`Exitx)(dfspsetstack')indfspset[`Exploret](** Functional queues for BFS *)moduleFQ=structtype'at={hd:'alist;tl:'alist;}exceptionEmpty(* invariant: if hd=[], then tl=[] *)let_makehdtl=matchhdwith|[]->{hd=List.revtl;tl=[]}|_::_->{hd;tl;}letempty=_make[][]letlist_is_empty=function|[]->true|_::_->falseletis_emptyq=list_is_emptyq.hdletpushqx=_makeq.hd(x::q.tl)letpop_exnq=matchq.hdwith|[]->assert(list_is_emptyq.tl);raiseEmpty|x::hd'->letq'=_makehd'q.tlinx,q'endletbfs~psett=letrecbfspsetq()=ifFQ.is_emptyqthen`Nilelselett,q'=FQ.pop_exnqinmatcht()with|`Nil->bfspsetq'()|`Node(x,_)whenpset#memx->bfspsetq'()(* loop *)|`Node(x,l)->letq'=List.fold_leftFQ.pushq'linletpset'=pset#addxin_consx(bfspset'q')inbfspset(FQ.pushFQ.emptyt)letrecforcet:([`Nil|`Nodeof'a*'blist]as'b)=matcht()with|`Nil->`Nil|`Node(x,l)->`Node(x,List.mapforcel)letfind~psetft=letrec_find_klfl=matchl()with|`Nil->None|`Cons(x,l')->matchfxwith|None->_find_klfl'|Some_asres->resin_find_klf(bfs~psett)(** {2 Pretty-printing} *)letpppp_xfmtt=(* at depth [lvl] *)letrecppfmtt=matchtwith|`Nil->()|`Node(x,children)->letchildren=filterchildreninmatchchildrenwith|[]->pp_xfmtx|_::_->Format.fprintffmt"@[<v2>(@[<hov0>%a@]%a)@]"pp_xxpp_childrenchildrenandfilterl=letl=List.fold_left(funaccc->matchc()with|`Nil->acc|`Node_assub->sub::acc)[]linList.revlandpp_childrenfmtchildren=(* remove empty children *)List.iter(func->Format.fprintffmt"@,";ppfmtc)childreninppfmt(t());()(** {2 Pretty printing in the DOT (graphviz) format} *)moduleDot=structtypeattribute=[|`Colorofstring|`Shapeofstring|`Weightofint|`Styleofstring|`Labelofstring|`Idofstring|`Otherofstring*string](** Dot attributes for nodes *)typegraph=(string*attributelisttlist)(** A dot graph is a name, plus a list of trees labelled with attributes *)letmk_idformat=letbuf=Buffer.create64inPrintf.kbprintf(fun_->`Id(Buffer.contentsbuf))bufformatletmk_labelformat=letbuf=Buffer.create64inPrintf.kbprintf(fun_->`Label(Buffer.contentsbuf))bufformatletmake~namel=(name,l)letsingleton~namet=(name,[t])(* find and remove the `Id attribute, if any *)letrec_find_idaccl=matchlwith|[]->raiseNot_found|`Idn::l'->n,List.rev_appendaccl'|x::l'->_find_id(x::acc)l'let_pp_attrfmtattr=matchattrwith|`Colorc->Format.fprintffmt"color=%s"c|`Shapes->Format.fprintffmt"shape=%s"s|`Weightw->Format.fprintffmt"weight=%d"w|`Styles->Format.fprintffmt"style=%s"s|`Labell->Format.fprintffmt"label=\"%s\""l|`Other(name,value)->Format.fprintffmt"%s=\"%s\""namevalue|`Id_->()(* should not be here *)letrec_pp_attrsfmtl=matchlwith|[]->()|[x]->_pp_attrfmtx|x::l'->_pp_attrfmtx;Format.pp_print_charfmt',';_pp_attrsfmtl'letppout(name,l)=(* nodes already printed *)lettbl=Hashtbl.create32in(* fresh name generator *)letnew_name=letn=ref0infun()->lets=Printf.sprintf"node_%d"!ninincrn;sin(* the name for some node is either defined, either a fresh random
name *)letget_namex=try_find_id[]xwithNot_found->new_name(),xin(* recursive printing (bfs) *)letrecauxq=ifFQ.is_emptyqthen()elselet(parent,x),q'=FQ.pop_exnqinletq'=pp_nodeq'?parentxinauxq'andpp_nodeq?parentt=matcht()with|`Nil->q|`Node(x,l)->letname,attrs=get_namexinbeginmatchparentwith|None->()|Somen->Format.fprintfout" %s -> %s;@,"nnameend;ifnot(Hashtbl.memtblname)then(Hashtbl.addtblname();Format.fprintfout"@[%s [%a];@]@,"name_pp_attrsattrs;List.fold_left(funqy->FQ.pushq(Somename,y))ql)elseqinletq=List.fold_left(funqy->FQ.pushq(None,y))FQ.emptylin(* preamble *)Format.fprintfout"@[<hv 2>digraph \"%s\" {@,"name;auxq;Format.fprintfout"}@]@.";()letpp_singlenameoutt=ppout(singleton~namet)letprint_to_filefilenameg=letoc=open_outfilenameinletfmt=Format.formatter_of_out_channelocintryppfmtg;Format.pp_print_flushfmt();close_outocwithe->close_outoc;raiseeletto_file?(name="graph")filenametrees=letg=make~nametreesinprint_to_filefilenamegend