Vous êtes sur la page 1sur 19

Programmation dynamique

Université Ferhat Abbas Sétif


Faculté des Sciences
Computer science département
Algorithmique Avancée et complexité
Prof: Allaoua Refoufi
Semestre1 2020/2021
Cours AAC05
Contenu du cours 05

 CoursAAC05
 Exemple3: La plus longue chaine palindromique
 Exemple4 : le problème du sac à dos (knapsack problem)
 Exemple5 : plus court chemin dans les graphes
Plus longue séquence palindromique non contiguë
Problème
Etant donné une chaine de caractères A[1..n], il s’agit d’identifier la plus longue
séquence palindromique non contiguë (PLSP) contenue dans A. Cette séquence
est bien sur un palindrome.
Exemple dans la chaine CHARACTER , la PLSP est CARAC
Dans la chaine TURBOVENTILATOR, la PLSP est ROTATOR
Stratégie : on va identifier un sous problème , qui est A[i..j] pour i  j
On définit L(i,j) = taille de la plus longue séquence palindromique non contiguë
contenue dans A[i..j]
L’algorithme est assez direct :
L(i,j)
if i = j then return 1 // un seul caractère
if A[i]=A[j] then if i+1=j then return 2
else return 2+L(i+1,j-1)
else return max{L(i+1,j),L(i,j-1)}
Explication: Si A[i]=A[j] la longueur est égale à 2 qu’on va ajouter à la longueur de la PLSP qu’on
déterminer dans la chaine A[i+1..j-1]
Sinon, ce sera le maximum des PLSP qu’il faut identifier dans les chaines A[i+1..j] et A[i..j-1]
La complexité n’est autre que (n2)( le nombre de sous chaines dans une chaine de longueur n)
Ce qui manque, maintenait pour avoir un algorithme optimal, c’est le cache. Car on voit bien qu
va faire appel à la fonction plusieurs fois pour la même valeur. On doit donc sauvegarder
résultats intermédiaires.
EXERCICE : réécrire cet algorithme en sauvegardant les résultats intermédiaires(mémoïsation).
Le problème du sac à dos

On dispose de n objets de volumes positifs w1, w2, . . . ,wn et de


valeurs positives , respectivement v1, v2, . . . , vn
On a un sac à dos de capacité maximale en volume de W .
Problème: Remplir le sac à dos de sorte de maximiser la valeur
des objets inclus tout en respectant la contrainte de volume du
sac.
Un peu d’histoire
 Ce problème fait partie des 21 problèmes NP-complets identifiés par
Richard Karp en 1972. Ces 21 problèmes sont réputés comme les
problèmes les plus difficiles en optimisation combinatoire. Nous
verrons prochainement les problèmes NP-complets.
 Nous pouvons retrouver le problème du sac à dos dans de nombreux
domaines :
• dans les systèmes financiers, où l’idée est la suivante : étant donné un
certain montant d’investissement dans des projets, quels projets
choisir pour que le tout rapporte le plus d’argent possible ;
• pour la découpe de matériaux, afin de minimiser les pertes dues aux
chutes ;
• dans le chargement de cargaisons (avions, camions, bateaux…) ;
• ou encore, dès qu’il s’agit de préparer une valise ou un sac à dos
pour une randonnée ou un voyage.
Rappel: comment développer un algorithme de
Programmation dynamique
A. Structure: Caractériser la structure de la solution optimale, c’est à dire
décomposer le problème en sous problèmes et identifier la relation
entre la structure de la solution optimale du problème original et les
solutions des sous problèmes.
B. Principle d’optimalité: Définir récursivement la valeur de la solution
optimale. Cela revient à exprimer la solution du problème original en
termes de solutions optimales des sous problèmes.
C. Calcul ascendant (Bottom-up computation): Calculer la valeur de la
solution optimale par une approche ascendante en utilisant un
tableau.
D. Construction de la solution optimale: Construire la solution optimale à
partir des valeurs précédemment calculées.
Il existe deux versions pour le problème du sac à dos :
(1) “0-1 knapsack problem”
(2) “Fractional knapsack problem”
(1) dans la première version les objets sont indivisibles; on peut soit prendre l’objet i
intégralement, soit ne pas le prendre. C’est cette version qui nous interesse et qu’on
va traiter à l’aide de la programmation dynamique.
(2) dans la seconde version les objets sont divisibles: on peut en prendre une
fraction. Cette version est traitée par un algorithme glouton assez simple.
Le problème du sac à dos possède la propriété de sous structure optimale, c'est-à-
dire que l'on peut construire la solution optimale du problème à i variables à partir
du problème à i-1 variables. Cette propriété permet d'utiliser une méthode de
résolution par programmation dynamique.
Formulation du problème
 Toute formulation commence par un énoncé des données. Dans notre cas, nous
