Feat: import du travail de Cédric
This commit is contained in:
commit
f407e96641
195
FOAD-bloc5-corrige.py
Normal file
195
FOAD-bloc5-corrige.py
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from random import randint
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
|
||||||
|
### Images de "tests" ####################################################################################
|
||||||
|
|
||||||
|
t1 = [
|
||||||
|
[0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0],
|
||||||
|
[0, 0, 1, 1, 0],
|
||||||
|
[0, 1, 0, 0, 1],
|
||||||
|
]
|
||||||
|
|
||||||
|
t2 = [
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[1, 1, 1, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 1, 1, 1, 1, 1],
|
||||||
|
[0, 0, 0, 1, 0, 0, 1, 0, 1, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 1, 0, 1, 0],
|
||||||
|
]
|
||||||
|
|
||||||
|
##########################################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def aff(t):
|
||||||
|
plt.imshow(t, cmap="binary")
|
||||||
|
# plt.xticks( [i for i in range(len(t[0]))] )
|
||||||
|
# plt.yticks( [i for i in range(len(t))] )
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def marque_carre(t, lig, col, taille):
|
||||||
|
for y in range(taille):
|
||||||
|
for x in range(taille):
|
||||||
|
t[lig - y][col - x] = 0.25
|
||||||
|
t[lig][col] = 0.30
|
||||||
|
|
||||||
|
|
||||||
|
def genere_tab_alea(n, ratio_noir):
|
||||||
|
t = []
|
||||||
|
for lig in range(n):
|
||||||
|
t.append([])
|
||||||
|
for col in range(n):
|
||||||
|
alea = randint(0, 100)
|
||||||
|
(t[lig]).append(1 if alea <= ratio_noir else 0)
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
def PlusGrandCarreBlanc_Rec(t, lig, col):
|
||||||
|
global compteur_naif
|
||||||
|
compteur_naif += 1
|
||||||
|
if t[lig][col] == 1:
|
||||||
|
return 0
|
||||||
|
elif (lig == 0) or (col == 0):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
# Petit truc pour éviter de calculer toutes les valeurs dans le min si une des trois est déjà à 0 (au min)
|
||||||
|
h = PlusGrandCarreBlanc_Rec(t, lig - 1, col)
|
||||||
|
if h == 0:
|
||||||
|
return 1
|
||||||
|
g = PlusGrandCarreBlanc_Rec(t, lig, col - 1)
|
||||||
|
if g == 0:
|
||||||
|
return 1
|
||||||
|
gh = PlusGrandCarreBlanc_Rec(t, lig - 1, col - 1)
|
||||||
|
if gh == 0:
|
||||||
|
return 1
|
||||||
|
return min(g, h, gh) + 1
|
||||||
|
# return min(PlusGrandCarreBlanc_Rec(t, lig - 1, col), PlusGrandCarreBlanc_Rec(t, lig - 1, col - 1), PlusGrandCarreBlanc_Rec(t, lig, col - 1)) + 1
|
||||||
|
|
||||||
|
|
||||||
|
def PlusGrandCarreBlanc_memo(t, lig, col):
|
||||||
|
global compteur_memo
|
||||||
|
compteur_memo += 1
|
||||||
|
if t_memo[lig][col] != -1:
|
||||||
|
return t_memo[lig][col]
|
||||||
|
if t[lig][col] == 1:
|
||||||
|
t_memo[lig][col] = 0
|
||||||
|
return 0
|
||||||
|
elif (lig == 0) or (col == 0):
|
||||||
|
t_memo[lig][col] = 1
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
res = (
|
||||||
|
min(
|
||||||
|
PlusGrandCarreBlanc_memo(t, lig - 1, col),
|
||||||
|
PlusGrandCarreBlanc_memo(t, lig, col - 1),
|
||||||
|
PlusGrandCarreBlanc_memo(t, lig - 1, col - 1),
|
||||||
|
)
|
||||||
|
+ 1
|
||||||
|
)
|
||||||
|
t_memo[lig][col] = res
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def RechercheCarreBlanc_naif(t):
|
||||||
|
l, c = 0, 0
|
||||||
|
tmax = 0
|
||||||
|
nb_lig, nb_col = len(t), len(t[0])
|
||||||
|
for lig in range(nb_lig): # On parcourt les lignes
|
||||||
|
for col in range(nb_col): # on parcourt les colonnes
|
||||||
|
taille = PlusGrandCarreBlanc_Rec(
|
||||||
|
t, lig, col
|
||||||
|
) # (le tableau est carré donc toutes les lignes ont la même longueur)
|
||||||
|
if taille >= tmax: # Si taille est > à tmax
|
||||||
|
l, c = lig, col # on a lig,col qui sont les coordonnées voulues
|
||||||
|
tmax = taille # on met à jour le tmax
|
||||||
|
return l, c, tmax
|
||||||
|
|
||||||
|
|
||||||
|
def RechercheCarreBlanc_memo(t):
|
||||||
|
l, c, tmax = 0, 0, 0
|
||||||
|
nb_lig, nb_col = len(t), len(t[0])
|
||||||
|
for lig in range(nb_lig):
|
||||||
|
for col in range(nb_col):
|
||||||
|
taille = PlusGrandCarreBlanc_memo(
|
||||||
|
t, lig, col
|
||||||
|
) # On utilise PlusGrandCarreBlanc_memo()
|
||||||
|
if taille >= tmax:
|
||||||
|
l, c = lig, col
|
||||||
|
tmax = taille
|
||||||
|
return l, c, tmax
|
||||||
|
|
||||||
|
|
||||||
|
def PlusGrandCarreBlanc_BU(t):
|
||||||
|
nb_lig, nb_col = len(t), len(t[0])
|
||||||
|
res = [[-1 for _ in range(nb_col)] for _ in range(nb_lig)]
|
||||||
|
for lig in range(nb_lig):
|
||||||
|
for col in range(nb_col):
|
||||||
|
if t[lig][col] == 1: # sous-problème de taille "0"
|
||||||
|
res[lig][col] = 0
|
||||||
|
elif lig == 0 or col == 0: # sous-problème de taille "1"
|
||||||
|
res[lig][col] = 1
|
||||||
|
else:
|
||||||
|
res[lig][col] = 1 + min(
|
||||||
|
res[lig - 1][col], res[lig][col - 1], res[lig - 1][col - 1]
|
||||||
|
)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def RechercheCarreBlanc_BU(t):
|
||||||
|
l, c, tmax = 0, 0, 0
|
||||||
|
nb_lig, nb_col = len(t), len(t[0])
|
||||||
|
res = PlusGrandCarreBlanc_BU(t) # Avec l'algorithme BOTTOM UP
|
||||||
|
for lig in range(nb_lig):
|
||||||
|
for col in range(nb_col):
|
||||||
|
taille = res[lig][
|
||||||
|
col
|
||||||
|
] # On utilise le tableau fournit par PlusGrandCarreBlanc_BU()
|
||||||
|
if taille >= tmax:
|
||||||
|
l, c = lig, col
|
||||||
|
tmax = taille
|
||||||
|
return l, c, tmax
|
||||||
|
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# Programme principal
|
||||||
|
#############################################
|
||||||
|
|
||||||
|
compteur_naif = 0
|
||||||
|
compteur_memo = 0
|
||||||
|
n = 40
|
||||||
|
ratio = 50
|
||||||
|
|
||||||
|
t_memo = [[-1 for i in range(n)] for j in range(n)]
|
||||||
|
t3 = genere_tab_alea(n, ratio)
|
||||||
|
|
||||||
|
s = time()
|
||||||
|
res = RechercheCarreBlanc_naif(t3)
|
||||||
|
e = time()
|
||||||
|
print("Durée de l'algo naif : ", e - s, "nombre d'appels récursifs : ", compteur_naif)
|
||||||
|
|
||||||
|
s = time()
|
||||||
|
res = RechercheCarreBlanc_memo(t3)
|
||||||
|
e = time()
|
||||||
|
print(
|
||||||
|
"Durée de l'algo avec memoïsation : ",
|
||||||
|
e - s,
|
||||||
|
"nombre d'appels récursifs : ",
|
||||||
|
compteur_memo,
|
||||||
|
)
|
||||||
|
|
||||||
|
s = time()
|
||||||
|
res = RechercheCarreBlanc_BU(t3)
|
||||||
|
e = time()
|
||||||
|
print("Durée de l'algo avec BOTTOM UP : ", e - s)
|
||||||
|
|
||||||
|
marque_carre(t3, res[0], res[1], res[2])
|
||||||
|
aff(t3)
|
325
FOAD-bloc5.md
Normal file
325
FOAD-bloc5.md
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
# Recherche du plus grand carré blanc dans une "image"
|
||||||
|
|
||||||
|
## Objectif et déroulement
|
||||||
|
|
||||||
|
On considère le problème suivant : étant donné une image monochrome $n \times n$, déterminer le plus grand carré qui ne contient aucun point noir.
|
||||||
|
|
||||||
|
Le but du TP est d'établir plusieurs algorithmes permettant de trouver le plus grand carré blanc dans une image.
|
||||||
|
|
||||||
|
Déroulement du TP :
|
||||||
|
|
||||||
|
- Conception d'un algorithme récursif naïf : ```RechercheCarreBlanc_naif()```
|
||||||
|
- Programmation dynamique - Utilisation de la mémoïsation : ```RechercheCarreBlanc_memoisation()```
|
||||||
|
- Programmation dynamique - Optimisation par "Bottom_up" : ```RechercheCarreBlanc_BU()```
|
||||||
|
|
||||||
|
# Conception d'un algorithme récursif naïf : ```RechercheCarreBlanc_naif()```
|
||||||
|
|
||||||
|
## Une image c'est quoi ?
|
||||||
|
|
||||||
|
Une image, c'est un tableau de tuples qui représentent les couleurs des pixels. Dans le cadre de ce TP, nous nous limiterons à des images noir et blanc :
|
||||||
|
|
||||||
|
![Image N/B](1.png)
|
||||||
|
|
||||||
|
```python
|
||||||
|
t=[
|
||||||
|
[1,0,0,1,0,0,1,0,0,1],
|
||||||
|
[0,0,0,0,0,0,1,0,0,0],
|
||||||
|
...
|
||||||
|
[0,0,0,0,1,0,0,0,1,0]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
```t[5][1]==1``` car le pixel de la ligne ```5``` et de la colonne ```1``` est noir. (Attention les numéros des lignes/colonnes commencent à 0).
|
||||||
|
|
||||||
|
## Etude du problème
|
||||||
|
|
||||||
|
L'objectif est de trouver le carré blanc le plus grand possible à partir d'un pixel donné (coin inférieur droit).
|
||||||
|
|
||||||
|
- ```PlusGrandCarreBlanc_Rec(lig,col)``` : Retourne la taille du carré blanc à partir du coin inférieur droit (ligne,colonne).
|
||||||
|
|
||||||
|
Par ex :
|
||||||
|
|
||||||
|
- ```PlusGrandCarreBlanc_Rec(1,2) == 2```
|
||||||
|
- ```PlusGrandCarreBlanc_Rec(6,4) == 2```
|
||||||
|
|
||||||
|
![Image N/B](2.png)
|
||||||
|
|
||||||
|
>
|
||||||
|
> 01. Pour l'image suivante, donner le résultat de :
|
||||||
|
>
|
||||||
|
> - ```PlusGrandCarreBlanc_Rec(2,1) == ...```
|
||||||
|
> - ```PlusGrandCarreBlanc_Rec(1,2) == ...```
|
||||||
|
> - ```PlusGrandCarreBlanc_Rec(1,1) == ...```
|
||||||
|
>
|
||||||
|
>![Image N/B](3.png)
|
||||||
|
>
|
||||||
|
> 02. Quelle relation existe-il entre ```PlusGrandCarreBlanc_Rec(2,2)``` et les 3 valeurs précédentes ?
|
||||||
|
>
|
||||||
|
> 03. Généraliser ce résultat pour un pixel quelconque :
|
||||||
|
>
|
||||||
|
> ```PlusGrandCarreBlanc_Rec(lig,col) = min( ......... , ......... , ......... ) + .........```
|
||||||
|
>
|
||||||
|
> 4. Proposer un algorithme récursif pour ```PlusGrandCarreBlanc_Rec(i,j)``` :
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> def PlusGrandCarreBlanc_Rec(t,lig,col): # t est le tableau représentant l'image noir et blanc
|
||||||
|
>
|
||||||
|
> if t(lig, col) == 1: # Si le pixel est noir
|
||||||
|
> return ... # On retourne ...
|
||||||
|
>
|
||||||
|
> # Sinon :
|
||||||
|
> elif ...... : # Si le pixel est sur la 1ère ligne ou 1ère colonne
|
||||||
|
> return ... # On retourne ...
|
||||||
|
>
|
||||||
|
> else : # Sinon :
|
||||||
|
> return ... # On retourne 1 + min(PlusGrandCarre des pixels adjacents)
|
||||||
|
> # Adjacents => à gauche, en haut, en diagonale haut-gauche
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> 05. Tester votre algorithme sur le tableau suivant :
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> t=[ [0,0,0,1,0],
|
||||||
|
> [0,0,0,0,1],
|
||||||
|
> [1,0,0,0,0],
|
||||||
|
> [0,0,1,1,0],
|
||||||
|
> [0,1,0,0,1] ]
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> >>> print(PlusGrandCarreBlanc_Rec(t,2,2))
|
||||||
|
> 2
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> **Remarque :** D'autres tableaux sont présent dans le fichier ```TP.py```
|
||||||
|
>
|
||||||
|
> **Remarque :** Lors de l'évaluation du minimum par ```min()```, l'interpréteur DOIT calculer les 3 valeurs à comparer. Or, nous pouvons lui éviter dans certains cas ce travail (et économiser un nombre d'appels récursifs). En effet, si la première valeur calculée est nulle alors le ```min(... , ... , ...)``` retournera FORCEMENT 0 et la fonction retournera 1. De même pour la seconde et la troisième.
|
||||||
|
>
|
||||||
|
> 6. Modifier ```PlusGrandCarreBlanc_Rec(lig,col)``` en tenant compte de la remarque précédente.
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> def PlusGrandCarreBlanc_Rec(t,lig,col):
|
||||||
|
> ...
|
||||||
|
> else :
|
||||||
|
> g = ... # Valeur du pixel de gauche
|
||||||
|
> if g==0:
|
||||||
|
> return 1
|
||||||
|
> h = ... # Valeur du pixel du haut
|
||||||
|
> if h==0:
|
||||||
|
> return 1
|
||||||
|
> ... # ...
|
||||||
|
> return ... # On retourne 1 + min(g,h,...)
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> 7. Ecrire un algorithme simple pour afficher ```t``` à l'aide de ```matplotlib``` et vérifier le bon fonctionnement de votre algorithme.
|
||||||
|
>
|
||||||
|
> > **Aide**
|
||||||
|
> >
|
||||||
|
> > ```python
|
||||||
|
> > import matplotlib.pyplot as plt
|
||||||
|
> > ...
|
||||||
|
> > plt.imshow(t,cmap='binary')
|
||||||
|
> > plt.show()
|
||||||
|
> > ```
|
||||||
|
>
|
||||||
|
> 8. Ecrire un algorithme qui parcourt toute l'image et qui retourne la ligne et la colonne du carré le plus grand ainsi que sa taille.
|
||||||
|
>
|
||||||
|
> - ```RechercheCarreBlanc_naif(t)``` : Retourne la ligne et la colonne du coin inférieur droit du carré blanc le plus grand ainsi que sa taille.
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> def RechercheCarreBlanc_naif(t):
|
||||||
|
> ...
|
||||||
|
> for lig in range(...):
|
||||||
|
> for col in range(...):
|
||||||
|
> ...
|
||||||
|
> return l,c,tmax
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> 9. Bonus : Faire en sorte d'afficher ce carré lors de l'affichage de l'image.
|
||||||
|
>
|
||||||
|
> 10. Ajouter un compteur (variable global) ```compteur_naif``` permetttant de compter le nombre d'appels récursifs
|
||||||
|
>
|
||||||
|
> 11. Ecrire une fonction permettant de générer un tableau de $n\times n$ content un ratio de points noir de ```ratio_noir```%
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> def genere_tab_alea(n, ratio_noir):
|
||||||
|
> ...
|
||||||
|
> return t
|
||||||
|
> ```
|
||||||
|
|
||||||
|
# Programmation dynamique - Utilisation de la mémoïsation : ```RechercheCarreBlanc_memoisation()```
|
||||||
|
|
||||||
|
Remplacons nous dans le cadre d'un cas simple, on cherche ```PlusGrandCarreBlanc_Rec(2,2)```.
|
||||||
|
|
||||||
|
![Image N/B](3.png)
|
||||||
|
|
||||||
|
> 1. Pendant l'appel de ```PlusGrandCarreBlanc_Rec(2,2)```, quelles sont les 3 appels récursifs qui vont être exécutés ?
|
||||||
|
>
|
||||||
|
> - Appel n°1 : ```PlusGrandCarreBlanc_Rec( ... , ... )```
|
||||||
|
> - Appel n°2 : ```PlusGrandCarreBlanc_Rec( ... , ... )```
|
||||||
|
> - Appel n°3 : ```PlusGrandCarreBlanc_Rec( ... , ... )```
|
||||||
|
>
|
||||||
|
> 2. Compléter le tableau suivant qui liste, pour les appels n°1, n°2 et n°3, les appels récursifs exécutés.
|
||||||
|
>
|
||||||
|
> Appel n°1 : ```PGCB_Rec( ... , ... )``` | Appel n°2 : ```PGCB_Rec( ... , ... )``` | Appel n°3 : ```PGCB_Rec( ... , ... )```
|
||||||
|
> ---------|----------|---------
|
||||||
|
> ```PGCB_Rec( ... , ... )``` | ```PGrCB_Rec( ... , ... )``` | ```PGCB_Rec( ... , ... )```
|
||||||
|
> ```PGCB_Rec( ... , ... )``` | ```PGrCB_Rec( ... , ... )``` | ```PGCB_Rec( ... , ... )```
|
||||||
|
> ```PGCB_Rec( ... , ... )``` | ```PGrCB_Rec( ... , ... )``` | ```PGCB_Rec( ... , ... )```
|
||||||
|
>
|
||||||
|
> 3. Quels appels sont redondants ? Proposez une solution pour éviter cela.
|
||||||
|
>
|
||||||
|
|
||||||
|
## Mise en place du tableau de mémoïsation
|
||||||
|
|
||||||
|
Pour économiser des appels récursifs, vous allez stocker **au fur et à mesure** les résultats de ces appels dans un tableau de même taille que l'image.
|
||||||
|
|
||||||
|
Ce tableau sera initialisé entièrement à ```-1```, ce qui signifie qu'aucun résultat n'a déjà été calculé pour ce pixel. Dans le cas contraire, il faudra stocker le résultat dans ce ```t_memo```
|
||||||
|
|
||||||
|
- ```t_memo``` : Tableau de même dimension que ```t``` qui stocke les valeurs de ```PlusGrandCarreBlanc_memo()``` au fur et à mesure des appels récursifs. Ce tableau est une variable globale.
|
||||||
|
|
||||||
|
> 4. Initialiser la variable globale ```t_memo```.
|
||||||
|
>
|
||||||
|
> **Aide :** En une ligne ... ```t_memo = [[-1 for i in ... ] for j ... ]```
|
||||||
|
>
|
||||||
|
> **Remarque :** On peut être malin et faire une copie de ```t``` en remplaceant les ```1``` (pixel noir) par des ```0``` (résultat connu) et les ```0``` (pixels blancs) par des ```-1``` (résultat inconnu)
|
||||||
|
|
||||||
|
## Évolution de ```PlusGrandCarreBlanc_Rec()``` en ```PlusGrandCarreBlanc_memo()```
|
||||||
|
|
||||||
|
> 5. En vous aidant de ```PlusGrandCarreBlanc_Rec()```, écrire la fonction ```PlusGrandCarreBlanc_memo()``` en stockant et utilisant les résultats précédamment calculés dans le tableau ```t_memo```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def PlusGrandCarreBlanc_memo(t, lig, col):
|
||||||
|
if t_memo[lig][col] != -1: # Utilisation d'une valeur présente dans t_memo
|
||||||
|
return ...
|
||||||
|
if t[lig][col] == 1:
|
||||||
|
...
|
||||||
|
return ...
|
||||||
|
```
|
||||||
|
|
||||||
|
> 6. Effectuer les tests sur différents pixels d'une image et sur différentes images. Vous pouvez aussi utiliser la fonction ```genere_tab_alea(n, ratio_noir)``` pour valider votre algorithme.
|
||||||
|
|
||||||
|
## Pour aller plus vite ... ```RechercheCarreBlanc_memo()``` ?
|
||||||
|
|
||||||
|
```PlusGrandCarreBlanc_memo()``` est une fonction équivalente à ```PlusGrandCarreBlanc_Rec()``` mais normalement plus rapide.
|
||||||
|
|
||||||
|
Il reste donc à parcourir une image pour trouver les coordonnées du coin inférieur droit du plus grand carré blanc dans l'image.
|
||||||
|
|
||||||
|
> 7. Ecrire la fonction ```RechercheCarreBlanc_memo()``` qui retourne les coordonnées du coin inférieur droit du plus grand carré blanc ainsi que sa taille.
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> def RechercheCarreBlanc_memo(t):
|
||||||
|
> l, c, tmax = 0, 0, 0
|
||||||
|
> ...
|
||||||
|
> return l, c, tmax
|
||||||
|
> ```
|
||||||
|
|
||||||
|
## Complexité
|
||||||
|
|
||||||
|
> 8. A l'aide du module ```time```, mesurer la différence de performance de l'algorithme naïf et de celui qui utilisa le mémoïsation sur des images de tailles et de "ratio de noir" différents.
|
||||||
|
>
|
||||||
|
> $~$ | ```n=10``` / ```ratio=50``` | ```n=30``` / ```ratio=50``` | ```n=50``` / ```ratio=40``` | ```n=70``` / ```ratio=35```
|
||||||
|
> ---------|----------|---------|----------|----------
|
||||||
|
> ```RechercheCarreBlanc_Rec``` | $~$ | $~$| $~$| $~$
|
||||||
|
> ```RechercheCarreBlanc_memo``` | $~$ | $~$| $~$| $~$
|
||||||
|
>
|
||||||
|
> 9. De la même manière que pour l'algorithme naïf, implanter un ```compteur_memo``` qui permettra de compter le nombre d'appels récursifs. Effectuer les tests avec les mêmes paramètres que dans la question précédente.
|
||||||
|
>
|
||||||
|
> $~$ | ```n=10``` / ```ratio=50``` | ```n=30``` / ```ratio=50``` | ```n=50``` / ```ratio=40``` | ```n=70``` / ```ratio=35```
|
||||||
|
> ---------|----------|---------|----------|----------
|
||||||
|
> ```RechercheCarreBlanc_Rec``` | $~$ | $~$| $~$| $~$
|
||||||
|
> ```RechercheCarreBlanc_memo``` | $~$ | $~$| $~$| $~$
|
||||||
|
>
|
||||||
|
> Uniquement avec ```RechercheCarreBlanc_memo```, mesurer le temps d'exécution de l'algorithme avec ```n=500``` / ```ratio=50``` puis avec ```n=1000``` / ```ratio=50```.
|
||||||
|
>
|
||||||
|
> 10. Par combien a été multiplié le temps d'exécution lorsque ```n``` a doublé ? Conjecturer sur la complexité de cet algorithme.
|
||||||
|
>
|
||||||
|
> 11. Le gain de performance est-il subtanciel ?
|
||||||
|
>
|
||||||
|
|
||||||
|
![Roadrunner](https://media1.tenor.com/images/272319d1c44ce6047b25e7f266da00a0/tenor.gif)
|
||||||
|
|
||||||
|
# Programmation dynamique - Optimisation "Bottom Up" : ```RechercheCarreBlanc_BU()```
|
||||||
|
|
||||||
|
L'optimisation "BOTTOM UP", consiste à traiter les problèmes du plus évident (les "plus petits") au moins évident (les "plus gros") en stockant les résultats au fur et à mesure dans un tableau.
|
||||||
|
|
||||||
|
Il faut toutefois identifier un ordre dans lequel résoudre les sous-problèmes. Dans notre cas l'ordre est :
|
||||||
|
|
||||||
|
- Traiter les problèmes de taille "0" : Les cases noires
|
||||||
|
- Traiter les problèmes de taille "1" : Les cases sur la première ligne et première colonne
|
||||||
|
- Traiter les problèmes de taille "2" : ...
|
||||||
|
|
||||||
|
Le tableau de "résultats", qui stocke au fur et à mesure les résultats de ````PlusGrandCarreBlanc(lig,col)````, se nommera ```res```.
|
||||||
|
|
||||||
|
> 1. Compléter, à la main, le tableau ```res``` pour les problèmes de taille "0".
|
||||||
|
>
|
||||||
|
> - Si le ```pixel(lig,col)``` est noir alors ```res[lig][col] = 0```
|
||||||
|
>
|
||||||
|
|
||||||
|
![Image N/B](4.png)
|
||||||
|
|
||||||
|
> 2. Compléter, à la main, le précédent tableau ```res``` pour les problèmes de taille "1".
|
||||||
|
>
|
||||||
|
> - Si le ```pixel(lig,col)``` est sur la première ligne et/ou colonne alors ```res[lig][col] = 1```
|
||||||
|
>
|
||||||
|
|
||||||
|
![Image N/B](4.png)
|
||||||
|
|
||||||
|
> 3. En l'état actuel, peut-on, à l'aide de ```res```, calculer ```PlusGrandCarreBlanc(1,1)``` directement (sans calcul intermédiaire) ? et ```PlusGrandCarreBlanc(2,2)``` ?
|
||||||
|
>
|
||||||
|
> 4. Comment faut-il parcourir le tableau pour être sûr qu'à chaque appel, l'algorithme dispose des résultats des problèmes de taille inférieur.
|
||||||
|
>
|
||||||
|
> 5. Ecrire un algorithme ```PlusGrandCarreBlanc_BU()``` qui :
|
||||||
|
>
|
||||||
|
> - Initialise le tableau ```res``` à -1
|
||||||
|
> - Complète ```res``` avec les résultats de taille "0" (les cases noires)
|
||||||
|
> - Complète ```res``` avec les résultats de taille "1" (1ère ligne/colonne)
|
||||||
|
> - Parcours l'image et calcule les résultats de taille supérieur
|
||||||
|
> - Et retourne ```res```
|
||||||
|
|
||||||
|
**Aide :**
|
||||||
|
|
||||||
|
- Remplir un tableau ```res```, qui a la même taille que l'image, et qui est initialisé -1 dans toutes les cases.
|
||||||
|
- A l'aide de 2 boucles imbriquées sur les lignes et colonnes :
|
||||||
|
- Si le ```t[lig][col]``` est noir, affectez ```0``` à ```res[lig][col]```
|
||||||
|
- Sinon si ```lig==0``` ou ```col==0```, affectez 1 à ```res[lig][col]```
|
||||||
|
- Sinon affectez ```min(res[lig][col-1] , res[lig-1][col-1] , res[lig-1][col] ) + 1``` à ```res[lig][col]```
|
||||||
|
- Retourner ```res```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def PlusGrandCarreBlanc_BU(t):
|
||||||
|
nb_lig, nb_col = ...
|
||||||
|
res = [[-1 for i in ...] for j in ...]
|
||||||
|
for lig in range(nb_lig):
|
||||||
|
for col in range(nb_col):
|
||||||
|
...
|
||||||
|
return res
|
||||||
|
```
|
||||||
|
|
||||||
|
## .... et trouver le carré blanc le plus grand (presque à la vitesse de la lumière) : ```RechercheCarreBlanc_BU()```
|
||||||
|
|
||||||
|
> 6. Ecrire ```RechercheCarreBlanc_BU()``` qui retourne les coordonnées du coin inférieur droit du plus grand carré blanc ainsi que sa taille à l'aide de l'algorithme précédent.
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> def RechercheCarreBlanc_BU(t):
|
||||||
|
> l, c, tmax = 0, 0, 0
|
||||||
|
> ...
|
||||||
|
> return l, c, tmax
|
||||||
|
> ```
|
||||||
|
|
||||||
|
## Comparaison des algorithmes
|
||||||
|
|
||||||
|
> 7. Comparer le temps d'éxecution des ces algorithmes.
|
||||||
|
>
|
||||||
|
> $~$ | ```n=100``` / ```ratio=30``` | ```n=300``` / ```ratio=20``` | ```n=1000``` / ```ratio=20``` | ```n=3000``` / ```ratio=40```
|
||||||
|
> ---------|----------|---------|----------|----------
|
||||||
|
> ```RechercheCarreBlanc_memo``` | $~$ | $~$| $~$| $~$
|
||||||
|
> ```RechercheCarreBlanc_BU``` | $~$ | $~$| $~$| $~$
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Programmation dynamique = Gain en performance
|
||||||
|
|
||||||
|
L'étude théorique d'un problème permet une optimisation précise de l'algorithme qui le résoudra.
|
||||||
|
|
||||||
|
![Programmation dynamique](https://www.artelys.com/wp-content/uploads/2018/11/formation4.jpg)
|
BIN
FOAD-bloc5.pdf
Normal file
BIN
FOAD-bloc5.pdf
Normal file
Binary file not shown.
BIN
ProgrammationDynamique.pdf
Normal file
BIN
ProgrammationDynamique.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user