Vous êtes sur la page 1sur 20

1

Chapitre 5: La programmation dynamique





1. Introduction

La programmation dynamique est un paradigme de conception quil est possible de voir comme
une amlioration ou une adaptation de la mthode diviser et rgner. Ce concept a t introduit par
Bellman, dans les annes 50, pour rsoudre typiquement des problme doptimisation.
Pour la petite histoire, Bellman a choisi le terme programmation dynamique dans un souci de
communication : son suprieur ne supportait ni le mot recherche ni celui de
mathmatique . Alors il lui a sembl que les termes programmation et dynamique
donnaient une apparence qui plairait son suprieur. En ralit, le terme programmation signifiait
lpoque plus planification et ordonnancement que la programmation au sens quon lui donne
de nos jours. En un mot, la programmation dynamique est un ensemble de rgles que tout un
chacun peut suivre pour rsoudre un problme donn.
La programmation dynamique est similaire la mthode diviser et rgner en ce sens que, une
solution dun problme dpend des solutions prcdentes obtenues des sous-problmes. La
diffrence significative entre ces deux mthodes est que la programmation dynamique permet
aux sous-problemes de se superposer. Autrement dit, un sous-problmes peut tre utilis dans la
solution de deux sous-problmes diffrents. Tandis que lapproche diviser et rgner cre des
sous-problmes qui sont compltement spars et peuvent tre rsolus indpendamment lun de
lautre. Une illustration de cette diffrence est montre par la Figure 5.1. Dans cette figure, le
problme rsoudre est la racine, et les descendants sont les sous-problmes, plus faciles
rsoudre. Les feuilles de ce graphe constituent des sous-problmes dont la rsolution est triviale.
Dans la programmation dynamique, ces feuilles constituent souvent les donnes de lalgorithme.
La diffrence fondamentale entre ces deux mthodes devient alors claire: les sous-problmes
dans la programmation dynamique peuvent tre en interaction, alors dans la mthode diviser et
rgner, ils ne le sont pas.


diviser et rgner programmation dynamique

Une seconde diffrence entre ces deux mthodes est, comme illustr par la figure ci-dessus, est
que la mthode diviser et rgner est rcursive, les calculs se font de haut en bas. Tandis que la
programmation dynamique est une mthode dont les calculs se font de bas en haut : on
2
commence par rsoudre les plus petits sous-problmes. En combinant leur solution, on obtient les
solutions des sous-problmes de plus en plus grands.


