• Aucun résultat trouvé

CHAPITRE V. TRANSFORMATION DE MODELES M2M

5.3. Règles génériques de transformation

5.3.4. Règles spécifiques à AtomicDEVS

a) Répertorier les valeurs qui deviendront LitteralBasicValues

À présent, nous nous proposons de collecter l’intégralité des valeurs manipulées par le modèle source et de les instancier sous forme de LBV dans le modèle DEVS cible avec une seule règle. Nous restons très généraux, l’implémentation étant trop liée au type de méta-modèle source. On suppose donc ici que l’intégralité des valeurs a été collectée suite à l’exécution de ces règles.

rule collectLBV(s : SourceMM!Model) { foreach (s.valeursManipulees){

//selon le formalisme d’entrée, la collecte des valeurs est différente, nous supposons ici qu’elle est déjà faite grâce à « valeursManipulees » et que le type est vérifié

createLBV(s.valeursManipulées) } }

rule createLBV(m : valeur) { //le type de la valeur n’est pas connu, on le //renseignera donc manuellement, mais on peut aussi écrire une fonction qui le

fait automatiquement

to lbv : DEVS!LitteralBasicValue

lbv.isAlwaysTyped=renseigné manuellement lbv.(int/str/char/bool)val=m.valeur }

Pour finir, il faut simplement créer un lien entre la référence handles de AtomicDEVS et ces LBV, en appelant collectLBV() sur l’instance s :

dev.handles = collectLBV(s)

158 b) Création d’une ou plusieurs StateVar

L’état d’un modèle atomique DEVS à un instant t est caractérisé par les valeurs des différentes StateVar qui le composent (notion de dimension). La tâche qui consiste à créer ces StateVar dans le modèle cible en fonction du modèle source dépend de la représentation des états dans le formalisme source.

Au vu de la caractérisation des formalismes d’entrée que nous avons effectuée, nous pouvons supposer ici que les différents types d’états du modèle source sont connus et que leurs valeurs ont été créées sous forme de LitteralBasicValues dans le modèle cible. Nous supposons par ailleurs que la valeur initiale de chaque famille d’états (qui correspondront à des StateVar) du modèle source est connue. Il ne faut pas oublier que les StateVars ne contiennent pas toutes des types énumérés et que les valeurs littérales qu’elles sont susceptibles d’avoir ne sont pas forcément connues à l’avance. L’essentiel est que chaque StateVar créée possède une valeur initiale.

Nous proposons ici le squelette de cette règle dont le but est de créer une StateVar et de renseigner sa valeur initiale avec une LBV déjà créée. Cette règle doit ensuite être adaptée au cas par cas. Elle est appelée pour chaque nouvelle StateVar que l’on désire créer.

rule createStateVar() { to sv : DEVS!StateVar

sv.DEVSid= ‘stateVar1’ //à incrémenter automatiquement sv.isAlwaysTyped=renseigné manuellement

sv.initial_value=<LBV créée précédemment correspondant à l’état initial>

}

c) Création des règles correspondant aux Conditions

Avant de pouvoir exprimer des fonctions DEVS à partir notamment des transitions présentes dans le modèle source, nous devons disposer des éléments qui composent nos règles DEVS (pour mémoire, composées de Conditions et d’Actions).

− fonctions permettant de réaliser des tests (sur les états, le port d’entrée…),

− fonctions permettant de décrire des actions (changement d’état, envoi de valeur sur une sortie).

Les règles de transformation dont nous fournissons la description ci-après ne seront jamais utilisées de manière isolée mais génèreront les briques des DEVSRules composant chaque fonction DEVS.

La règle qui nous sera la plus utile est celle qui permet la création d’une

StateVarComparison. Le membre gauche de cette règle porte sur une StateVar, que l’on supposera unique pour simplifier, et le membre droit contiendra une LBV choisie parmi les LBV déjà créées dans le modèle de destination, telle que cette LBV corresponde à la valeur de l’état source de la transition passée en paramètre. Si la StateVar n’était pas unique dans le modèle DEVS cible, il faudrait alors implémenter, en amont, une fonction qui sélectionne celle qui est concernée par la transition.

rule createSVC(s: SourceMM!State, sv: DEVS!StateVar) { to sv : DEVS!StateVarComparison

159 left_member <- sv, // on suppose que la //SVC se fait toujours sur stateVar1

right_member <- selectionner(DEVS!LBV, s.valeur) }

Dans le même ordre d’idées, on peut implémenter simplement la règle createIPC() qui se charge de créer une InputPortComparison à partir de la transition (supposée évènementielle) passée en paramètre, ou à partir d’un évènement d’entrée. Le membre gauche de cette règle est un port d’entrée, choisi de la même manière que la fonction selectionner() ci-dessus a choisi une LBV dont la valeur correspondait avec la valeur de l’état source. Le membre droit est une DEVSXpression, en général une LBV, choisie aussi de la même manière.

rule createIPC(t: SourceMM!Transition) { //t est supposée évènementielle

left_member <- selectionner(DEVS!InputPort, t.valeurPort) right_member <- selectionner(DEVS!LBV, t.valeurEvenementEntree) }

