簡體   English   中英

如何在不使用循環的情況下從表示過渡的int * char * int列表中以圖形方式表示自動機

[英]How can I represent an automaton graphically from a list of int*char*int representing the transitions without using loops

我做了一條稱為自動機的記錄,其中包含表示自動機所需的5個字段,我應該使用圖形來表示每個狀態和從轉換列表中的轉換,而無需使用for或while循環僅使用遞歸函數

transitions :(int*char*int) list;

使用graphviz進行實際繪圖可能是最簡單的。 它會自動從節點和邊的列表中繪制圖形,這正是您輸入的內容。 函數fmt_transition生成一個邊,函數fmt_transitions通過pp_print_list將其提升到轉換列表,並將其包裝到正確的標頭中。

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)

如果在某些測試數據上進行嘗試,則會得到所需的測試文件:

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的調用是:

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

如果直接從ocaml調用它,則還可以將數據直接管道傳輸到點中,而無需先將其寫入磁盤。

另外,您也可以使用類似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 |> cleanup將把數據發送到dot並打開ghostview。 為防止達到打開文件的限制,請等待一聲喊叫終止進程並關閉通道,這是在cleanup完成的。

如果要改用圖像庫,則可能需要在調用clean之前將cmd的定義替換為“ dot -Tpng”並從stdin中讀取圖像數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM