couleur, 1 diapo sur 1 page

publicité
FP
Plan du chapitre 2
A. Notion de récursivité
B. Récursivité dans ℕ
 C. Récursivité dans séq(α)
inf201 : algorithmique et programmation fonctionnelle
Récursivité dans séq(α)
C.I) Définition récursive de séq(α)
a) Notion de séquence
 Jusqu’à présent : données manipulées unitaires (même si de
type complexe). On parle de données scalaires
 Types produits : nuplets de taille donnée et fixe
Comment manipuler des collections de données de taille
arbitraire ?
→ séquences d’éléments
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
a) Notion de séquence
Séquence d’éléments : collection de données (éléments)
- de même type
- de taille quelconque (finie)
- imposant un ordre (premier, deuxième ,… dernier)
Structure de données fondamentale en info (modélisation)
Ex : - liste d’étudiants
- “main” dans un jeu de carte
- relevés de données scientifiques
etc.
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
b) Définition de l’ensemble (type) séq(α)
1- Séquence d’entiers (on pose α=ℤ)
Ensemble des séquences sur ℤ définit récursivement par :
- l’entité de base Nil (appelé « séquence vide »)
- les éléments construits à partir d’un entier et d’une séquence d’entiers :
Cons(pr, fin) (constructeur de séquence appelé « ajout à gauche »)
Représentation graphique :
... /... cf tableau
Représentation mathématique :
séq(ℤ) = {Nil} U {Cons(pr,fin) / pr ∈ ℤ, fin ∈ séq(ℤ)}
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
type seqEntier = Nil | Cons of int * seqEntier
seqEntier : type somme récursif
Exemples :
Cons(1,Nil) : séquence (singleton) ne contenant que l’entier 1
Cons(1,Cons(2,Cons(3,Nil))) : séquence contenant 1,2 et 3 (dans cet ordre)
/!\ Cons(1,Cons(2,Cons(3,Nil))) ≠ Cons(2,Cons(1,Cons(3,Nil))), la plupart du temps
Cons(pr, fin) :
séquence constituée d’un premier entier (noté pr) et
d'une séquence d’entiers (notée fin)
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
Exemple de fonction sur séq(ℤ) :
SPEC
longueur d’une séquence
Profil
longueur : séq(ℤ) → N
Sémantique
longueur(s) est le nombre d’éléments de s
REAL
on calcule le « nombre de Cons »
(1) longueur(Nil)
=0
(2) longueur(Cons(pr,fin)) = 1 + longueur(fin)
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
Longueur d’une séquence : preuve de terminaison
On pose mesure(s) = |s|
où |s| : cardinal de s (vue comme un ensemble de Cons)
1) mesure à valeur dans ℕ par définition du cardinal
2) mesure décroit strictement entre 2 appels récursifs :
mesure (Cons(pr, fin)) > mesure(fin)
car |Cons(pr,fin)| = 1 + |fin|
et 1 + |fin| > |fin| = mesure(fin)
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
Implémentation :
let rec longueur (s:seqEntier) : int = match s with
| Nil
-> 0
(* d’après éq. (1) *)
| Cons(pr,fin) -> 1 + longueur(fin) (* d’après éq. (2) *)
# let s1:seqEntier = Cons (3, Cons (1 , Cons (2 , Nil))) ;;
# longueur s1 ;;
- : int = 3
inf201 : algorithmique et programmation fonctionnelle
FP
C.I) Définition récursive de séq(α)
c) Généralisation :
séquences de bool, séquence de réels, séquence de cartes,
séquence de séquences … : seqEntier, seqBool, seqCarte, seqSeq ?
=> séq doit être un type polymorphe :
séq(α) : séquence d'éléments du (même) type quelconque α
(tous les éléments ont le même type, quelconque)
Interêt : écriture de fonctions polymorphes sur les séquences
(indépendantes du type des éléments de la séquence)
En Caml, α est noté 'a, séq(α) est noté 'a list
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
C.II) Définition de fonctions récursives dans séq(α)
a) Fonctions à 1 paramètre de type séq(α)
Exemple : prédicat appartient
SPEC
Profil
app : α → séq(α) → �
Sémantique : (app e s) = vrai si e ϵ s
Exemples :
– (app 1 Nil) = faux
– (app 1 Cons(1,Nil)) = vrai
– (app 1 Cons(2,Cons(3,Nil))) = faux
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
REAL
Équations de récurrence :
(1) (app e Nil) = faux
(2) (app e Cons(pr,fin)) = ?
Tout dépend de e :
(2a) (app e Cons(e,fin)) = vrai
(2b) Soit e ≠pr,
(app e Cons(pr,fin)) = (app e fin)
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
REAL
Implémentation 1 :
analyse par cas par filtrage et
composition conditionnelle (pour discriminer les éq 2a et 2b)
let rec app (e:'a) (s:'a seq) : bool =
match s with
| Nil
-> false (* cf éq 1 *)
| Cons(pr,fin) -> if e = pr then
true (* cf éq 2a *)
else
(app e fin) (* cf éq 2b *)
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
REAL
Implémentation 2 :
analyse par cas par filtrage et
composition booléenne
let rec app (e:'a) (s:'a seq) : bool
match s with
| Nil
-> false (* cf éq
| Cons(pr,fin) -> e = pr || (app
(* cf éq 2a et
inf201 : algorithmique et programmation fonctionnelle
=
1 *)
e fin)
2b *)
FP
Récursivité dans séq(α)
REAL
Implémentation 3 :
analyse par cas par composition conditionnelle et
composition booléenne
let rec app (e:'a) (s:'a seq) : bool =
if s = Nil then
false (* cf éq 1 *)
else (* s non vide *)
let Cons(pr,fin) = s in
e = pr || (app e fin)
(* cf éq 2a et 2b *)
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
REAL
Implémentation 4 :
analyse par cas par composition booléenne uniquement
let rec app (e:'a) (s:'a seq) : bool =
.
.
.
Voir TD
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
b) Nouvelle notation (plus pratique) pour séq(α)
●
●
Nil ≡> []
Cons(pr,fin) ≡> pr :: fin
(::) : opérateur d’ajout à gauche)
En Caml, 'a list est prédéfini grâce aux « constructeurs » [] et ::
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
Cons(1, Cons(2, Cons(3, Nil))) ≡> 1 :: (2 :: (3 :: [])))
= 1 :: 2 :: 3 :: [] (:: est associatif à droite)
démo
(((1 :: 2) :: 3) :: []) => erreur de type (2 n’est pas une séq. d’entiers)
1 :: 2 :: 3 :: [] s’écrit plus simplement [1 ; 2 ; 3]
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
Le filtrage est possible sur des motifs utilisant [] et ::
[] séquence vide
[e] ou e::[] séquence à un seul élément (singleton)
[e1; e2] ou e1::e2::[]
e1::fin
e1::e2::fin
séquence à deux éléments
séquence à au moins un élément (non vide)
séquence à au moins deux éléments
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
c) Implémentation du prédicat app avec la nouvelle notation
let rec app (e:'a ) (s:'a list) : bool =
match s with
| []
-> false
| pr :: fin -> e = pr || (app e fin)
app prédéfini en Caml : List.mem
démo
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
Exemples d’appel
app 1 [] ;;
# - : bool = false
app 1 [1 ; 2 ; 3] ;;
# - : bool = true
app 0 [1 ; 2 ; 3] ;;
# - : bool = false
app 'a' ['c' ; 'b' ; 'a'] ;;
# - : bool = true
# app 'a' [1 ; 2 ; 3] ;;
Error: This expression has type int but an expression
was expected of type char
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
d) Testeur et sélecteurs sur les séquences
Testeur sur séq(α) (prédicat) : (_=[])
Profil
(=[]) : séq(α) → �
Sémantique : (=[]) (s) teste si s est la séquence vide
Sélecteurs sur séq(α) : tete et queue
Profils
tete : séq(α)*
→ α
queue: séq(α)*
→ séq(α)
Rem :
séq(α)* = séq(α) \ {[]}
séquences non vide
Sémantique :
tete(s) : premier élément de la séquence s
queue(s) : s privée de son premier élément
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
Attention : tête et queue non définies sur []
Propriété :
∀ e ϵ α, s ϵ séq(α),
tete(e::s) = e
queue(e::s) = s
Réalisation de tête et queue : … /…
tête et queue prédéfinies en Caml :
List.hd (head) et List.tl (tail)
inf201 : algorithmique et programmation fonctionnelle
FP
C.II) Définition de fonctions récursives dans séq(α)
Implémentation d'une fonction séq(α)
On choisira soit :
- filtrage sur les motifs [] et pr :: fin
- composition conditionnelle utilisant testeur et sélecteurs
Exemple : nouvelle version du prédicat app
let rec app (e:'a ) (s:'a list) : bool =
if s=[] then
false
else (* s non vide *)
e=(List.hd s) || (app e (List.tl s))
inf201 : algorithmique et programmation fonctionnelle
FP
Récursivité dans séq(α)
C.III) Modèles d'analyse dans séq(α)
a) Modèle d'analyse Mséq(α) (fonction quelconque récursive à un
paramètre de type séq(α)):
Composition
- entité base
Équations
: []
(1) f [] = ...
cas base
- constructeur : (::) (2) f(pr::fin) = ... f(fin) ...
cas réc.
Décomposition 1
Implantation 1 : an. par cas par filtrage
filtrage motifs
[]
_::_
let rec f (s:’a
match s with
| []
->
*) ...
| pr::fin ->
...
inf201 : algorithmique et programmation fonctionnelle
list) : ... =
(* d'après éq (1) :
(* d'après éq (2) : *)
f(fin)...
FP
C.III) Modèles d'analyse dans séq(α)
Composition
- entité base
Équations
: []
(1) f [] = ...
cas base
- constructeur : (::)
Décomposition 2
(2) f(pr::fin) = ... f(fin) ...
cas réc.
Implantation 2 : an. par cas par exp. cond.
testeur :
et utilisation sélecteurs tête et queue
_=[]
sélecteurs :
List.hd
List.tl
let rec f (s:’a list) : ... =
if s =[]
then (* d'après éq (1) : *) ...
else (* d'après éq (2) : *)
... f(List.tl s)...
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
b) Application du modèle Mséq(α)
SPÉC
inversion d'une séquence
Profil
inv : séq(α) → séq(α)
Sémant. inv ([e1 ; ... ; en]) = [en ; ... ; e1]
Ex :
a)
b)
c)
inv ([2 ; 1 ; 3]) = [3 ; 1 ; 2]
inv (['c' ; 'a' ; 'm' ; 'l' ]) = [‘l' ; ‘m' ; ‘a' ; ‘c' ])
inv ([‘k' ; 'a' ; ‘y' ; ‘a‘ ; ‘k’ ]) = [‘k' ; 'a' ; ‘y' ; ‘a‘ ; ‘k’ ]
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
Composition
- entité base
Équations
: []
- constructeur : (::)
(1) inv [] = ...
cas base
(2) inv (pr::fin) = ... inv (fin) ... cas réc.
(1)
Évident ([])
(2)
prenons un exemple : pr::fin = 2::([1 ; 3])
inv(2::([1 : 3])) = ... inv ([1 ; 3]) ...
[3 ; 1 ; 2]

