récursivité - h4 · des bricoles récursivité complexité références tabledesmatières...

76
Des bricoles Récursivité Complexité Références Récursivité Émeric Tourniaire 28 novembre 2016

Upload: lenga

Post on 11-Sep-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

Des bricoles Récursivité Complexité Références

Récursivité

Émeric Tourniaire

28 novembre 2016

Des bricoles Récursivité Complexité Références

Table des matières

Des bricolesPreuve d’algorithmeAppel de fonction

RécursivitéSuites récurrentesExemples de suites

Complexité

Références

Des bricoles Récursivité Complexité Références

Exponentiation (pas) rapide

a13 “ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a ˆ a

def pow(a,b):res = 1for i in range(b):

res = res*areturn res

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 a

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 aa4 3 a

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 aa4 3 aa8 1 a5

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 aa4 3 aa8 1 a5

a16 0 a13

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 aa4 3 aa8 1 a5

a16 0 a13

Invariant : resˆ accb

Des bricoles Récursivité Complexité Références

Exponentiation rapide

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

accn bn resn

a 13 1a2 6 aa4 3 aa8 1 a5

a16 0 a13

Invariant : resˆ accb

Optimal ?

Des bricoles Récursivité Complexité Références

Non.

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

accn bn resn

a 13 1a2 6 aa4 3 aa8 1 a5

a16 0 a13

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

accn bn resn

a 13 1 1a2 6 a 0a4 3 a 1a8 1 a5 1a16 0 a13

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

accn bn resn

a 13 1 2a2 6 a 1a4 3 a 2a8 1 a5 1

0 a13

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq

• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

accn bn resn

a 13 1 2a2 6 a 1a4 3 a 2a8 1 a5 1

0 a13

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.

• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ ay5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

Des bricoles Récursivité Complexité Références

Non.

• b en binaire.13 “ 8` 4` 1 “ Ę11012

• lpnq “ tlgpnqu` νpnq• a13 “ a ˆ a4 ˆ a8

• a15 “ a ˆ a2 ˆ a4 ˆ a8

3` 3 “ 6 multiplications.• a15 “ pa3q5 y “ a3 “ a ˆ a ˆ a

y5 “ py ˆ yq2 ˆ y2` 3 “ 5 multiplications.

Des bricoles Récursivité Complexité Références

Non.

Several authors have published statements (without proof) thatthe binary method actually gives the minimum possible number ofmultiplications. But that is not true.

(D. E. Knuth, AoCP, V. 2, ed 3, 4.6.3)

Des bricoles Récursivité Complexité Références

Non.

Several authors have published statements (without proof) thatthe binary method actually gives the minimum possible number ofmultiplications. But that is not true.

(D. E. Knuth, AoCP, V. 2, ed 3, 4.6.3)

Des bricoles Récursivité Complexité Références

Non.

• La méthode de factorisation est meilleure.

Faux (exemple, a33)

• lp2nq “ lpnq ` 1

Faux (exemple, lp191q “ lp382q “ 11)

Des bricoles Récursivité Complexité Références

Non.

• La méthode de factorisation est meilleure.Faux (exemple, a33)

• lp2nq “ lpnq ` 1

Faux (exemple, lp191q “ lp382q “ 11)

Des bricoles Récursivité Complexité Références

Non.

• La méthode de factorisation est meilleure.Faux (exemple, a33)

• lp2nq “ lpnq ` 1Faux (exemple, lp191q “ lp382q “ 11)

Des bricoles Récursivité Complexité Références

Méthode du paysan russe

def mult(a,b):acc = ares = 0while b>0:

if b%2==1:res = res+acc

acc = acc+accb = b//2

return res

Des bricoles Récursivité Complexité Références

Deux exemples simples

def f(x):return x*x

for i in range(10):print(f(i))

Des bricoles Récursivité Complexité Références

Deux exemples simples

def f(x):a=x+1return a

a=12b=f(a)print(a,b)

Des bricoles Récursivité Complexité Références

Flot du programme

__main__

a = 12

b = f(a)

print(a,b)

A

f()

def f(x):a = x+1return a

Des bricoles Récursivité Complexité Références

Flot du programme

__main__

a = 12

b = f(a)

print(a,b)

A

f()

def f(x):a = x+1return a

Des bricoles Récursivité Complexité Références

Fonctions en cascade

def fonction(i):def f(x):return x+i

return f

l = [fonction(i) for i in range(10)]

