Notation Z
Logiciels: 
 * Z-Eves
 * Ztec (vérification de types)
   * Accepte les format de fichier LateX, ZSL et ZBX pour la notation Z.
 * Zans (animation des spec. Z)

En Z, on modélise les actions
a) les opérations modifient les variables du système (écriture/modification/ajout)
b) les requêtes ne modifient pas les variables du système (lecture)

Le système est représenté par un schéma d'état:
a) une partie déclaration
b) une partie prédicative où sont énoncés les invariants. 
Rappel: un invariant est une condition qui doit toujours être vraie pour chaque état du système.

Un document Z se séparent en 7 sections distinctes:
1) les types utilisés 
2) les définitions axiomatiques
3) le schéma d'états (peut être construit avec plusieurs petit schémas)
4) Initialisation du système (sous forme de schéma)
5) Opérations et les requêtes (sous forme de schéma)
6) Traitement des cas "anormaux" (sous forme de schéma)
7) Les versions finales des opérations.

1) les types utilisés 
global
	identifiant: type

Exemple
global
	monEntier: Z
	monNaturel: N
	monNaturelSansZero: N1

2) les définitions axiomatiques (ou les définitions de constantes)
axiom
	monEntier = 5
end axiom

3) le schéma d'états (peut être construit avec plusieurs petit schémas)

4) Initialisation du système (sous forme de schéma)
%%init-schema NomSchema

5) Opérations et les requêtes (sous forme de schéma)

6) Traitement des cas "anormaux" (sous forme de schéma)

7) Les versions finales des opérations.


Langage
A) Les types de base:
 - prédéfinis: Z (entier), N (naturel), N1 (naturel sans zéro)
 - inventé: [TYPE1, TYPE2, TYPE3]
   Ce qui veut dire: une variable peut être de type TYPE1, TYPE2 ou TYPE3.
   Exemple:  variable1: TYPE1
             variable2: TYPE2
             variable3: TYPE3
 - énuméré: ETAT ::= on | off | idle
   Ce qui veut dire: un variable de type ETAT peut avoir seulement les valeurs on, off ou idle.
   Exemple:  variable1: ETAT
             variable1' = on
             variable1' = off
             variable1' = idle
 - Équilalence: TYPE2 == TYPE1
   Exemple:  DE     == 1..6
             ENTIER == Z
             NODOC  == {4,8,42,56}

B) Les variables
Déclaration:        identifiant  : type
Variable d'entrée:  identifiant? : type
Varable de sortie:  identifiant! : type
Exemple: 
 [PERSONNE, STUDENT]
 ETAT ::= a | b | c
 DE == 1..6
 var1 : PERSONNE
 var2 : ETAT
 var3 : {2,4,16,22}
 var4 : DE
 tested : P STUDENT    (P signifie Powerset, un ensemble de type STUDENT]
 listeEtat : P ETAT

C) Expressions arithmétiques
 - arithmétiques: +, -, mod, div, *, succ x (successeur, x=x+1)
 - relation     : =, /= (pas égal), <, <=, >, >=
 - ensemble     : sub (sous ensemble), subeq (sous ensemble ou égal), {} (ensemble vide0, 
                  in, notin, 
                  || (union), && (intersection), \, #, P (powerset), & (multiplication x)
   Note: l'opérateur & (multiplication) produit des paires
 - logique: true, false, not, <=>, =>, and, or

D) Ensemble
 - description simple      
 - sous forme d'intervalle 1..6
 - en compréhension        {1,2,3,4,5,6,7}

E) Les fonctions
   Fonction partielle             +->
   Fonction totale                -->
   Fonction injective partielle   >+>
   Fonction injective totale      >->
   Fonction subjective partielle  +>>
   Fonction subjective totale     ->>
   Bijection                      >->>

F) Les relations
   Relation: R : A <-> B 
   R~ : relation inverse de R, B vers A (R doit etre une fonction)
   Forme un couple entre les éléments de l'ensemble A avec les éléments de l'ensemble B
   On peut aussi l'écrire:  Relation : P (A x B)

   Opérateur: 
    dom Rel : retourne le domaine de la relation (un ensemble)
    ran Rel : retourne l'image de la relation (un ensemble)

