• Aucun résultat trouvé

Initialisation de la vérification

4.2 Sémantique des règles

4.3.2 Initialisation de la vérification

Correction

Pour un automate A et une règle de réécriture R, on note R (A) = ApplyRule(R,A). Avec ces notations, on a :

Théorème 4. Soit R = (g0)· w1· (g1)· w2. . . wn· (gn)/ f0· F0· f1· F1·... · F

n· fn+1une règle de réécriture et A un automate de treillis. On a :

R (L (A)) ⊆ L (R (A)) Démonstration. Soit R = (g0)· w1· (g1)· w2. . . wn· (gn)/ f0· F

0 · f1·... · F n· fn+1

Soit w ∈ L ( A). Si w est reconnu par la garde (g0)· w1· (g1)· w2. . . wn· (gn), cela signifie que nous pouvons le décomposer en w= u0.v1.u1.v2.u2. . . vn.unavec :

— Pour i= 1..n, vi v wi

— Pour i= 0..n, chaque lettre uiest plus petite que gi Puisque w ∈ L (A), nous considérons un chemin q0

u0

−− q1b −−v q1 1e. . . vn −− qen

un

−− qf dans A, i.e. il y a des séquences acceptantes (qb1,v1, q1

e) ∈ matches(w1, A), (q2 b,v2, q2

e) ∈ matches(w2, A), . . . , (qbn,vn, qn

e) ∈ matches(wn, A), telles que ∀i,vi v vi.

Dans l’algorithme ApplyRule, ces séquences acceptantes génèrent un automate A0. En appliquant les fonctions de réécriture f0· F0· f1· F1·... · F

n· fn+1à w, nous obtenons R (w) qui est reconnaissable

par l’automate A0. Ainsi, R (w) ∈ L (A0) ⊆ L (R ( A)). 

Toutefois, il est à noter que nous n’avons pas la relation R (L (A)) ⊇ L (R (A)) comme nous le montrons dans cet exemple :

Exemple 5. Soit A l’automate de treillis reconnaissant le langage L = {[0,0],[1,1]} (i.e. un seul processus avec une variable pouvant être 0 ou 1) et soit R la règle de réécriture > / f1 · f2 où f1 : x 7→ 2x et f2 : x 7→ 4x alors R (L (A)) = {[0,0].[0,0] , [2,2].[4,4]}. Mais R(A) est un automate de treillis reconnaissant 4 mots :

L (R (A))= {[0,0] · [0,0] , [2,2] · [4,4] , [0,0] · [4,4] , [2,2] · [0,0]}.

4.3.2 Initialisation de la vérification

Configuration initiale

Avant de débuter la phase d’analyse, il est nécessaire de définir la classe de système que l’on souhaite analyser. Nous en distinguons deux principales : les configurations à nombre de processus fixe (e.g. 4.8a) et les configurations à processus non-bornés (e.g. 4.8b où N = +∞). Ce choix dépend principalement du type de propriétés à prouver. La première classe permet d’obtenir un résultat généralement plus précis puisqu’aucune abstraction n’est faite au départ sur le nombre de processus traités. En revanche, la deuxième permet de généraliser une propriété à tout nombre de processus ce qui est utile pour certaines

4.3. VÉRIFICATION DU SYSTÈME 65

classes de programmes comme, par exemple, des algorithmes numériques pouvant être exécutés sur différentes plates-formes de calcul. Ce choix est donc laissé à l’utilisateur selon le type de propriété cherchant à être prouvée.

{id= 0} {id= 1} {id= 2} (a) Configuration à 3 processus

{id= 0}

{id ∈ [1; N ]}

(b) Configuration à 1+ N processus

Figure 4.8 – Configurations modulaires

Sélection des domaines abstraits

Les automates de treillis pouvant être paramétrés par un domaine abstrait, nous pouvons établir selon la nécessité de précision et de performance le domaine à utiliser. Dans la suite de ce chapitre, nous emploierons le domaine des polyèdrespour nous intéresser à la précision atteignable pour notre type d’analyse. Les parties séquentielles de nos systèmes profiteront ainsi des relations que ceux-ci apportent et nous verrons par la suite que certaines de ces relations peuvent être propagées à l’état global notamment lorsque la taille évolue dynamiquement.

Traduction vers le modèle

