我编写了一个程序,它从点文件中的节点和边列表中编写自动机图,并使用ocaml
通过imagemagick
中的unix模块打开它。它工作正常,它在linux上编译和执行时打开了生成的图像,但在cygwin
上,由于某种原因它不起作用。我已在graphviz
上安装了imagemagick
和cygwin
,但没有运气。这是该程序的代码:
(*d'abord definissons le type automate*)
type automate = {
etat_initial : int;
ensemble_des_etats : int list;
alphabets : char list;
transitions :(int*char*int) list;
etats_finaux : int list
};;
(*prenons une variable a1 du type automate qu'on a definit precedemment comme exemple*)
let a1={
etat_initial=1;
ensemble_des_etats=[1;2];
alphabets=['a';'b'];
transitions=[(1,'a',1);(1,'b',2);(2,'a',2);(2,'b',1)];
etats_finaux=[2]
};;
(*pour tester si un automate est complet ou non on a besoin de trois fonctions*)
(*la premiere donne l'image d'un couple (etat,caractere) par une transition*)
let rec image e a t=
match t with
[]->[]
|x::l-> let (i,j,k)=x in if (i=e && j=a) then k::(image e a l)
else image e a l ;;
(*la deuxieme donne une liste qui contient tout les couples d'un etat (etat,caractere)
qui n'ont pas d'image donc si image e la lt=[] cela veut dire que l'automate est n'est pas complet dans cet etat*)
let rec nodef e la lt=
match la with
| [] -> []
| a::la'-> if image e a lt = [] then (e,a)::nodef e la' lt else nodef e la' lt;;
(*la troisieme applique nodef sur tout les element d'une liste*)
let rec est_complet le la lt =
match le with
| [] -> []
| e::le'-> nodef e la lt :: est_complet le' la lt;;
(*ici c'est l'application directe de toutes les fonctions precedentes sur un automate*)
let complet auto=
if est_complet auto.ensemble_des_etats auto.alphabets auto.transitions = []
then true else false ;;
(*la partie qui teste est ce qu'un automate est complet termine ici*)
(*on s'interesse maintenant a faire une fonction qui teste si un automate est deterministe*)
(*d'abord on realie la fonction membre qui retourne true si un element donné en parametre est membre d'une liste false sinon*)
let rec membre a l =
match l with
| [] -> false
| x::rl -> x=a || membre a rl;;
(*ensuite on definie deux fonctions dans une*)
let est_det a=
(*la premiere pour voir si une liste contient des doublons*)
let rec appartient l = match l with
[] -> false
| x::r -> (membre x r) || (appartient r);
in
(*la deuxieme pour rendre une liste de paires a partir d'une qui contenait des triplets*)
let rec mettre_en_couple l =
match l with
|[]->[]
|(a,b,c)::l1->(a,b)::mettre_en_couple l1;
in
(*et enfin on applique la premiere fonction sur la liste rendu par la deuxieme*)
let l = mettre_en_couple a
in
appartient l;;
let deterministe auto=
if est_det auto.transitions=false then true else false;;
(*ici c'est l'application directe de toutes les fonctions precedentes sur un automate*)
(*pour representer un automate graphiquement en utilisant graphviz on necessite 4 fonctions*)
(*la premiere pour ecrire dans un fichier qui sera passé par la sortie standard stdout vers la fonction dessiner_automate,le fichier fmt
contiendra la description suivant la condition appliqué a une transition de l'automate du graph en langage dot*)
let fmt_transition auto fmt (inedge,by,outedge)=
if membre outedge auto.etats_finaux=true then
Format.fprintf fmt "@[node [shape = doublecircle]%d;@]" outedge;
if inedge=auto.etat_initial then
Format.fprintf fmt "@[node [shape = point]start;node [shape = circle];start -> %d ;@]"inedge ;
Format.fprintf fmt "@[%d -> %d [label=\"%c\"];@]" inedge outedge by;;
(*la deuxieme fonction levera la premiere sur toute les transitions de l'automate *)
let fmt_transitions fmt auto=
Format.fprintf fmt "@[<v 2>digraph output {@,%a@,@]}@,@."
(Format.pp_print_list (fmt_transition auto)) auto.transitions
;;
(*la troisieme va lancer la commande d'affichage de l'image genere par le fichier dot passe en parametre dans
un environement linux depuis ocaml *)
let dessiner_automate auto =
let cmd = "dot -Tpng | display -" 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 auto;
channels
let cleanup channels =
(* missing: flush channels, empty buffers *)
Unix.close_process_full channels;;
dessiner_automate a1 ;;
print_newline()