G) Ensemble et quantificateurs
   { declaration | predicat @ expression }
   { declaration | predicat }
   { declaration @ expression }

   Exemple: 
   Ensemble des nombres de 200 à 300
   NB1 = {i : 0..200 | i >= 100 and i <= 150 @ 2*i} 
   Ce lit: Place dans l'ensemble NB1, la liste des nombres "i multipliés par 2", 
           tel que i est plus grand ou égale à 100 et plus petit ou égale à 150 
           depuis l'ensemble de départ des nombres de 0 à 200.
   Ensemble des nombres de 100 à 150
   NB2 = {i : 0..200 | i >= 100 and i <=150 }
           Place dans l'ensemble NB2, la liste des nombres i
           tel que i est plus grand ou égale à 100 et plus petit ou égale à 150 
           depuis l'ensemble de départ des nombres de 0 à 200.
   Ensemble des conditions vraie / fausses de 0 à 200
   NB3 = {i : 0..200 @ i >= 100 ET i <=150 }
         Place dans l'ensemble NB3, le résultat booléen de la condition
         "i est plus grand ou égale à 100 et plus petit ou égale à 150" 
         depuis l'ensemble de départ des nombres de 0 à 200.
         Ce qui donne faux de 0 à 99, vrai de 100 à 150 et faux de 151 à 200
   Ensemble de couple (d'une fonction)
   COUPLE = { x, y : Z | y= 3x + 8 @ (x,y) }
         Place dans l'ensemble COUPLE, les couples formés de x et de y
         tel que y = 3x + 8
         depuis les deux ensembles x (entiers) et y (entiers)

 Quantificateurs
 Pour tous les éléments de l'ensemble (ou des ensemble), le prédicat est vrai tant que la contrainte est respectée.
  forAll declaration | contrainte @ predicat
 Il existe au moins un élément de l'ensemble (ou des ensemble) tel que le prédicat est vrai si on respecte la contrainte.
  exists declaration | contrainte @ predicat
 Il existe seulement un élément de l'ensemble (ou des ensemble) tel que le prédicat est vrai si on respecte la contrainte.
  exists1 declaration | contrainte @ predicat

2. Schémas
2.1 Définition axiomatique pour définir des constantes en Z
Définition:
| déclaration
+------------
| prédicative
Exemple 1:
| capacite : N
| lampe : {on, off}
+------------------
| capacite = 468

Exemple 2:
global 
  capacite: N;
  lampe : {on, off}
axiom
  capacite = 468
  lampe = on
end axiom

2.2. Schéma
+--- Nom ----
| déclaration
+------------
| prédicat 
+------------

schema nom
  déclaration
where
  prédicat
end schema

+--- Avion -------------
| abord : P Personne
+-----------------------
| #abord >= capacite
+-----------------------

Opérations sur les schémas
A) Inclusions
B) Inclusions décorées
C) Inclusion Delta : modification du système
D) Inclusion Xi.

A) Inclusion
+--- S ---
| avion
+---------
|
+---------
Le résultat: le schéma S comprend toutes les déclaration de "avion" et tous ses prédicats
Les prédicats sont fusionnés à ceux qui existent dans S (avec and)
Utilisation: sert à construire un schéma du système par morceau

B) Inclusion dérivée
+--- S ---
| avion'
+---------
|
+---------
Résultat: le schéma S contient toutes les déclarations des variables' du schéma "avion"
Tous les prédicats de avion dans leurs versions prime '
Utiliser pour l'action d'initialisation des schémas.

C) Inclusion Delta
+--- S ---
| delta avion
+---------
|
+---------
Résultat: Les déclarations de l'avion en version prime' et non prime 
Les prédicats de avion en version ' et non '
Utiliser pour spécifier les opérations
Exemple:
+--- Embarquer ---
| delta avion
| p? : PERSONNE
| m! : MESSAGE
+---------
| #abord < capacite
| p? notin abord
| abord' = abord || {p?}
| m! = OK
+---------

Signifie en objet:
avion::test_embarquer(PERSONNE p?) {

  si avion.abord.length < avion.capacite AND p? notin avion.abord {
    abordtmp = avion.abord
    MESSAGE m! = avion.embarquer(p?);
    assert( avion.abord = ( abordtmp || {p?} ) );
    assert( m! == OK );
  }

}

D) Inclusion Xi
+--- S ---
| [-] avion
+---------
|
+---------
Résultat: pareil que Delta 
Dans la partie prédicative, pour chaque variable système, on voit apparaître variable' = variable.
Utiliser pour spécifier des requêtes ou des actions
qui ne modifient pas l'état du système.


Version Finale
===============
action =^= action0 \/ action1 \/ action2 \/ ...
Exemple:
+-- debarquer0 ----
| delta avion
| p? : PERSONNE
| m! : MESSAGE
+------------------
| p? in abord
|
| abord' = abord \ {p?}
| m! = OK
+------------------


+-- debarquer1 ----
| [-] avion
| p? : PERSONNE
| m! : MESSAGE
+------------------
| p? notin abord
| m! = FAILED
+------------------
debarquer =^= debarquer0 \/ debarquer1

Règle 1: Les associations deviennent des fonctions ou des relations.
Exemple:
PERSONNE --> DATE
PERSONNE +-> DATE
ensemble' = ensemble || {(x?,d?)}
ensemble' = ensemble || {x?->d?}

Règle 2: parmis tous les attributs des éléments du domaine, qu'est-ce qui permet de distinguer 2 éléments?
anniversaire : NOM +-> DATE
Qu'arrive-t-il au auxtres attributs
Former des paires...