Avant de débuter la phase de vérification, il est également nécessaire de traduire nos programmes vers notre modèle. Nous donnons ici l’idée générale de cette traduction que nous développerons en détail dans le chapitre suivant. Comme pour notre précédent langage, nous partons du graphe de flot de contrôle et considérons toutes les transitions de celui-ci. Pour chaque transition labellisée par une instruction séquentielle (i.e. affectation, boucle, conditionnelle, etc.), nous générons une règle qui reconnaît un processus et en réécrit un. Par exemple, l’affectation : x := 5 de la localité L10à L11sera traduit par la règle e.g. L10× >/ f : (l, ρ) 7→ hL11, ρ[x 7→ 5]i. Pour les instructions globales (i.e. communications, créations de processus), des règles seront générées selon les squelettes présentés dans la section 4.2. Pour les communications point-à-point, il est important de noter qu’il est nécessaire de générer une règle pour chaque couple du produit cartésien des instructions send/receive. Par la suite, nous discuterons des optimisations que nous pouvons effectuer pour réduire cet ensemble de règles.

Nous distinguons cependant la manière dont nous traitons les instructions séquentielles et les ins-tructions globales. Les règles de réécriture générées à partir des insins-tructions séquentielles sont disposées sous forme d’un transducteur tournesol T exactement comme présenté dans le chapitre 3. Les règles traduites des instructions globales sont considérées comme un ensemble et appliquées à chaque itération par une fonction que l’on nommera également R.

Une dernière opération est nécessaire : la génération des partitions de treillis qui vont composer l’al-phabet de nos automates de treillis. Pour cela, nous parcourons l’ensemble des instructions et générons pour chacune une partition contenant la localité de l’instruction ainsi qu’un environnement défini à >. Nous effectuons ceci pour l’ensemble des instructions hormis les conditionnelles où nous générons, pour chaque instruction suivante, une partition où l’environnement satisfait la garde.

4.4 Calcul de l’espace d’atteignabilité

Premièrement, il est nécessaire d’adapter l’algorithme de calcul d’espace d’atteignabilité afin de maintenant considérer l’application les règles de réécriture. Nous définissons l’algorithme présenté par la Figure 4.9 comme notre nouvelle itération de point-fixe. Ce nouvel algorithme intègre l’application des différentes règles de réécriture générées à partir du programme en effectuant l’union entre les tran-sitions séquentielles et globales.

A0= I An+1=     An si T (An) t R (An) v An AnO (Ant T (An) t R (An)) sinon Tα(I )= lim n→+∞An

Figure 4.9 – Calcul de l’espace d’atteignabilité avec règles de réécriture

Nous nous intéressons désormais à un programme exemple (Figure 4.10) où le processus d’identi-fiant 0 crée dynamiquement 5 nouveaux processus qui stockent dans une variable x le double de leur identifiant. Puis, les variables x des différents processus sont additionnées et le résultat est stocké dans la variable res du processus 0 qui est finalement transmise à tous les autres processus par un broadcast.

Dans cet exemple, nous nous intéressons à deux propriétés : — il y a au maximum 6 processus présents à tout instant ;

— aux états terminaux du programme, le résultat du calcul, contenu dans la variable res, est borné. En effectuant l’analyse, nous obtenons un invariant décrit par la Figure 4.11. Pour des raisons de

1 main () : 2 id := get_id () ; 3 res := 0; 4 5 if id = 0 then 6 i := 0; 7 while i < 5 do 8 create ( child_id ); 9 i := i + 1 10 done; 11 x := 0 12 else 13 x := id + id 14 endif; 15 16 reduce(+ , x , res , 0) ; 17 broadcast(res , 0) ; 18 19 return

(a) Programme source

Transitions locales g1 / f1 . . . gn / fn >/ f : σ 7→ σ Rcreate= > · hL8× >i · >/

F1: ((ls, ρs), (lcr, ρcr) 7→ hls, ρs[size 7→ ρs(size)+ 1]i · f1: (lcr, ρcr) 7→ hL9, ρcr[size 7→ ρcr(size)+ 1]i · F2: ((ls, ρs), (lcr, ρcr) 7→ hls, ρs[size 7→ ρs(size)+ 1]i ·

f2: (lcr, ρcr) 7→ hL2, ρinit[ id 7→ ρcr(size); size 7→ ρcr(size)+ 1]i Rbroadcast= . . .

Rreduce= . . .

(b) Règles traduites