aboutsummaryrefslogtreecommitdiff
path: root/semestre 4/algo/1- Validité et terminaison.typ
diff options
context:
space:
mode:
Diffstat (limited to 'semestre 4/algo/1- Validité et terminaison.typ')
-rw-r--r--semestre 4/algo/1- Validité et terminaison.typ174
1 files changed, 174 insertions, 0 deletions
diff --git a/semestre 4/algo/1- Validité et terminaison.typ b/semestre 4/algo/1- Validité et terminaison.typ
new file mode 100644
index 0000000..480c5b7
--- /dev/null
+++ b/semestre 4/algo/1- Validité et terminaison.typ
@@ -0,0 +1,174 @@
+#import "@local/template:1.0.0": *
+#import "@local/callout:1.0.0": *
+
+#show: doc.with(
+ authors: (
+ (name: "William Hergès", affiliation: "Sorbonne Université", email: "william@herges.fr"),
+ ),
+ page_title: "Validité et terminaison",
+)
+
+= Définitions élémentaires
+
+Un algorithme sert à résoudre un problème.
+
+#defn[
+ Un _problème_ $P$ est identifié par un nom, un ensemble de paramètres et une description de la solution.
+]
+
+#defn[
+ Une _instance d'un problème_ $P$ est une valeur possible pour les paramètres du problème.
+]
+
+Définition du problème de tri~:
+- nom~: tri
+- paramètres~: un entier $n$ et un tableau $"tab"$ de $0$ à $n-1$ de tailles $n$
+- solution~: le tableau $"tab"$ trié par ordre croissant
+
+#defn[
+ Un _programme_ est composé de~:
+ - un ensemble fini de variables
+ - des opérations élémentaires portant sur les variables (arithmétiques, logiques, affectations)
+ - des structures de contrôle permettant de définir un ordre sur les opérations élémentaires
+]
+
+#defn[
+ Un _algorithme_ qui résoud un problème $P$ est un programme qui vérifie les deux propriétés suivantes~:
+ - *terminaison*~: l'algorithme appliqué à toute instance du problème effectue un nombre fini d'opérations
+ - *validité*~: l'algorithme résoud le problème $P$ pour toute instance de $P$
+]
+
+Un algorithme doit donc produire une solution en un temps fini qui fonctionne toujours.
+
+On parle aussi de _correction_ pour la validité.
+
+#defn[
+ Une _fonction_ est un algorithme qui renvoie une valeur.
+]
+
+= Problèmes sur un algorithme
+
+Soit $A$ un algorithme pour résoudre un problème $P$.
+- Se termine-t-il~? → terminaison (cette séance)
+- Résoud-il $P$~? → validité (cette séance)
+- Est-il efficace~? → complexité (séance 3)
+
+== Exemple
+
+Soit le programme
+```py
+def fibo(n):
+ if n == 0:
+ return 0
+ x = 0
+ y = 1
+ i = 1
+ while i < n:
+ z = x+y
+ x = y
+ y = z
+ i = i+1
+ return y
+```
+On cherche à savoir s'il calcule bien le $n$-ième terme de la suite de Fibonacci.
+
+Le corps de boucle est composé d'instructions élémentaires et elle est effecutée $n-1$ fois.
+Donc elle se termine pour tout $n$ dans $NN$.
+
+Pour vérifier la correction du programme, on va suivre les variables présentes dans le programme.
+Cela revient à faire du débuggage.
+Un bon point d'arrêt est en fin de corps de boucle.
+Par exemple, on pourrait avoir~:
+#table(
+ columns: (1fr,) * 3,
+ inset: 0.5em,
+ align: center,
+ stroke: (y: none),
+ table.hline(),
+ table.header([i], [$x_i$], [$y_i$]),
+ table.hline(),
+ [1], [0], [1],
+ [2], [1], [1],
+ [3], [1], [2],
+ [4], [2], [3],
+ [5], [3], [5],
+ [6], [5], [8],
+ table.hline(),
+)
+On obtient alors $8$ pour $n=6$.
+
+Pour la démontrer proprement, on la fait par récurrence.
+Soit $cal(P)$ la propriété telle que~:
+$ forall i in [|1,n|], quad cal(P)_i: quad x_i = F_(i-1) and y_i = F_i $
+On a que $cal(P)_1$ est vérifiée.
+
+Soit $k in NN^*$ tel que $cal(P)_k$ soit vraie.
+$ y_(k+1) = x_k + y_k = F_(k)+F_(k-1) = F_(k+1) $
+et
+$ x_(k+1) = y_k = F_k $
+Donc, $cal(P)_(k+1)$ est vraie.
+
+Ainsi, pour tout $n$ dans $NN$, $cal(P)$ est vraie.
+
+_manque la fin de la démo_
+
+== Méthode générale
+
+#warning[
+ Nous n'avons pas besoin d'un raisonnement par récurrence pour montrer la terminaison d'un programme.
+]
+
+#defn[
+ Un _invariant de boucle_ es une propriété qui est vérifiée à chaque exécution du corps de cette boucle.
+ Elle est toujours vraie à la fin de la boucle, après avoir incrémentée notre $i$.
+]
+
+#warning[
+ Tous les invariants ne sont pas utiles~!
+]
+
+Pour montrer la validité, on~:
+1. détermine un invariant de boucle
+2. démontre l'invariant par récurrence sur le nombre d'itérations
+3. étudie la sortie de boucle pour conclure sur la validité de la boucle
+
+== Autre exemple
+
+On cherche l'indice de l'élément minimum d'un tableau.
+On propose ce programme~:
+```py
+def RechercheMin(tab):
+ imin = 0
+ i = 0
+ while i < len(tab):
+ if tab[i] < tab[imin]:
+ imin[i]
+ i = i+1
+ return imin
+```
+
+Notons $n$ la taille de `tab`.
+
+Le nombre d'exécution de ce programme est borné.
+En effet, on exécute au maximum $n$ fois le corps de la boucle.
+
+Soit $cal(P)$ la propriété suivante~:
+$ forall i in [|0, n|],quad cal(P)_i: quad forall j in [|0, i|], "tab"["imin"_i] <= "tab"[j] $
+$cal(P)_0$ est trivialement vraie.
+
+Posons $k$ dans $[|0,n|]$ telle que $cal(P)_k$ soit vraie.
+On pose~:
+$ "imin"_(k+1) = cases(
+ k+1 &"si"& "tab"[k+1] < "tab"["imin"_k],
+ "imin"_k &"sinon"&
+) $
+Or, comme $cal(P)_k$ est vraie, on a $"tab"[i] >= "tab"["imin"_i]$ pour tout $i$ dans $[|0,k|]$.
+De plus, on a $"tab"[k+1]>="tab"["imin"_(k+1)]$ et $"tab"["imin"_(k+1)] <= "tab"["imin"_k]$ par définition de
+$"imin"_(k+1)$.
+Donc $cal(P)_(k+1)$ est vraie.
+
+Ainsi, pour tout $i$ dans $[|0,n|]$, $cal(P)_i$ est vérifiée.
+
+En sortie de boucle, $cal(P)_n$ est vraie et renvoie $"imin"_n$.
+Comme $cal(P)_n$ est vraie, $"tab"["imin"_n]$ est le plus petit élément de `tab`.
+Alors, le programme est valide.