Prog Dyn
Prog Dyn
Prog Dyn
1 Exemples
1.1 La suite de Fibonnacci
La suite de Fibonnacci est définie par récurrence par
F0 = 0, F1 = 1 et Fn = Fn−1 + Fn−2 pour n > 2
1
return T [ n ]
Une deuxième approche : On n’utilise que deux listes, on utilise ainsi moins d’em-
placement dans la mémoire
def coeff_bin_dyn2 ( n : int , p : int ) - > int :
assert n >= 1 and p >= 0
T1 = [0]*( n +1)
T1 [0] , T1 [1] = 1 ,1
for lig in range (2 , n +1):
T2 = [0]*( n +1)
T2 [0] , T2 [ lig ]=1 ,1
for col in range (1 , lig ):
T2 [ col ] = T1 [ col ]+ T1 [ col -1]
T1 = T2
2
return T1 [ p ]
longueur i 1 2 3 4 5 6 7 8 9 10
prix pi (euros) 1 5 8 9 10 17 17 20 34 30
rn = max(pn , r1 +rn−1 , r2 +rn−2 , ....., rn−1 +r1 ) = max(pn , r1 +rn−1 , r2 +rn−2 , ....., rk +
rn−k ) avec k 6 n//2 et r1 = 1
3
3 Propriété de la sous structure optimale
Définition 1. On dit qu’un problème vérifie la propriété de la sous-structure optimale
si une solution optimale contient en elle des solutions optimales de sous-problèmes
Exemple :
Dans un graphe pondéré le chemin le plus court de la source s à un sommet v passant
par w contient le chemin le plus court de s à w et le chemin le plus court de w à v
Preuve
Par l’absurde :
c c
Supposons que s → v soit le plus court et on décompose s → v en
c1 c2
s→ w→ v
c1 c01
Si s → w n’est pas le plus court alors il existe s → w plus court (soit en poids soit
1 c 1 2c0 c 1 2 c c
en nombre d’arcs) que s → w et dans ce cas s → w→ v est plus court que s → w→ v
ce qui est absurde
Théorème 1. Lorsqu’un problème vérifie la propriété de la sous-structure optimale on
peut penser à la programmation dynamique pour le coder par une formule de récurrence
4
On part de nb_pieces(0) qui vaut 0 en ajoutant une pièce de valeur 2, pour
aller vers nb_pieces(2), ce qui fait donc 1 pièce en tout.
On part de nb_pieces(1) qui vaut 1 en ajoutant une pièce de valeur 1, pour
aller vers nb_pieces(2), ce qui fait en tout 2 pièces.
On prend le minimum de ces deux nombres et on obtient nb_pieces(2) = 1.
3. Que vaut nb_pieces(3) ?
En procédant comme précédemment on compare nb_pieces(3 - 2) + 1 et 1 +
nb_pieces(3 - 1) et on prend le plus petit des deux nombres.
On obtient nb_pieces(3) = 2.
Dans le cas général on obtient la formule de récurrence suivante :
Si P est un ensemble de pièces où P = {p1 <, p2 , ... < pn } les pi sont entiers, si v est
une valeur entière et strictement positive, alors :
Si v = 0 alors on prend 0 pièces
Sinon nb_pieces(v) = min(1 + nb_pieces(v-p)) où p ∈ P et v − p > 0
= 1 + min(nb_pieces(v-p))) où p ∈ P et v − p > 0
def nb_pieces (v , P ):
"""
v un entier >= 0
P une liste d ’ entiers strictement positifs
"""
assert v >= 0
if v == 0:
return 0
return 1 + \
min ([ nb \ _pieces (v - p ) for p in P if v - p >= 0])
5
5 Le problème du sac à dos
Problème
Etant donné un sac à dos de charge maximale W = 30 kg il s’agit d’optimiser en
valeur le contenu du sac à dos en remplissant le sac avec les objets suivants de prix en
euros pi et de poids wi en kg.
Chaque objet est unique et ne peut être pris qu’une fois.
Objets 0 1 2 3
pi (euros) 7 4 3 3
wi (kg) 13 12 8 10
6
Explication de la formule de récurrence pour le problème du sac à dos.
Admettons que le problème du sac à dos vérifie la propriété de la sous-structure
optimale
Dans ce cas si dans la solution optimale P(i,w) l’objet i s’y trouve alors on peut
isoler cet objet de poids poids[i] et de prix prix[i] et écrire suivant le principe de
la sous-structure optimale
P (i, w) = P (i − 1, w − poids[i]) + prix[i]
Si l’objet i ne s’y trouve pas c’est parce que :
1. Soit il est trop lourd dans le sens où w < poids[i], dans ce cas P (i, w) = P (i−1, w)
2. Soit P (i − 1, w − poids[i]) + prix[i] < P (i − 1, w)
D’où la formule de récurrence :
Exercice
1. Ecrire une fonction Python prix_max(prix,poids,W) qui renvoie le prix maxi-
mal obtenu avec les objets pour un poids total 6 W
2. Ecrire une fonction sol_max(prix,poids,W) qui renvoie une solution maximale
au problème.
Indication :
(a) Construire le tableau P comme dans la fonction sac_a_dos(prix,poids)
(b) Initialiser un tableau solution de longueur égale au tableau poids unique-
ment avec des 0
(c) Partir du coin inférieur droit du tableau P, c’est à dire de P(n-1,W) et faire
marche arrière jusqu’à arriver à P(0,0) en appliquant la règle suivante :
Si P(i-1,w) > P(i,w) alors on a pris l’objet i donc solution[i] = 1 et ensuite
aller à P(i-1,w-poids[i])
Sinon aller à P(i-1,w)
7
4. Quatrième étape : A l’aide du tableau et de manière descendante construire
une solution optimale
8
Ecrire une fonction Python nb_differences(sequ1:str,sequ2,str) qui ren-
voie le nombre de différences entre deux chaînes de même longueur
2. Or les séquences ne sont pas toujours de même longueur, et il n’est pas forcément
pertinent de comparer les séquences dans l’ordre des caractères.
Pour se donner la possibilité de comparer des caractères de position différente
dans leur séquence respective on introduit dans l’une ou l’autre des séquences
un caractère spécial, le gap noté -
Par exemple ACTGTA et CTGTAC ont un nombre de différences de 6 si on
les compare dans l’ordre des caractères, par contre on se rend compte intuitive-
ment que le bloc CTGTA est dans les deux séquences ce qui montre une grande
familiarité entre les deux séquences.
En introduisant un gap à la fin de la première séquence et au début de la
deuxième séquence
ACTGTA -
- CTGTAC
puis en comptant le nombre de différences comme en 1) on arrive cette fois ci à
un nombre de différences de 2.
9
9 Exercices
Ex 1
Utiliser le module time et chronométrer le temps d’exécution de
1. fibo(20) et fibo(30)
2. fibo_dyn(20) et fibo_dyn(30)
3. coeff_bin(10,2) et coeff_bin(30,6)
4. coeff_bin_dyn(30,6) et coeff_bin_dyn(100,20)
5. coeff_bin_dyn2(30,6) et coeff_bin_dyn2(100,20)
Ex 2
Utiliser le module time et chronométrer le temps d’exécution de nb_pieces(v) et
nb_pieces_dyn(v)
Ex 3
1. Définir une fonction récursive nb_barres(n) qui retourne le nombre optimal de
barres
2. Définir une fonction itérative nb_barres_dyn(n) qui retourne le nombre optimal
de barres obtenu par programmation dynamique
Ex 4
Ecrire une fonction itérative decoupe_barres(n) qui retourne sous forme de liste
la découpe de la barre donnant un revenu maximal.
Ex 5
Dans un tableau triangulaire sont rangés des nombres par exemple :
tab = [[3] ,
[4 , 8] ,
[5 , 2 , 1] ,
[2 , 4 , 3 , 9]]
10