récursivité · desbricoles récursivité complexité références exponentiation(pas)rapide a13 =...
TRANSCRIPT
Des bricoles Récursivité Complexité Références
Récursivité
Émeric Tourniaire
10 décembre 2019
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*accb = 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*accb = 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*accb = 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*accb = 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*accb = 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*accb = b//2
return res
accn bn resn
a 13 1a2 6 aa4 3 aa8 1 a5a16 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*accb = b//2
return res
accn bn resn
a 13 1a2 6 aa4 3 aa8 1 a5a16 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*accb = b//2
return res
accn bn resn
a 13 1a2 6 aa4 3 aa8 1 a5a16 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 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ y2 + 3 = 5 multiplications.
Des bricoles Récursivité Complexité Références
Non.
‚ b en binaire.13 = 8 + 4 + 1 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ y2 + 3 = 5 multiplications.
accn bn resn
a 13 1a2 6 aa4 3 aa8 1 a5a16 0 a13
Des bricoles Récursivité Complexité Références
Non.
‚ b en binaire.13 = 8 + 4 + 1 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ 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 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ 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 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)
‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ 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 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ y2 + 3 = 5 multiplications.
Des bricoles Récursivité Complexité Références
Non.
‚ b en binaire.13 = 8 + 4 + 1 = Ę1101
2
‚ l(n) = tlg(n)u + ν(n)‚ a13 = a ˆ a4 ˆ a8
‚ a15 = a ˆ a2 ˆ a4 ˆ a83 + 3 = 6 multiplications.
‚ a15 = (a3)5 y = a3 = a ˆ a ˆ ay5 = (y ˆ y)2 ˆ 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)
‚ l(2n) = l(n) + 1
Faux (exemple, l(191) = l(382) = 11)
Des bricoles Récursivité Complexité Références
Non.
‚ La méthode de factorisation est meilleure.Faux (exemple, a33)
‚ l(2n) = l(n) + 1
Faux (exemple, l(191) = l(382) = 11)
Des bricoles Récursivité Complexité Références
Non.
‚ La méthode de factorisation est meilleure.Faux (exemple, a33)
‚ l(2n) = l(n) + 1Faux (exemple, l(191) = l(382) = 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+ireturn f
li = [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+ireturn f
li = [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 li[i´1](x)+1return f
li = [fonction(i) for i in range (1000)]
li [0](5) ? li [500](5) ? li [1000](1) ?
Des bricoles Récursivité Complexité Références
Pile de contextes
li[10]
A
li[9]
B
li[8]
…
APile de
contextes
B…
Des bricoles Récursivité Complexité Références
Pile de contextes
li[10]
A
li[9]
B
li[8]
…
APile de
contextes
B…
Des bricoles Récursivité Complexité Références
Pile de contextes
li[10]
A
li[9]
B
li[8]
…
APile de
contextes
B
…
Des bricoles Récursivité Complexité Références
Pile de contextes
li[10]
A
li[9]
B
li[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*accb = 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*accb = b//2
return res
‚ bn+1 = bn//2
‚ accn+1 = acc2n
‚
#
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 resif 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 = acc2n
‚
#
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 1if b%2 == 1:
return a*pow(a*a, b//2)else:
return pow(a*a, b//2)
‚ bn+1 = bn//2
‚ accn+1 = acc2n
‚
#
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 1if 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 1if 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 1if 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 fonctions
def trace(func):def wrapper(*args):
print("␣"* wrapper.space , end="")print('{}␣<´␣{}'. format(func.__name__ , args))wrapper.space += 1val = func(*args)wrapper.space ´= 1print("␣"* wrapper.space , end="")print('{}␣´>␣{}'. format(func.__name__ , 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 1if 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 ´> 4096
pow ´> 4096pow ´> 8192Out: 8192
Des bricoles Récursivité Complexité Références
Décoration de fonctions
def pow(a, b, res =1):if b == 0:
return resif 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 ´> 8192
pow ´> 8192pow ´> 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 ´> 1
fact ´> 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 ´> 1
fact ´> 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 1return fibo(n´1) + fibo(n´2)
Des bricoles Récursivité Complexité Références
Exemples de suitesfi
bo´>
1fi
bo´>
2fi
bo<´
(1,)
fibo
´>
1fi
bo´>
3fi
bo´>
8fi
bo<´
(4,)
fibo
<´(3
,)fi
bo<´
(2,)
fibo
<´(1
,)fi
bo´>
1fi
bo<´
(0,)
fibo
´>
1fi
bo´>
2fi
bo<´
(1,)
fibo
´>
1fi
bo´>
3fi
bo<´
(2,)
fibo
<´(1
,)fi
bo´>
1fi
bo<´
(0,)
fibo
´>
1fi
bo´>
2fi
bo´>
5fi
bo´>
13
fibo
<´(6
,)fi
bo<´
(5,)
fibo
<´(4
,)fi
bo<´
(3,)
fibo
<´(2
,)fi
bo<´
(1,)
fibo
´>
1fi
bo<´
(0,)
fibo
´>
1fi
bo´>
2fi
bo<´
(1,)
fibo
´>
1fi
bo´>
3fi
bo<´
(2,)
fibo
<´(1
,)fi
bo´>
1fi
bo<´
(0,)
fibo
´>
1fi
bo´>
2fi
bo´>
5fi
bo<´
(3,)
fibo
<´(2
,)fi
bo<´
(1,)
fibo
´>
1fi
bo<´
(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 areturn 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
$
’
&
’
%
Q(1) = Q(2) = 1
Q(n) =Q(n ´ Q(n ´ 1))
+Q(n ´ Q(n ´ 2))
Des bricoles Récursivité Complexité Références
Exemples de suites
‚ Factorielle n!‚ Fibonacci Fn‚ PGCD‚ Suite de Hopfstadter‚ Suite de Ackerman
$
’
&
’
%
A(0, n) = n + 1
A(m, 0) = A(m ´ 1, 1) si m ą 0
A(m, n) = A(m ´ 1,A(m, n ´ 1))
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␣{}␣vers␣{}". format(a, b))else:
hanoi(n´1, a, 6´a´b)print("On␣déplace␣un␣disque␣de␣{}␣vers␣{}". format(a, 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 += 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 += 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 C(n) en fonction de C(k) avec k ă n‚ Factorielle : C(n) = C(n ´ 1) + 1
C(n) = O(n)‚ Fibonacci : C(n) = C(n ´ 1) + C(n ´ 2)
C(n) = O(Fn)
‚ Dichotomie : C(n) = C(n/2) + 1C(n) = O(lg(n))
‚ Hanoi : C(n) = 2C(n ´ 1) + 1C(n) = O(2n)
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 »‚ C(n) = 1 + C(n/2)‚ C(n) = O(lg(n))
def dicho(x, l):""" Cherche si x est dans
l triée """if l en (l)==0:
return Falsek = l en (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 »‚ C(n) = 1 + n/2 + C(n/2)‚ C(n) = O(n)
def dicho(x, l):""" Cherche si x est dans
l triée """if l en (l)==0:
return Falsek = l en (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 »‚ C(n) = 1 + n/2 + C(n/2)‚ C(n) = O(n)‚ 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 C(n) = 2 ˆ C(n/2) + O(n),alors C(n) = O(n lg n)
Des bricoles Récursivité Complexité Références
Garder du cache
def cache(func):memoire = {}def wrapper(*args):
if args not in memoire: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