Des bricoles Récursivité Complexité Références

Fonctions en cascade

def fonction(i):def f(x):return x+i

return fl = [fonction(i) for i in range(10)]

Des bricoles Récursivité Complexité Références

Fonctions en cascade

def fonction(i):if i == 0:

return identitedef f(x):

return L[i-1](x)+1return f

L=[fonction(i) for i in range(1000)]

L[0](5) ? L[500](5) ? L[1000](1) ?

Des bricoles Récursivité Complexité Références

Pile de contextes

L[10]

A

L[9]

B

L[8]

. . .

APile de

contextes

B. . .

Des bricoles Récursivité Complexité Références

Pile de contextes

L[10]

A

L[9]

B

L[8]

. . .

APile de

contextes

B. . .

Des bricoles Récursivité Complexité Références

Pile de contextes

L[10]

A

L[9]

B

L[8]

. . .

APile de

contextes

B

. . .

Des bricoles Récursivité Complexité Références

Pile de contextes

L[10]

A

L[9]

B

L[8]

. . .

APile de

contextes

B. . .

Des bricoles Récursivité Complexité Références

Définition de la récursivité

Des bricoles Récursivité Complexité Références

Définition de la récursivité

DéfinitionUne fonction est récursive si elle s’appelle elle-même

Des bricoles Récursivité Complexité Références

Définition de la récursivité

Définition bisUne fonction est récursive si elle s’appelle elle-même mais c’estmieux si elle termine (attention aux conditions initiales !).

Des bricoles Récursivité Complexité Références

Définition de la récursivité

PropriétéPour bien comprendre la récursivité, il faut bien comprendre larécursivité.

Des bricoles Récursivité Complexité Références

Définition de la récursivité

def ping():print("Ping")pong()

def pong():print("Pong")ping()

Des bricoles Récursivité Complexité Références

Suites récurrences

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

Des bricoles Récursivité Complexité Références

Suites récurrences

def pow(a,b):acc = ares = 1while b>0:

if b%2==1:res = (res*acc)

acc = (acc*acc)b = b//2

return res

• bn`1 “ bn{{2• accn`1 “ acc2

n

#

resn`1 “ resn

resn`1 “ resn ˆ accn

Des bricoles Récursivité Complexité Références

Suites récurrences

def pow(a,b,res=1):if b==0:return res

