123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291(**************************************************************************)(* *)(* This file is part of OcamlGraph. *)(* *)(* Copyright (C) 2009-2010 *)(* CEA (Commissariat � l'�nergie Atomique) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1, with a linking exception. *)(* *)(* It 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. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the file ../LICENSE for more details. *)(* *)(* Authors: *)(* - Julien Signoles (Julien.Signoles@cea.fr) *)(* - Jean-Denis Koeck (jdkoeck@gmail.com) *)(* - Benoit Bataille (benoit.bataille@gmail.com) *)(* *)(**************************************************************************)moduletypeG=sigtypetmoduleV:sigtypettypelabelvallabel:t->labelvalhash:t->intvalequal:t->t->boolendmoduleE:sigtypetendvaliter_succ:(V.t->unit)->t->V.t->unitvaliter_pred:(V.t->unit)->t->V.t->unitvalfind_edge:t->V.t->V.t->E.tendmoduletypeTree=sigtypetmoduleV:sigtypettypelabelvalcreate:label->tvallabel:t->labelvalhash:t->intvalequal:t->t->boolendmoduleE:Sig.EDGEwithtypevertex=V.tvalcreate:?size:int->unit->tvaladd_vertex:t->V.t->unitvaladd_edge_e:t->E.t->unitendmoduletypeS=sigmoduleTree:TreewithtypeE.label=unittypetvalget_structure:t->Tree.tvalget_root:t->Tree.V.tvalget_tree_vertices:Tree.V.label->t->Tree.V.tlistvalis_ghost_node:Tree.V.t->t->boolvalis_ghost_edge:Tree.E.t->t->boolexceptionGhost_nodevalget_graph_vertex:Tree.V.t->t->Tree.V.labelendmoduleBuild(G:G)(Tree:TreewithtypeV.label=G.V.tandtypeE.label=unit)(GA:sigtypetvaliter_succ:(G.V.t->unit)->t->G.V.t->unitvaliter_pred:(G.V.t->unit)->t->G.V.t->unitend)=structmoduleTree=TreemoduleH=Hashtbl.Make(G.V)moduleHT=Hashtbl.Make(Tree.V)moduleHE=Hashtbl.Make(structtypet=Tree.E.tletequalxy=Tree.E.comparexy=0lethash=Hashtbl.hashend)typet={structure:Tree.t;(* the tree itself *)root:Tree.V.t;(* the root *)(* nodes of the tree corresponding to the original nodes *)assoc_vertex_table:Tree.V.tH.t;ghost_vertices:unitHT.t;ghost_edges:unitHE.t;}(* Getter *)letget_structuret=t.structure;;letget_roott=t.root;;(** Give the list of vertices in the tree graph representing a vertex
from the old graph *)letget_tree_verticesvertextree=tryH.find_alltree.assoc_vertex_tablevertexwithNot_found->assertfalse;;(** True if the vertex is not to be shown *)letis_ghost_nodevtree=HT.memtree.ghost_verticesv;;(** True if the edge is not to be shown *)letis_ghost_edgeetree=HE.memtree.ghost_edgese;;exceptionGhost_node;;(** Give the old graph vertex represented by a vertex in the tree -
@raise Ghost_node if the vertex is a ghost vertex *)letget_graph_vertexvertextree=ifis_ghost_nodevertextreethenraiseGhost_nodeelseTree.V.labelvertex;;(* Explore the graph from a vertex and build a tree -
Will be used forward and backward *)letbuildsrc_graphtreesrc_vertextree_rootbackward_flagdepth=letcomplete_to_depthvmissing=letpred_vertex=refvinletnext_vertex=refvinfor_i=1tomissing-1donext_vertex:=Tree.V.create(Tree.V.labelv);HT.addtree.ghost_vertices!next_vertex();letnew_ghost_edge=ifbackward_flagthenTree.E.create!next_vertex()!pred_vertexelseTree.E.create!pred_vertex()!next_vertexinTree.add_edge_etree.structurenew_ghost_edge;HE.addtree.ghost_edgesnew_ghost_edge();pred_vertex:=!next_vertex;doneinlethas_succ=reffalseinletvertex_visited=H.create97inletqueue=Queue.create()inH.addvertex_visitedsrc_vertextrue;(* Initialize queue *)ifdepth<>0thenifbackward_flagthenGA.iter_pred(funa->Queue.add(a,tree_root,depth)queue)src_graphsrc_vertexelseGA.iter_succ(funa->Queue.add(a,tree_root,depth)queue)src_graphsrc_vertex;(* Empty queue *)letrecempty_queue()=ifnot(Queue.is_emptyqueue)thenbeginletvertex,origin_vertex,depth=Queue.takequeueinifdepth>0thenbeginletnew_vertex=Tree.V.createvertexinH.addtree.assoc_vertex_tablevertexnew_vertex;ifbackward_flagthenbeginletnew_edge=Tree.E.createnew_vertex()origin_vertexinTree.add_edge_etree.structurenew_edgeendelsebeginletnew_edge=Tree.E.createorigin_vertex()new_vertexinTree.add_edge_etree.structurenew_edgeend;ifnot(H.memvertex_visitedvertex)thenbeginH.addvertex_visitedvertextrue;letiterf=f(funa->Queue.add(a,new_vertex,depth-1)queue;has_succ:=true)src_graphvertexinifbackward_flagtheniterGA.iter_predelseiterGA.iter_succ;ifnot!has_succthencomplete_to_depthnew_vertexdepth;has_succ:=false;endelseifdepth<>1thenbeginifbackward_flagthenGA.iter_pred(fun_->has_succ:=true)src_graphvertexelseGA.iter_succ(fun_->has_succ:=true)src_graphvertex;if!has_succthenbeginletghost_vertex=Tree.V.createvertexinHT.addtree.ghost_verticesghost_vertex();letnew_edge=ifbackward_flagthenTree.E.createghost_vertex()new_vertexelseTree.E.createnew_vertex()ghost_vertexinTree.add_edge_etree.structurenew_edge;complete_to_depthghost_vertex(depth-1)endelsecomplete_to_depthnew_vertexdepth;has_succ:=false;endend;empty_queue()endinempty_queue()(* [JS 2010/11/10] trying to simplify the algorithm. Not finish yet
let new_build graph tree root troot depth backward =
let first = ref true in
let q = Queue.create () in
(* invariant: [h] contains exactly the vertices which have been pushed *)
let must_add_ghost = ref true in
let add_tree_vertex v =
let tv = if !first then troot else Tree.V.create v in
first := false;
Tree.add_vertex tree.structure tv;
H.add tree.assoc_vertex_table v tv;
tv
in
let add_tree_edge tsrc dst =
let tdst = add_tree_vertex dst in
let tsrc, tdst = if backward then tdst, tsrc else tsrc, tdst in
let e = Tree.E.create tsrc () tdst in
Tree.add_edge_e tree.structure e;
tdst, e
in
let push n src dst =
if n < depth then Queue.add (dst, n + 1) q;
ignore (add_tree_edge src dst);
must_add_ghost := false
in
let loop () =
while not (Queue.is_empty q) do
let v, n = Queue.pop q in
let tv = add_tree_vertex v in
must_add_ghost := true;
(if backward then GA.iter_pred else GA.iter_succ) (push n tv) graph v;
if !must_add_ghost then
let tsrc = ref tv in
for i = n to depth do
let tdst, te = add_tree_edge !tsrc v in
HT.add tree.ghost_vertices tdst ();
HE.add tree.ghost_edges te ();
tsrc := tdst
done
done
in
Queue.add (root, 0) q;
loop ()
*)(** Build a tree graph centered on a vertex and containing its
predecessors and successors *)letmakesrc_graphsrc_vertexdepth_forwarddepth_backward=lettree={structure=Tree.create();root=Tree.V.createsrc_vertex;assoc_vertex_table=H.create97;ghost_vertices=HT.create17;ghost_edges=HE.create17;}inH.addtree.assoc_vertex_tablesrc_vertextree.root;Tree.add_vertextree.structuretree.root;buildsrc_graphtreesrc_vertextree.rootfalsedepth_forward;buildsrc_graphtreesrc_vertextree.roottruedepth_backward;(* new_build src_graph tree src_vertex tree.root depth_forward false;
new_build src_graph tree src_vertex tree.root depth_backward true;*)treeendmoduleMake(G:G)(Tree:TreewithtypeV.label=G.V.tandtypeE.label=unit)=Build(G)(Tree)(G)moduleMake_from_dot_model(Tree:TreewithtypeV.label=DGraphModel.DotG.V.tandtypeE.label=unit)=Build(DGraphModel.DotG)(Tree)(structtypet=DGraphModel.dotg_modelletiter_succfg=g#iter_succfletiter_predfg=g#iter_predfend)