inf201 : algorithmique et programmation fonctionnelle
[3 ; 1]
Il suffit d'ajouter 2
à droite de [3 ; 1]
FP
C.III) Modèles d'analyse dans séq(α)
Ajout de 2 à droite de [3 ; 1] =>
[3 ; 1] @ 2
[2]
Opérateur @ : séq(α) → séq(α) → séq(α) prédéfini en Caml
(concaténation de deux séquences d’éléments)
RÉAL
Algo
inversion d'une séquence
Équations :
(1) inv [] = []
(2) inv (pr::fin) = inv (fin) @ [pr]
→
inf201 : algorithmique et programmation fonctionnelle
Vérifier les types !!
FP
C.III) Modèles d'analyse dans séq(α)
(2) inv (pr::fin) = inv (fin) @ [pr]
RÉAL INFO
inversion d'une séquence (suite)
Terminaison : mesure(s) = |s|
où |…| est la fonction cardinal
1) mesure est à valeur dans ℕ
car |…| est de profil : séq(α) -> ℕ
2) mesure (pr :: fin) > mesure(fin)
car |pr::fin| = 1 + |fin|
et
1 + |fin| > |fin|
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
RÉAL INFO
Décomposition
filtrage motifs
[]
_::_
inversion d'une séquence (suite)
Implantation : an. par cas par filtrage
let rec inv (s:'a list) :
match s with
| []
-> (* d'après
[]
| pr::fin -> (* d'après
inv(fin) @
inf201 : algorithmique et programmation fonctionnelle
'a list =
éq (1) : *)
éq (2) : *)
[pr]
FP
C.III) Modèles d'analyse dans séq(α)
RÉAL INFO
inversion d'une séquence
(suite)
Décomposition 2
Implantation 2 : an. par cas par exp. cond.
- testeur
et utilisation sélecteurs tête et queue
: _=[]
- sélecteurs :
List.hd (tête)
List.tl (queue)
let rec inv (s:'a list):'a list =
if s = []
then (* d'après éq. (1) : *) []
else (* d'après éq. (2) : *)
inv(List.tl s) @ [List.hd s]
Nota : inv ([‘r’;’e’;’s’;’s’;’a’;’s’;’s’;’e’;’r’]) ?
Une séquence p telle que inv(p)=p est dite “palindrome”
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
c) Fonctions à 1 paramètre de type séq(α)*
Certaines fonctions ne sont définies que sur les séquences non
vide, notées séq(α)*
Exemple avec α = minuscule, séquence non vide de minuscules :
mot
DÉF MATH D'ENS
déf
minuscules = {'a', ..., 'z'}
déf
mot = séq(minuscule)*
DÉF INFO DE TYPES
type minuscule = char (* {'a', ..., 'z'} *)
type mot = minuscule list (* non vide *)
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
SPÉC MATH
longueur d'un mot
Profil
long : mot → ℕ*
Sémant.
long (m) est le nombre de lettres du mot m
Ex :
a)
b)
long (['o' ;'c' ;'a' ;'m' ;'l']) = 5
∀c ∈ minuscule, long ([c]) = 1
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
RÉAL INFO
Algo
longueur d'un mot
Équations :
(1) long ([pr]) = 1
(2) long (pr::fin) = 1 + long (fin) , où fin ≠ []
Terminaison mesure(...) = …
preuve : .../...
Implémentation
.../...
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
d) Généralisation : modèle MSéq(α)*
(* non vide *)
singleton
Composition
Équations
- entité base: [pr]
(1) f ([pr]) = ...
- constructeur : (::)
Décomposition
(2) f (pr::fin) = ... f (fin) ..., où fin ≠ []
Implantation : an. par cas par filtrage
let rec f (s:'a list) : ... =
match s with
singleton
| [e] -> (* d'après éq (1) : *) ...
| pr::fin-> (* d'après éq (2) : *)
... f(fin)...
NB : « this pattern-matching is not exhaustive »
filtrage motifs
[_]
_::_
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
e) Application de Mséq(α)*
prédicat : une séquence est-elle croissante ?
SPÉC MATH
une séquence d'entiers est elle croissante ?
Profil
estCroiss : séq*(ℤ) →�
Sémant.
estCroiss ([e1 ;... ;en]) ssi e1 ≤ ... ≤ en (n ≥ 1)
Ex :
a) estCroiss ([1 ; 2 ; 2 ; 4]) = vrai
b) estCroiss ([1 ; 3 ; 2]) = faux
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans Séq(α)
Composition
Équations
- entité base: pr::[]
(1) estCroiss ([pr]) = ...
- constructeur : (::)
(2) estCroiss (pr::fin) = ... estCroiss(fin) ...
avec fin ≠ []
(1)
vrai
(2)
prenons un exemple : pr::fin = 3::([1;2;3])
EstCroiss 3::([1;2;3]) = ... estCroiss ([1;2;3]) ...
faux

