我如何从int * char * int列表中以图形方式表示一个自动机,而不使用循环来表示转换 [英] How can I represent an automaton graphically from a list of int*char*int representing the transitions without using loops
问题描述
我创建了一个名为automaton的记录,其中包含表示自动机所需的5个字段,我应该使用图形来表示每个状态并从转换列表中进行转换,而不使用for或while循环。递归函数
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;
推荐答案
使用 graphviz 来做实际的绘图。它会自动从节点和边缘列表中绘制图形,这正是您输入的内容。函数 fmt_transition
产生一个边,函数 fmt_transitions
通过 pp_print_list 转换为转换列表,并将其封装到正确的标题中。
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;;
结果为:
digraph output
{
1 -> 2 [label="a"];
2 -> 1 [label="b"];
1 -> 1 [label="b"];
}
对graphviz的调用是:
The call to graphviz is:
dot -T pdf -o output.pdf < input.dot
如果您直接从ocaml中调用它,您还可以直接将数据直接转换为点首先将其写入磁盘。
If you call it directly from ocaml, you can also pipe the data directly into dot without writing it to disk first.
或者,您也可以使用外部查看器,例如gv:
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
调用 call_dot test1 |>清理
会将数据发送到点并打开ghostview。为了防止打开文件的限制,一个留言等待终止进程并关闭频道,这在 cleanup
中完成。
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
.
如果您想要使用图像库,则可能需要使用dot -Tpng替换cmd的定义,并在调用清理前从stdin读取图像数据。
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.
这篇关于我如何从int * char * int列表中以图形方式表示一个自动机,而不使用循环来表示转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!