INF 321 R´ ecursivit´ e
Eric Goubault
Cours 5
10 juin 2013
Dans le dernier ´ episode...
On a vu:
Classes et m´ethodes dynamiques
Le traitement des erreurs et les exceptions Classes abstraites, interfaces, packages On va voir:
Les fonctions r´ecursives (programmation)
Les fonctions r´ecursives primitives et partielles (th´eorie de la calculabilit´e)
Un peu de complexit´e
Ce code a t-il un sens?
i n t a c k (i n t n , i n t p ) { i f ( n==0) r e t u r n p +1;
i f ( p==0) r e t u r n a c k ( n−1 , 1 ) ; r e t u r n a c k ( n−1, a c k ( n , p−1 ) ) ; }
ackun sens car la suite d’appel termine toujours:
ack(1,1)
ack(1,0)→x
ack(0,1)→2 x →2 ack(0,x) →3
→3
Discut´e formellement au cours 7...
De facon g´ en´ erale
Preuve de terminaison
On consid`ere l’ordre lexicographique sur N×N: (x,y)<(x0,y0) ssi
x <x0
x =x0 et y<y0 ack(0,p) =p+ 1: termine
ack(n+ 1,0) =ack(n,1): (n,1)<(n+ 1,0) d´ecroˆıt ack(n+ 1,p+ 1) =ack(n,ack(n+ 1,p)):
(n+ 1,p)<(n+ 1,p+ 1) et
(n,ack(n+ 1,p))<(n+ 1,p+ 1) d´ecroˆıt
Appels r´ ecursifs de fonctions
R´ecursif?
une fonction qui s’appelle elle-mˆeme...
plus g´en´eralement, ungraphe d’appelde fonction, cyclique: f appellegqui appelleh...qui appelle f!
Pour quoi faire?
s t a t i c i n t i t e r (i n t x ) { w h i l e ( x<1000) x = x +2;
r e t u r n x ; }
s t a t i c i n t a c c i t e r (i n t x ,i n t a c c ) { i f ( x>=1000) r e t u r n a c c ;
r e t u r n a c c i t e r ( x +2 , a c c + 2 ) ; } s t a t i c i n t i t e r (i n t x ) {
r e t u r n a c c i t e r ( x , 0 ) ; }
Les boucles simples peuvent s’exprimer comme des appels r´ecursifs, parfois de facon plus naturelle (!?)....
Mais surtout, la r´ecursivit´e permet d’´ecrire des fonctions qu’on ne pourrait pas coder autrement! (cf. calculabilit´e, fin du cours)
Fonction d’Ackermann!
On d´efinit:
a c k e r m a n n ( 0 , p ) = S u c c ( p )
a c k e r m a n n ( S u c c ( n ) , 0 ) = a c k e r m a n n ( n , 1 )
a c k e r m a n n ( S u c c ( n ) , S u c c ( p ) ) = a c k e r m a n n ( n , a c k e r m a n n ( S u c c ( n ) , p ) )
n’est pas impl´ementable par boucles, par contre:
Java
s t a t i c i n t a c k e r m a n n (i n t n , i n t m) { i f ( n==0) r e t u r n m + 1 ;
e l s e i f (m==0) r e t u r n a c k e r m a n n ( n−1 , 1 ) ;
e l s e r e t u r n a c k e r m a n n ( n−1 , a c k e r m a n n ( n , m−1 ) ) ; }
De mˆ eme dans d’autres langages...
C
i n t a c k e r m a n n (i n t n , i n t m) { i f ( n == 0 ) r e t u r n m + 1 ;
e l s e i f (m == 0 ) r e t u r n a c k e r m a n n ( n−1 , 1 ) ;
e l s e r e t u r n a c k e r m a n n ( n−1 , a c k e r m a n n ( n , m− 1 ) ) ; }
Caml
l e t r e c a c k e r m a n n = f u n c t i o n
| ( 0 , n )−> n + 1
| (m, 0 ) −> a c k e r m a n n (m−1 , 1 )
| (m, n ) −> a c k e r m a n n (m−1 , a c k e r m a n n (m, n− 1 ) ) ; ;
Attention!
Probl`eme de d´efinition circulaire:
s t a t i c i n t f (f i n a l i n t x ) { r e t u r n f ( x ) ;
}
Compilation, ex´ecution...
> j a v a c t o t o . j a v a
t o t o . j a v a : 7 : c a n n o t r e t u r n a v a l u e f r o m method whose r e s u l t t y p e i s v o i d r e t u r n f ( 1 ) ;
ˆ 1 e r r o r
(boucle infinie=pas de valeur de retour - le compilateur ne
Appels r´ ecursifs
Reprenons une d´efinition de fonction r´ecursive, simple
fact(0)=1
fact(n+1)=(n+1)*fact(n) (factorielle)
Version r´ ecursive
Java
s t a t i c i n t f a c t (f i n a l i n t x ) { i f ( x == 0 ) r e t u r n 1 ;
r e t u r n x∗f a c t ( x−1 ) ; }
On a la terminaison que si xest positif...
C
i n t f a c t (c o n s t i n t x ) { i f ( x == 0 ) r e t u r n 1 ; r e t u r n x∗f a c t ( x−1); }
Caml
S´ emantique?
Par d´eroulement
fact(3)
Pile d’appel
Maintient unepile permettant aux appelants successifs de se souvenir:
du sited’appel (pour pouvoir revenir `a l’ex´ecution dans l’appelant apres le return):
1 s t a t i c i n t f a c t (f i n a l i n t x ) { 2 i f ( x == 0 ) r e t u r n 1 ; 3 r e t u r n x∗f a c t ( x−1); }
Apr`es l’appel defact(x- 1);revenir ligne 3
du contexted’appel (pour pouvoir retrouver les valeurs des variables locales `a l’appelant, apr`esreturn...): ici la valeur de xde l’appelant - plus plus tard...
S´ emantique
Par d´eroulement fact(3)
fact(2)
Pile d’appel:
PC Ctx l.3 x=3
S´ emantique
Par d´eroulement fact(3)
fact(2)
fact(1)
Pile d’appel:
PC Ctx l.3 x=3 l.3 x=2
S´ emantique
Par d´eroulement fact(3)
fact(2)
fact(1)
fact(0)
Pile d’appel:
PC Ctx l.3 x=3 l.3 x=2 l.3 x=1
S´ emantique
Par d´eroulement fact(3)
fact(2)
fact(1)
1
Pile d’appel:
PC Ctx l.3 x=3 l.3 x=2
S´ emantique
Par d´eroulement fact(3)
fact(2)
1
Pile d’appel:
PC Ctx l.3 x=3
S´ emantique
Par d´eroulement fact(3)
2
Pile d’appel:
PC Ctx
Finit avec 3∗2 = 6, ouf!
Couteux?
> j a v a F a c t 1 0 0 0 0 0 0
E x c e p t i o n i n t h r e a d ”main ” j a v a . l a n g . S t a c k O v e r f l o w E r r o r a t F a c t . f a c t ( f a c t . j a v a : 5 )
a t F a c t . f a c t ( f a c t . j a v a : 5 ) . . .
(outre le fait que la valeur obtenue si c’etait possible d´epasse largement ce qui est repr´esentable en machine!)
Oui et non: r´ecursivit´e tr`es utile (indispensable parfois) mais faire attention quand mˆeme...
R´ ecursion terminale et d´ er´ ecursivisation
Retraduire en it´eratif...(quand c’est possible) On peut bien sˆur transformer ce code en (puisque c’est une d´efinition r´ecursive primitive cf. plus loin...):
Java
s t a t i c i n t f a c t (f i n a l i n t x ) { i n t i ;
i n t r e s = 1 ;
f o r ( i =x ; i>=2; i =i−1) r e s = i∗r e s ;
r e t u r n r e s ; }
En C et Caml
C
i n t f a c t (c o n s t i n t x ) { i n t i ;
i n t r e s = 1 ; f o r ( i =x ; i>=2; i−−)
r e s = i∗r e s ; r e t u r n r e s ;
Caml
l e t f a c t n = l e t n b r = r e f 1 i n
f o r i = 1 t o n do
n b r := ( ! n b r ∗ i ) done;
! n b r ; ;
Comment faire cette transformation?
R´ecursion terminale
s t a t i c i n t a f a c t (i n t n , i n t a c c ) { i f ( n == 0 ) r e t u r n a c c ;
r e t u r n a f a c t ( n−1 , n∗a c c ) ; } s t a t i c i n t t e r m i n a l f a c t (i n t n ) {
r e t u r n a f a c t ( n , 1 ) ; }
Exemple de r´ecursion terminale: suite d’appels avec un cas de terminaison, pour lesquels il n’y a pas besoin de m´emoriser ce qu’il reste `a faire apr`es les retours de fonctions (grˆace `a l’accumulateur acc)
Permet au compilateur de transformer automatiquement en code it´eratif, et n’a pas `a sauvegarder tous les ´etats
interm´ediaires sur la pile.
Permet d’´economiser de la m´emoire, pas d”’explosion”
m´emoire possible avec ces appels r´ecursifs.
Comparaison des suite d’appels r´ ecursifs terminal/pas terminal
Appel r´ecursif non-terminal (rappel):
fact(3)
fact(2)
fact(1)
fact(0)
Pile d’appel:
PC Ctx l.3 x=3 l.3 x=2 l.3 x=1
Comparaison des suite d’appels r´ ecursifs terminal/pas terminal
Appel terminal r´ecursif:
fact(3)
afact(3,1)
afact(2,3)
afact(1,6)
fact(0,6)=6
Renvoie 6 imm´ediatement, aucun besoin de pile! (juste le coˆut 23
Principe de r´ ecurrence structurelle (listes lin´ eaires)
SoitP une propri´et´e qui nous int´eresse sur un domaine de valeurs...
Ex.: les entiers naturels
Si P est vraie en 0 (on ´ecritP(0))
Et si P(n)→P(succ(n)), alors P est vraie sur toutN Ex.: les listes
Si P est vraie en ()
Et si P(l) vraie pour toutes les listes de longueurn implique P(cons(car,l)) est vraie (pour toute valeur de car, et toute liste l de longueurn); alorsP est vraie sur toutListN Cons´equence directe de la r´ecurrence sur les entiers car on a la fonctiontotale length:List → , et
Comment impl´ emente t-on length ?
Par r´ecurrence structurelle (sur les fonctions)! Programmation directe de la d´efinition math´ematique:
Java
c l a s s L i s t { . . .
s t a t i c i n t l e n ( L i s t l ) { i f ( l == n u l l)
r e t u r n 0 ; e l s e
r e t u r n l e n ( l . t l ) + 1 ; }
}
Cas de r´ ecurrence terminale!
D´er´ecursivisation:
s t a t i c i n t l e n ( L i s t l ) { i n t i = 0 ;
w h i l e ( l != n u l l) { i = i +1;
l = l . t l ; }
r e t u r n i ; }
Un peu de p´ edantique
Preuve qu’on calcule bien ce qu’on veut calculer...
SoitP(l) = ”length(l) =len(l)”:
P(()) est vraie carlength(()) = 0 =len(())
Supposons P(l) vraie pour toute liste de longueur n, on calcule length(cons(car,l)) =length(l) + 1 =n+ 1 et len(cons(car,l)) =len(l) + 1 =n+ 1 par hypoth`ese de r´ecurrence. Donc on a P(cons(car,l)).
On a doncP(l) vraie pour toutes les listeslin´eaires l.
Remarque: la fonctionlenne termine pas si on part de la liste circulairel =cons(0,l)...
Partage or not partage?
Java
Si partage sans cycle, on peut toujours d´efinir la fonction length et raisonner par r´ecurrence structurelle.
On ´economise juste en m´emoire, et cela peut permettre de faire du hash-consing sur les listes...
Ex. fonction append: on veut concat´ener une listel2 au bout de la listel1:
s t a t i c L i s t append ( L i s t l 1 , L i s t l 2 ) { i f ( l 1 == n u l l) r e t u r n l 2 ;
i f ( l 2 == n u l l) r e t u r n l 1 ; l 1 . t l = append ( l 1 . t l , l 2 ) ; r e t u r n l 1 ;
}
Exemple d’ex´ ecution
Que donne?
append ( l 1 , l 3 ) ; append ( l 2 , l 3 ) ;
Avec:
l1 4|. 5|null
l2 1|null
l3 2|. 3|null
Exemple d’ex´ ecution
Premi`ere ´etape append ( l 1 , l 3 ) ;
. . .
append ( l 1 . t l . t l , l 3 ) ; . . .
Avec:
l1 4|. 5|.
l2 1|null
Exemple d’ex´ ecution
Deuxi`eme ´etape append ( l 2 , l 3 ) ;
. . .
append ( l 2 . t l , l 3 ) ; . . .
Avec:
l1 4|. 5|.
l2 1|.
l3 2|. 3|null
Alternativement (pas de partage)
Java
s t a t i c L i s t c o p y ( L i s t l ) { i f ( l == n u l l) r e t u r n n u l l;
r e t u r n new L i s t ( l . hd , c o p y ( l . t l ) ) ; }
s t a t i c L i s t append ( L i s t l 1 , L i s t l 2 ) {
i f ( l 1 == n u l l) r e t u r n c o p y ( l 2 ) ; // r e t u r n l 2 ; r e t u r n new L i s t ( l 1 . hd , append ( l 1 . t l , l 2 ) ) ;
}
Exemple d’ex´ ecution
Que donne?
append ( l 1 , l 3 ) ; append ( l 2 , l 3 ) ;
Avec:
l1 4|. 5|null
l2 1|null
l3 2|. 3|null
Exemple d’ex´ ecution
Premi`ere ´etape
append ( l 1 , l 3 ) ;
. . .
new L i s t ( l 1 . hd , new L i s t ( l 1 . t l . hd ,
append ( l 1 . t l . t l , l 3 ) ) ) ; . . .
Avec:
l1 4|. 5|null
l2 1|null
l3 2|. 3|null
append(l1,l3) 4|. 5|.
2|. 3|null
Exemple d’ex´ ecution
Deuxi`eme ´etape
append ( l 2 , l 3 ) ;
. . .
new L i s t ( l 2 . hd , append ( l 2 . t l , l 3 ) ) ;
. . .
Avec:
l3 2|. 3|null
append(l1,l3) 4|. 5|.
2|. 3|null
append(l2,l3) 1|. 2|.
3|null
Partage or not partage?
Partage possible de l’argument gauche, de l’argument droit, des deux, ou d’aucun des deux...
Int´erˆet/inconv´enient: si on modifieen place les listesl1,l2 oul3,append(l1,l3); et append(l2,l3);ne sont pas modifi´ees.
Tout d´epend de ce que l’on veut faire, y r´efl´echir avant de taper un code!
Int´ erˆ et de la r´ ecursion? calculabilit´ e...
Que calcule t-on avec tout sauf la r´ecursion (dans les entiers)?
Fonctions r´ecursives primitives (RP)
Plus petit ensemblede fonctions deNn versNm contenant:
3 fonctions de base: 0, succ, projections
la composition de fonctions r´ecursives primitives: si h, g1, . . . ,gk sont des fonctions RP, h(g1, . . . ,gk) est dans RP les fonctions d´efinies parr´ecursion primitive: g et h RP, g :Np→N,h:Np+2→N, alors f :Np+1→N d´efinie par:
∀y ∈Np,f(0,y) =g(y)
∀i∈N,y ∈Np, f(succ(i),y) =h(i,f(i,y),y)
R´ ecursion primitive
Programmation
Les fonctions r´ecursives primitives se programment dans tout langage de programmation, `a l’aide d’une simple instruction it´erative for:
f ( x , y ) { z = g ( y ) ;
p o u r ( i =0; i<=x−1; i = i +1) { z = h ( i , z , y ) ;
}
r e t o u r n e ( z ) ; }
Quelques fonctions r´ ecursives primitives
Pr´edecesseur
p r e d ( 0 ) = 0 p r e d ( s u c c ( x ) ) = x
R´ecursion primitive avec p= 0, g = 0, h(x,y) =x: f(0) = g
= 0
f(succ(i)) = h(i,f(i))
= i
Quelques fonctions r´ ecursives primitives
Somme de deux entiers
somme ( 0 , y ) = y
somme ( s u c c ( x ) , y ) = s u c c ( somme ( x , y ) )
R´ecursion primitive avec p= 1, g(y) =y, h(x,z,y) =succ(z):
f(0,y) = g(y)
= y
f(succ(i),y) = h(i,f(i,y),y)
= succ(f(i,y))
Quelques fonctions r´ ecursives primitives
Produit de deux entiers
p r o d u i t ( 0 , y ) = 0
p r o d u i t ( s u c c ( x ) , y ) = somme ( y , p r o d u i t ( x , y ) )
R´ecursion primitive avec p= 1, g = 0, h(x,z,y) =somme(y,z):
f(0,y) = g
= 0
f(succ(i),y) = h(i,f(i,y),y)
= somme(f(i,y),y)
De mˆeme pour somme de deux fonctions RP, produit de deux fonctions RP
Principe de minimisation born´ ee
Sif :Np+1→N est RP, et il existeM tel que quelque soit y∈Np, il existe x ∈N,x ≤M tel quef(x,y) = 0; alors:
g(y) = min{x ∈N,f(x,y) = 0}
est une fonction RP deNp vers N
Alternativement: les fonctions RP sont les fonctions contenant 0, succ et les projections, stables par composition, et par
minimisation born´ee.
Limitation des fonctions r´ ecursives primitives
Terminaison
Dans RP, on ne peut d´efinir que des fonctions totales (qui terminent toujours).
Cette fonction totale est-elle r´ecursive primitive?
a c k e r m a n n ( 0 , p ) = s u c c ( p )
a c k e r m a n n ( s u c c ( n ) , 0 ) = a c k e r m a n n ( n , 1 )
a c k e r m a n n ( s u c c ( n ) , s u c c ( p ) ) = a c k e r m a n n ( n , a c k e r m a n n ( s u c c ( n ) , p ) )
La fonction d’Ackerman est-elle r´ ecursive primitive?
Essayez de la d´efinir avec des boucles...
i n t a c k (i n t n , i n t p ) { i f ( p==0)
f o r ( i =0; i<=n−1; i = i +1) { ? ? . . .
R´ecurrence emberlificot´ee sur 2 indices!
Pas dans RP, mais calculable en un certain sens!
Il faut pouvoir´ecrire des fonctions et les appeler de mani`ere r´ecursive
i n t a c k (i n t n , i n t p ) { i f ( n==0) r e t u r n p +1;
i f ( p==0) r e t u r n a c k ( n−1 , 1 ) ; r e t u r n a c k ( n−1, a c k ( n , p−1 ) ) ;
Pourquoi Ackerman n’est-elle pas r´ ecursive primitive?
Quelques valeurs deA(m,n)
m / n 0 1 2 3
0 1 2 3 4
1 2 3 4 5
2 3 5 7 9
3 5 13 29 61
4 13 65533 265533 A(3,265533)
5 65533 A(4,65533) A(4,A(5,1)) ...
6 A(5,1) A(5,A(5,1)) A(5,A(6, 1)) ...
A n’est pas dans RP
Ack croit plus vite que toute fonction RP
∀f :Nk →N∈RP,∃a tel que
f(a1, . . . ,ak)<A(a,max(a1, . . . ,ak)).
Sch´ema de preuve On prouve que:
la fonctionx →0 est major´ee par A(0,x) =x+ 1 la fonctionx →succ(x) est major´ee par A(1,x) =x+ 2 les projections πkn(x1, . . . ,xn) =xk sont major´ees par A(0,max(x1, . . . ,xn)) =max(x1, . . . ,xn) + 1
Puis que sig1, . . . ,gm sont telles que gi(x)<A(rgi,maxx), et h tel queh(x)<A(rh,maxx) alors f =h(g1, . . . ,gm) est telle que
Fin de l’argument
Fin de la preuve
Enfin, soitf ∈RP d´efinie par r´ecursion primitive (avecg et h).
Supposonsg(x)<A(rg,maxx), h(x)<A(rh,maxx), alors une r´ecurrence simple montre que
f(i,x)<A(rf,max{i,x}) avecrf = 1 +max(rg,rh).
RP est leplus petit ensemble contenant 0, succ, les projections, stable par composition et r´ecursion primitive, donc toute fonction dans RP peut ˆetre major´ee par un A(a, .).
Argument diagonal de Cantor On consid`ereg(a) =A(a,a)
Supposons g dans RP, alors ∃rg,∀a,g(a)<A(rg,a):
impossible, consid´ererg(rg) =A(rg,rg)!
Que calcule t-on au final?
(avec la r´ecursion!) Fonctions partielles
Une fonction partiellef de Nn versNm est une fonction d´efinie sur un sous-ensemble deNn, allant vers Nm
On notef(x) =⊥ pour lesx∈Nn tels quef n’est pas d´efinie enx (recodage en une fonction dansNm∪ {⊥})
Que calcule t-on au final?
(avec la r´ecursion!)
Fonctions r´ecursives partielles (R)
Plus petit ensemble R de fonctionspartiellesdeNn versNm contenant:
3 fonctions de base: 0, succ, projections
la composition de fonctions r´ecursives partielles: sih, g1, . . . ,gk sont des fonctions R, h(g1, . . . ,gk) est dans R R est clos par minimisation (pas forc´ement born´ee!): si f :Np+1 →Nest R, alors
g(y) = min{x ∈N|f(x,y) = 0}
est une fonction R de Np versN
En particulier si pour uny, il n’existe aucun x tel quef(x,y) = 0, alorsg(y) est non-d´efinie, i.e. g(y) =⊥.
Quelques propri´ et´ es et exemples
Rapport avec RP
RP ⊆R bien ´evidemment...
R est exactement l’ensemble des fonctions partielles obtenues par au plus une minimisation d’une fonction dans (RP) Exemple
La fonction d’Ackermann est dans (R) ...
Est-ce tout?
Th`ese de Church
Les fonctions R sont aussi appel´ees “fonctions calculables”
“Les seules fonctions calculables algorithmiquement, par une machine, sont les fonctions de R”
Th`ese v´erifi´ee dans tous les mod`eles de calcul connus:
λ-calcul (cf. PCF cours 9), tout langage de programmation actuel, machine de Turing, machine de Post etc.
On dit qu’une machine (ou langage) estTuring complets’il permet de calculer toutes les fonctions calculables - Java, C, Caml sont Turing complets
C’est bien la calculabilit´e/d´ecidabilit´e mais quand c’est calculable, cela l’est `a quel coˆut? (→ complexit´e)
Est-ce tout?
Th`ese de Church
Les fonctions R sont aussi appel´ees “fonctions calculables”
“Les seules fonctions calculables algorithmiquement, par une machine, sont les fonctions de R”
Th`ese v´erifi´ee dans tous les mod`eles de calcul connus:
λ-calcul (cf. PCF cours 9), tout langage de programmation actuel, machine de Turing, machine de Post etc.
On dit qu’une machine (ou langage) estTuring complets’il permet de calculer toutes les fonctions calculables - Java, C, Caml sont Turing complets
C’est bien la calculabilit´e/d´ecidabilit´e mais quand c’est calculable, ut? (→
Exemple: inversion na¨ıve de liste
Naivement...:
s t a t i c L i s t add (f i n a l L i s t x , f i n a l i n t y ) { i f ( x == n u l l) r e t u r n new L i s t ( y , n u l l) ; r e t u r n new L i s t ( x . hd , add ( x . t l , y ) ) ; }
s t a t i c L i s t r e v e r s e (f i n a l L i s t x ) { i f ( x == n u l l) r e t u r n n u l l;
r e t u r n add ( r e v e r s e ( x . t l ) , x . hd ) ; }
Complexit´ e algorithmique
Complexit´e?
On va compter le nombre d’op´erations ´el´ementaires effectu´ees par add(dans un premier temps), en fonction de lataillede ses arguments
on suppose un coˆut unitaire pour chaque op´eration arithm´etique, pour chaque test, pour chaque allocation m´emoire etc. (pas tout `a fait vrai sur une machine moderne, mais pas compl`etement faux quand on raisonne `aproportions pr`es)
la taille d’une liste l (de scalaires) est compt´ee comme ´etant
´
egale `alength(l).
De l”’ordre de”n2!
Exemple : inversion non naive de liste
Code final:
s t a t i c L i s t r e v a p p e n d (f i n a l L i s t x , f i n a l L i s t y ) { i f ( x == n u l l) r e t u r n y ;
r e t u r n r e v a p p e n d ( x . t l , new L i s t ( x . hd , y ) ) ; }
s t a t i c L i s t r e v e r s e (f i n a l L i s t x ) { r e t u r n r e v a p p e n d ( x ,n u l l) ; }
De l’ordre den op´erations!
Remarque: version it´ erative:
Code final:
On parcourt la liste dans un sens, pour reconstruire une autre dans l’autre!
s t a t i c L i s t r e v e r s e ( L i s t x ) { L i s t r e s = n u l l;
w h i l e ( x != n u l l) {
r e s = new L i s t ( x . hd , r e s ) ; x = x . t l ;
}
r e t u r n r e s ; }
Que veut-on dire par “est de l’ordre de” ( ∼ )?
Notations de Landau et de Hardy
Comme en analyse (ici, pourf,g deux fonctions de NversN):
f =O(g) ssi ∃α,N,∀n∈N,n ≥N =⇒ f(n)≤αg(n) f =o(g) ssi ∀,∃N,∀n∈N,n≥N =⇒ f(n)≤g(n) f ∼g ssi limn→∞f(n)
g(n) = 1 En fait, plus utile pour nous:
L’ordre de grandeur...:
f = Ω(g) ssi∃α,N,∀n ∈N,n≥N =⇒ f(n)≥αg(n) f = Θ(g) ssi∃α, β,N,∀n∈N,
n ≥N =⇒ βg(n)≤f(n)≤αg(n)
Complexit´ e d’un algorithme
En moyenne, dans le cas le pire...
Etant donn´e un probl`eme de taille n, la complexit´e d’un algorithme estf(n), le nombre d’op´erations´el´ementairesimpliqu´ees dans son calcul:
Complexit´e en moyenne: moyenne arithm´etique des nombres d’op´erations pour une taillen
Complexit´e dans le cas le pire: max des nombres d’op´erations pour une taille n
(sur une machines´equentielle)
Complexit´ e d’un probl` eme
Exemple
La complexit´e (dans le cas le pire, et en moyenne) de reverse (naif) est en Θ(n2)
La complexit´e d’un probl`eme est la meilleure complexit´e d’un algorithme r´esolvant ce probl`eme:
Classes de complexit´ e
Complexit´e en temps
Dans l’ordre (strictement) croissant, les plus classiques:
Temps Classe Exemple
Θ(1) temps constant addition d’entiers (machine) Θ(log(n)) temps logarithmique
Θ(n) temps lin´eaire inversion de liste Θ(n log(n)) temps quasi-lin´eaire tri
Θ(n2) temps quadratique produit matrice vecteur Θ(np) temps polynomial multiplication de matrices Θ(en) temps exponentiel plus tard...
Classes de complexit´ e
On note classiquement:
L pour le temps logarithmique (fonctions tr`es peu coˆuteuses) P (ou PTIME) pour le temps polynomial (pas trop coˆuteuses) EXPTIME pour le temps exponentiel (tr`es coˆuteuses)
Exemple d’ordres de grandeur (en secondes)
Classe/n 1 2 5 10 . . . 20 50
L 0... 0.3 0.7 1 1.3 1.7
Θ(n) 1 2 5 10 20 50
Θ(n log(n)) 0... 0.6 3.5 10 26 85
Θ(n2) 1 4 25 100 400 2500
Θ(n3) 1 8 125 1000 8000 125000
Θ(en) 2.7 7.4 148 22026 4.9.108 5.2.1021 Ce dernier nombre fait environ 1.6.1014 ann´ees alors que l’ˆage de l’univers estim´e est d’environ 15.109 ann´ees;
Notre syst`eme solaire aura disparu depuis bien longtemps...
Pour aller plus loin: classe NP;
NP-compl´ etude
Sans rentrer dans les d´etails...
Probl`emes les “plus durs” dont on peut v´erifier la solution en temps polynomial
H´elas beaucoup de probl`emes classiques sont NP-complet:
exemple SAT, d´eterminer si une formule logique (propositionnelle) est toujours vraie ou pas
aussi compliqu´e qu’´enum´erer les valeurs bool´eennes pour toutes les variables (exponentiel) et tester si la formule est vraie avec ces affectations (polynomial)
ex.: a∨ ¬a, essayera=true puisa=false...
On ne connaˆıt `a l’heure actuelle que des algorithmes
EXPTIME au mieux pour r´esoudre les probl`emes NP-complets On ne sait pas `a l’heure actuelle siP 6=NP (mais bien sˆur
Complexit´ e en espace
On compte non pas le temps mais le nombre d’octets n´ecessaire `a r´esoudre un probl`eme algorithmique...
R´esum´e...
L⊆P ⊆PSPACE ⊆EXPTIME
Remarquez le rapport complexit´e en temps et en espace...
Pour aller plus loin...INF 423!
C’est tout pour aujourd’hui...
La prochaine fois
Logique propositionnelle (rappels), et th´eorie de la preuve (automatisation en COQ)
Logique des pr´edicats
Java Modeling Language (JML) Bon TD!
C’est tout pour aujourd’hui...
La prochaine fois
Logique propositionnelle (rappels), et th´eorie de la preuve (automatisation en COQ)
Logique des pr´edicats
Java Modeling Language (JML) Bon TD!