vrai
3 ≤ tête ([1;2;3]) et ..
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
RÉAL (suite)
Équations :
(1) estCroiss ([pr]) = vrai
(2) estCroiss (pr::fin) =
pr ≤ (tête fin) et estCroiss(fin) avec fin ≠ []
NB : «avec fin ≠ []» fondamental, car :
tête : séq(α)* → a
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
RÉALISATION
(fin)
croissance d'une séquence d'entiers
Implémentation
let rec estCroiss (s:int list (* non vide *)): bool =
match s with
| [pr] -> true
| pr :: fin ->
(pr <= (List.hd fin)) && (estCroiss fin)
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
f) Fonctions à 1 paramètre séq(α) avec découpage à DROITE
Jusqu'à présent : découpage à gauche d'une séquence s : s = pr::fin
Certaines éq. réc. s'expriment naturellement selon un découpage à
droite : s = déb @ ([der])
@ : séq(α) → séq(α) → séq(α) (concaténation)
der : séq(α)* → α
dernier élément de s
déb : séq(α)* → séq(α)
début de la séquence s  s privé de der (analogue à queue)
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
exemple : valeurs cumulées d’une séquence
SPEC
Profil
vc : séq(ℤ) → séq(ℤ )
Sémant. vc ([e1;e2;…;en]) = [e1;e1+e2;…;e1+e2+…en]
Ex. & prop.
vc([4;3;2]) = [4;7;9]
∀ e ∊ ℤ, vc([e]) = [e]
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
Réalisation
Algo
éq. rec. découpage à gauche ??
(1) vc([]) = []
(2) vc(pr::fin) = … vc(fin)…
Exemple : vc(4::[3;2]) = f(vc([3;2]) = f([3;5]) ?
Nécessite d’introduire une fonction f d’ajout d’un
entier à tous les éléments d’une séquence d’entiers
→ Recherche d’une solution avec découpage à droite
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
Réalisation
Algo
éq. rec. découpage à droite
(1) vc([]) = …
(2) vc(deb@[der]) = … vc(deb)…
Exemple : vc([4;3]@[2]) = f(vc([4;3]) = f([4;7]) ?
Il suffit d’ajouter 9 à droite (somme de la séquence [4;3;2])
 D’où :
(1) vc([]) = []
(2) vc(deb@[der]) = vc(deb) @ [somme(deb@[der])]
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
Réalisation
let rec vc (s: int list) : int list = match s with
| [] -> []
| déb @ [der] -> vc(déb) @ [somme(déb@[der])]
syntax error
 NB : filtrage non possible sur l’opérateur @ (ce n’est pas un
constructeur)
→ analyse par cas par expression conditionnelle et utilisation des
sélecteurs déb et der
inf201 : algorithmique et programmation fonctionnelle
FP
C.III) Modèles d'analyse dans séq(α)
g) Modèle d'analyse MDséq(α) modèle fonctions à 1 paramètre de type
séq(α) avec découpage à droite
Composition
- entité base
Équations
: []
(1) f [] = ...
cas base
- constructeur : _@[_] (2) f(déb@[der]) = ... f(déb) ... cas réc.
Décomposition
Implantation : an. par cas par exp. cond.
- testeur : _=[]
let rec f (s:’a list)
if s=[]
then (* d'après éq
else (* d'après éq
... f(déb
- sélecteurs :
déb
der
inf201 : algorithmique et programmation fonctionnelle
: ... =
(1) : *) ...
(2) : *)
s)...
FP
C.III) Modèles d'analyse dans séq(α)
Implémentation de vc (fin)
let rec vc (s: int list) : int list =
if s=[] then
[]
else (vc (deb s)) @ [somme s]
Avec somme, rec et der (application de MGséq(α))
let rec somme (s : int list) : int = match s with
| [] -> 0
| pr::fin -> pr + somme(fin)
let rec der (s : 'a list) : 'a = match s with
| [e] -> e
| pr::fin -> der(fin)
let rec deb (s: 'a list):'a list = match s with
| [e] -> []
| pr::fin -> pr::deb(fin)
inf201 : algorithmique et programmation fonctionnelle
FP
Téléchargement