我如何从int * char * int列表中以图形方式表示一个自动机,而不使用循环来表示转换 [英] How can I represent an automaton graphically from a list of int*char*int representing the transitions without using loops

查看:162
本文介绍了我如何从int * char * int列表中以图形方式表示一个自动机,而不使用循环来表示转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个名为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