Search code examples
ocamlvisualizationimage-graphviz

How to visualize/draw automata in ocaml?


I am doing composition of automata. So at the end of that, I want to draw the composed automata also. So are there any libraries for that in ocaml? or are there ocaml wrappers written for any graph visualization tool? I have googled for it but didn't get much for ocaml. Any comments on ocamlgraph? I will get more than 100 states in composed automata.


Solution

  • Use ocamlgraph -- it is a graph library that can generate a dot/graphviz file for you but can also do a lot of other stuff that maybe interesting for handling your automata. The library can do fixpoints, spanning trees, graph search, find strongly connected components, etc., etc.

    Here is a complete example of some directed graph with labeled edges + module for doing depth-first-search + module for creating dot-representations of it:

    (* representation of a node -- must be hashable *)
    module Node = struct
       type t = int
       let compare = Pervasives.compare
       let hash = Hashtbl.hash
       let equal = (=)
    end
    
    (* representation of an edge -- must be comparable *)
    module Edge = struct
       type t = string
       let compare = Pervasives.compare
       let equal = (=)
       let default = ""
    end
    
    (* a functional/persistent graph *)
    module G = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled(Node)(Edge)
    
    (* more modules available, e.g. graph traversal with depth-first-search *)
    module D = Graph.Traverse.Dfs(G)
    
    (* module for creating dot-files *)
    module Dot = Graph.Graphviz.Dot(struct
       include G (* use the graph module from above *)
       let edge_attributes (a, e, b) = [`Label e; `Color 4711]
       let default_edge_attributes _ = []
       let get_subgraph _ = None
       let vertex_attributes _ = [`Shape `Box]
       let vertex_name v = string_of_int v
       let default_vertex_attributes _ = []
      let graph_attributes _ = []
    end)
    

    with that you can write your program; e.g. something like this:

    (* work with the graph ... *)
    let _ =
       let g = G.empty in
       let g = G.add_edge_e ...
       ...
       let file = open_out_bin "mygraph.dot" in
       let () = Dot.output_graph file g in
       ...
       if D.has_cycle g then ... else ...