Illustration 1: On dbute nos exemples par celui du calcul des nombres de Fibonacci. Le
problme est de calculer le n premiers nombres de Fibonacci donns par la formule suivante :

) 2 ( ) 1 ( ) (
; 1 ) 1 ( ; 1 ) 0 (
+ =
= =
n F n F n F
F F


Lalgorithme implantant cette formule est alors comme suit :

Algorithme 1

int function Fibo(int n){

if (n <= 1)
return 1 ;
else return(Fibo(n-1)+Fibo(n-2))
}

Nous avons vu que la complexit de cet algorithme est en exponentielle. La raison de cette
inefficacit est due la multiplicit de calcul dun mme nombre, comme le montre la figure ci-
dessous sur n =4.


Figure 5.2.
3
La clef une solution plus efficace est dviter la multiplicit de rsolution du mme sous-
problme. On amliore de loin la complexit temporelle si, une fois calcul, on sauvegarde un
rsultat, par exemple dans une table. Et au besoin, on le prend de cette table. Cette remarque nous
amne la solution suivante :

Algorithme 2

int function Fib(int n){

if (Fib(n) solution est dans la table)
return table[n] ;
if (n<= 2)
return 1;
else {
sol = Fib(n-1) + Fib(n-2)
sauvegarder sol dans table comme solution Fib(n) ;
return (sol) ;
}
}

Cette approche de rsolution est connue sous le nom de fonctions mmoire, qui est trs lie la
programmation dynamique. On y reviendra un peu loin. En suupprimant la rcursivit, nous
crivons cet algorithme dans une forme typique de la programmation dynamique.

Algorithme 3

int function Fib(int n){
F[1] =1 ; F[2] =1 ;
For (i=2 ; i<=n ; i++)
F[i] = F[i-1] + F[i-2];
return (F[i]);
}

Illustration 2 : Avanons un peu plus dans ce concept en prenant un autre exemple qui est celui
du calcul du coefficient binomial.

Si on implante directement cette expression sous cette forme, on obtient la fonction suivante :




4
int function B(int n,k) {
if (k = = 0) || (k = = n)
return 1
else return(B(n-1,k-1) + B(n-1,k);
} \\ fin de fonction

Voyons voir lexcution de cette fonction sur un exemple de donnes: n = 5 et k = 2. Remarquez
le nombre de fois, par exemple que, le terme
|
|
.
|

\
|
1
2
est calcul.


Exercice: montrer que la complexit temporelle de cette fonction est en
|
|
.
|

\
|
k
n
.

Pour viter de calculer plusieurs fois un nombre, lide est de crer un tableau o on calcule tous
les nombres de petites tailles, ensuite, de tailles de plus en plus grandes avant darriver au
nombre dsir. Pour ce faire, on procde comme suit :

5


Pour calculer donc B(n,k), on procde comme suit:

for(i=0 ; i<=n ; i++)
for (j=0; j<=min{i,k}; j++)
if (i==0) ||(j==i)
B[i,j] = 1;
else B[i,j] = B[i-1,j-1] + B[i-1,j]
return (B[n,k]);

On remplit le tableau B ligne par ligne comme suit



Complexit de lalgorithme : cette complexit est rduite au remplissage de la moiti du tableau
B. Comme le nombre dlments de B est de n k , la complexit de lalgorithme est par
consquent en ) (kn O .

Remarque : Il est intressant de constater que seule la moiti de la matrice B est utilise pour
calculer B[n,k]. Autrement dit, un tableau une dimension suffirait pour faire ces calculs. On
obtient alors lalgorithme suivant :

6




2. Quand et comment utiliser la mthode de la programmation dynamique

La programmation est un outil gnral de rsolution de problmes. Toutefois, il ny pas de rgle
pour affirmer que la programmation dynamique peut ou ne peut tre utilise pour rsoudre tel ou
tel problme.
Le gros du travail, si on veut utiliser cette mthode, rside tout dabord dans lobtention de
lexpression rcursive de la solution en fonction de celle des sous-problmes (de taille plus
petite). Notons que dans les problmes doptimisation, cette manire dobtenir la solution
optimale partir des solutions optimales des sous problmes sappelle le principe doptimalit
de Bellman. Il est important de souligner que ce principe, bien que naturel, nest pas toujours
applicable.

Exercice : Trouver un exemple o ce principe nest pas applicable.

Une fois cette expression obtenue, on analyse ce qui se passe dans une implantation rcursive
nave : si on se rend compte que la solution de mme problmes est calcule plusieurs fois, on est
alors dans le cadre de la programmation dynamique. Le dcoupage du problme devrait
naturellement conduire la dfinition de la table (qui peut tre de dimension 1,2,3, ).
Remarquez quune case de la table correspond un sous-problme. Par ailleurs, le nombre de
sous-problmes peut tre trs grand. La complexit obtenue, de lalgorithme de programmation
dynamique, nest pas forcment polynomial.

Si on est dans le cadre de la mthode de la programmation dynamique, les tape suivies peuvent
tre rsumes comme suit :

a. obtention de lquation rcursive liant la solution dun problme celle de sous-
problmes.
b. initialisation de la table: cette tape est donne par les condition initiale de lquation
obtenue ltape 1.
c. remplissage de la table: cette tape consiste rsoudre les sous-problmes de taille de
plus en plus grandes, en se servant bien entendu de lquation obtenue ltape 1.
7
d. lecture de la solution : ltape 3 ne conduit qu la valeur (optimale) du problme de
dpart. Elle ne donne pas directement la solution conduisant cette valeur. En gnrale,
pour avoir cette solution, on fait un travail inverse en lisant dans la table en partant de la
solution finale et en faisant le chemin inverse des calculs effectus en ltape 3.


3. tude de quelques exemples.

Dans cette section, il sera question de voir en action la mthode de la programmation dynamique
sur des problmes essentiellement doptimisation.

3.1. Dterminer le plus court chemin dans un graphe algorithme de Floyd
Soit un graphe ) , ( V X G = ayant X comme ensemble de sommets et V comme ensemble d'arcs.
Le poids de larc a est un entier naturel not ) (a l . La longueur d'un chemin est gale la somme
des longueurs des arcs qui le composent. Le problme consiste dterminer pour chaque couple
) , (
j i
x x de sommets, le plus court chemin, s'il existe, qui joint
i
x
j
x .
Nous commenons par donner un algorithme qui dtermine les longueurs des plus courts chemins
notes ) , (
j i
x x . Par convention, on note = ) , (
j i
x x s'il n'existe pas de chemin entre
i
x et
j
x
(en fait il suffit dans la suite de remplacer par un nombre suffisamment grand par exemple la
somme des longueurs de tous les arcs du graphe). La construction effective des chemins sera
examine ensuite. On suppose qu'entre deux sommets il y a au plus un arc. En effet, s'il en existe
plusieurs, il suffit de ne retenir que le plus court.
Les algorithmes de recherche de chemins les plus courts reposent sur l'observation trs simple
(mais combien importante) suivante:
Remarque
Si f est un chemin de longueur minimale joignant x y et qui passe par , alors il se dcompose
en deux chemins de longueur minimale l'un qui joint x z et l'autre qui joint z y.
Dans la suite, on suppose les sommets numrots
n
x x x ,..., ,
2 1
et, pour tout 0 > k , on considre la
proprit
k
P suivante pour un chemin: ) ( f P
k
: Tous les sommets de f, autres que son origine et
son extrmit, ont un indice strictement infrieur k.
On peut remarquer dune part qu'un chemin vrifie
1
P si, et seulement si, il se compose d'un
unique arc. Dautre part la condition
1 + n
P est satisfaite par tous les chemins du graphe. Notons
par ) , (
j i k
x x la longueur du plus court chemin vrifiant la proprit
k
P et qui a pour origine
i
x
et pour extrmit
j
x . Cette valeur est si aucun tel chemin n'existe. Ainsi = ) , (
1 j i
x x s'il
n'y a pas d'arc entre
i
x et
j
x , et vaut ) (a l , si a est cet arc. D'autre part =
+1 n
.
8
Le lemme suivant permet de calculer les
1 + k
connaissant les ) , (
j i k
x x . On en dduira un
algorithme itratif.
Lemme Les relations suivantes sont satisfaites par les
k
:
)) , ( ) , ( ), , ( min( ) , (
1 j k k j i k j i k j i k
x x x x x x x x + =
+

Preuve
Soit un chemin de longueur minimale satisfaisant
1 + k
P , ou bien il ne passe pas par
k
x et on a la
relation suivante qui est vrifie :

) , ( ) , (
1 j i k j i k
x x x x =
+

ou bien il passe par
k
x et, d'aprs la remarque ci-dessus, il est compos d'un chemin de longueur
minimale joignant
i
x
k
x et satisfaisant
k
P et d'un autre minimal aussi joignant
k
x
j
x . Ce
chemin est donc de longueur : ) , ( ) , (
j k k j i k
x x x x + .
L'algorithme suivant pour la recherche du plus court chemin met jour une matrice delta[i,j] qui
a t initialise par les longueurs des arcs et par un entier suffisamment grand s'il n'y a pas d'arc
entre
i
x et
j
x . chaque itration de la boucle externe, on fait crotre l'indice k du
k
P calcul.
for k := 1 to n
for i := 1 to n
for j := 1 to n
delta[i,j] := min(delta[i,j], delta[i,k] + delta[k,j])
Sur l'exemple du graphe donn sur la Figure 5.3, on part de la matrice
1
donne par

9


Figure 5.3: Un graphe aux arcs valus
Aprs le calcul on obtient:

Pour le calcul effectif des chemins les plus courts, on utilise une matrice qui contient suiv[i,j], le
sommet qui suit i dans le chemin le plus court qui va de i j. Les valeurs suiv[i,j] sont initialises
j s'il existe un arc de i vers j et sinon ; suiv[i,i] est lui initialis i. Le calcul prcdent qui
a donn peut s'accompagner de celui de en procdant comme suit:
for k := 1 to n
for i := 1 to n
for j := 1 to n
if delta[i, j] > (delta[i, k] + delta[k, j]) then
begin
delta[i, j] := delta[i, k] + delta[k, j];
suivant[i, j] := suivant[i, k];
end;
Une fois le calcul des deux matrices effectu, on peut retrouver le plus court chemin qui joint i
j , laide la procdure ci-dessous:




10

procedure PlusCourtChemin(i, j: integer);
var k: integer;
begin
k := i;
while k <> j do
begin
write (k, ' ');
k := suivant[k, j];
end;
writeln(j);
end;
Sur l'exemple prcdent, on obtient la matrice suivante:


3.2: Multiplication chane de matrices

Soit n matrices
n
M M M ,..., ,
2 1
; chaque matrice
i
M possde
1 i
d lignes et
i
d colonnes. Le
problme est deffectuer
n
M M M ...
2 1
en un minimum doprations de multiplications.

Rappels

a. Pour faire le produit
2 1
M M , il est ncessaire que le nombre de colonnes de
1
M soit gal au
nombre de ligne de
2
M

b. Le nombre de multiplications engendres par
j i
M M , de dimension respectivement de
) (
1 i i
d d

et ) (
j i
d d est gal
j i i
d d d
1
.

Parce que la multiplication est une opration associative (
3 2 1 3 2 1
) ( ) ( M M M M M M = , il
existe une multitude de manires deffectuer le produit entre les matrices. Par exemple, soit les
trois matrices suivantes :

) 5 13 ( A ; ) 89 5 ( B ; ); 3 89 ( C ) 34 3 ( D

11

Effectuons les calculs des combinaisons de produit suivants :

D C B A M ) ) (( =
: AB 5785 89 5 13 = multiplications
: ) ( C AB 3471 3 89 13 = multiplications
: ) ) (( D C AB 1326 34 3 13 = multiplications
---------------------
10 582 multiplications


: ) ) (( D C AB 10582 multiplications
: ) )( ( CD AB 52201 multiplications
: )) ( ( D BC A 2856 multiplications
: ) ) (( D BC A 4 055 multiplications
: )) ( ( CD B A 26 418 multiplications

Ide 1 : la mthode brute: On insre les parenthses de toutes les manires possibles et ensuite,
pour chacune delle, on compte le nombre de multiplications engendres. Procdons comme pour
diviser et rgner en subdivisant le problme en deux sous-problmes comme suit :

) ... )( ... (
2 1 2 1 n i i i
M M M M M M M =
+ +
(1)

Si ) (n t est le cot pour effectuer le produit ci-dessus, alors ) (i t va reprsenter le cot du
produit ) ... (
2 1 i
M M M et ) ( i n t celui de ) ... (
2 1 n i i
M M M
+ +
. Alors, pour un i
donn, le cot du produit est clairement ) ( i n t ) (i t . Comme lindice i de sparation peut tre
nimporte laquelle des positions 1,2,,n-1, alors la relation entre ) (n t , ) (i t et ) ( i n t est
comme suit :

) ( ) ( ) (
1
1
i n t i t n t
n
i
=

=


1 ) 1 ( = t (pourquoi donc ?)

Exercice : rsoudre lquation rcurrente ci-dessus.

Ide 2: la programmation dynamique

1. caractriser la structure dune solution optimale

si n j i m
ij
1 ; : solution optimale pour le faire le produit ) ... (
2 1 j i i
M M M
+ +
, alors la
solution du problme est le calcul de
n
m
1


12



) ... )( ... (
2 1 2 1 n i i i
M M M M M M M =
+ +







solution optimale solution optimale

i
m
1

n i
m
1 +


2. dfinir rcursivement la valeur dune solution optimale en fonction des solution optimales
des sous-problmes.

Les sous-problmes : Dterminer le cot minimum dun parenthtisage de

) ... (
2 j i i
M M M
+



i = j : aucune multiplication : 0 =
ij
m
i < j :
ij
m = cot minimum pour calculer le produit ) ... (
2 k i i
M M M
+

+
cot minimum pour calculer le produit ) ... (
2 1 j k k
M M M
+ +

+
cot pour multiplier les deux matrices
j k i
d d d
1


Comme, on ne sait pas priori o placer lindice k, on doit essayer toutes les positions et prendre
celle qui engendre le moins de multiplications. Cela donne donc :

< + +
=
=
+
<
j i d d d m m
j i
m
j k i j k ik
j k i
ij
; { min
; 0
1 1


Exercice : implanter lquation rcursive ci-dessus, et dterminer sa complexit temporelle et
spatiale.

3. Au lieu de calculer la rcurrence directement (autrement dit, dune manire descendante), on
utilise lapproche ascendante de la programmation dynamique comme suit :

Construction de la table diagonale par diagonale. La diagonale s contient les lments
ij
m tel que
s i j = ; pour s= 0,1,2,3,,n-1, cest--dire pour les diffrences dindice de plus en plus
grandes.
13
; 0 = s ; 0 =
ii
m ; ,..., 2 , 1 n i =

; 1 = s ;
1 1 1 + +
=
i i i ii
d d d m ; 1 ,..., 2 , 1 = n i

; 1 n s < < { }
s i k i s i k ik
s i k i
s ii
d d d m m m
+ + +
+ <
+
+ + =
1 1
min ; ,..., 2 , 1 s n i =


Lalgorithme sera alors comme suit :

1. for (i=1; i<=n; i++)
m[i,i]=0 ;
2. for (i =1; i<=n-1; i++)
m[i,i+1] = d[i-1]*d[i]*d[i+1];
3. for (s =2; i <= n-1; s++)
for(i=1; i<= n-s; i++)
m[i,i+s] = { min
s i k i + <
m[i,k]+m[k+1,i+s]+d[i-1]*d[k]*d[i+s]};

Complexit : Clairement, elle est en ) (
3
n O : les deux boucles for imbriques sont excutes en
) (
2
n O multiplies par le calcul du minimum qui sexcute en ) (n O .

Illustration Reprenons lexemple prcdent savoir :

) 5 13 ( A ; ) 89 5 ( B ; ); 3 89 ( C ) 34 3 ( D

s = 1 : ; 5785
12
= m ; 1335
23
= m ; 9087
34
= m
s = 2 : 1530 } 3 89 13 ; 3 5 13 min{
34 12 23 11 13
= + + + + = m m m m m
1845 } 34 3 5 ; 34 89 5 min{
44 23 34 22 24
= + + + + = m m m m m
s = 3 ; 2856 } 34 3 13 ; 34 89 13 ; 34 5 13 min{
44 13 34 12 24 11 14
= + + + + + + = m m m m m m m .

Pour dterminer lordre dans lequel les matrices sont multiplies, on procde comme suit en
lisant les valeurs de k de la fin vers le dbut. Ainsi,

14
m est donn par k =3 ;
13
m est donn par k =2 ;

Ce qui signifie que le produit doit tre fait comme suit :
4 3 2 1
) ) (( M M M M






14
3.3. Problme du sac dos en nombres entiers
Nous avons introduit au chapitre prcdent le problme du sac dos. Rappelons la dfinition de
ce problme.
Soit un ensemble de n objets { } n N ,..., 2 , 1 = , et un sac dos pouvant contenir un poids maximal
de W. Chaque objet a un poids
i
w et un gain
i
v . Le problme consiste choisir un ensemble
d'objets parmi les n objets, au plus un de chaque, de telle manire que le gain total soit maximis,
sans dpasser la capacit W du sac. Dans cette version que nous prsentons dans ce chapitre, un
objet est soit choisi soit ignor. Autrement dit, les objets sont indivisibles, et de ce fait nous ne
pouvons pendre une portion dun objet dans le sac.
En termes mathmatiques, nous avons ce qui suit :
. 1 , 0
max
1
=


=
i
i i
i
n
i
i
x
W x w
x v

Lintgralit des objets rend ce problme difficile rsoudre. La stratgie vorace propose dans
le chapitre prcdent ne fonctionne plus dans ce cas.
Exercice : Donner un exemple o les diffrentes stratgies voraces auxquelles vous pourriez
penser ne gnrent pas la solution optimale.
Exercice : un simple algorithme pour ce problme est de gnrer toutes les solutions possibles
(un objet est soit choisi soit ignor). Concevoir lalgorithme bas sur cette stratgie. Montrer que
sa complexit est en ) 2 (
n
O
Proprit rcursive du problme :
La programmation dynamique peut tre dveloppe en divisant le problme en deux sous-
problme comme suit :
j i
P
,
dsigne le gain maximum gnr par le choix des i premiers objets dont la somme des poids
ne dpasse pas W, alors rsoudre le problme revient trouver la valeur de
W n
P
,
.
En calculant
j i
P
,
la squences dobjets peut tre divise en deux : les ) 1 ( i premiers objets et
lobjet i. Lobjet i est soit choisi soit ignor dans
j i
P
,
.
15
si lobjet i est choisi, avant de linclure, on doit sassurer que son poids ne dpasse pas la capacit
j du sac dos. Si tel est le cas, alors il contribue la solution optimale par le gain
i
v . Par
consquent, nous avons bien
ij
P =
i w j i
v P
i
+
, 1

Si lobjet i nest pas choisi dans la solution optimale. Dans ce cas, nous avons la capacit du sac
inchange. Il suffirait donc de trouver la solution optimale parmi les 1 i premiers objets, soit
j i
P
, 1
.
Bien entendu, pour trouver
j i
P
,
, il suffirait de prendre le maximum entre le cas o lobjet est
choisi ou ignor.
Les cas de base sont :
j i
P
,
= 0 pour i = 0 ou j = 0 (pourquoi donc ?)
Cela nous amne aux relations rcursives suivantes :

+
> <
= =
=

} , max{
0 ; ;
0 ... ... 0 ; 0
, 1 , 1
, 1
i w j i j i
i j i ij
v p p
i w j p
j ou i
P
i

Lalgorithme de programmation dynamique est alors comme suit :
1. For (i=1 ;i<=n ; i++)
P[i,0] = 0;
2. For (i=1 ;i<=k ; i++)
P[0,i] = 0;
3. For (i=1 ;i<=n ; i++)
For (j=1 ;i<=k ; j++){
P[i,j]=P[i-1,j];
if (j >=
i
w ){
if (P[i-1,j-
i
w ]+
i
v >P[i-1,j])
P[i,j] = P[i-1,j-
i
w ]+
i
v ; }
}

Complexit: Il est clair que cette complexit est domine par les deux boucles for imbriques
lune dans lautre : une est itre k fois et lautre est itre n fois. Par consquent, la complexit
de tout lalgorithme est en ) (kn O .

16
Exemple: Soient les donnes suivantes relatives aux objets. La capacit maximal du sac est 11 :




En appliquant lalgorithme ci-dessus, on obtient la table P suivante :
0 1 2 3 4 5 6 7 8 9 10 11
1 0 1 1 1 1 1 1 1 1 1 1 1
2 0 1 6 7 7 7 7 7 7 7 7 7
3 0 1 6 7 7 18 19 24 25 25 25 25
4 0 1 6 7 7 18 22 24 28 29 29 40
5 0 1 6 7 7 18 22 28 29 34 35 40
La solution optimale est donc donne par P[5,11] = 40. Pour retrouver les objets faisant partie de
la solution optimale, on procde comme suit :
- P[5,11] est donn par P[4,11], car lors du calcul de P[5,11] = min{P[4,11],P[4,11-
5
w ]+
5
v } = P[4,11]}. Cela signifie que lobjet 5 ne fait partie de la solution optimale.
- Ensuite P[4,11] est donn par P[3, 11-
4
w ] +
4
v = P[3,5]. Autrement dit, lobjet 4 est
choisi.
- Ensuite P[3,5] est donn par P[2,5-
3
w 1]+
3
v = P[2,0]+18. Lobjet 3 est choisi.
- En continuant de la sorte, on trouve que P[2,0] = P[1,0]=P[0,0].

Les objets faisant partie de la solution optimale sont don : lobjet 4 et lobjet 3.

Exercice : crire un algorithme qui dtermine la composition de la solution optimale.


3.4 : Problme du voyageur de commerce

Dfinition : tant un graphe valu ) , ( V X G = . Le problme du voyageur de commerce consiste,
en partant dun sommet donn, de trouver un cycle de poids minimum passant par tous les
sommets une et ne seule fois, et retournant au sommet de dpart.

Sans perte de gnralit, on identifie les n sommets par les entiers { } n ,..., 2 , 1 , et on suppose que le
cycle commence au sommet 1. La distance entre deux sommets i et j est note par
ij
d .

Pour obtenir lquation de rcurrence rsolvant ce problme, procdons comme suit :

item valeur poids
1 1 1
2 6 2
3 18 5
4 22 6
5 28 7
17
Il est clair que tout cycle est constitu dun arc (1,k) et dun chemin simple (partant de k et
passant une et une seule fois par tous les sommets de V-{1,k}.

Soit donc D[i,S] la distance dun plus court chemin partant de i, passant par tous les points de S,
une et seule fois, et se terminant au sommet 1. La relation suivante nest donc pas difficile
tablir :

| | { } | | { } j S j D d S i D
ij
S j
+ =

, min , (a)

La solution optimale est donc donne par D[1,V-{1}].

{ } | | { } | | { } j V j D d V D
ij
n j
, 1 , min 1 , 1
2
+ =


Il est clair que D[i,]=
1 i
d .

Nous avons donc partitionner lensemble V-{1}. Le nombre de sous-ensemble quon en gnrer
est donc 1 2
1

n
. Par consquent, la dimension de la table construire est ) 1 ( n par 1 2
1

n
.

Par exemple pour n = 4, on aura construire la table suivante :







Illustration : Soit donc le graphe suivant :

0 10 15 20
5 0 9 10
6 13 0 12
8 8 9 0

Nous avons donc :
D[2, ] = 5 ; D[3, ] = 6 ; D[4, ] = 8 ;
| | + =
23
} 3 { , 2 d D D[3, ] =15 ; | | ; 18 } 3 { , 2 = D
| | ; 18 } 2 { , 3 = D | | ; 20 } 4 { , 3 = D
| | ; 13 } 2 { , 4 = D | | ; 15 } 3 { , 4 = D
{} {2} {3} {4} {2,3} {2,4} {3,4}
1
2
3
18
Ensuite, on calcule | | S i D , avec |S| =2 ; S i i ; 1 .
| | { } | | { } | | 25 } 3 { , 4 , 4 , 3 min } 4 , 3 { , 2
24 23
= + + = D d D d D
| | { } | | { } | | 25 } 2 { , 4 , 4 , 2 min } 4 , 2 { , 3
34 32
= + + = D d D d D
| | { } | | { } | | 23 } 2 { , 3 , 3 , 2 min } 3 , 2 { , 4
43 42
= + + = D d D d D
Finalement, on obtient :
| | | | | | | | { } } 3 , 2 { , 4 , } 4 , 2 { , 3 , } 4 , 3 { , 2 min } 4 , 3 , 2 { , 1
14 13 12
D d D d D d D + + + =
= { } 35 43 , 40 , 35 = .
La valeur de la solution optimale est donc 35.
Pour le parcours faire ayant la valeur optimale de 25, on procde de la manire suivante:
pour chaque | | S i D , , on retient lindice j minimisant le membre droit de lquation (a), en
commenant toujours partir de la valeur de la solution optimale et en rebroussant chemin
jusqu trouver la solution complte. Ainsi, dans notre exemple, nous avons
Lindice minimisant | | } 4 , 3 , 2 { , 1 D est 2. Le cycle donc commence par 1 et doit passer par le
sommet 2. Le reste du cycle peut tre obtenu partir de | | } 4 , 3 { , 2 D . Lindice minimisant cette
expression est 4. Par consquent, le cycle devra ensuite passer par le sommet 4. Le reste du cycle
peut tre obtenu de | | } 3 { , 4 D . Lindice minimisant cette expression ne peut tre que 3. Le cycle
est donc 1-2-4-3-1.
Complexit : On doit remplir tout le tableau de dimension ) 1 ( n par 1 2
1

n
. De Plus, le calcul
de chaque D[i,S] ncessite lexamen de |S| autres cases (pour dterminer le minimum). Par
consquent, la complexit de cet algorithme est en ) 2 (
2 n
n O .
Exercice : dterminer la complexit spatiale de cet algorithme.

4. Les fonctions mmoire

Tout comme la mthode diviser et rgner calcule des valeurs plusieurs fois, la programmation
dynamique peut calculer elle aussi des valeurs inutiles. En effet, on faisant les calculs de bas en
haut, on est amener calculer des valeurs qui peuvent ne pas tre utiliser par la suite: on calcule
tous les sous-problmes de petite taille, ensuite de taille un peu plus grande et ainsi de suite, sans
se soucier si ces valeurs vont entrer dans le calcul de la valeur optimale du problme de dpart.
La technique de la fonction mmoire permet de combiner llgance de la mthode diviser et
19
rgner (de la rcursivit) avec lefficacit de la programmation dynamique. Lide donc est
dutiliser un tableau T avec la fonction rcursive f exprimant la rsolution du problme donn.

Fonction f(x1,x2,,xn)
{
si T[x1,x2,,xn] la valeur dinitialisation
alors retourner T[x1,x2,,xn] ;
sinon {
s = f(x1,x2,,xn) ;
T[x1,x2,,xn] = s ;
retourner s ;
}
}

De ce fait, on gagne ne pas calculer inutilement certaines cases.


Remarque : Le premier exemple quon a vu est celui du calcul des nombre de Fibonacci.

Prenons comme deuxime exemple celui du voyageur de commerce. Si on veut implanter notre
solution dune manire ascendante, nous rencontrons le problme voqu au dbut du ce
chapitre : certaines valeurs de D[i,S] sont recalcules plusieurs fois et lalgorithme est trs
inefficace.

Exercice : Montrer que L,implantation ascendante de la fonction (a) ci-dessus gnre une
complexit en O(n !).

Pour calculer D[i,S] dune manire ascendante, nous avons besoin de gnrer tous les ensembles
vides, puis contenant un lment, puis deux, etc. La conception d un tel gnrateur nest
certainement pas difficile mais elle est certainement fastidieuse.

Lutilisation dune fonction mmoire consiste adjoindre la fonction rcursive une table de
taille suffisante. Initialement, tous les lments de cette table ont une valeur spciale indiquant
quils ne sont pas encore dfinis. Ensuite, chaque fois quon appelle la fonction, on regarde dans
la table pour voir si cette valeur a t dj calcule sur les mme paramtres. Si cest le cas, on
retourne la valeur stocke dans la table. Autrement, on procde au calcul de la fonction. Avant de
retourner la valeur de la fonction, on la stocke dans la table lendroit appropri. De cette
manire, on naura pas calculer la fonction plus dune fois. Pour les mmes valeurs des
paramtres. Cela nous donne limplantation suivante :

On initialise les lments de tab 1 (une distance ne peut tre ngative).






20
fonction D(int i, set S){

si S = retourner
1 i
d ;
si tab[i,S] 0 retourner tab[i,S];
petitshort = un grand nombre;
pour S j faire
distance = }); { , ( j S i D d
ij
+
si distance < petitshort
petishort = distance ;
tab[i,S] = petitshort ;
retourner petitshort;

La fonction D allie la clart de la conception diviser et rgner (rcursive) avec lefficacit de la
programmation dynamique.

Exercice : Montrer comment calculer le coefficient binomial en utilisant une fonction mmoire.


Sources

1. G. Brassard, P. Bratley (1996): Fundamentals of algorithmics, Prentice Hall
2. E. Horowitz, S. Sahni, S., Rajasekaran (1997): Computer algorithms, Computer Sciences
Press.
3. J.J. Levy: Notes de cours dalgorithmique, cole Polytechnique, France.