Ajout       : Union ||
Soustraction:       \
Mise à jour : (+)   += 
Exemple:  ann' = ann  \ { x? -> d? } || { x? -> d? }
          ann' = ann' \ { x? -> ann(x?) } || { x? -> d? }
          ann' += { x? -> d? }

Le résultat est une fonction qui "fonctionne" comme f partout
dans le domaie sauf pour les éléments qui concernent "g".

Zans se sert des invariants pour complétés les post-conditions

Exemple:
scheme Retrait
 Delta Carnet;
 nom? : NOM;
where
 nom? in amis;
 ann' = ann \ { x? -> ann(x?)}
 amis' = amis \ { nom? }
end schema

Parenthèse:
En Z, les schémas sevent à construire des preuves
exists x in N | filtre @ predicat;
exists Carnet? @ ajout
exists amis ? P nom; ann : NOM +-> DATE | amis' = dom ann @ ...

la caractéristique (attribut) qui rend un objet unique
nous permet d'écrire des fonctions ayant pour domaine l'ensemble des attributs
Que faire avec les attribus qui reste?

+--- choix ---
| amis : P NOM
| adresse : NOM +-> ADRESSE
| courriel: NOM +-> COURRIEL
| ann     : NOM +-> DATE
+-------------

Test d'appartenance
===================
Choix 1 : nom? in amis
Choix 2 : exists d: date and a:adresse and c: courriel @ (nom?, d, a, c) in amis
Choix 3 : amis : P nom
          info : nom +-> P (adresse & courriel & date)

Carte! = { a:amis | ann(a) = aujourdhui? @ a }
         { n:nom  | n in amis and ann(n) = aujourdhui? @ n }
         { a:amis | (a, aujourdhui?) in ann @ a }
         { n:nom  | (a:adresse, c:courriel @ (n, aujourdhui?,c,a) in amis) @ n }

1 à N
emprunts : client +-> P video
emprunts : client <-> video
           P (client & video)

Pour toute relations:
R |> s : restreindre l'image de R à l'ensemble s
s <| R : restreindre le domaine de R à s
R +> s : restreindre l'image de R à tout ce qui n'est pas dans s
s <+ R : restreindre le domaine de R à tout ce qui n'est pas dans s
Exemple:
 {42} <| emprunts  : retourne seulement les enregistrements dont le domaine est 42.

fonction param = fonction(param)

Séquence
========
Une séquence est un tableau (ensemble d'index associé à un ensemble d'élément)

Fonction de N -> [x]
chaineCaractere: seq CHAR
nomSequence: seq  TYPE ex: route = <<MTL, QC, TOR, MTL>>
nomSequence: iseq TYPE ex: route = <<MTL, QC, TOR>> (pas de doublons)

Route correspond à un ensemble de paire avec index  { (1, MTL), (2, QC), (3, TOR), (4, MTL) }
Accès à une valeur:  nomSequence(index)  (index commence à 1)
Opérateur:           first nomSequence   (retourne la première valeur)
                     last  nomSequence   (retourne la dernière valeur)
                     tail  nomSequence   (retourne une sequence de tous les éléments sauf la première valeur)
                     front nomSequence   (retourne une sequence de tous les éléments sauf la derniere valeur)
Concaténation:       nomSequence ^ nomSequence2
Longueur:            #nomSequence

Test:
élément fais partie de la séquence       :  élement in ran sequence
élément ne fait pas partie de la séquence:  élément not in ran sequence
                     
Pour convertir un ensemble de paire en séquence, on utilise
squash( ensemble_de_paire )

Initialisation:
schema SeqInit
 NomSchema'
where
 sequence' = <<>>
end schema

Représenter une suite de caractère:
1. Définir le caractère.
[CHAR]
2. Créer un schéma texte qui contient une variable avec une séquence de caractère (suite avec ordre = séquence)
+- text --
| chaine : seq CHAR 
+---------

Retourner la position d'une chaine dans une chaine. pos = strstr(text, chaineChercher)
S'il est vrai qu'il existe une chaine "avant" concaténé à la chaine pat? concaténé à la chaine apres
qui équivaut à ma chaine alors la position est égale au nombre de caractère avant ma chaine + 1.
Si ce n'est pas vrai (condition contraire), alors je retourne 0.
+---------
| [-] text
| pat?: seq CHAR
| pos!: N
+---------
| ( (exists avant, apres: seq CHAR @ avant ^ pat? ^ apres = chaine ) /\ pos! = #before + 1 )
|  \/
| ( not (!exists avant, apres: seq CHAR @ avant ^ pat ? ^ apres = chaine ) /\ pos! = 0 )
+---------
Notation: ( pre1 est vrai ET post1 est vrai ) OU ( pre2 est vrai ET post2 est vrai )
Note, qu'il pourrait exister plusieurs before, mais que c'est seulement le premier qui est retourné

Hyperliens...