0

I made a record called automaton containing the 5 fields required to represent an automaton I'm supposed to use graphics to represent every state and transition from the transitions list without using for or while loops only recursive functions

transitions :(int*char*int) list;
Vaibhav Mule
  • 5,016
  • 4
  • 35
  • 52

1 Answers1

3

It might be easiest to use graphviz to do the actual drawing. It automatically draws a graph from a list of nodes and edges, which is exactly what your input is. The function fmt_transition generates one edge, the function fmt_transitions lifts it via pp_print_list to lists of transitions and wraps it into the correct header.

let fmt_transition fmt (inedge,by,outedge) =
  Format.fprintf fmt "@[%d -> %d [label=\"%c\"];@]" inedge outedge by

let fmt_transitions fmt =
  Format.fprintf fmt "@[<v 2>digraph output {@,%a@,@]}@,@."
    (Format.pp_print_list fmt_transition)

If we try it on some test data, we get the test file we wanted:

let test1 = [ (1,'a',2); (2,'b',1); (1,'b',1)] in
fmt_transitions Format.std_formatter test1;;

results in:

digraph output
{
   1 -> 2 [label="a"];
   2 -> 1 [label="b"];
   1 -> 1 [label="b"];
}

The call to graphviz is:

dot -T pdf -o output.pdf < input.dot

If you call it directly from ocaml, you can also pipe the data directly into dot without writing it to disk first.

Alternatively, you can also use an external viewer like gv:

let call_dot data =
  let cmd = "dot -Tps | gv -" in
  let (sout, sin, serr) as channels =
    Unix.open_process_full cmd (Unix.environment ()) in
  let fmt = Format.formatter_of_out_channel sin in
  Format.fprintf fmt "%a@." fmt_transitions data;
  channels

let cleanup channels =
  (* missing: flush channels, empty buffers *)
  Unix.close_process_full channels

The call call_dot test1 |> cleanup will send the data to dot and open ghostview. To prevent hitting the limit of open files, one shout await the termination of the process and close the channels, which is done in cleanup.

If you want to use an image library instead, you might want to replace the definition of cmd by "dot -Tpng" and read the image data from stdin before you call cleanup.

lambda.xy.x
  • 4,918
  • 24
  • 35
  • i know it's easier to use graphviz but is there a way so that i can use only the graphics module of ocaml maybe with a recursive function that acts on the elements of the list or maybe more than one function –  Jan 23 '17 at 21:44
  • and also i would like to note that i did not find the way to output the file generated by ocaml from ocaml –  Jan 23 '17 at 22:42
  • How you go on depends on your further plans -- for static data, piping the dot output into evince / ghostview could be enough. If you want a user interface, you might create an image instead and use the ocaml gtk bindings. There's also [ocamlgraph](https://github.com/backtracking/ocamlgraph) but I have no experience with it. In the worst case, you can use the annotation output of graphviz to find a good placement for the nodes and do the rest with the low level drawing functions in a gdk canvas. – lambda.xy.x Jan 24 '17 at 00:55
  • but where is the dot file can you give me an example of how to execute the program with this example : –  Jan 24 '17 at 18:56
  • let a1={ etat_initial=[0]; ensemble_des_etats=[1;2]; alphabets=['a';'b']; transitions=[(1,'a',1);(1,'b',2);(2,'a',2)]; etats_finaux=[1] };; –  Jan 24 '17 at 18:56
  • how can i do it in a way that when you execute the program the pdf or image from the dot file opens up thats the tricky thing to do –  Jan 24 '17 at 18:58
  • the data is always from an automaton i defined a record the automaton in use could be different though –  Jan 24 '17 at 18:59
  • can you explain to me more about how is the dot file created and how to transform it to bmp or jpg without getting out of ocaml maybe then i could load it with ocamlimage –  Jan 24 '17 at 19:14
  • I added some code explaining how to directly pipe the output to ghostview and what you need to do to adjust it reading the output back to ocaml. – lambda.xy.x Jan 25 '17 at 13:32
  • By the way, the exec functionality is completely independent of the problem. – lambda.xy.x Jan 25 '17 at 13:34
  • thanks its a little clearer now its just that i have never worked with graphviz or dot so what you were explaining was like chinese to me can you tell me how to read the png file with ocamlimage per example and what did you mean by the exec functionality do you think this code here is enough if i have graphviz already installed im on a deadline here sorry if i bothered you with too much questions –  Jan 25 '17 at 20:09
  • I assumed this is an exercise, so I didn't want to give you a full solution, just the pieces you need in order to solve it yourself. I haven't done any GUI programming in ocaml so far, so I can only help you up to the point where you have an image generated. How you display it also depends on a lot on the actual problem specification. – lambda.xy.x Jan 25 '17 at 22:38