avons un sac à dos de volume maximal W et n objets. Pour chaque objet i, nous
avons un volume wi et une valeur vi.
 Pour quatre objets (n = 4) et un sac à dos d’un volume maximal de 13 cm3 (W =
13), nous avons par exemple les données suivantes :
objet valeur volume volume du sac à dos
1 5 5 13
2 4 6
3 8 6
4 7 4
Ensuite, il nous faut définir les variables qui représentent en quelque sorte les
actions ou les décisions qui amèneront à trouver une solution. On définit la
variable xi associée à un objet i de la façon suivante :
xi = 1 si l’objet i est pris dans le sac, et
xi = 0 si l’objet i n’est pas pris dans le sac.
Dans notre exemple, une solution réalisable est de mettre les objets 3 et 4
dans le sac à dos, nous avons donc : x1 = 0, x2 = 0, x3 = 1, et x4 = 1. On donnera
la solution sous la forme d’un entier en base 2, c’est-à-dire 0011, dans notre
exemple.
Cela signifie que le nombre total de solutions possibles pour n éléments 𝑒𝑠𝑡 2𝑛
Puis il faut définir les contraintes du problème. Ici, il y en a deux :
la somme des volumes de tous les objets dans le sac doit être inférieure ou égale
au volume maximal du sac à dos.
𝑛
1 𝑤𝑖 𝑥𝑖 W
Ensuite, il faut exprimer la fonction qui traduit notre objectif : maximiser la valeur
totale des objets dans le sac.
𝑛
Maximiser 1 𝑣𝑖 𝑥𝑖
Et bien sur 𝑥𝑖 = 0,1 𝑝𝑜𝑢𝑟 𝑖 = 1, 𝑛
On impose aussi que W soit un entier
La solution brutale (2𝑛 ) 𝑛′ 𝑒𝑠𝑡 𝑝𝑎𝑠 𝑎𝑐𝑐𝑒𝑝𝑡𝑎𝑏𝑙𝑒, 𝑐𝑎𝑟 𝑒𝑥𝑝𝑜𝑛𝑒𝑛𝑡𝑖𝑒𝑙𝑙𝑒.
Définition
C(i, M) = valeur de la solution quand on choisit parmi les i premiers objets
de 1 à i, en respectant la contrainte de volume M.
Comment peut on exprimer un problème C(i,M) en termes de sous problemes ?
Tout simplement en disant que : soit l’objet i est pris pour atteindre la valeur
optimale, soit il n’est pas pris. C’est une approche ascendante.
C(i,M) = max{ C(i-1,M – wi) + vi ,C( i – 1,M)}
0 𝑠𝑖 𝑖 = 0 𝑜𝑢 𝑀 = 0
C(i,M) = 𝐶 𝑖 − 1, 𝑀 𝑠𝑖 𝑤𝑖 > 𝑀
max{𝐶 𝑖 − 1, 𝑀 − 𝑤𝑖 + 𝑣𝑖, 𝐶 𝑖 − 1, 𝑀 } 𝑠𝑖 𝑖 > 0 𝑒𝑡 𝑤𝑖 < 𝑀
a) C(i,M) =0 si i=0 ou M=0 évident
b) C(i,M)=C(i-1,M) si wi > M : si le volume de l’objet i dépasse M on ne le prend
pas
c) C(i,M)=maximum{C(i-1,M),C(i-1,M-wi)+vi} : sinon soit on ne prend pas l’objet i
et la valeur totale sera donc C(i-1,M); soit on prend l’objet i et la valeur sera C(i-
1,M-wi) +vi , c’est-à-dire ce qu’on aura pris parmi les i-1 objets restants en
respectant le volume M-wi auquel on va ajouter ce qu’on a gagné en prenant
l’objet i, c’est-à-dire vi.
On va appliquer cette formulation à notre exemple
Objets(1,2,3,4), volumes_respectifs(5,6,6,4),valeurs_respectives(5,4,8,7) et W=13
On C(4,13)=max{C(3,13),C(3,13-4)+7} = max{C(3,13),C(3,9)+7}
On a aussi C(3,13)=max{C(2,13),C(2,13-6)+8}=max{C(2,13),C(2,7)+8}
C(2,13)=max{C(1,13),C(1,13-6)+4}=max{C(1,13),C(1,7)+4}
C(1,13)=max{0,5}=5 et ainsi de suite
L’ algorithme consiste alors à remplir un tableau bidimensionnel à W + 1 lignes
et n + 1 colonnes. Chaque entrée du tableau nécessite un temps constant (1),
le temps d’éxecution sera donc (nW).

