From 2c9a9bd84bd4da750b6baf8e08ca3fdde5c63247 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 16 Jul 2014 15:16:06 +0200 Subject: Many corrections. --- readme.pdf | Bin 211011 -> 221365 bytes readme.tm | 686 +++++++++++++++++++++++++++++++++---------------------------- 2 files changed, 369 insertions(+), 317 deletions(-) diff --git a/readme.pdf b/readme.pdf index a0d4280..c97712f 100644 Binary files a/readme.pdf and b/readme.pdf differ diff --git a/readme.tm b/readme.tm index 2f0e33f..c7a0b2f 100644 --- a/readme.tm +++ b/readme.tm @@ -23,7 +23,7 @@ <\itemize> noyau dataflow (opérations arithmétiques élémentaires, opérateurs > et ), pas de prise en charge des - horloges explicites (primitves , , ...) + horloges explicites (primitives , , ...) blocs @@ -32,7 +32,7 @@ prises en compte) - Dans ce document nous metterons au clair les points suivants : + Dans ce document nous mettrons au clair les points suivants : <\enumerate> Spécification du sous-ensemble de SCADE considéré @@ -57,6 +57,8 @@ + Par la suite, nous ne considérons que des programmes SCADE bien typés. + @@ -158,8 +160,11 @@ >, il existe un unique état > qui remplit la condition. - Pour traduire l'init et le reset, on introduit dans chaque scope - > plusieurs variables : + Un scope > correspond à un ensemble de définitions (de + variables, d'automates, ou de blocs activate), identifiés par un chemin. + Chaque scope dispose d'une horloge propre. Pour traduire l'init et le + reset, on introduit dans chaque scope > plusieurs variables + : <\itemize> >> : indique que le scope devra être @@ -168,8 +173,8 @@ >> : indique que le scope est à l'état initial dans ce cycle - >> : indique qu'un scope est actif dans - ce cycle + >> : indique qu'un scope est actif dans ce + cycle Un nouveau scope est introduit dans chaque body d'un bloc activate ou d'un @@ -185,15 +190,15 @@ défini - L'état > est défini par |)>=true>, + L'état > est défini par |)>=tt>, où est le scope racine englobant tout le programme ; toutes les autres variables de > pouvant prendre n'importe quelle valeur. - On suppose que chaque instance de est numérotée, et pour - chaque e>, on introduit la variable > qui - enregistre la valeur de dans l'état et qui sert de mémoire pour le - pre. + On suppose que chaque instance de est numérotée. Pour chaque + e>, on introduit la variable > qui + enregistre la valeur de dans le cycle courant et qui sert de + mémoire pour le pre lors du cycle suivant. Par la suite, que ce soit dans l'étude de la sémantique par réduction ou par traduction, on notera toujours la mémoire (c'est-à-dire @@ -203,20 +208,27 @@ On définit notre ensemble d'environnements comme étant - \\\|}>>, la - valeur > signifiant qu'une variable n'a pas encore pris sa + \\\|}>>, la + valeur > signifiant qu'une variable n'a pas encore pris sa valeur. Pour chaque élément de programme, on va introduire un certain nombre de règles de réduction. On applique ces règles jusqu'à en déduire - s>, avec x\\,s\\>. + s>, avec x\\,s\\>. - Les déductions de la forme s> signifient ``avec la - mémoire , on peut déduire du système l'état (partiel) ''. + Les déductions de la forme s> signifient \S avec la + mémoire , on peut déduire du système l'état (partiel) \T. Les déductions de la forme e\>v> - signifient ``avec la mémoire et l'état partiellement calculé + signifient \S avec la mémoire et l'état partiellement calculé , l'expression calculée dans le scope > - prend la valeur ''. + prend la valeur \T (la flèche >> + correspond à une réduction par valeur dans le scope >). + + On notera \x=e> pour signifier \S dans le scope + > on a la définition \T, de même pour les + définitions de blocs activate et d'automates. On notera + \pre e> pour signifier que + e> apparaît dans le scope >. @@ -227,7 +239,7 @@ toujours actif et jamais reset par la suite : <\equation*> - s|l\s\t|]>\f|]>> + s|l\s\tt|]>\ff|]>> \; @@ -240,34 +252,32 @@ init ou pas : <\equation*> - s>||r>>>>>>|l\s>\t|]>> + s>||r>>>>>>|l\s>\tt|]>> <\equation*> - s>||\r>>||>|)>=t>>>>>|l\s>\f|]>> + s>||\r>>||>|)>=tt>>>>>|l\s>\ff|]>> <\equation*> - s>||\r>>||>|)>=f>>>>>|l\s>\l>|)>|]>> + s>||\r>>||>|)>=ff>>>>>|l\s>\l>|)>|]>> \; En particulier, pour le scope racine on instancie ces règles avec - r|)>\l|)>=t> + r|)>\l|)>=tt> Ces règles permettent d'exprimer le calcul d'une expression. On note - > le scope dans lequel l'expression est évaluée. - - <\equation*> - c\>c>,c\\ - + > le scope dans lequel l'expression est évaluée. On note + > n'importe quel opérateur binaire : + ,/,mod,\,\,\,\,=,\,\,\>. - <\equation*> - \\|l,s\x\>s>,x\\ - + <\eqnarray*> + c\>c>,c\\>||\\|l,s\x\>s>,x\\>>>> + <\equation*> pre e\>l|)>> @@ -277,13 +287,9 @@ e\>v>||e\>v>>>>>|l,s\e\e\>v\v> - <\equation*> - >|)>=t>||e\>v>>>>>|l,s\\e|)>\>v> - - - <\equation*> - >|)>=f>||e\>v>>>>>|l,s\\e|)>\>v> - + <\eqnarray*> + >|)>=tt>||e\>v>>>>>|l,s\\e|)>\>v>>||>|)>=ff>||e\>v>>>>>|l,s\\e|)>\>v>>>>> + <\equation*> etc\ @@ -295,20 +301,26 @@ >, on donne les deux règles suivante : <\equation*> - s>||>|)>=t>||e\>v>>>>>|l\s\v|]>> + s>||>|)>=tt>||e\>v>>>>>|l\s\v|]>>,\\pre + e <\equation*> - s>||>|)>=f>>>>>|l\s\l|)>|]>> + s>||>|)>=ff>>>>>|l\s\l|)>|]>>,\\pre + e - + <\equation*> + \; + - Pour toute affectation apparaissant dans le scope + + + Pour toute définition apparaissant dans le scope >, on donne la règle suivante : <\equation*> - s>||>|)>=t>||e\>v>>>>>|l\sv|]>> + s>||>|)>=tt>||e\>v>>>>>|l\sv|]>>,\\x=e @@ -322,60 +334,52 @@ > : <\equation*> - s>||>|)>=f>>>>>|l\s>\f|]>>\f|]>> + s>||>|)>=ff>>>>>|l\s>\ff|]>>\ff|]>> - <\equation*> - s>||>|)>=t>||c\>t>>>>>|l\s>\t|]>>\f|]>> - + <\eqnarray*> + s>||>|)>=tt>||c\>tt>>>>>|l\s>\tt|]>>\ff|]>>>||s>||>|)>=tt>||c\>ff>>>>>|l\s>\ff|]>>\tt|]>>>>>> + - <\equation*> - s>||>|)>=t>||c\>f>>>>>|l\s>\f|]>>\t|]>> - + (implicitement sur toutes les règles : \activate if + c then b else b>) Les deux scopes > et > héritent de la condition de reset du scope >. - On note l'automate, > son état initial. Les règles - d'activation des différents scopes des états se font en fonction de la - variable > définie pour l'automate comme suit : - - <\equation*> - s>||r>>>>>>|l\s=s|]>> - + On se place dans le cadre \A>. On note + > l'état initial de . Les règles d'activation des + différents scopes des états se font en fonction de la variable + > définie pour l'automate comme suit : - <\equation*> - s>||\r>>>>>>|l\s=l|)>|]>> - + <\eqnarray*> + s>||r>>>>>>|l\s=s|]>>>||s>||\r>>>>>>|l\s=l|)>|]>>>>>> + Puis pour chaque état >, on définit > son scope dans lequel on traduit son corps, puis on rajoute la règle d'activation suivante : - <\equation*> - s>|||)>=s>>>>>|l\s>=t|]>> - - - <\equation*> - s>|||)>\s>>>>>|l\s>=f|]>> - + <\eqnarray*> + s>|||)>=s>>>>>|l\s>=tt|]>>>||s>|||)>\s>>>>>|l\s>=ff|]>>>>>> + Dans tous les scopes >, la condition de reset peut être éventuellement augmentée d'un > avec une condition du type >|)>=t>, où la variable - >> est mise à true dès que l'on emprunte - une transition qui reset, et à false le reste du temps. + >> est mise à dès que l'on + emprunte une transition qui reset, et à le reste du temps. La règle pour une transition |c>s> sont du style : <\equation*> - s>|||)>=s>||c\>t>>>>>|l\s\s|]>> + s>|||)>=s>||c\>tt>>>>>|l\s\s|]>> - À cela, il faut rajouter les conditions qui disent que l'on emprune + À cela, il faut rajouter les conditions qui disent que l'on emprunte exactement une transition à chaque cycle, ainsi que la partie qui définit les variables >>. @@ -428,110 +432,81 @@ Initialisation : - <\equation*> - s|l\s\t|]>\f|]>> - - - <\equation*> - s - >|||)>=t>>>>>|l\s>\t|]>> - - - <\equation*> - s - >|||)>=f>|||)>=t>>>>>|l\s\f|]>> - + <\eqnarray*> + s|l\s\tt|]>\ff|]>>>||s + >|||)>=tt>>>>>|l\s\tt|]>>>>>> + - <\equation*> - s - >|||)>=f>|||)>=f>>>>>|l\s\l|)>|]>> - + <\eqnarray*> + s + >|||)>=ff>|||)>=tt>>>>>|l\s\ff|]>>>||s + >|||)>=ff>|||)>=ff>>>>>|l\s\l|)>|]>>>>>> + - Affectation : + Définition (la réduction par valeur de en + une valeur se fait selon les règles données ci-dessus) : <\equation*> - s>|||)>=t>||a-b\v>>>>>|l\sv|]>> + s>|||)>=tt>||a-b\v>>>>>|l\sv|]>> - Affectations de > et : + Définitions de > et : <\equation*> - s>|||)>=t>||pre|)> + s>|||)>=tt>||pre|)> a\v>>>>>|l\sv|]>> <\equation*> - s>|||)>=t>||pre + s>|||)>=tt>||pre b|)>\v>>>>>|l\sv|]>> - Affectation de : + Définition de : <\equation*> - s>|||)>=t>||not + s>|||)>=tt>||not pre half|)>\v>>>>>|l\sv|]>> Mémorisation des valeurs pour , et - : + (on écrit aussi les règles pour le cas où le scope + est inactif à titre d'exemple simplement ; en pratique celles-ci sont + éliminées puisque le scope racine est toujours actif) : - <\equation*> - s>|||)>=t>||a\v>>>>>|l\s\v|]>> - - - <\equation*> - s>|||)>=t>||b\v>>>>>|l\s\v|]>> - - - <\equation*> - s>|||)>=t>||half\v>>>>>|l\s\v|]>> - - - <\equation*> - s>|||)>=f>>>>>|l\s\l|)>|]>> - + <\eqnarray*> + s>|||)>=tt>||a\v>>>>>|l\s\v|]>>>||s>|||)>=ff>>>>>|l\s\l|)>|]>>>>>> + - <\equation*> - s>|||)>=f>>>>>|l\s\l|)>|]>> - + <\eqnarray*> + s>|||)>=tt>||b\v>>>>>|l\s\v|]>>>||s>|||)>=ff>>>>>|l\s\l|)>|]>>>>>> + - <\equation*> - s>|||)>=f>>>>>|l\s\l|)>|]>> - + <\eqnarray*> + s>|||)>=tt>||half\v>>>>>|l\s\v|]>>>||s>|||)>=ff>>>>>|l\s\l|)>|]>>>>>> + Activation des deux moitiés du activate : - <\equation*> - s>|||)>=t>||half\t>>>>>|l\s:=t|]>\f|]>> - - - <\equation*> - s>|||)>=t>||half\f>>>>>|l\s:=f|]>\t|]>> - + <\eqnarray*> + s>|||)>=tt>||half\tt>>>>>|l\s:=tt|]>\ff|]>>>||s>|||)>=tt>||half\ff>>>>>|l\s:=ff|]>\tt|]>>>>>> + <\equation*> - s>|||)>=f>>>>>|l\s:=f|]>\f|]>> + s>|||)>=ff>>>>>|l\s:=ff|]>\ff|]>> - Affectation de et dans la première moitié : + Définition de et dans la première moitié : - <\equation*> - s>|||)>=t>||la+1\v>>>>>|l\sv|]>> - - - <\equation*> - s>|||)>=t>||lb\v>>>>>|l\sv|]>> - + <\eqnarray*> + s>|||)>=tt>||la+1\v>>>>>|l\sv|]>>>||s>|||)>=tt>||lb\v>>>>>|l\sv|]>>>>>> + Et dans la deuxième moitié : - <\equation*> - s>|||)>=t>||la\v>>>>>|l\sv|]>> - - - <\equation*> - s>|||)>=t>||lb+1\v>>>>>|l\sv|]>> - + <\eqnarray*> + s>|||)>=tt>||la\v>>>>>|l\sv|]>>>||s>|||)>=tt>||lb+1\v>>>>>|l\sv|]>>>>>> + Et c'est tout. @@ -549,7 +524,7 @@ On utilise des formules ``à trous'' pour faire la traduction. Un trou > correspond à la fonction e>, une formule x=\> correspond à la fonction - a\x=e>, etc. L'argument d'une fonction trou peut + a\x=e>, etc. L'argument d'une formule à trou peut aussi être un couple d'expressions, ainsi +\> correspond à la fonction \e+f>. @@ -559,23 +534,40 @@ > et devant être placée dans le trou . En pratique, on divise en deux fonctions, une pour les expressions booléennes et une pour les expressions numériques. Le résultat d'une traduction doit - généralement être une formule booléenne. - - On note > n'importe quel opérateur binaire : - ,/,mod,\,\,\,\,=,\,\,\>. + être une formule booléenne. Les règles sont les suivantes : <\eqnarray*> - ,,e,\,e|)>,w|)>>||,e,\|)>,\,T,e,\|)>|]>>>|c\\,,,e,\,e|)>,w|)>>||,e,\f.T,,\,e|)>,w,\,\,\|]>|)>|)>>>|c\\,T,c,w|)>>||>>|x\\,T,x,w|)>>|||]>>>|,pre - e,w|)>>|||)>|]>>>|,e\e,w|)>>||>|)>\T,e,w|)>|)>\s>|)>\T,e,w|)>|)>>>|,e\e,w|)>>||,,e|)>,w\\|]>|)>>>|,if - c then e else e,w|)>>||,c,\|)>\T,e,w|)>|)>\T,c,\|)>\T,e,w|)>|)>>>|,-e,w|)>>||,e,w|]>|)>>>|,\e,w|)>>||,e,w\|]>|)>>>>> + e,w|)>>|||)>|]>>>|,e\e,w|)>>||>|)>\T,e,w|)>|)>\s>|)>\T,e,w|)>|)>>>|,e\e,w|)>>||,,e|)>,w\\|]>|)>>>|,if + c then e else e,w|)>>||,c,\|)>\T,e,w|)>|)>\T,c,\|)>\T,e,w|)>|)>>>|,-e,w|)>>||,e,w|]>|)>>>|,\e,w|)>>||,e,w\|]>|)>>>>> + + + Par la suite, on définira la fonction de traduction d'une définition par : + + <\eqnarray*> + ,x=e|)>>||,e,s=\|)>>>>> - Par la suite, une affectation sera traduite par la formule - booléenne ,e,x=\|)>>. + Dans le cas d'une multi-affectation ,\,x=e>, + on utilisera la traduction suivante : + + <\eqnarray*> + ,,\,x=e|)>|)>>||,e,s|)>=\\*\*\s|)>=\|)>>>>> + + + Dans le cas où l'on doit traduire une instanciation de noeud + ,\,v|)>> (c'est le cas + dans notre implémentation puisqu'on ne fait pas d'inlining), on nomme + ,\,r> les valeurs renvoyées par le noeud et + on utilise la règle ,n,\,v|)>,w|)>=w|)>,\,s|)>|]>>. + Il faut par ailleurs générer la traduction des définitions données dans le + noeud et s'occuper de passer les arguments (nommés + ,\,arg>), en introduisant des équations du + type ,v,s|)>=\|)>>. <\example> Effectuons par exemple la traduction de 0 then y @@ -583,7 +575,7 @@ <\eqnarray*> ||,if - y\0 then y else -y,x=\|)>>>|||,y\0,\|)>\T,y,x=\|)>|)>\T,y\0,\|)>\T,-y,x=\|)>|)>>>|||0\x=y|)>\0|)>\x=-y|)>>>>> + y\0 then y else -y,s=\|)>>>|||,y\0,\|)>\T,y,s=\|)>|)>\T,y\0,\|)>\T,-y,s=\|)>|)>>>|||\0\s=s|)>\\0|)>\s=-s|)>>>>> @@ -593,12 +585,12 @@ <\eqnarray*> ||,0\prex + 1,s=\|)>>>|||>|)>\T,0,s=\|)>|)>\s>|)>\T,prex - + 1,s=\|)>|)>>>|||>|)>\s=0|)>\s>|)>\T,x,1|)>,s=\+\|)>|)>>>|||>|)>\s=0|)>\s>|)>\=\+\|)>,prex,\|)>,T,1,\|)>|)>|)>>>|||>|)>\s=0|)>\s>|)>\=\+\|)>|)>,1|)>|)>>>|||>|)>\s=0|)>\s>|)>\s=l|)>+1|)>>>>> + + 1,s=\|)>|)>>>|||>|)>\s=0|)>\s>|)>\T,x,1|)>,s=\+\|)>|)>>>|||>|)>\s=0|)>\s>|)>\T,1,|s=l|)>+\|)>|)>|)>>>|||>|)>\s=0|)>\s>|)>\s=l|)>+1|)>>>>> Remarque : dans une étape à part, il faut penser à mémoriser une valeur pour >, c'est-à-dire à introduire l'équation - |)>=s> + |)>=s>. @@ -611,11 +603,11 @@ activate). De manière générale, un scope a deux traductions qui sont produites : une pour le cas où ce scope est actif, et une pour le cas où il est inactif (dans le cas inactif, il s'agit simplement de perpétuer les - mémoires). Ainsi la traduction d'un bloc `` else b>'' sera du style + mémoires). Ainsi la traduction d'un bloc \S else b> \T sera du style T|)>\T|)>|)>\c\T|)>\T|)>|)>>. - Tout cela est long à écrire, aussi nous nous contenterons de donner un + Tout ceci est long à écrire, aussi nous nous contenterons de donner un exemples. <\example> @@ -653,16 +645,15 @@ fixe. Ce n'est cependant pas cette solution que nous avons choisi de mettre en - place, notre solution est plus proche de la sémantique par réduction - définie plus haut. + place, notre solution est plus proche de la sémantique par réduction. Nous avons choisi de représenter un état du programme en cours de calcul comme une valeur mutables, où les variables sont calculées au fur et à mesure qu'on les demande. La structure peut donc contenir à un instant donné pour une certaine variable soit une valeur, soit une fonction - à appeller pour que cette valeur soit calculée et rajoutée à . + à appeler pour que cette valeur soit calculée et rajoutée à . - La procédure de calcul consiste à activer le scope racine, puis à appeller + La procédure de calcul consiste à activer le scope racine, puis à appeler les fonctions de calcul sur les variables de sortie jusqu'à ce qu'on obtienne des valeurs. On enregistre ensuite la portion d'état qui nous intéresse pour le cycle suivant. @@ -670,20 +661,28 @@ L'activation d'un scope se fait selon la procédure suivante : <\itemize> - Pour une affectation , rajouter dans pour la - variable la fonction qui calcule et rajoute la valeur - trouvée dans . + Pour une définition de variable , rajouter dans + pour la variable la fonction qui calcule et rajoute la + valeur trouvée dans . Pour un bloc activate, rajouter dans pour toutes les - variables returnées par le bloc, la fonction qui choisit la branche à + variables renvoyées par le bloc, la fonction qui choisit la branche à activer en calculant les conditions et active le scope correspondant. Pour un automate, rajouter dans pour toutes les variables - returnées par l'automate, la fonction qui choisit l'état à activer en se + renvoyées par l'automate, la fonction qui choisit l'état à activer en se basant sur l'état enregistré au cycle précédent, et active le scope correspondant. + Le calcul de la valeur prise par une expression , utilisée dans une + condition ou pour une définition de variable, peut faire appel à d'autres + variables du programme. À ce moment si une valeur a été mémorisée on + l'utilise, sinon on appelle la fonction de calcul pour cette variable. + Lorsque le calcul d'une variable est \S en cours \T, ce statut est + enregistré dans , ce qui permet de détecter les cycles de + dépendances. + L'étape d'enregistrement des variables d'intérêt pour le cycle suivant comporte notamment une phase de calcul des transitions faibles empruntées par les automates du programme, pour qu'à l'étape suivante le calcul puisse @@ -693,15 +692,6 @@ - \; - - > - > - - \; - - \; - Le but de l'interprétation abstraite est de prouver certaines propriétés sur un programme. Pour cela, nous passons par une première approximation, la sémantique collectrice, que nous approximons une seconde fois en la @@ -712,8 +702,9 @@ Notons > l'ensemble des variables. On note - =\\\> : c'est l'union - des variables de type énumération et des variables de \ type numérique. + > l'ensemble des variables de type énumération et + > les variables de type numérique, de sorte que + =\\\>. Un état du système est une fonction \\>, où > représente l'ensemble des valeurs (numériques ou @@ -725,12 +716,12 @@ <\eqnarray*> ||\ - \| s|)>=t|}>>>>> + \| s|)>=tt|}>>>>> Entre deux cycles, les variables qui comptent réellement dans sont les variables actif et reset pour les scopes, les variables d'état pour les - automates, et les valeurs des . + automates, et les mémoires des . Vision habituelle : on a une suite d'états ,s,\> qui représentent la mémoire entre deux @@ -749,14 +740,14 @@ > par une fonction que l'on appellera fonction de cycle. Cette fonction copie uniquement les variables dont les valeurs précédentes sont utiles pour le calcul de la transition, et préfixe leur noms d'un - prefixe standard, ``L'', qui indique que ce sont des variables , - c'est-à-dire qu'on a leur valeur du cycle précédent. - - La fonction de cycle \\|)>> - s'occupe de faire passer les valeurs suivantes aux valeurs actuelles (nous - écrivons cette fonction comme non-déterministe car après cette fonction un - certain nombre de variables sont oubliées et on considère que leurs valeurs - n'ont pas d'importance). Elle peut être définie à partir d'un ensembles de + préfixe standard, \S \T, qui indique que ce sont des variables de + type , c'est-à-dire des copies de valeurs du cycle précédent. + + On note cette fonction de cycle \\|)>> ; nous écrivons + cette fonction comme non-déterministe car après cette fonction un certain + nombre de variables sont oubliées et on considère que leurs valeurs n'ont + pas d'importance. Elle peut être définie à partir d'un ensembles de variables , qui sont les variables qui nous intéresseront lors du calcul de la transition : @@ -766,22 +757,19 @@ x|)>=s|}>>>>> - \; - Déroulement d'un cycle : on prend l'état après passage par la fonction de cycle, on y met les valeurs des entrées du système. On applique ensuite la fonction \\> qui calcule toutes les variables du système (elle peut être définie comme la saturation - de la sémantique par réduction, comme le point fixe de l'application d'une - formule, ou plus classiquement comme l'application d'une série - d'instructions en style impératif, résultat de la compilation du + de la sémantique par réduction, comme le point fixe de l'application + répétée d'une formule, ou plus classiquement comme l'application d'une + série d'instructions en style impératif, résultat de la compilation du programme). On peut à ce moment récupérer les valeurs de sorties. Avec nos notations : > est la restriction de |)>+i|)>> aux variables de - sortie , où |)>+i> correspond à - définir les variables de |)>> et de - >. + sortie, où |)>+i> correspond à définir + les variables de |)>> et de >. <\remark> En principe, quel que soit c|)>>, @@ -792,18 +780,19 @@ - On s'intéresse maintenant à l'exécution d'un programme SCADE quel que + On s'intéresse maintenant à l'exécution d'un programme SCADE quelles que soient ses entrées >. On peut faire des hypothèses sur ces entrées en utilisant la directive du langage. On suppose que l'on dispose d'une fonction \> qui nous dit si un environnement - est conforme à la spécification. + \\> qui nous dit si un + environnement est conforme à la spécification donnée par les directives + . On s'intéresse maintenant à la sémantique non déterministe suivante : <\eqnarray*> >||\ - \| s|)>=t|}>>>|>|||)>>>|>||x>,a\c,q|)>=t|}>>>>> + \| s|)>=tt|}>>>|>|||)>>>|>||x>,a\c,q|)>=tt|}>>>>> \; @@ -846,7 +835,7 @@ Cette fonction fait correspondre à une partie de > sa meilleure approximation dans le domaine abstrait (par exemple dans le cas - des polyhèdres, l'abstraction d'un ensemble fini de points est leur + des polyèdres, l'abstraction d'un ensemble fini de points est leur enveloppe convexe, mais un cercle n'a pas de meilleure abstraction). Dans tous les cas, on s'attend à ce que @@ -855,14 +844,15 @@ d'autre part. De base ici, nous avons deux choix simples pour > : - les intervalles et les polyhèdres convexes. Ceux-ci sont considérés acquis + les intervalles et les polyèdres convexes. Ceux-ci sont considérés acquis pour la suite ; on les note > et >, avec les fonctions de concrétisation > et > associées. - On note > l'ensemble des égalités et inégalités sur des - variables de >. Par exemple les éléments suivants sont des - équations de > : 5*x-2>. + On note > l'ensemble des équations (égalités et inégalités) + sur des variables de >. Par exemple les éléments suivants + sont des équations de > : + 5*x-2>. Pour \> et \>, on note e> si l'expression est vraie dans l'état . @@ -883,7 +873,7 @@ La fonction de transition est représentée dans l'abstrait par une fonction > qui correspond à l'application d'un certain nombre de contraintes de >, ainsi que de disjonction de cas. - On remarque que l'aspect impératif disparait complètement, on n'a plus + On remarque que l'aspect impératif disparaît complètement, on n'a plus qu'un ensemble d'équations et de disjonctions. La traduction du programme SCADE en formule logique donne directement une formule de ce style que l'on peut appliquer sur un environnement abstrait. @@ -906,6 +896,34 @@ Cela correspond à oublier un certain nombre de variables qui ne nous intéressent plus, et à renommer celles que l'on garde. + <\example> + Soit le programme suivant : + + <\verbatim> + node counter() returns(x: int) + + \ \ x = 0 -\ (if pre x = 5 then 0 else pre x + 1) + + + Celui-ci est traduit par une formule du style : + + <\eqnarray*> + ||\Lnreset>>||>|\ff>>||>||\tt\x=0|)>>>|>|\ff\|x=0|)>>>|>|5\x=Lx+1|)>>>>>>|)>|)>>>>>>|)>>>>> + + + Les deux variables qui ont besoin d'être perpétuées d'un cycle au suivant + sont > et , la fonction de cycle + > est donc définie à partir de + ,x|}>>. + + La fonction >, quant à elle, reflète directement la + structure de la formule : + + <\eqnarray*> + >|||init\Lnreset|\>\|nreset\ff|\>||init\tt|\>\|x=0|\>>>|>||init\ff|\>||Lx=5|\>\|x=0|\>>>|>||Lx\5|\>\|x=Lx+1|\>>>>>>|)>>>>>>|)>>>>> + + + Par facilité, on note =c\f>. Étant donné qu'un programme est essentiellement une grosse boucle, la valeur qui nous intéresse est l'abstraction de donnée par : @@ -914,7 +932,7 @@ >||>i.I\g|)>>>>> - Où > est l'état initial du système et est défini par + Où > est l'état initial du système et est défini par =|i|\>|)>>, où est une équation du type =tt>. @@ -925,9 +943,9 @@ <\itemize> Contraintes numériques : les variables sont dans >, les constantes dans > (ou - >), les opérateurs sont - ,\,=,\,\>. On note - > l'ensemble de telles contraintes. + >), les opérateurs sont ,\, + mod,=,\,\>. On note > l'ensemble + de telles contraintes. Contraintes énumérées : les variables sont dans >, les constantes dans un ensemble fini qui dépend @@ -945,7 +963,7 @@ Les variables booléennes peuvent être représentées par et - , par exemple on peut introduire les restrictions suivantes (en + , par exemple on peut introduire les transformations suivantes (en notant > l'ensemble des variables à valeurs booléennes) : @@ -954,24 +972,26 @@ Les résultats sont généralement plus que médiocres. De plus, on ne peut pas - représenter ainsi les valeurs d'énumérations ayant plus de deux éléments. + représenter ainsi de façon exacte les valeurs d'énumérations ayant plus de + deux éléments (puisqu'on se restreint à une enveloppe convexe). Pour l'analyse de programmes SCADE, l'analyse de l'ensemble de la boucle de contrôle comme une seule valeur dans un environnement abstrait numérique - est insuffisante. Il nous a donc été crucial de développer deux domaines + est insuffisante. Il nous a donc été crucial de développer des domaines abstraits capables de faire des disjonctions de cas afin de traiter de manière plus fine l'évolution du programme. - Nous souhaitons pouvoir faire des disjonctions de cas selons les valeurs - des variables de >. Par exemple si on a un automate + Nous souhaitons pouvoir faire des disjonctions de cas selon les valeurs des + variables de >. Par exemple si on a un automate dont la variable d'état s'appelle et évolue dans l'ensemble >, on voudrait pouvoir isoler cette variable des autres, ne plus l'inclure dans le domaine abstrait et l'utiliser pour différencier plusieurs valeurs abstraites. Il nous faut donc redéfinir le domaine abstrait > et surtout la - fonction d'application d'une condition |e|\>>. + fonction d'application d'une condition |e|\>> + avec \>. @@ -988,97 +1008,96 @@ il faudrait noter x\\>, > l'ensemble des valeurs possibles pour la valeur , qui peut être différent selon la variable - on - est ammené à faire un peu de typage, il faut en particulier s'assurer que + est amené à faire un peu de typage, il faut en particulier s'assurer que les contraintes que l'on donne sont entre deux variables pouvant prendre les mêmes valeurs). On considère dans cette section que l'on a un domaine abstrait - > capable de gérer les contraintes sur les variables - numériques et sur les variables énumérées, mais sans relation entre les - deux. Le domaine > représente une abstraction de - =\\|)>\\>. - On note > et > les éléments - bottom et top de ce treillis, > et - > les bornes inf et sup de ce treillis. - - La particularité des variables d'état est que l'on ne réalise pas + > capable de gérer les contraintes sur les + variables numériques et sur les variables énumérées, mais sans relation + entre les deux. Le domaine > représente une + abstraction de =\\|)>\\>. + On note > et > les éléments + bottom et top de ce treillis, > et + > les bornes inf et sup de ce treillis, ainsi que + > son opérateur de widening. On note + |\|\>> la fonction + de restriction par une contrainte. + + La particularité des variables de disjonction est que l'on ne réalise pas d'abstraction sur celles-ci : on représente directement un état par une valuation de ces variables, dans \\=\>. - On peut le munir d'une structure de treillis : - \,\|}>> forme un - treillis plat : x,y\\,x\y\x=y>, - x\\,\\x\\> - (l'utilité de cette structure n'apparait pas.) On appelle toujours =\\\>, où =\\\\\>. On a une injection évidente de > dans |)>>, on identifie donc - \> à \\|\x\\,s=\|}>>. - De même on identifie \> à - \ \| \x\\\\,s=\|}>>. + \> à \\|\x\\,s=d|}>>. + De même on identifie \> à + \ \| \x\\\\,s=e|}>>. On construit maintenant le domaine abstrait disjonctif comme suit : <\eqnarray*> - >||\\>>|>||\>d\\|)>>>>> + >||\\>>|>||\>d\\|)>>>>> Les éléments > et > sont définis comme suit : <\eqnarray*> - >||d.\>>|>||d.\>>>> + >||d.\>>|>||d.\>>>> - On vérifie bien que |)>=\> - et |)>=\>. + On vérifie bien que |)>=\> et + |)>=\>. On peut aussi définir les opérations > et > : <\eqnarray*> - t>||d.\t|)>>>|t>||d.\t|)>>>>> + t>||d.\t|)>>>|t>||d.\t|)>>>>> Enfin, la partie intéressante : on peut définir un certain nombres d'opérateurs de restriction : <\itemize> - x,y\\,\s\\>, + x,y\\,\s\\>, <\eqnarray*> - |x=y|\>>||d.>|=d>>|>|>>>>>>||x\y|\>>||d.>|\d>>|>|>>>>>>>> + |x=y|\>>||d.>|=d>>|>|>>>>>>||x\y|\>>||d.>|\d>>|>|>>>>>>>> x\\,\v\\>, <\eqnarray*> - |x=v|\>>||d.>|=v>>|>|>>>>>>||x\v|\>>||d.>|\v>>|>|>>>>>>>> + |x=v|\>>||d.>|=v>>|>|>>>>>>||x\v|\>>||d.>|\v>>|>|>>>>>>>> |e|\>> est donc défini correctement pour tout \>, où > est - l'ensemble des conditions sur variables de disjonction. Pour toute - expression \> ou - \>, le domaine > est - sensé savoir les prendre en compte de manière satisfaisante, on définit - donc : + l'ensemble des conditions sur variables de disjonction de + >. Pour toute expression + \> ou \>, le + domaine > est sensé savoir les prendre en + compte de manière satisfaisante, on définit donc : <\eqnarray*> - e\\\\,|e|\>>||d.|e|\>|)>>>>> + e\\\\,|e|\>>||d.|e|\>|)>>>>> L'opérateur de widening reste problématique. On peut définir un opérateur de widening point par point : <\eqnarray*> - - t>||d.s\t>>>> + + t>||d.s \ + t>>>> Mais celui-ci est peu satisfaisant car chaque état @@ -1091,32 +1110,36 @@ > et une fonction de cycle > (par facilité, on notera =c\f>), l'ensemble des états accessible par le système est =lfp>s.I\g|)>>, - où =|i|\>|)>>. + où =|i|\>|)>>. - Définitions : pour \\>, notons - > : \\\> - tel que >=\d.>|\\>, notons + > : \\\> + tel que >=\d.>|d>>|>|>>>>>> Le principe des itérations chaotiques peut s'écrire comme suit : - <\eqnarray*> - >||>>|>||\\| - s\\|}>>>>> - + <\itemize> + Poser : - Tant que \\>, on répète le - processus suivant : + <\eqnarray*> + >||>>|>||\\| + s\\|}>>>>> + - <\eqnarray*> - >|>| - >>|>||>|)>|)>>>|>||\D>>|>||\\|}>|)>\\\|s\s|}>>>>> - + Tant que \\>, on répète + le processus suivant : + + <\eqnarray*> + >|>| + >>|>||>|)>|)>>>|>||\D>>|>||\\|}>|)>\\\|s\s|}>>>>> + + Intuitivement : > représente l'ensemble des états possibles pour notre système de transition. À chaque itération, on choisit un état qui a grossi depuis la dernière fois. On calcule ses successeurs et - on met à jour l'ensemble des états que l'on connait. + on met à jour l'ensemble des états que l'on connaît. Problème : ici on ne fait pas de widening, et on peut être à peu près sûr que l'analyse ne terminera pas (sauf cas simples). Pour cela, on introduit @@ -1126,14 +1149,16 @@ <\eqnarray*> >||>>|>||\\| - s\\|}>>>|,0>>||>>>> + s\\|}>>>|,0>>||>>>> <\eqnarray*> >|>| - >>|>||>|)>|)>>>|>||d.\D>|K,n>>>|\D>|>>>>>>|,n+1>>||,n>\\\| - s\\\s\s|}>>>|>||\\|}>|)>\\\|s\s|}>>>>> + >>|>||>|)>|)>>>|>||d. + \ D>|K,n>>>| + \ D>|>>>>>>|,n+1>>||,n>\\\| + s\\\s\s|}>>>|>||\\|}>|)>\\\|s\s|}>>>>> Ie : si un état est apparu à une étape, et si à une étape ultérieure il @@ -1144,18 +1169,21 @@ permettent de réduire le domaine abstrait ? La définition précédente n'est peut-être pas la bonne, car elle risque d'appliquer des élargissements que l'on ne sait plus ensuite comment rétrécir pour refaire apparaître les - bonnes conditions. Cherchons une autre forme d'itération, par exemple : + bonnes conditions. Nous proposons comme forme final le processus + d'itération suivant : <\eqnarray*> >||>>|>||\\| - s\\|}>>>|,0>>||>>>> + s\\|}>>>|,0>>||>>>> <\eqnarray*> >|>| - >>|>||>|)>>i.r>\g|)>|)>>>|>||\g|)>>>|>||d.\D>|K,n> et d\a>>|\D>|>>>>>>|,n+1>>||,n>\\\| - s\\\s\s|}>>>|>||\\|}>|)>\\\|s\s|}>>>>> + >>|>||>|)>>i.r>\g|)>|)>>>|>||\g|)>>>|>||d. + \ D>|K,n> et d\a>>| + \ D>|>>>>>>|,n+1>>||,n>\\\| + s\\\s\s|}>>>|>||\\|}>|)>\\\|s\s|}>>>>> Où le point fixe > est calculé avec appel au @@ -1164,7 +1192,12 @@ point fixe en boucle sur lui-même. Ensuite seulement on s'occupe de savoir ce qu'il peut propager aux autres états. - + + + Nous proposons dans ce paragraphe un second domaine abstrait capable de + faire des disjonctions de cas, et qui permet de mieux traîter des problèmes + ayant un nombre important de variables de type énuméré reliées entre elles + par des relations complexes. Définition du domaines abstraits avec graphes de décision : on va écrire ici une définition mathématique des opérateurs que l'on a implémenté. On @@ -1173,27 +1206,33 @@ pratique mais qui peuvent être considérés comme un traitement à part (ce n'est rien de plus que de la mémoisation et du partage). - Il y a deux domaines de variables, - > pour les énumérés et > pour - les variables numériques. Il y a deux domaines pour les contraintes, - > les contraintes sur les énumérés (de la forme - y> ou v,v\\>) et - > les contraintes sur les variables numériques - (égalités ou inégalités). + + + Il y a deux domaines de variables, > pour les + énumérés et > pour les variables numériques. Il y a + deux domaines pour les contraintes, > les + contraintes sur les énumérés (de la forme y> ou + v,v\\>) et > + les contraintes sur les variables numériques (égalités ou inégalités). + + - On note > le domaine des - valeurs numériques et >, >, + On note > le domaine des valeurs numériques et + >, >, |\|\>>, >, >, >, >, > les éléments correspondants dans ce domaine. On considère que : - D\\\\\\|)>> + D\\|)>> (avec + =\\\\\>) donne toutes les valuations possibles pour les variables de >. - On définit un ordre sur les variables de - > : =,x,\,x|}>> + + + On définit un ordre sur les variables de > : + =,x,\,x|}>> (bien choisi pour réduire la taille du graphe). On définit ensuite une valeur du domaine disjonctif, ie un EDD, par un type @@ -1247,11 +1286,11 @@ L'opération > est définie comme suit : <\eqnarray*> - \V|)>>||t|)>>>|,v\s,\,v\s|)>\C,v\s,\,v\s|)>>||,v\s\s,\,v\s\s|)>>>|,v\s,\,v\s|)>\s>|\V|)>>||t|)>>>||,v\s,\,v\s|)>>>|>|,v\s,\,v\s|)>>>>>>>||,v\s\s,\,v\s\s|)>>>|,v\s,\,v\s|)>\s>|\|)>>>>>||x,\s\s>>|>>|\s\s>>>>>|)>|\>>>>>>>>>> - et symmétriquement lorsque \\|)>> + et symétriquement lorsque \\|)>> (le noeud le plus haut est celui correspondant à la variable d'indice le plus faible, pour respecter l'ordre). @@ -1267,14 +1306,14 @@ Pour les conditions sur les énumérés, on définit d'abord : <\eqnarray*> - v|)>>||V|)>,v\V|)>,v\\\\|)>>>|v|)>>||V|)>,v\V|)>,v\\\\|)>>>|\x|)>>|v|)>>||\,v\\,v\\\\|)>>>|v|)>>||\,v\\,v\\\\|)>>>|\x|)>>|j>>|,v\c\v|)>,\,v\c\v|)>|)>>>|\x|)>>|j>>|,v\c\v|)>,\,v\c\v|)>|)>>>>> - et symmétriquement lorsque i>. + et symétriquement lorsque i>. - On peut ensuite poser : + On peut ensuite poser, pour \> : <\eqnarray*> |e|\>>||\s>>>> @@ -1291,8 +1330,10 @@ i\\|)>>>|s\s>>>> - Sur nos EDD, on définit une opération - :D\D\D> comme suit : + + + Sur nos EDD, on définit une opération :D\D\D> + comme suit : <\eqnarray*> ,V|)>>||>| b>||>>>|>,V|)>|)>>||t|)>>| t|)>>|=\,b|)>>>|t|)>>|>>>>>>|>,v\s,\,v\s|)>|)>>|\>>|,\f>|)>>>|>>|\f>|)>>>>>>|)>>>>> @@ -1315,30 +1356,33 @@ >, plus on passe et à notre fonction >>). Explication : lorsque l'on doit faire l'union de deux feuilles, on fait un widening si et seulement si les deux feuilles - sont accessibles selont exactement la même formule booléenne sur les + sont accessibles selon exactement la même formule booléenne sur les énumérés dans et . - On enrichit un peu notre arbre au niveau - des feuilles pour enregistrer quelques informations supplémentaires : + > + + On enrichit un peu notre arbre au niveau des feuilles pour enregistrer + quelques informations supplémentaires : <\eqnarray*> |>|>>|||>>>|||,v\s,v\s,\,v\s|)>>>>> - L'étoile correspondra à : ``cette feuille est nouvelle, il faut l'analyse - comme nouveau cas'', et l'indice \> correspond à : - ``cette feuille est là depuis itérations'', où le permet + L'étoile correspondra à : \S cette feuille est nouvelle, il faut l'analyse + comme nouveau cas \T, et l'indice \> correspond à : \S + cette feuille est là depuis itérations \T, où le permet d'implémenter un délai de widening. - On définit maintenant une fonction d'accumulation > comme - suit (> correspond à un delai de widening) : + On se donne > un délai de widening, paramètre de l'analyse. On + définit maintenant une fonction d'accumulation > comme + suit : <\eqnarray*> - b>||>>>|>|)>,V|)>>|\>>|>>|>>,V|)>|)>>||>>>|>>,V|)>|)>>||t|)>>>|=\,b|)>\ + b>||>>>|>,V|)>>|\>>|>>|>>,\|)>>||>>>|>>,V|)>|)>>|| t|)>>>|=\,b|)> i\\>>|t|)>>>|>>>>>>|>,v\s,\,v\s|)>|)>>|\i>>|,\f>|)>>>|>>|\f>|)>>>>>>|)>>>>> @@ -1356,7 +1400,8 @@ \s|)>\s>>|>|>>>>>>|>,s,V>|)>>||>>>|>,s,C,v\s,\,v\s|)>|)>>||,v\f>,s,s|)>,\,v\f>,s,s|)>|)>>>>> - On commence avec : + Nous sommes maintenant en mesure de décrire le processus d'itérations + chaotiques à proprement parler. On commence avec : <\eqnarray*> >||> @@ -1384,7 +1429,7 @@ de widening convenable) Dans tous les cas, on refait une itération. Les étoiles finiront bien par - disparaitre. + disparaître. Si il n'existe pas de telle feuille étoilée dans > : @@ -1395,6 +1440,10 @@ Dans ce cas, on s'arrête si =s>. + + + + \; <\initial> @@ -1422,12 +1471,15 @@ > > > - > - > - > - > - > + > + > + > + > + > > + > + > + > > > > @@ -1477,7 +1529,7 @@ > |2.3.5Règles de réduction pour - les affectations |.>>>>|> + les définitions de variables |.>>>>|> > |2.3.6Règles de réduction pour -- cgit v1.2.3