Module pile avec les fonctions : PUSH(int I), POP(), TOP()
Module int avec les fonctions : succ(), pred()
Il n’y a pas d’autres possibilités !
Soit extP fonction d’extension pour le programme P
extP : traces canoniques x appels de P → traces canoniques
Exemple :
extPUSH(PUSH(2).PUSH(5), PUSH(3)) = PUSH(2).PUSH(5).PUSH(3)
PUSH(2).PUSH(5) représente l'état "avant", PUSH(3) représente un appel de PUSH (une extension de l'état "avant") et PUSH(2).PUSH(5).PUSH(3) représente le nouvel état.
Considérons la trace T égale à P1(...).P2(...). ... . Pn(...)
La trace canonique équivalente à T est définie à l’aide de la fonction red (réduction).
red(T) = extPn( red(P1(…).P2(…). … . Pn-1(…) ), Pn(…)) si n > 1
red(T) = extP1( _ , P1(…)) si la trace vide est canonique
red(T) = extP1( _c , P1(…)) si la trace vide n’est pas canonique et _c représente la trace canonique équivalente à la trace vide
Trois catégories de jetons :
La légalité est définie pour les appels.
PUSH(4).POP().POP().PUSH(2).TOP().PUSH(6)
Le deuxième appel de POP() est illégal mais la trace entière est équivalente à PUSH(2).PUSH(6).
Ci-dessous x et y sont des noms d’objet, T, T1, T2 sont des traces et S est une portion d’une trace (une sous-chaîne de caractères).
symbolisme formel | signification |
---|---|
_ (soulignement) | trace vide |
. | séparateur entre des éléments dans une représentation écrite de traces |
[S]i=m..n | portion Z d’une trace qui est obtenue comme suit : dénotons par Sα la chaîne S dans laquelle toutes les occurrences de i ont été remplacées par α; Z = _ si m > n ou Z = Sm.Sm+1. ... .Sn si m ≤ n |
(x,T1) ≡ (y,T2) | équivalence de traces (définie par la fonction d’extension) |
T1 ≡ T2 | ∀ x,y; (x,T1) ≡ (y,T2) |
* | symbole générique utilisé dans des traces canoniques |
P(...)↓ | la valeur retournée par l’invocation P(...) |
P(..., a↓, ...) | la valeur retournée dans l’argument de sortie a |
P(...)↓v | v est la valeur retournée par l’invocation P(...) |
P(..., a↓b, ...) | b est la valeur retournée dans l’argument de sortie a |
<M> | l'ensemble des traces canoniques dans le module M |
<<M>> | l'ensemble de toutes les traces dans le module M |
Si une trace contient des appels de programmes non-déterministes, des valeurs de sortie apparaîtront dans cette trace.
Nom de programme | Arg#1 | Arg#2 | Type de résultat |
---|---|---|---|
P | m:VO | int:V | |
Q | m:O | ||
R | m:V | int |
Remarque :
Les lettres V et O après le type d'argument (m ou int) décrivent le mode de passage d'argument :
Nous devons spécifier
Plus formellement, une spécification d’un module contient :
Comment interpréter la notation suivante ?
PUSH((n,T)↓, a) = T.PUSH(*,a)
Un état du module dont les objets sont dénotés par les
noms n1,n2,...,nn peut être présenté par une séquence
(n1,val1), (n2,val2), ..., (nn,valn)
L’effet de l’invocation PUSH(n,a) peut être illustré comme suit :
PROGRAMMES D'ACCÈS
Nom de programme | Arg#1 | Arg#2 | Type de résultat |
---|---|---|---|
PUSH | pile:VO | int:V | |
POP | pile:VO | ||
TOP | pile:V | int |
canonique(T) ≡ ∃n:int, a1,...,an:int; T = [PUSH(*, ai)]i=1..n
légalité(PUSH((n,T), a)) = %legal%
PUSH((n,T)↓, a) = T.PUSH(*, a)
légalité(POP((n,T))) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
POP((n,T)↓) = T1 where T1:<pile>; a:int; (T = T1.PUSH(*,a))
légalité(TOP(T)) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
TOP(T)↓ = a where T1:<pile>; a:int; (T = T1.PUSH(*, a))
Exercice : réduisez la trace ci-dessous à une trace canonique.
PUSH(n,5).POP(n).TOP(n).PUSH(n,3).PUSH(n,5).PUSH(n,11).POP(n).PUSH(n,7).POP(n)
PROGRAMMES D'ACCÈS
Nom de programme | Arg#1 | Arg#2 | Type de résultat |
---|---|---|---|
CREATESTACK | pile:O | ||
PUSH | pile:VO | int:V | |
POP | pile:VO | ||
TOP | pile:V | int |
canonique(T) ≡ T = _ ∨ ∃n:int, a1,...,an:int; T = CREATESTACK(*).[PUSH(*, ai)]i=1..n
légalité(CREATESTACK(n)) = %legal%
CREATESTACK(n↓) = CREATESTACK(*)
légalité(PUSH((n,T), a)) =
Condition | Valeur |
---|---|
T = _ | %pile_invalide% |
T ≠ _ | %legal% |
PUSH((n,T)↓, a) = T.PUSH(*, a)
légalité(POP((n,T))) =
Condition | Valeur |
---|---|
T = _ | %pile_invalide% |
length(T) = 1 | %vide% |
length(T) > 1 | %legal% |
POP((n,T)↓) = T1 where T1:<pile>; a:int; (T = T1.PUSH(*,a))
légalité(TOP(T)) =
Condition | Valeur |
---|---|
T = _ | %pile_invalide% |
length(T) = 1 | %vide% |
length(T) > 1 | %legal% |
TOP(T)↓ = a where T1:<pile>; a:int; (T = T1.PUSH(*, a))
Le module implémente une file d’entiers dont la capacité ≤ 12.
PROGRAMMES D'ACCÈS
Nom de programme | Arg#1 | Arg#2 | Type de résultat |
---|---|---|---|
ADD | file12:VO | int:V | |
REMOVE | file12:VO | ||
FRONT | file12:V | int |
canonique(T) ≡ ∃n:int, a1,...,an:int; (T = [ADD(*, ai)]i=1..n ∧ 0 ≤ n ≤ 12)
légalité(ADD((n,T), a)) =
Condition | Valeur |
---|---|
length(T) = 12 | %pleine% |
length(T) < 12 | %legal% |
ADD((n,T)↓, a) = T.ADD(*, a)
légalité(REMOVE((n,T))) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
REMOVE((n,T)↓) = T1 where T1:<file12>; a:int; (T = ADD(*,a).T1)
légalité(FRONT(T)) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
FRONT(T)↓ = a where T1:<file12>; a:int; (T = ADD(*, a).T1)
PROGRAMMES D'ACCÈS
Nom de programme | Arg#1 | Arg#2 | Type de résultat |
---|---|---|---|
PUSH | pile:VO | int:V | |
POP | pile:VO | ||
TOP | pile:V | int |
canonique(T) ≡ ∃n:int, a1,...,an:int; (T = [PUSH(*, ai)]i=1..n ∧ n ≤ taille)
légalité(PUSH((n,T), a)) = %legal%
PUSH((n,T)↓, a) =
Condition | Valeur |
---|---|
length(T) < taille | T.PUSH(*, a) |
length(T) = taille | T1.PUSH(*, a) where T1:<pile> b:int; (T = PUSH(*, b).T1) |
légalité(POP((n,T))) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
POP((n,T)↓) = T1 where T1:<pile>; a:int; (T = T1.PUSH(*,a))
légalité(TOP(T)) =
Condition | Valeur |
---|---|
T = _ | %vide% |
T ≠ _ | %legal% |
TOP(T)↓ = a mod 255 where T1:<pile>; a:int; (T = T1.PUSH(*, a))
type specifié: intg
PROGRAMMES D'ACCÈS
Nom de programme | Arg#1 | Type de résultat |
---|---|---|
GETINT | intg:VO | int:R |
Commentaire : 'R' est utilisé pour indiquer une valeur non-déterministe.
canonique(T) ≡ ∃n:int, x1,...,xn:int; (T = [GETINT(*)↓xi)]i=1..n ∧ ∀i:int; (1 ≤ i ≤ n ⇒ xi < xi+1))
légalité(GETINT((n,T))) = %legal%
GETINT((n,T)↓)↓v = S1.GETINT(*)↓v.S2 where S1,S2:<intg> (T = S1.S2 ∧ canonique(S1.GETINT(*)↓v.S2))
GETINT((n,T))↓a | ¬∃S1,S2:<intg> [T = S1.GETINT(*)↓a.S2]