if b%2==1:return pow(a*a,b//2,res*a)

else:return pow(a*a,b//2,res)

• bn`1 “ bn{{2• accn`1 “ acc2

n

#

resn`1 “ resn

resn`1 “ resn ˆ accn

Des bricoles Récursivité Complexité Références

Suites récurrences

def pow(a,b):if b==0:return 1

if b%2==1:return a*pow(a*a,b//2)

else:return pow(a*a,b//2)

• bn`1 “ bn{{2• accn`1 “ acc2

n

#

resn`1 “ resn

resn`1 “ resn ˆ accn

Des bricoles Récursivité Complexité Références

Décoration de fonctions

• Trace de la fonction• Lisibilité• Décorateur

def pow(a,b):if b==0:return 1

if b%2==1:return a*pow(a*a,b//2)

else:return pow(a*a,b//2)

Des bricoles Récursivité Complexité Références

Décoration de fonctions

• Trace de la fonction• Lisibilité• Décorateur

def pow(a,b):print(a,b)if b==0:return 1

if b%2==1:return a*pow(a*a,b//2)

else:return pow(a*a,b//2)

Des bricoles Récursivité Complexité Références

Décoration de fonctions

In: pow(3,15)3 159 781 36561 143046721 0Out: 14348907

def pow(a,b):print(a,b)if b==0:return 1

if b%2==1:return a*pow(a*a,b//2)

else:return pow(a*a,b//2)

Des bricoles Récursivité Complexité Références

Décoration de fonctions

• Trace de la fonction• Lisibilité• Décorateur

def madecoration(func):def wrapper(args):

# Des trucsfunc(args)# D’autres trucs

return wrapper

func = madecoration(func)

Des bricoles Récursivité Complexité Références

Décoration de fonctionsdef trace(func):def wrapper(*args):print("␣"* wrapper.space,end="")print(’{}␣<-␣{}’ . format(func.__name__,str(args)))wrapper.space += 1val = func(*args)wrapper.space -= 1print("␣"* wrapper.space,end="")print(’{}␣->␣{}’ . format(func.__name__,str(val)))return val

wrapper.space=0return wrapper

@tracedef pow(a,b):...

Des bricoles Récursivité Complexité Références

Décoration de fonctions

def pow(a,b):if b==0:return 1

if b%2==1:return a*pow(a*a,b//2)

else:return pow(a*a,b//2)

In: pow(2,13)pow <- (2, 13)pow <- (4, 6)pow <- (16, 3)pow <- (256, 1)pow <- (65536, 0)pow -> 1

pow -> 256pow -> 4096pow -> 4096

pow -> 8192Out: 8192

Des bricoles Récursivité Complexité Références

Décoration de fonctions

def pow(a,b,res=1):if b==0:return res

if b%2==1:return pow(a*a,b//2,res*a)

else:return pow(a*a,b//2,res)

In: pow(2,13)pow <- (2, 13)pow <- (4, 6, 2)pow <- (16, 3, 2)pow <- (256, 1, 32)pow <- (65536, 0, 8192)pow -> 8192

pow -> 8192pow -> 8192pow -> 8192

pow -> 8192Out: 8192

Des bricoles Récursivité Complexité Références

Décoration de fonctions

Guido Van RossumI don’t believe in recursion as the basis of all programming. This isa fundamental belief of certain computer scientists, especially thosewho love Scheme and like to teach programming by starting with a"cons" cell and recursion. But to me, seeing recursion as the basisof everything else is just a nice theoretical approach to fundamentalmathematics (turtles all the way down), not a day-to-day tool.

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

@tracedef fact(n):if n==0:return 1

elsereturn n*fact(n-1)

In: fact(3)fact <- (3,)fact <- (2,)fact <- (1,)fact <- (0,)fact -> 1fact -> 1fact -> 2

fact -> 6Out: 6

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!Comment faire pour que cesoit récursif terminal ?

• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

@tracedef fact(n):if n==0:return 1

elsereturn n*fact(n-1)

In: fact(3)fact <- (3,)fact <- (2,)fact <- (1,)fact <- (0,)fact -> 1fact -> 1fact -> 2

fact -> 6Out: 6

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

def fibo(n):if n<=1:return 1

return fibo(n-1) + fibo(n-2)

Des bricoles Récursivité Complexité Références

Exemples de suitesfibo

->1

fibo

->2

fibo

<-(1,)

fibo

->1

fibo

->3

fibo

->8

fibo

<-(4,)

fibo

<-(3,)

fibo

<-(2,)

fibo

<-(1,)

fibo

->1

fibo

<-(0,)

fibo

->1

fibo

->2

fibo

<-(1,)

fibo

->1

fibo

->3

fibo

<-(2,)

fibo

<-(1,)

fibo

->1

fibo

<-(0,)

fibo

->1

fibo

->2

fibo

->5

fibo

->13

fibo

<-(6,)

fibo

<-(5,)

fibo

<-(4,)

fibo

<-(3,)

fibo

<-(2,)

fibo

<-(1,)

fibo

->1

fibo

<-(0,)

fibo

->1

fibo

->2

fibo

<-(1,)

fibo

->1

fibo

->3

fibo

<-(2,)

fibo

<-(1,)

fibo

->1

fibo

<-(0,)

fibo

->1

fibo

->2

fibo

->5

fibo

<-(3,)

fibo

<-(2,)

fibo

<-(1,)

fibo

->1

fibo

<-(0,)

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

def pgcd(a,b):if b==0:return a

return pgcd(b,a%b)

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

$

&

%

Qp1q “ Qp2q “ 1Qpnq “Qpn ´ Qpn ´ 1qq

`Qpn ´ Qpn ´ 2qq

Des bricoles Récursivité Complexité Références

Exemples de suites

• Factorielle n!• Fibonacci Fn

• PGCD• Suite de Hopfstadter• Suite de Ackerman

$

&

%

Ap0, nq “ n ` 1Apm, 0q “ Apm ´ 1, 1q si m ą 0Apm, nq “ Apm ´ 1,Apm, n ´ 1qq

Des bricoles Récursivité Complexité Références

Tours de Hanoï

PrincipePour déplacer n disques du pic a au pic b, on déplace n ´ 1disques du pic a au c, puis on déplace le dernier disque de a à b,puis on déplace les n ´ 1 disques de c à b.

Des bricoles Récursivité Complexité Références

Tours de Hanoï

PrincipePour déplacer n disques du pic a au pic b, on déplace n ´ 1disques du pic a au c, puis on déplace le dernier disque de a à b,puis on déplace les n ´ 1 disques de c à b.

Des bricoles Récursivité Complexité Références

Tours de Hanoï

PrincipePour déplacer n disques du pic a au pic b, on déplace n ´ 1disques du pic a au c, puis on déplace le dernier disque de a à b,puis on déplace les n ´ 1 disques de c à b.

Des bricoles Récursivité Complexité Références

Tours de Hanoï

PrincipePour déplacer n disques du pic a au pic b, on déplace n ´ 1disques du pic a au c, puis on déplace le dernier disque de a à b,puis on déplace les n ´ 1 disques de c à b.

Des bricoles Récursivité Complexité Références

Tours de Hanoï

PrincipePour déplacer n disques du pic a au pic b, on déplace n ´ 1disques du pic a au c, puis on déplace le dernier disque de a à b,puis on déplace les n ´ 1 disques de c à b.

Des bricoles Récursivité Complexité Références

Tours de Hanoï

def hanoi(n,a,b):if n==1:print("On␣déplace␣un␣disque␣de",a,"vers",b)

else:hanoi(n-1,a,6-a-b)print("On␣déplace␣un␣disque␣de",a,"vers",b)hanoi(n-1,6-a-b,b)

Des bricoles Récursivité Complexité Références

Permutations

ProblèmeGénérer toutes les permutations d’une liste d’éléments ?

def permut(l1,l2):if l2==[]:

return [l1]res=[]for i in l2:

res = res+ permut(l1+[i],[k for k in l2 if k!=i])return res

Des bricoles Récursivité Complexité Références

Permutations

ProblèmeGénérer toutes les permutations d’une liste d’éléments ?def permut(l1,l2):

if l2==[]:return [l1]

res=[]for i in l2:

res = res+ permut(l1+[i],[k for k in l2 if k!=i])return res

Des bricoles Récursivité Complexité Références

Evaluation de la complexité

• Équation donnant Cpnq en fonction de Cpkq avec k ă n• Factorielle : Cpnq “ Cpn ´ 1q ` 1

Cpnq “ Opnq• Fibonacci : Cpnq “ Cpn ´ 1q ` Cpn ´ 2q

Cpnq “ OpFnq

• Dichotomie : Cpnq “ Cpn{2q ` 1Cpnq “ Oplgpnqq

• Hanoi : Cpnq “ 2Cpn ´ 1q ` 1Cpnq “ Op2nq

Des bricoles Récursivité Complexité Références

Piège à complexité

• Coûts « cachés »

Des bricoles Récursivité Complexité Références

Piège à complexité

• Coûts « cachés »• Cpnq “ 1` Cpn{2q• Cpnq “ Oplgpnqq

def dicho(x,l):""" Cherche si x est dans

l triée """if len(l)==0:

return Falsek = len(l)//2if x==l[k]:

return Trueif x<l[k]:

return dicho(x,l[:k])return dicho(x,l[k+1:])

Des bricoles Récursivité Complexité Références

Piège à complexité

• Coûts « cachés »• Cpnq “ 1` n{2` Cpn{2q• Cpnq “ Opnq

def dicho(x,l):""" Cherche si x est dans

l triée """if len(l)==0:

return Falsek = len(l)//2if x==l[k]:

return Trueif x<l[k]:

return dicho(x,l[:k])return dicho(x,l[k+1:])

Des bricoles Récursivité Complexité Références

Piège à complexité

• Coûts « cachés »• Cpnq “ 1` n{2` Cpn{2q• Cpnq “ Opnq• Meilleure version. . .

def dicho(x,l,a,b):""" Cherche si x est dans

l[a:b] triée """if b-a==1:

return l[a] == xk = (a+b)//2if x==l[k]:

return Trueif x<l[k]:

return dicho(x,l,a,k)return dicho(x,l,k+1,b)

Des bricoles Récursivité Complexité Références

Diviser pour régner

ThéorèmeSi on a une complexité de la forme Cpnq “ 2ˆ Cpn{2q ` Opnq,alors Cpnq “ Opn lg nq

Des bricoles Récursivité Complexité Références

Garder du cache

def cache(func):memoire = {}def wrapper(*args):

if args not in cache:memoire[args] = func(*args)

return memoire[args]return wrapper

Des bricoles Récursivité Complexité Références

• http://info-llg.fr/commun-mp/?a=cours• The art of Computer Programming• http://neopythonic.blogspot.fr/2009/04/tail-recursion-elimination.html