Files
TermNSI/Programmation_Dynamique/TP_Vaccin.md

160 lines
5.9 KiB
Markdown

# TP — L'Algorithme du Vaccin
## Contexte
Vous êtes ingénieur·e en bio-informatique dans un laboratoire pharmaceutique. Une nouvelle épidémie virale se propage, et votre équipe dispose d'un **bioréacteur** capable de produire des anticorps pendant un temps limité.
Vous avez identifié **n variants du virus**, chacun nécessitant :
- un **temps de production** (en heures) pour fabriquer les anticorps correspondants
- une **efficacité estimée** (score de 1 à 100) contre la souche circulante
Le bioréacteur ne peut fonctionner que pendant **T heures** au total. Vous devez choisir quels anticorps produire pour **maximiser l'efficacité totale** du vaccin, sans dépasser le temps disponible.
> Ce problème est directement modélisé par le **problème du sac à dos 0/1** : chaque anticorps est produit entièrement ou pas du tout.
**Exemple de données :**
| Anticorps | Temps (h) | Efficacité | Ratio eff/temps |
|-----------|-----------|------------|-----------------|
| Alpha | 3 h | 40 | 13,3 |
| Bêta | 5 h | 70 | 14,0 |
| Gamma | 2 h | 30 | **15,0** ← meilleur |
| Delta | 7 h | 100 | 14,3 |
| Epsilon | 6 h | 85 | 14,2 |
Temps disponible : **10 heures**
---
## Partie 1 — Comprendre le problème
**Question 1.** En utilisant l'algorithme glouton (trier par ratio efficacité/temps décroissant), quels anticorps choisissez-vous ? Quelle est l'efficacité totale obtenue ?
**Question 2.** Essayez d'autres combinaisons à la main. Trouvez-vous une solution d'efficacité strictement supérieure à celle du glouton ?
**Question 3.** Combien y a-t-il de combinaisons possibles en tout pour `n = 5` anticorps ? Pour `n = 30` ? Qu'en déduisez-vous sur une approche exhaustive ?
---
## Partie 2 — Formulation récursive
Notons `vaccin(i, t)` l'efficacité maximale qu'on peut atteindre en choisissant parmi les `i` premiers anticorps avec un temps restant de `t` heures.
**Question 4.** Quels sont les cas de base de cette fonction récursive ?
**Question 5.** Écrivez la relation de récurrence pour `vaccin(i, t)` sachant que l'anticorps `i` a un temps de production `duree_i` et une efficacité `eff_i`.
**Question 6.** Implémentez la version naïve `vaccin_naif(anticorps, i, t)` :
```python
def vaccin_naif(anticorps, i, t):
# anticorps : liste de tuples (duree, efficacite)
# À compléter
pass
# Test
anticorps = [(3, 40), (5, 70), (2, 30), (7, 100), (6, 85)]
n = len(anticorps)
print(vaccin_naif(anticorps, n, 10)) # doit afficher 140
```
---
## Partie 3 — Version Top-Down (mémoïsation)
**Question 7.** Pourquoi la version naïve recalcule-t-elle des sous-problèmes ? Donnez un exemple de sous-problème qui serait recalculé plusieurs fois.
**Question 8.** Implémentez `vaccin_memo(anticorps, temps_total)` avec mémoïsation :
```python
def vaccin_memo(anticorps, temps_total):
memo = {}
def vaccin(i, t):
# À compléter
pass
return vaccin(len(anticorps), temps_total)
```
**Question 9.** Vérifiez que vous obtenez le même résultat qu'à la Question 6.
---
## Partie 4 — Version Bottom-Up (tableau)
**Question 10.** Remplissez à la main le tableau `tableau[i][t]` pour les **3 premiers anticorps** (Alpha, Bêta, Gamma) avec un temps total de **6 heures** :
| | t=0 | t=1 | t=2 | t=3 | t=4 | t=5 | t=6 |
|---|---|---|---|---|---|---|---|
| i=0 (aucun) | | | | | | | |
| i=1 (Alpha 3h, 40) | | | | | | | |
| i=2 (+Bêta 5h, 70) | | | | | | | |
| i=3 (+Gamma 2h, 30) | | | | | | | |
**Question 11.** Implémentez `vaccin_bottom_up(anticorps, temps_total)` :
```python
def vaccin_bottom_up(anticorps, temps_total):
n = len(anticorps)
# tableau[i][t] = efficacité max avec les i premiers anticorps, temps t disponible
tableau = [[0] * (temps_total + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
duree, eff = anticorps[i - 1]
for t in range(temps_total + 1):
# À compléter
pass
return tableau[n][temps_total]
```
**Question 12.** Vérifiez que vous obtenez 140 pour l'exemple complet (5 anticorps, 10 heures).
---
## Partie 5 — Reconstruction de la solution
**Question 13.** Modifiez `vaccin_bottom_up` pour qu'elle retourne non seulement l'efficacité maximale, mais aussi la **liste des anticorps sélectionnés** :
```python
def vaccin_reconstruction(anticorps, temps_total):
"""
Retourne (efficacite_max, liste_anticorps_choisis)
"""
n = len(anticorps)
tableau = [[0] * (temps_total + 1) for _ in range(n + 1)]
# Remplissage du tableau (identique à vaccin_bottom_up)
# À compléter
# Reconstruction : on remonte le tableau
choisis = []
t = temps_total
for i in range(n, 0, -1):
# À compléter
pass
return tableau[n][temps_total], choisis
```
**Question 14.** Testez votre fonction. Vérifiez que les anticorps sélectionnés ont bien une durée totale ≤ 10 heures et une efficacité totale de 140.
**Question 15.** Quelle est la complexité en temps et en espace de la version bottom-up ? Exprimez-la en fonction de `n` (nombre d'anticorps) et `T` (temps total disponible).
---
## Partie 6 — Bonus : contraintes supplémentaires
**Question 16.** *(Bonus)* En réalité, certains anticorps sont **incompatibles** entre eux (ils réagissent chimiquement). Supposez que les anticorps Alpha et Gamma ne peuvent pas être produits ensemble.
Comment modifieriez-vous l'algorithme pour prendre en compte cette contrainte ? Proposez une approche (pas nécessairement de code).
---
Auteur : Florian Mathieu
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.