d) Création des règles correspondant aux Actions

Commençons par décrire la règle la plus simple, celle qui à partir d’une transition du modèle source décrit en termes DEVS un changement d’état (StateChangeAction). Elle se base également sur une transition, et son membre gauche est stateVar1. Cette règle ne présente aucune difficulté particulière.

rule createSCA(t: SourceMM!Transition, sv: DEVS!StateVar) { to sv : DEVS!StateChangeAction

state_to_be_changed <- sv

new_value <- selectionner(DEVS!LBV, t.valeurEtatCible) }

Enfin, définissons la règle qui décrit l’action d’envoyer une valeur sur un port de sortie (OutputAction). Le modèle source n’a pas forcément de port de sortie ni de règle associée. Mais, comme DEVS a toujours besoin d’une fonction de sortie, il faudra pourtant en créer une.

Dans ce cas, la fonction de sortie sera associée à un état (en fait, à la valeur d’une StateVar), et il incombe au méta-modeleur de choisir de quelle manière : arbitrairement si le formalisme source ne se prête pas à la création de fonctions de sortie dans DEVS, ou pas si au contraire certaines transitions du formalisme source peuvent correspondre à des sorties DEVS. Un bon exemple est celui des états terminaux d’un automate à états finis passé en entrée.

Ici, on supposera que si elle existe dans le modèle source, l’action de renvoyer une valeur sur un port de sortie est contenue dans le modèle. Le port est choisi parmi la liste de ports du modèle DEVS dont le portID correspond au port de sortie concerné dans le modèle d’entrée. Le message est choisi parmi les LBV créées dans le modèle DEVS.

rule createOA(m: SourceMM!Model) { to sv : DEVS!OutputAction if (m.output<>0) {

message <- selectionner(DEVS!LBV, m.output.message) port <- selectionner(DEVS!OutputPort, m.output.idPort)} }

160 e) Fonctions DEVS

À partir des règles ci-dessus, nous pouvons construire facilement dans le modèle cible toutes les règles DEVS dont nous avons besoin.

Commençons par la plus simple, la règle qui crée des DeltaIntRule. On suppose que la transition passée en paramètre est une transition temporelle, et pas une transition déclenchée par une perturbation extérieure survenant sur un port d’entrée.

rule createDeltaIntRule(t: SourceMM!Transition, sv: DEVS!StateVar) { //t est

temporelle

to sv : DEVS!DeltaIntRule

tests <- createSVC(t.source,sv) changes_state <- createSCA(t,sv) }

Créer des TARules n’est guère plus complexe. Il suffit de récupérer dans le modèle source la durée de vie de chaque état.

rule createTARule(s: SourceMM!State, sv: DEVS!StateVar) { //t est temporelle to sv : DEVS!TimeAdvanceRule

tests <- createSVC(s,sv) ta_value <- t.time

}

Créer une DeltaExtRule se fait de manière très similaire à la création d’une

DeltaIntRule. Il suffit seulement de renseigner en plus le type d’évènement qui surviendra. Ici la transition t est supposée évènementielle.

rule createDeltaExtRule(t: SourceMM!Transition, sv: DEVS!StateVar) { //t est

évènementielle to sv : DEVS!DeltaExtRule tests <- createSVC(t.source,sv) tests_input_event <- createIPC(t) changes_state <- createSCA(t,sv) }

Enfin, une LambdaRule dispose, en plus d’une StateVarComparison basique, du message que le modèle devra envoyer sur le port de sortie. Elle est, selon la définition de base du formalisme DEVS, associée à un état, et théoriquement prend donc en paramètre un état, non une transition. Cependant, nous faisons le choix de passer en paramètre de cette règle de transformation une transition, pour une raison pratique : il arrive souvent que la sortie soit associée à une transition, dans les formalismes de la famille F2 (d’où l’appel à t.message) rule createLambdaRule(t: SourceMM!Transition, sv:DEVS!StateVar){

//t est temporelle to sv : DEVS!LambdaRule tests <- createSVC(s,sv) sends_message <- createOA(t.message) } f) Synthèse

Nous venons d’énoncer des règles qui, pour une famille donnée, caractérisée en 5.1.4, permettent de transformer tout modèle source en un modèle DEVS équivalent, typé par le méta-modèle MetaDEVS. Nous allons maintenant aborder concrètement deux cas de transformations vers DEVS, en adaptant, toujours à l’aide du pseudo-code que nous avons

161 présenté, les fonctions génériques ci-dessus. Nous ne ferons pas figurer ici les collectes des éléments dans les modèles sources, car elles alourdiraient considérablement notre description. De plus, la manière de collecter des éléments dans les modèles sources dépend en grande partie de l’implémentation choisie (i.e. du langage M2M employé). Nous nous contenterons donc de décrire brièvement ces collectes et nous nous concentrerons uniquement sur l’élément essentiel des règles de transformation : le corps des règles de transformation proprement dites. Nous renvoyons le lecteur aux annexes de ce mémoire pour consulter le code complet, implémenté, des transformations M2M avec ATL : l’annexe 5 donne le code de la transformation BasicDEVS vers DEVS, l’annexe 6 le code de la transformation FSM vers DEVS.