From a2c8a0ce4cd2cb5e583c8c8c37ffe4736f8dde19 Mon Sep 17 00:00:00 2001 From: Kylian Fontaine <kylian.fontaine@etu.univ-lyon1.fr> Date: Fri, 28 Jun 2024 14:52:15 +0200 Subject: [PATCH] da hors lemmes, declaration des forall --- Readme.md | 2 +- bin/main.ml | 15 +-- lib/ast.ml | 162 +++++++++++++++++++------- lib/gencoq.ml | 82 +++++++------ lib/{graphtest.ml => graphmeasure.ml} | 0 lib/parser.mly | 24 ++-- 6 files changed, 183 insertions(+), 102 deletions(-) rename lib/{graphtest.ml => graphmeasure.ml} (100%) diff --git a/Readme.md b/Readme.md index f6b3f3b..c9c7fe2 100644 --- a/Readme.md +++ b/Readme.md @@ -37,7 +37,7 @@ Rigidity := Flexible delta ``` Couleur : Red; Blue; Yellow; Green; Purple; Orange -- Robot := Permet de definir des champs privée et publique pour le robot, il est necessaire de lister les éléments privée puis les éléments public +- Robot := Permet de definir des champs privés et publiques pour le robot, il est necessaire de lister les éléments privés puis les éléments publiques - Private : Champ 1; Champ 2; ... - Public : Champ 3; Champ 4; ... diff --git a/bin/main.ml b/bin/main.ml index c4a96a9..7cbc768 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,15 +1,10 @@ open Dsl -let repo = "./sourcegenerate";; +(*let repo = "./sourcegenerate";; let files =Array.to_list (Sys.readdir repo);; print_endline(String.concat "; " files);; - +*) let gen (x : string) = - let path = repo ^"/"^ x in - Gencoq.generate (Interface.parse_description path) x;; - -List.map gen files;; -(* -if (Ast.check_sensors_desc desc) && (Ast.check_activelyup desc)then -print_endline (Ast.string_of_description desc);; -*) \ No newline at end of file + Gencoq.generate_coq (Interface.parse_description x) (Filename.basename x);; + +gen Sys.argv.(1);; diff --git a/lib/ast.ml b/lib/ast.ml index b3633a4..a6ff2f8 100644 --- a/lib/ast.ml +++ b/lib/ast.ml @@ -1,4 +1,4 @@ -open Graphtest + (*ROBOGRAM*) type binop = @@ -205,14 +205,6 @@ type information = | Roles of (int * string) list | Share of share - - -type measure = Measure of int * G.t -(* Une description c'est 1: description de l'environnement et des capacites des robot - 2: robogram *) -type description = Description of (information list) * (expr list) * measure - - (*FONCTION SUR LES SETS*) (** [length s] retourne la longueur du set [s] @param [s] 'a set dont on veut la longueur @@ -222,7 +214,7 @@ let rec length_set (s:'a set): int = | Vide -> 0 | Some (s,_) -> 1 + (length_set s) -(*[push s e] ajoute un element e au set s +(**[push s e] ajoute un element e au set s @param s de type 'a set @param e de type 'a @return un set correspondant au set s avec l'ajout de e *) @@ -273,7 +265,7 @@ let rec string_of_expression (e : expr) : string = | Set s -> string_of_set s string_of_expression | Let (v,e1,e2) -> "Déclaration de la variable " ^ v ^ " avec definition : " ^ string_of_expression e1 ^ " dans \n(" ^string_of_expression e2 ^")" | Fun (s,e) -> "Fonction qui prend en parametre " ^ s ^ " et retourne (" ^ string_of_expression e ^")" - | App (f,arg) -> "("^ string_of_expression f ^") appliqué a (" ^ string_of_expression arg ^")" + | App (f,arg) -> "("^string_of_expression f ^" "^ string_of_expression arg^")" | Point (k,v) -> "Valeur du champ " ^ v^ " de "^ k ^"" | LengthSet s -> (match s with | Set s' -> "Taille de "^string_of_expression s ^ " : " ^ string_of_int (length_set s') @@ -288,7 +280,15 @@ let rec string_of_expression (e : expr) : string = l)^ "\nend" | Cons (head,tail) -> string_of_expression head ^ " :: " ^ string_of_expression tail - +(**[get_param f] retourne la liste des paramtre d'une application de fonction, + si un des parametre et aussi une application de fonction, cela retournera les parametre de la deuxieme application + @param f [expr] + @return [expr list]*) +let rec get_param (f:expr) : expr list= + match f with + | App(f',Var v)-> Var v:: get_param f' + | App(f',v)-> get_param v @ get_param f' + | _-> [] let string_of_synchro (s:synchro) : string = match s with @@ -342,7 +342,7 @@ let rec string_of_value (v : value) : string = | Intern c -> "Lumiere interne avec couleur :" ^ String.concat ", " (List.map string_of_color c) | Extern c ->"Lumiere externe avec couleur :" ^ String.concat ", " (List.map string_of_color c) | All c ->"Lumiere visible par tous avec couleur :" ^ String.concat ", " (List.map string_of_color c) - ) + ) let string_of_field (f : field) : string = match f with | Private (s,v)-> "Private: "^s^"->"^ string_of_value v @@ -360,30 +360,8 @@ let string_of_rigidity (r: rigidity) : string = | Rigide -> "Rigide" | Flexible _ -> "Flexible" -let rec string_of_description (desc:description) : string = - match desc with - | Description (infos,robogram,_) -> - "Description environnement:\n" ^String.concat "\n" (List.map string_of_information infos) - ^"\nRobogram : \n " ^ String.concat "\n" (List.map string_of_expression robogram) -and string_of_information (info: information) : string = - match info with - | Sync s -> "Sync: " ^ (string_of_synchro s) - | Rigidity r ->(match r with - | Rigide -> "Rigidity: Rigide" - | Flexible d -> "Rigidity: Flexible d'une distance delta = " ^ string_of_expression d) - - | Space e -> "Espace: " ^ (string_of_espace e) - | Byzantines b -> string_of_byzantine b - | Sensors s -> "Sensors: [" ^ String.concat "; " (List.map string_of_sensor s) ^ "] " - | Robot r -> "Robot : ["^ String.concat "; " (List.map string_of_field r) ^ "]" - | Roles r -> "Roles :" ^ String.concat "\n " (List.map string_of_role r) - | ActivelyUpdate a -> "Champ qui sont mise a jour par le robogram: " ^ String.concat ", " (List.map string_of_valretr a ) - | Share s ->"Share : " ^ (match s with - |Fullcompass -> "Fullcompass" - |Chirality -> "Chirality" - |DirectionShare -> "Direction" - |OneAxisOrientation ->"1-axis orientation") - + + (** [info_sync i] verifie qu'une information est une information sur la synchronisation @param i information @return bool *) @@ -400,6 +378,101 @@ let info_space (i : information):bool = | Space _ -> true | _ -> false + + + + +(*GRAPH*) +module Node = struct + type t = expr + let compare = compare + let hash = Hashtbl.hash + let equal = (=) +end + +module Edge = struct + type t = string + let compare = compare + let default = "" +end + + +module G = Graph.Imperative.Digraph.ConcreteLabeled(Node)(Edge) + + +type edge = +| Nolab of (expr * expr) + +let graph_from_edges (el : edge list)= + let g = G.create () in + let nolab = fun (x, y) -> + let vx = G.V.create x in + let vy = G.V.create y in + G.add_edge g vx vy + in + let rec add_edge (el : edge list) = + match el with + | [] -> () + | (Nolab h)::t -> nolab h ; add_edge t + in add_edge el; + g + + + let png_from_graph g = + let graph = G.fold_vertex (fun v acc -> + let succs = List.map string_of_expression (G.succ g v)in + let v' = string_of_expression v in + let edges = List.fold_left (fun acc s -> + + acc ^ "\"" ^ v' ^ "\" -> \"" ^ s ^ "\";\n") "" succs in + acc ^ "\"" ^ v' ^ "\";\n" ^ edges + ) g "" in + let dot = "digraph G {\nrankdir=LR;\n" ^ graph ^ "}" in + let oc = open_out "graph.dot" in + Printf.fprintf oc "%s\n" dot; + close_out oc; + ignore (Sys.command "dot -Tpng graph.dot -o graph.png") + + +(*/GRAPH*) + + + +type measure = Measure of int * G.t +(* Une description c'est 1: description de l'environnement et des capacites des robot + 2: robogram *) +type description = Description of (information list) * (expr list) * measure + + + +let rec string_of_description (desc:description) : string = + match desc with + | Description (infos,robogram,_) -> + "Description environnement:\n" ^String.concat "\n" (List.map string_of_information infos) + ^"\nRobogram : \n " ^ String.concat "\n" (List.map string_of_expression robogram) + + +and string_of_information (info: information) : string = +match info with +| Sync s -> "Sync: " ^ (string_of_synchro s) +| Rigidity r ->(match r with + | Rigide -> "Rigidity: Rigide" + | Flexible d -> "Rigidity: Flexible d'une distance delta = " ^ string_of_expression d) + +| Space e -> "Espace: " ^ (string_of_espace e) +| Byzantines b -> string_of_byzantine b +| Sensors s -> "Sensors: [" ^ String.concat "; " (List.map string_of_sensor s) ^ "] " +| Robot r -> "Robot : ["^ String.concat "; " (List.map string_of_field r) ^ "]" +| Roles r -> "Roles :" ^ String.concat "\n " (List.map string_of_role r) +| ActivelyUpdate a -> "Champ qui sont mise a jour par le robogram: " ^ String.concat ", " (List.map string_of_valretr a ) +| Share s ->"Share : " ^ (match s with + |Fullcompass -> "Fullcompass" + |Chirality -> "Chirality" + |DirectionShare -> "Direction" + |OneAxisOrientation ->"1-axis orientation") + + + (** [check_description d] verifie que la description [d] possède bien les informations minimales attendu pour une description et que chaque type d'information soit unique @@ -465,7 +538,7 @@ let check_sensor (s: sensor) (r:field list):bool = let check_sensors_desc (d:description) :bool = let res= List.find_opt (fun x -> not (check_sensor x (get_robot d))) (get_sensors d) in match res with - | Some x -> print_endline("Error : " ^(match x with |Custom (x',_)-> x' | _->"")^" is not declared public in robot"); false + | Some x -> raise(Failure("Error : " ^(match x with |Custom (x',_)-> x' | _->"")^" is not declared public in robot")) | _-> true (**[check_activelyup d] verifie que les champs renseignés dans activelyupdate soient déclarés dans robot @@ -474,9 +547,10 @@ let check_sensors_desc (d:description) :bool = let check_activelyup (d:description) :bool = let field_to_pair f = List.map(fun x -> match x with Public x -> x | Private x -> x) f in let aux s l = List.exists (fun (x,_) -> x = s) (field_to_pair l) in - let res = List.find_opt (fun x -> not (aux x (get_robot d))) (get_activelyup d) in + let fields_to_check f = List.filter (fun x -> (x <> "Location") && (x <> "Direction")) f ;in + let res = List.find_opt (fun x -> not (aux x (get_robot d))) (fields_to_check(get_activelyup d)) in match res with - | Some x -> print_endline("Error : " ^x^" x is not declared in robot"); false + | Some x -> raise(Failure("Error : " ^x^" is not declared in robot")) | _-> true @@ -488,9 +562,11 @@ let check_light d : bool = let rec check flist = ( fun x -> match x with | [] -> true - | Public (_,Light(Intern _))::_ -> false - | Private (_, Light(Extern _))::_ -> false + | Public (_,Light(Intern _))::_ -> raise(Failure("Error light in wrong field")) + | Private (_, Light(Extern _))::_ -> raise(Failure("Error light in wrong field")) | _::t-> check t ) flist in - check (get_robot d) \ No newline at end of file + check (get_robot d) + + diff --git a/lib/gencoq.ml b/lib/gencoq.ml index e11f80a..991f658 100644 --- a/lib/gencoq.ml +++ b/lib/gencoq.ml @@ -1,11 +1,11 @@ open Ast -(*open Formula*) open Coq let geometry =[("isobarycenter",Formula.Raw("isobarycenter")); + ("barycenter",Formula.Raw("barycenter")); ("on_SEC"),Formula.Raw("on_SEC")] let observation =[("elements", Formula.Raw("(elements s)")); ("support"), Formula.Raw("support s")] @@ -113,8 +113,6 @@ let rec expr_to_coq (r : expr) : Formula.t = | Diff -> Infix(expr_to_coq x,"!=",expr_to_coq y) | Impli -> Infix(expr_to_coq x, "->", expr_to_coq y) | Equiv -> Infix(expr_to_coq x,"<->",expr_to_coq y) - - ) | Cons (e1,e2) -> App(Raw("cons"), ([expr_to_coq e1;expr_to_coq e2])) | Fun (s,e) -> Fun(Some s, expr_to_coq e) @@ -185,17 +183,17 @@ let instance_space (s: space) (d : information list): stmt list = *) let instance_updfunc_rigid (valret : string) (d: information list):stmt list = if not(get_space d = "Ring") then - Instance("UpdateFunc",Raw("update_function ("^valret^") (Similarity.similarity "^valret^") unit"),Raw("{update := fun _ _ _ target _ => target;update_compat := ltac:(now repeat intro) }")) - ::RawCoq(["Instance Rigid : RigidSetting.";"Proof using . split. reflexivity. Qed."])::[] + Instance("UpdFun",Raw("update_function ("^valret^") (Similarity.similarity "^valret^") unit"),Raw("{update := fun _ _ _ target _ => target;update_compat := ltac:(now repeat intro) }")) + ::RawCoq(["Instance Rigid : RigidSetting.";"Proof using . split. reflexivity. Qed."])::[] else - Instance("FrameChoice",App(Cst "frame_choice",[Raw("(Z * bool)")]),Raw(" {frame_choice_bijection := + Instance("FC",App(Cst "frame_choice",[Raw("(Z * bool)")]),Raw(" {frame_choice_bijection := fun nb => if snd nb then Ring.sym (fst nb) else Ring.trans (fst nb); frame_choice_Setoid := eq_setoid _ }")):: - Instance("UpdateFunc",Raw("update_function direction (Z * bool) unit"),Raw("{ + Instance("UpdFun",Raw("update_function direction (Z * bool) unit"),Raw("{ update := fun config g _ dir _ => move_along (config (Good g)) dir; update_compat := ltac:(repeat intro; subst; now apply move_along_compat) }"))::[] let instance_updfunc_Flexible (d:expr) (valret : string): stmt list = - Instance("UpdateFunc",Raw("update_function (path "^valret^") (Similarity.similarity "^valret^") ratio"),Raw(" FlexibleUpdate "^string_of_expression d)) + Instance("UpdFun",Raw("update_function (path "^valret^") (Similarity.similarity "^valret^") ratio"),Raw(" FlexibleUpdate "^string_of_expression d)) ::[] @@ -206,12 +204,12 @@ let instance_updfunc_Flexible (d:expr) (valret : string): stmt list = *) let instance_rigidity (r:rigidity) (valret : string) (world: information list): stmt list = match r with(*TODO: Est-ce la bonne maniere d'ecrire l'UpdateFunc?*) - | Rigide -> Instance("RobotChoice",Raw("robot_choice "^ valret),Raw("{ robot_choice_Setoid := "^valret^"_Setoid}")) - ::Instance("ActiveChoice",App(Var(0,"update_choice"),[Cst("unit")]),Raw("NoChoice")) + | Rigide -> Instance("RC",Raw("robot_choice "^ valret),Raw("{ robot_choice_Setoid := "^valret^"_Setoid}")) + ::Instance("UC",App(Var(0,"update_choice"),[Cst("unit")]),Raw("NoChoice")) :: instance_updfunc_rigid valret world - | Flexible d -> Instance("RobotChoice",Raw("robot_choice (path "^ valret^")"),Raw("{ robot_choice_Setoid := path_Setoid "^valret^"}")) - ::Instance("ActiveChoice",App(Cst("update_choice"),[Cst("ratio")]),Raw "Flexible.OnlyFlexible") + | Flexible d -> Instance("RC",Raw("robot_choice (path "^ valret^")"),Raw("{ robot_choice_Setoid := path_Setoid "^valret^"}")) + ::Instance("UC",App(Cst("update_choice"),[Cst("ratio")]),Raw "Flexible.OnlyFlexible") ::Var(string_of_expression d,Raw("R")) ::instance_updfunc_Flexible d valret @@ -251,10 +249,10 @@ let instance_byzantine (x : int ) : stmt list = *) let instance_sync (s : synchro) : stmt list = match s with - | Async -> [RawCoq(["Instance InactiveChoice: Async not implemented - Instance InactiveFunc : Async not implemented"])] - | _ -> [RawCoq([ "Instance InactiveChoice : inactive_choice unit := NoChoiceIna."; - "Instance InactiveFunc : inactive_function unit := NoChoiceInaFun."])] + | Async -> [RawCoq(["Instance ic: Async not implemented + Instance InaFun : Async not implemented"])] + | _ -> [RawCoq([ "Instance IC : inactive_choice unit := NoChoiceIna."; + "Instance InaFun : inactive_function unit := NoChoiceInaFun."])] (**[instance_sensors s] permet d'instancier l'observation celon la liste des capteurs [s] Ne prend en compte que la range et la multiplicité pour le moment @param s [sensor list] correspondant a la liste des capteurs de la description @@ -354,39 +352,51 @@ let generate_robogram (r : expr list) (d: information list) : stmt list = ::[] | [] -> Def ("Robogram_pgm (s : observation)",Raw(valretcoq),Raw("[]")) ::[] -let rec n_times (x : int) :string = - if x > 0 then n_times (x -1)^"*"^"nat" - else "nat" - -let generate_lemmas (g : Graphtest.G.t) : stmt list = - Graphtest.G.fold_vertex (fun v acc -> - let succs = Graphtest.G.succ g v in + +(**[generate_lemmas g] retourne la liste de stmt correspondant au lemme extrait du graph g + @param g [G.t] + @return [stmt list]*) +let generate_lemmas (g : Ast.G.t) : stmt list = + Ast.G.fold_vertex (fun v acc -> + let succs = Ast.G.succ g v in + let forall v = + String.concat " " (List.map string_of_expression (Ast.get_param v)) + in if succs <> [] then - let rcs = List.map (fun x -> x ^ " (round config)") succs in - Lemma("lemma"^string_of_int (List.length acc),Raw(v^" config -> "^String.concat " \\/ " rcs),[])::acc + let rcs = List.map (fun x -> x ^ " (round Robogram da config)") (List.map string_of_expression succs) in + Lemma("lemma"^string_of_int (List.length acc),Forall(("config "^forall v),Raw(string_of_expression v^" config -> "^String.concat " \\/ " rcs)),[])::acc else acc ) g [] - +(**[generate_measure m] retourne la liste de stmt correspondant a la generation de la mesure + @param m [measure] + @return [stmt list] *) let generate_measure (Measure(i,g): measure) : stmt list = - let ret = String.concat "*"(List.init i (fun _ ->"nat")) in + let ret = String.concat "*"(List.init i (fun _ ->"nat")) in let to_change = String.concat ","(List.init i (fun _ ->"0%nat"))in - Graphtest.png_from_graph g; - Graphtest.print_relations_test g; - let lems =List.rev (generate_lemmas g) in + Ast.png_from_graph g; + let lems =Var("da",Cst "demonic_action")::List.rev (generate_lemmas g) in RawCoq(["Function measure (s : observation) : "^ret ^" := - - ("^to_change^")."; (*TODO: à modifié pour utiliser le graph*) + ("^to_change^")."; (*TODO: *) "Instance measure_compat : Proper (equiv ==> Logic.eq) measure."])::proof_to_complete@lems -let generate (Description(d,r,m) : description) (section_name : string)= - if Ast.check_light (Description (d,r,m)) then + +(**[generate_coq d] genere a partir de la description complete (world,robogram,measure) l'instance coq + @param descritpion + @return [unit] *) +let generate_coq (Description(d,r,m) : description) (section_name : string)= + if Ast.check_light (Description (d,r,m)) && + Ast.check_activelyup (Description(d,r,m)) && + Ast.check_sensors_desc (Description(d,r,m)) + then + let file_out = open_out ("./generate/"^section_name^".v") in let format_file = Format.formatter_of_out_channel file_out in let section = Section(section_name,(generate_instances d)@newline::generate_robogram r d@newline::generate_measure m) in Format.fprintf format_file "%a@." Coq.pretty_l ((generate_requires d)@[section]); - close_out file_out + close_out file_out; + print_endline(section_name^".v is generated") else - raise(Failure("Error light in wrong field")) \ No newline at end of file + () \ No newline at end of file diff --git a/lib/graphtest.ml b/lib/graphmeasure.ml similarity index 100% rename from lib/graphtest.ml rename to lib/graphmeasure.ml diff --git a/lib/parser.mly b/lib/parser.mly index 777e464..113c850 100644 --- a/lib/parser.mly +++ b/lib/parser.mly @@ -1,6 +1,5 @@ %{ open Ast - open Graphtest %} %token EOF @@ -311,23 +310,24 @@ pattern : measure: -| PARENOPEN l = separated_list(COMMA,VARIABLE) PARENCLOSE el = edge_list {Measure(List.length l,graph_from_edges el)} + | PARENOPEN l = separated_list(COMMA,VARIABLE) PARENCLOSE el = edge_list {Measure(List.length l,graph_from_edges el)} edge : -| v1 = sommet ARROW v2 = sommet {Nolab(v1,v2)} + | v1 = sommet ARROW v2 = sommet {Nolab(v1,v2)} edge_list : -| v = list(edge) { v } + | v = list(edge) { v } sommet : -| p = prop {string_of_expression p} + | p = prop {p} prop : -| PARENOPEN prop propop prop PARENCLOSE {BinOp($2,$3,$4)} -| NOT prop {Not $2} -| VARIABLE {Var $1} + | PARENOPEN prop propop prop PARENCLOSE {BinOp($2,$3,$4)} + | NOT prop {Not $2} + | VARIABLE {Var $1} + | PARENOPEN f = appfunc PARENCLOSE {f} propop : -| AND {And} -| OR {Or} -| IMPLICATION {Impli} -| EQUIVALENCE {Equiv} \ No newline at end of file + | AND {And} + | OR {Or} + | IMPLICATION {Impli} + | EQUIVALENCE {Equiv} \ No newline at end of file -- GitLab