Corrigé

publicité
20052006
AAC- TD-TP
Master d'Informatique-S1
UFR IEEA
TP 2 - Programmation Dynamique versus Algorithmes GloutonsSystèmes de monnaie ecace
Compte-rendu/Corrigé
Objectif:
Le problème traité ici est le problème est de trouver un système de monnaie ecace tel qu'il a
été commenté par Jean-Paul Delahaye dans Pour La science de Septembre 2005. Ce problème très simple est
utilisé ici pour illustrer les algorithmes gloutons -donnent-ils toujours la solution optimale- et leur lien avec la
Programmation Dynamique.
Ceux qui le désirent peuvent retrouver à /home/enseign/tison/AAC0506/articleDelahaye.pdf l'article de
Jean-Paul Delahaye : Merci à Jean-Paul qui a mis à disposition cet article.
Rendez la monnaie
Rappel du problème:
n
Q 1.
On dispose d'un système de monnaie:
faciales sont
{a1 , . . . , an },
avec
est le nombre de pièces distinctes, et les valeurs
1 = a1 < a2 . . . < an .
Pour chaque valeur, le nombre de pièces est non borné.
S
Etant donnée une quantité
entière, on veut trouver une façon de "rendre" la somme
S
avec un nombre de
pièces minimum. Donc:
Donnée:
Syst
un système de pièces:
avec
1 = a1 < a2 < ... < an
S
n,
le nombre de types de pièces,
a1 , .., an ,
les n valeurs faciales, entières positives
un entier naturel, la somme à payer
Sortie:
Pn
i=1 ki ∗ ai = S
L'algorithme glouton
k1 , ..., kn
tel que
Pn
i=1 ki .
qui minimise
Q 1.1.
Soit l'algorithme glouton qui consiste à utiliser d'abord le plus grand possible de pièces
grand possible de pièces
an−1
an ,
puis le plus
si nécessaire, etc.
Proposez deux systèmes pour lesquels l'algorithme glouton n'est pas optimal.
Par exemple, pour les pièces
{1, 20, 30}
-prendre par exemple la somme
40-
et les pièces
{1, 5, 6}
-prendre la somme
10-.
On notera
Ef fg (S, Syst) le nombre de pièces nécessaires dans Syst pour payer S avec l'algorithme glouton.
a1 = 1, a2 = d, a3 = d2 , . . . , ai = di−1 , . . . , an = dn−1 , pour un certain entier d (d > 1).
Q 1.2. Supposons que
Montrer que dans ce cas l'algorithme glouton donne toujours une solution optimale.
Il y a plusieurs façons -assez proches-de prouver l'optimalité du glouton:
•
Schéma classique par échange:
g = g1 , ..., gn la solution produite par la solution gloutonne,
o = o1 , ..., on une solution optimale.
Si g = o, g est bien optimale. Sinon, soit j le plus grand entier tel que gj 6= oj .
On a nécessairement gj > oj , vu la dénition de l'heuristique.
Soit une instance du problème et pour cette instance, soit
On a de plus, puisque les deux solutions payent la même somme:
i=n
X
gi ∗ ai =
i=1
Comme
gi = oi
pour
i
supérieur à
j,
i=n
X
oi ∗ ai
i=1
on a
i=n
X
gi ∗ ai =
i=j+1
i=n
X
oi ∗ ai
i=j+1
et donc:
i=j
X
i=1
gi ∗ ai =
i=j
X
i=1
oi ∗ ai
Donc
i=j−1
X
oi ∗ ai =
i=1
i=j−1
X
gi ∗ ai + (gj − oj) ∗ aj ≥ (gj − oj ) ∗ aj ≥ aj
i=1
Montrons que cela implique qu'au moins un des
i=j−1
X
oi ∗ ai ≤
i=j−1
X
i=1
Pi=j−1
Pi=j−1
ai =
i=1
qui contredit l'hypothèse.
D'où comme
i=1
oi , 1 ≤ i ≤ j − 1
est supérieur ou égal à
i=j−1
X
(d − 1) ∗ ai ≤ (d − 1) ∗
i=1
di−1 =
Pi=j−2
i=0
d.
En eet sinon,
ai
i=1
di = (dj−1 − 1)/(d − 1),
on a
Pi=j−1
i=1
oi ∗ ai ≤ dj−1 − 1 < aj
j = 1!)
0
Donc, il existe i, 1 ≤ i ≤ j − 1 tel que oi soit au moins égal à d. Mais alors, soit o déni par:
o0l = ol pour l diérent de i et i + 1, o0i−1 = oi−1 et o0i = oi − d, o0i+1 = oi+1 + 1.
0
On peut vérier facilement que o est toujours solution et qu'elle utilise moins de pièces que o: o
ce
(Remarque; cela marche aussi si
ne serait donc pas
optimale!
Donc, nécessairement
g=o
et
g
est optimale.
Attention: l'idée intuitive que pour remplacer une pièce par des pièces de valeur moindre, on va utiliser plus de
pièces doit être étayée et il y a des valeurs pour lesquelles ça ne marche pas: par exemple, si on prend pour pièces
1 5 7 et comme somme à payer 10, la gloutonne n'est pas optimale: il vaut mieux utiliser 0 pièces de 7 que 1! En
eet, le problème n'est pas de payer
•
di
avec des pièces plus petites, mais
R + k ∗ di
On peut avoir une preuve plus directe mais non de type échange.
d − 1 pièces de type ai ,
d pièces par 1 pièce de valeur supérieure.
on = s%d, on−1 = (s div d)%d, ..., ..., o1 = s div dn−1
On montre facilement que dans l'optimale on a au plus
moins
d,
pour
i < n:
en eet, si on en a au
on peut remplacer ces
Donc on montre ainsi que
•
avec des pièces plus petites....
Une autre approche consiste à rapprocher ce problème du codage en base
d et donc ici on a remontré d'une certaine
façon l'unicité de la représentation.
La programmation dynamique
Q 1.3.
On a vu que l'algorithme glouton ne donne pas toujours la réponse optimale.
Proposer un algorithme en
optimale. On se contentera de
O(S ∗ n) qui utilise la programmation dynamique pour calculer la solution
calculer Ef f (S, Syst), le nombre de pièces nécessaires pour payer S (et non la
façon d'obtenir cette solution optimale).
Comme souvent, on peut modéliser de plusieurs façons le problème et arriver donc à des formulations diérentes de la
récurrence. Ce qui est important, c'est de comprendre comment on peut déduire les équations de la façon de construire
des solutions.
Soit donc
•
S
à payer:
Version 1 on considère
ap ,
la pièce de plus forte valeur faciale:
S < ap :on ne peut donc la prendre; on doit donc payer S avec les pièces de valuer a1 , ..., ap−1
.soit S ≥ ap : on a donc le choix entre prendre une pièce ap ou non (choix binaire) et prendre le meilleur choix.
On introduit donc Ef f (S, Syst, k) le nombre mini de pièces pour payer S dans le système des k premières pièces
de Syst et on a alors la récurrence suivante:
Ef f (S, Syst, p) = Ef f (S, Syst, p − 1) si S < ap .
Ef f (S, Syst, p) = min(Ef f (S, Syst, p − 1), 1 + Ef f (S − ap , Syst, p)) si S ≥ ap .
.soit
et les cas de base:
Ef f (0, Syst, p) = 0
Ef f (S, Syst, 1) = S
//a1
= 1;
Il faut donc ensuite utiliser la programmation dynamique: on a donc une table indexée par les valeurs de
les nos de pièces de
•
1
à
0
à
S
et
n.
ap ou non-, mais comme
0 à S/ap .
On a donc alors, Ef f (S, Syst, p) = min0≤k≤s/ap (k + Ef f (S − k ∗ ap , Syst, p − 1)).
Attention: certains ont écrit Ef f (S, Syst, p) = min(Ef f (S, Syst, p − 1), S/ap + Ef f (S%ap , p)): ce n'est pas vrai,
par exemple soit le système {1, 3, 4} et S = 10: l'optimal va prendre une pièce de 4 (et non 0 ou 2).
Version 2: on peut voir le premier choix non plus comme un choix binaire - je prends une
un choix d'un entier: combien d'ap je prends? A priori, on peut en prendre de
2
•
Version 3: on peut changer un peu la façon de voir et dire que le premier choix qu'on fait c'est la première pièce
k le plus grand entier de 1
Ef f (S, Syst) = 1 + min1≤i≤k Ef f (S − ai , Syst)
qu'on va utiliser. Soit
à
p
tel que
ak ≤ S .
On a alors:
(Ou, si on remplace la première pièce qu'on va utiliser par la plus grande:
Ef f (S, Syst, p) = 1 + min1≤i≤k Ef f (S − ai , Syst, i))
Les trois versions sont à peu près équivalentes, la première est peut-être la plus simple -c'est juste un choix binaire- la
troisième est moins coûteuse en espace!
Essayer de comparer la construction d'une solution avec cet algorithme avec celle d'une solution avec
l'algorithme glouton.
Dans chaque cas l'algo glouton fait le choix a priori; par exemple, dans la premièr version -min(Ef f (S, Syst, p
1), 1 + Ef f (S − val(p), Syst, p)-,
l'algorithme glouton n'explore que la possibilité
1 + Ef f (S − val(p), Syst, p).
−
Dons, si
on considère l'arbre des solutions, le glouton ne parcoure qu'une branche, le dynamique compresse l'arbre en regroupant
les noeuds correspondant aux mêmes appels.
Analyser la complexité de cet algorithme: est-il polynômial?
C'est toujours le même piège... Il n'est pas polynômial!!! (Il est pseudo-polynômial). En eet, la taille de la donnée
est
log S +
P
log ai + log n
Ecacité du système
et l'algo va être en
O(S ∗ n).
Q 2.
X , l'ecacité moyenne
Ef f moy(X, Syst) est simplement la moyenne des Ef f (S, Syst) pour S de 1 à X . De la
Ef f moyg (X, Syst) est la moyenne des Ef fg (S, Syst) pour S de 1 à X .
On cherche maintenant à calculer l'ecacité moyenne d'un système. Pour un entier
du système, notée
même façon,
Q 2.1.
Proposez et implémentez un algorithme en
O(X)
pour calculer
Ef f moyg (X, Syst).
O(X) comme demandé, il fallait
. ne pas calculer tous les Ef f moyg (s, Syst) indépendamment pour s de 0
lance tous les calculs de Ef f moyg (s, Syst), on recalcule plusieurs fois la même
Pour avoir un algorithme en
à
X
mais utiliser une table; en eet si on
chose!
. rééchir un peu pour que chaque calcul se fasse alors en temps constant; ce qui donne par exemple:
//solution gloutonne
//suppose les valeurs_faciales croissantes avec la première=1
private PbMonnaie pb;
public float sol(PbMonnaie pb){
this.pb=pb;
int n=0;
int moy=0;
int[] tab=new int[pb.S+1];
tab[0]=0;
for (int i=1; i<=pb.S; i++) {
//n: no de la plus piece de plus forte valeur <=i-1
if ((n<pb.nb_pieces-1) &&(i>=pb.valeurs_faciales[n+1])) n++;
//n: no de la plus piece de plus forte valeur <=i
tab[i]=tab[i % pb.valeurs_faciales[n]] + i/pb.valeurs_faciales[n];
//ou tab[i]=tab[i - pb.valeurs_faciales[n]] +1;
// ne change rien à la complexité ici
moy=moy+tab[i];
}
return (float)moy/pb.S;
}
Q 2.2.
Proposez et implémentez un algorithme en
O(X ∗ n)
pour calculer
Ef f moy(X, Syst).
Par exemple:
public float sol (PbMonnaie pb){
int moy=0;
int T[][]=new int[pb.S+1][pb.nb_pieces];
//T[i][j] memorisera Effmoy(i,j))
for (int i=0;i<=pb.S;i++) T[i][0]=i; //la pièce 1
for (int j=0;j<=pb.nb_pieces-1;j++) T[0][j]=0; //la somme 0
for (int i=1;i<=pb.S;i++) {
for (int j=1;j<=pb.nb_pieces-1;j++) {
3
if (i>=pb.valeurs_faciales[j])
T[i][j]=Math.min(T[i][j-1],1+T[i-pb.valeurs_faciales[j]][j]);
else
T[i][j]=T[i][j-1];
}
}
for (int i=0;i<=pb.S;i++) moy=moy+T[i][pb.nb_pieces-1];
return (float)moy/pb.S;
}
Q 2.3.
Expérimentez! Essayez de retrouver les résultats de Jerey Shallit sur les systèmes optimaux gloutons, en
xant
X à 99
et en se limitant aux systèmes à quelques pièces.
Bravo à ceux qui ont fait l'eort d'aller chercher les résultats de Jerey Shallit et de s'y comparer.
4
Téléchargement