On peut réecrire l’algorithme comme suit :


Initialiser C(j,0) = 0 pour tout j; C(0,w) = 0 pour tout w
for j = 1 to n:
for w = 1 to W:
if wj > w then C(j,w) = C(j-1,w)
else C(j,w) = max{ C(j – 1,w),C(j-1,w - wj) + vj}
return C(n,W)
On aura par conséquent à calculer toutes les valeurs de C(i,W) pour i = 0 à n et
M de 0 à W; on comprend maintenant pourquoi on exige que W soit un entier.
EXERCICE : remplir la matrice C pour en tirer la solution finale C(4,13) de
l’exemple donné en illustration.
Remarque : certaines valeurs de C(i,M) peuvent être redondantes, il est
recommandé de stocker les résultats intermédiaires (mémoïsation) en
utilisant un cache.
Il ne nous reste plus qu’à estimer la complexité de cet algorithme.
Il est aisé de voir que T(n,W)=(nW) qui semble assez raisonable quand W
n’est pas trop grand, mais ce n’est pas une complexité polynomiale puisque la
taille de l’input est proportionnelle à logW, plutot qu’à W.
Plus court chemin dans les graphes
Rappel
On a un graphe valué G=(V,E,l); où V est l’ensemble des sommets, E l’ensembles de
arêtes, et l une application qui à toute arête (u,v) associe une longueur positive ou nul
l(u,v).
On définit la distance entre deux sommets comme étant la longueur du plus cou
chemin (PCC) entre ces sommets. On note dist(s,u) la distance entre les sommets s et u.
Notre problème consiste à determiner le PCC entre deux sommets du graphe.
Commençons par une illustration assez simple :
2
A B 1
1
2 5 E
1
1 D
C 5 3
6 G
10
2
F

Supposons qu’on cherche le PCC du sommet A au sommet G; la seule façon


d’arriver au sommet G est de passer soit par le sommet E ou le sommet D, ou le
sommet F; on peut donc écrire que :
dist(A,G) = minimum{dist(A,E) + 3, dist(A,D) + 5,dist(A,F)+10}

August 13, 2012


Une relation similaire peut être utilisée pour chaque sommet du graphe.
En général on peut écrire que :
dist(s,v)=min{dist(s,u)+l(u,v)} pour tout u tel que (u,v) E
et dist(s,s)= 0 où s est le sommet source, u et v sont des sommets

Cet algorithme ne s’applique qu’aux graphes sans cycles.


Soit |E| le nombre d’arêtes et |V| le nombre de sommets du graphe, la
complexité de cet algorithme est proportionnelle au nombre d’arcs incidents à v,
autrement dit :
T(|E|,|V|) = 𝑣 (deg 𝑣 + 1) 𝑝𝑜𝑢𝑟 𝑣 𝑉
Donc T(|E|,|V|)=(|E|+|V|)
Prochain cours AAC006
Problèmes NP et NP-complets

Vous aimerez peut-être aussi