{ "cells": [ { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import random as rd\n", "from typing import Callable #pour annoter le type function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Partie I Tri et bases de données" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "def tri(L:[int])->None:\n", " \"\"\"Tri par insertion d'une liste L\"\"\"\n", " n = len(L)\n", " for i in range(1, n):\n", " j = i\n", " x = L[i]\n", " while 0 < j and x < L[j-1]:\n", " L[j] = L[j-1]\n", " j = j-1 \n", " L[j] = x " ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Test unitaires réussis\n" ] } ], "source": [ "#Tests unitaires\n", "for L in [[], [5, 2, 3, 1, 4], list(range(6)), list(range(5, -1, -1))]:\n", " tri(L)\n", " assert L == sorted(L)\n", "print(\"Test unitaires réussis\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q1" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "| i | j | x | L |\n", "| 1 | 1 | 2 | [5, 2, 3, 1, 4] |\n", "| 1 | 0 | 2 | [5, 5, 3, 1, 4] |\n", "| 1 | 0 | 2 | [2, 5, 3, 1, 4] |\n", "| 2 | 2 | 3 | [2, 5, 3, 1, 4] |\n", "| 2 | 1 | 3 | [2, 5, 5, 1, 4] |\n", "| 2 | 1 | 3 | [2, 3, 5, 1, 4] |\n", "| 3 | 3 | 1 | [2, 3, 5, 1, 4] |\n", "| 3 | 2 | 1 | [2, 3, 5, 5, 4] |\n", "| 3 | 1 | 1 | [2, 3, 3, 5, 4] |\n", "| 3 | 0 | 1 | [2, 2, 3, 5, 4] |\n", "| 3 | 0 | 1 | [1, 2, 3, 5, 4] |\n", "| 4 | 4 | 4 | [1, 2, 3, 5, 4] |\n", "| 4 | 3 | 4 | [1, 2, 3, 5, 5] |\n", "| 4 | 3 | 4 | [1, 2, 3, 4, 5] |\n" ] } ], "source": [ "# Question 1\n", "# faire un tableau d'états\n", "\n", "def tri(L, debug = False):\n", " \"\"\"Tri par insertion d'une liste L\"\"\"\n", " n = len(L)\n", " if debug:\n", " print(\"|{:^10}|{:^10}|{:^10}|{:^40}|\".format(\"i\",\"j\",\"x\", \"L\"))\n", " for i in range(1, n):\n", " j = i\n", " x = L[i]\n", " if debug:\n", " print(\"|{:^10d}|{:^10d}|{:^10d}|{:^40s}|\".format(i,j,x, str(L)))\n", " while 0 < j and x < L[j-1]:\n", " L[j] = L[j-1]\n", " j = j-1 \n", " if debug:\n", " print(\"|{:^10d}|{:^10d}|{:^10d}|{:^40}|\".format(i,j,x, str(L))) \n", " L[j] = x \n", " if debug:\n", " print(\"|{:^10d}|{:^10d}|{:^10d}|{:^40}|\".format(i,j,x, str(L)))\n", "\n", "\n", "L = [5, 2, 3, 1, 4]\n", "tri(L, debug = True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Q2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "**On démontre d'abord la terminaison de la fonction `tri` sur n'importe quelle entrée :**\n", "\n", "\n", "La boucle externe de la fonction `tri` est une boucle inconditionnelle et pour chaque itération de la boucle externe on a une boucle interne conditionnelle avec un entier positif `j` qui est un __variant de boucle__ car il décroît strictement à chaque itération. Par conséquent chaque itération de la boucle externe se termine et la boucle externe se termine car c'est une boucle inconditionnelle. **Ceci prouve la terminaison de la fonction `tri` sur n'importe quelle entrée.**\n", "\n", "\n", "\n", "**On démontre ensuite la correction de la fonction `tri` sur n'importe quelle entrée :**\n", "\n", "\n", "Pour la fonction `tri` précédente, on définit la propriété :\n", "\n", "_P(i):= `L[0:i+1]` triée dans l'ordre croissant à l'issue de l'itération `i`_ \n", "\n", "Démontrons que _P(i)_ est un **invariant** de la boucle externe de la fonction `tri`.\n", "\n", "* __Initialisation :__ Pour `i=0`, `L[0:0+1]` est un sous-tableau réduit à un seul élément `L[0]` donc il est nécessairement trié dans l'ordre croissant.\n", "* __Hérédité :__ Supposon que _P(i)_ soit vraie, `L[0:i+1]` est donc un sous-tableau trié dans l'ordre croissant. Lors de l'itération `i+1`, a boucle conditionnelle interne va insérer l'élément `L[i+1]` à sa place dans le sous-tableau `L[0:i+1]`. A la fin de l'itération `i+1` de la boucle externe, `L[0:i+2]` sera donc un sous-tableau d'éléments de `L` trié dans l'ordre croissant. **Ceci achève la preuve que _P(i)_ est un invariant de boucle.**\n", "\n", "\n", "La boucle externe se termine à l'issue de l'itération `i := n - 1`, en instanciant l'invariant en sortie de boucle, on obtient que _`L[0:n]` triée dans l'ordre croissant à l'issue de l'itération `i`_ ce qui équivaut à `L` triée dans l'ordre croissant. La postcondition fixée dans la spécification de la fonction `tri` est vérifiée et la fonction `tri` est donc correcte sur n'importe quelle entrée. **Ceci prouve la correction de la fonction `tri` sur n'importe quelle entrée.**\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Q3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le tri par insertion est de complexité linéaire dans le meilleur des cas (liste déjà classée) et quadratique dans le pire des cas (liste classée dans l'ordre inverse) :\n", "\n", "* __Cas le plus favorable :__ si la liste est déjà triée dans l'ordre croissant, la boucle interne n'est jamais exécutée car la condition pour la première itération, `x < L[j-1]` pour `x = L[i]` et `j = i`, n'est pas vérifiée. Les $n-1$ tours de la boucle conditionnelle externe sont exécutés ce qui fait une __complexité linéaire__. C'est le meilleur des cas car on ne peut avoir moins d'itérations de la boucle externe.\n", "* si la liste est déjà triée dans l'ordre décroissant, lorsque l'index de la boucle externe vaut `i`, la valeur `L[i]` doit être insérée en première position dans le sous-tableau déjà trié `L[0:i]` et donc elle est comparée et échangée successivement avec les `i` valeurs d'index compris entre `0` et `i-1` inclus. Lorsque la boucle externe se termine, on aura donc $\\sum_{i=1}^{n-1}i=\\frac{(n-1)n}{2}$ exécutions de la boucle interne. Cela fait une __complexité quadratique__ en $O(n^{2})$. On ne peut pas avoir de cas plus défavorable car au pire l'élément d'index `i` à insérer est comparé et échangé avec les `i` précédents déjà triés. \n", "\n", "Le __tri rapide__ a une complexité moyenne linéarithmique d'ordre de grandeur $O(n \\ln(n))$ et une complexité quadratique dans le pire des cas.\n", "\n", "Le __tri fusion__ a une complexité linéarithmique d'ordre de grandeur $O(n \\ln(n))$ dans tous les cas." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q4" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def tri_chaine(L):\n", " for k in range(len(L)):\n", " L[k][0], L[k][1] = L[k][1], L[k][0]\n", " tri(L)\n", " for k in range(len(L)):\n", " L[k][0], L[k][1] = L[k][1], L[k][0]" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Test réussi, L = [['Bresil', 76], ['Ouganda', 8431], ['Kenya', 26017]]\n" ] } ], "source": [ "# test unitaire\n", "L = [['Bresil', 76], ['Kenya', 26017], ['Ouganda', 8431]]\n", "tri_chaine(L)\n", "assert L == [['Bresil', 76], ['Ouganda', 8431], ['Kenya', 26017]]\n", "print(\"Test réussi, L = \", L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les valeurs des attributs iso, nom et annee ne sont pas distinctes pour tous les enregistrements de la table palu donc ces attibuts ne peuvent servir de clef primaire.\n", "En revanche les couples (nom, annee) ou (iso, annee) peuvent servir de clef primaire." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chargement de l'extension ipython-sql\n", "\n", "Voir " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%reload_ext sql\n", "%config SqlMagic.displaycon = False\n", "%config SqlMagic.autolimit = 100" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%sql sqlite:///mine-2016.db" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Contenu des tables :" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nomisoanneecasdeces
BresilBR200930931685
BresilBR201033466776
KenyaKE201089853126017
MaliML20113070352128
OugandaUG201015811608431
" ], "text/plain": [ "[('Bresil', 'BR', 2009, 309316, 85),\n", " ('Bresil', 'BR', 2010, 334667, 76),\n", " ('Kenya', 'KE', 2010, 898531, 26017),\n", " ('Mali', 'ML', 2011, 307035, 2128),\n", " ('Ouganda', 'UG', 2010, 1581160, 8431)]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql\n", "\n", "SELECT * FROM palu ;" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
paysperiodepop
BR2009193020000
BR2010194946000
KE201040909000
ML201114417000
UG201033987000
" ], "text/plain": [ "[('BR', 2009, 193020000),\n", " ('BR', 2010, 194946000),\n", " ('KE', 2010, 40909000),\n", " ('ML', 2011, 14417000),\n", " ('UG', 2010, 33987000)]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql\n", "\n", "SELECT * FROM demographie ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "~~~sql\n", "SELECT * FROM palu \n", " WHERE annee = 2010 AND deces >= 1000 ;\n", "~~~" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nomisoanneecasdeces
KenyaKE201089853126017
OugandaUG201015811608431
" ], "text/plain": [ "[('Kenya', 'KE', 2010, 898531, 26017), ('Ouganda', 'UG', 2010, 1581160, 8431)]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql\n", "\n", "SELECT * FROM palu \n", " WHERE annee = 2010 AND deces >= 1000 ;\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q7" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "~~~sql\n", "SELECT nom, pays, annee, cas * 1.0/ pop *100000 \n", " FROM palu JOIN demographie \n", " ON iso = pays AND annee = periode\n", " WHERE periode = 2011 \n", "~~~" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nompaysanneecas * 1.0/ pop *100000
MaliML20112129.6733023513907
" ], "text/plain": [ "[('Mali', 'ML', 2011, 2129.6733023513907)]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql\n", "\n", "SELECT nom, pays, annee, cas * 1.0/ pop *100000 \n", " FROM palu JOIN demographie \n", " ON iso = pays AND annee = periode\n", " WHERE periode = 2011 ;\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q8" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "~~~sql\n", "SELECT nom FROM palu \n", " WHERE annee = 2010 \n", " ORDER BY cas ASC LIMIT 1, 1 ;\n", "~~~" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", "
nom
Kenya
" ], "text/plain": [ "[('Kenya',)]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql\n", "\n", "SELECT nom FROM palu \n", " WHERE annee = 2010 \n", " ORDER BY cas ASC LIMIT 1, 1 ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Documentation du module sqlite3 sur " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[['Bresil', 76], ['Kenya', 26017], ['Ouganda', 8431]]\n" ] } ], "source": [ "import sqlite3 #module de manipulations de bases sqlite en Python\n", "con = sqlite3.connect('mine-2016.db') #connexion à la base\n", "cur = con.cursor() #création d'un curseur pour interroger la base\n", "requete = '''SELECT nom, deces FROM palu WHERE annee=2010'''\n", "cur.execute(requete) #exécution d'une requête sur la base par le biais du curseur\n", "con.commit() #enregistrement de la requête\n", "deces2010 = cur.fetchall() #récupération des résultats de la requête dans deces2010\n", "con.close() #fermeture de la connexion\n", "deces2010 = [list(t) for t in deces2010]\n", "print(deces2010) #affichage de deces2010" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[['Bresil', 76], ['Ouganda', 8431], ['Kenya', 26017]]\n" ] } ], "source": [ "tri_chaine(deces2010)\n", "print(deces2010)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Partie II Modèle à compartiments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Voir .\n", "\n", "Ci-dessous le graphe probabiliste d'un modèle à cinq compartiments.\n", "\n", "\n", "![SIRD](CompartmentalModel.jpg)\n", "\n", "Modèle à quatre compartiments (S,I,R,D) :\n", "\n", "* $S$ : sains ou susceptibles\n", "* $I$ : infectés\n", "* $R$ : rétablis, immunisés\n", "* $D$ : dead, morts\n", "\n", "\n", "Système différentiel, traduisant la dynamique du modèle :\n", "\n", "$\\begin{cases}\n", "\\frac{d}{dt}S(t)=-rS(t)I(t) \\\\\n", "\\frac{d}{dt}I(t)=rS(t)I(t) -(a+b)I(t) \\\\\n", "\\frac{d}{dt}R(t)=aI(t) \\\\\n", "\\frac{d}{dt}D(t)=bI(t) \\\\\n", "\\end{cases}$\n", "\n", "\n", "avec :\n", "\n", "* $r$ le taux de contagion\n", "* $a$ le taux de guérison\n", "* $b$ le taux de mortalité.\n", "\n", "\n", "Conditions initiales à l'instant $t=0$ :\n", "\n", "* $S(0)=0,95$\n", "* $I(0)=0,05$\n", "* $R(0)=D(0)=0$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le vecteur $X = (S, I, R, D)$ permet de transformer le système différentiel en une équation différentielle vectorialisée :\n", "$\\frac{d}{dt}X=f(X)$.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q11" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from typing import Callable #pour annoter le type function\n", "\n", "def f(X:[float], r:float, a:float, b:float)->np.ndarray: \n", " \"\"\"Fonction définissant l'équation différentielle dX/dt = f(X)\n", " Paramètres :\n", " r, a, b : de type flottant, taux de contagion, guérison, mortalité\n", " X = (S,I,R,D) de type liste de flottants\n", " Valeur renvoyée : de type array\n", " \"\"\"\n", " (S, I, R, D) = X\n", " return np.array([-r*S*I, r*S*I - (a + b)*I, a*I, b*I])\n", "\n", "def euler(f:Callable, N:int)->([float],[np.ndarray]):\n", " # Parametres\n", " tmax = 25. #temps maximal\n", " r = 1. #taux de contagion\n", " a = 0.4 #taux de guérison\n", " b = 0.1 #taux de mortalité\n", " X0 = np.array([0.95, 0.05, 0., 0.]) #vecteur X=(S,I,R,D)\n", " \n", " #initialisation du schéma d'Euler\n", " dt = tmax/N #pas de temps du schéma d'Euler \n", " t = 0\n", " X = X0\n", " tt = [t]\n", " XX = [X]\n", "\n", " # Schéma d’Euler\n", " for i in range(N):\n", " t = t + dt\n", " X = X + dt * f(X, r, a, b)\n", " tt.append(t)\n", " XX.append(X)\n", " return tt, XX" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([0,\n", " 3.5714285714285716,\n", " 7.142857142857143,\n", " 10.714285714285715,\n", " 14.285714285714286,\n", " 17.857142857142858,\n", " 21.42857142857143,\n", " 25.000000000000004],\n", " array([[ 0.95 , 0.05 , 0. , 0. ],\n", " [ 0.78035714, 0.13035714, 0.07142857, 0.01785714],\n", " [ 0.41705312, 0.26088056, 0.25765306, 0.06441327],\n", " [ 0.02847794, 0.1835976 , 0.63033957, 0.15758489],\n", " [ 0.00980479, -0.12558211, 0.89262185, 0.22315546],\n", " [ 0.01420232, 0.09427413, 0.71321884, 0.17830471],\n", " [ 0.00942049, -0.06929071, 0.84789617, 0.21197404],\n", " [ 0.01175175, 0.05211144, 0.74890945, 0.18722736]]))" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#exemple\n", "euler(f,7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Représentation graphique de l'évolution des catégories (S,I,R,D) du modèle à 4 compartiments." ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "plt.clf()\n", "N = 7\n", "tt, XX = euler(f, N)\n", "mark = ['o','s','x','*']\n", "for k in range(4):\n", " plt.scatter(tt, XX[:,k],marker=mark[k])\n", "N = 250\n", "tt, XX = euler(f, N)\n", "color = ['k','g','b','r']\n", "label = ['S','I','R','D']\n", "for k in range(4):\n", " plt.plot(tt, XX[:,k],color=color[k], label = label[k])\n", "plt.legend(loc='best')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q12" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour N = 250, le pas du schéma d'Euler est plus petit (puisque pas = dt = tmax/N avec tmax = 25 dans les deux cas) donc on obtient une meilleure approximation par la méthode d'Euler au prix d'un temps de calcul plus important.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q13" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Prise en compte du temps d'incubation $\\tau$ :\n", "\n", "Le système différentiel s'écrit désormais :\n", "\n", "$\\begin{cases}\n", "\\frac{d}{dt}S(t)=-rS(t)I(t-\\tau) \\\\\n", "\\frac{d}{dt}I(t)=rS(t)I(t-\\tau) -(a+b)I(t) \\\\\n", "\\frac{d}{dt}R(t)=aI(t) \\\\\n", "\\frac{d}{dt}D(t)=bI(t) \\\\\n", "\\end{cases}$\n", "\n", "\n", "Conditions initiales, on suppose que pour $t \\in [-\\tau,0]$ on a :\n", "\n", "* $S(t)=0,95$\n", "* $I(t)=0,05$\n", "* $R(t)=D(0)=0$\n", "\n" ] }, { "cell_type": "code", "execution_count": 150, "metadata": {}, "outputs": [], "source": [ "def f2(X:[float], Itau:float, r:float, a:float, b:float)->np.ndarray: \n", " \"\"\"Fonction définissant l'équation différentielle dX/dt = f(X)\n", " Paramètres :\n", " r, a, b : de type flottant, taux de contagion, guérison, mortalité\n", " Itau est la valeur de I(t - p * dt)\n", " X = (S,I,R,D) de type liste de flottants\n", " Valeur renvoyée : de type array\n", " \"\"\"\n", " (S, I, R, D) = X\n", " return np.array([-r*S*Itau, r*S*Itau - (a + b)*I, a*I, b*I])\n", "\n", "def euler2(f:Callable, N:int)->([float],[np.ndarray]):\n", " # Parametres\n", " tmax = 25. #temps maximal\n", " r = 1. #taux de contagion\n", " a = 0.4 #taux de guérison\n", " b = 0.1 #taux de mortalité\n", " X0 = np.array([0.95, 0.05, 0., 0.])\n", " \n", " #initialisation du schéma d'Euler\n", " dt = tmax/N #pas de temps du schéma d'Euler \n", " p = 50 #nombre de pas de retard\n", " t = 0\n", " X = X0\n", " tt = [t]\n", " XX = [X]\n", "\n", " # Schéma d’Euler\n", " for i in range(N):\n", " t = t + dt\n", " #avec décalage (temps >= p = 0)\n", " if i >= 50:\n", " Itau = XX[-p][1] \n", " X = X + dt * f2(X, Itau, r, a, b)\n", " #sans décalage sinon\n", " else:\n", " X = X + dt * f2(X, 0.05, r, a, b)\n", " tt.append(t)\n", " XX.append(X)\n", " return tt, XX" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Evolution du modèle avec taux d'incubation pour un pas N croissant" ] }, { "cell_type": "code", "execution_count": 149, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "N =10 X=(S,I,R,D)=[0.2499218 0.02776904 0.57784733 0.14446183]\n", "N =20 X=(S,I,R,D)=[0.26130585 0.02903398 0.56772813 0.14193203]\n", "N =30 X=(S,I,R,D)=[0.26498509 0.02944278 0.5644577 0.14111443]\n", "N =40 X=(S,I,R,D)=[0.26680393 0.02964486 0.56284096 0.14071024]\n", "N =50 X=(S,I,R,D)=[0.2678887 0.02976538 0.56187674 0.14046918]\n", "N =60 X=(S,I,R,D)=[0.24123236 0.04222103 0.57323728 0.14330932]\n", "N =70 X=(S,I,R,D)=[0.22368427 0.03947568 0.58947204 0.14736801]\n", "N =80 X=(S,I,R,D)=[0.21521869 0.03524511 0.59962897 0.14990724]\n", "N =90 X=(S,I,R,D)=[0.21113074 0.03196282 0.60552516 0.15138129]\n", "N =100 X=(S,I,R,D)=[0.20924834 0.02955866 0.60895441 0.1522386 ]\n" ] } ], "source": [ "#Exemple 2, \n", "for N in range(10, 101, 10):\n", " print(f\"N ={N}\", f\"X=(S,I,R,D)={euler2(f2,N)[1][-1]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q14" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calcul du temps d'incubation par une intégrale à densité.\n", "\n", "Le système différentiel s'écrit désormais :\n", "\n", "$\\begin{cases}\n", "\\frac{d}{dt}S(t)=-rS(t)\\int_{0}^{\\tau}I(t-s)h(s) ds \\\\\n", "\\frac{d}{dt}I(t)=rS(t)\\int_{0}^{\\tau}I(t-s)h(s) ds -(a+b)I(t) \\\\\n", "\\frac{d}{dt}R(t)=aI(t) \\\\\n", "\\frac{d}{dt}D(t)=bI(t) \\\\\n", "\\end{cases}$\n", "\n", "\n", "Conditions initiale, on suppose que pour $t \\in [-\\tau,0]$ on a :\n", "\n", "* $S(t)=0,95$\n", "* $I(t)=0,05$\n", "* $R(t)=D(0)=0$\n" ] }, { "cell_type": "code", "execution_count": 162, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def h(t, mu, sigma):\n", " \"\"\"Fonction de densité de la loi normale centrée réduite d'espérance mu\n", " et d'écart-type sigma\"\"\"\n", " return 1/(sigma * np.sqrt(2*np.pi))*np.exp(-((t -mu) / sigma)**2/2)\n", "\n", "\n", "def f2(X:[float], Itau:float, r:float, a:float, b:float)->np.ndarray: \n", " \"\"\"Fonction définissant l'équation différentielle dX/dt = f(X)\n", " Paramètres :\n", " r, a, b : de type flottant, taux de contagion, guérison, mortalité\n", " Itau est la valeur de integrale(0,tau, I(t-s)*h(s))\n", " X = (S,I,R,D) de type liste de flottants\n", " Valeur renvoyée : de type array\n", " \"\"\"\n", " (S, I, R, D) = X\n", " return np.array([-r*S*Itau, r*S*Itau - (a + b)*I, a*I, b*I])\n", "\n", "\n", "def euler3(f:Callable, N:int)->([float],[np.ndarray]):\n", " # Parametres\n", " tmax = 25. #temps maximal\n", " r = 1. #taux de contagion\n", " a = 0.4 #taux de guérison\n", " b = 0.1 #taux de mortalité\n", " X0 = np.array([0.95, 0.05, 0., 0.])\n", " \n", " #initialisation du schéma d'Euler\n", " dt = tmax/N #pas de temps du schéma d'Euler \n", " p = 50 #nombre de pas de retard\n", " t = 0\n", " X = X0\n", " tt = [t]\n", " XX = [X]\n", " \n", " #paramètres de la fonction de densité\n", " mu = (p * dt) / 2 #espérance (moitié de tau = (p *dt) / 2)\n", " sigma = (p * dt) / 6 #écart-type (tiers de esperance / 2)\n", " # Schéma d’Euler\n", " for i in range(N):\n", " t = t + dt\n", " #décalage si temps >= 50\n", " if i >= 50:\n", " #approximation de Integrale(0,tau,I(t-s)*h(s)) par la méthode des rectangles\n", " Itau = 0\n", " for j in range(p):\n", " Itau += XX[-1 - j][1] * h(j*dt, mu, sigma)\n", " Itau = Itau * dt\n", " X = X + dt * f2(X, Itau, r, a, b)\n", " #pas de décalage\n", " else:\n", " X = X + dt * f2(X, 0.05, r, a, b)\n", " tt.append(t)\n", " XX.append(X)\n", " return tt, XX" ] }, { "cell_type": "code", "execution_count": 163, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "N =10 X=(S,I,R,D)=[0.2499218 0.02776904 0.57784733 0.14446183]\n", "N =20 X=(S,I,R,D)=[0.26130585 0.02903398 0.56772813 0.14193203]\n", "N =30 X=(S,I,R,D)=[0.26498509 0.02944278 0.5644577 0.14111443]\n", "N =40 X=(S,I,R,D)=[0.26680393 0.02964486 0.56284096 0.14071024]\n", "N =50 X=(S,I,R,D)=[0.2678887 0.02976538 0.56187674 0.14046918]\n", "N =60 X=(S,I,R,D)=[0.26055832 0.03199848 0.56595456 0.14148864]\n", "N =70 X=(S,I,R,D)=[0.25512579 0.03011588 0.57180667 0.14295167]\n", "N =80 X=(S,I,R,D)=[0.24896389 0.02925372 0.57742591 0.14435648]\n", "N =90 X=(S,I,R,D)=[0.24098592 0.02913883 0.5839002 0.14597505]\n", "N =100 X=(S,I,R,D)=[0.23287764 0.02837823 0.5909953 0.14774883]\n" ] } ], "source": [ "#Exemple 2, \n", "for N in range(10, 101, 10):\n", " print(f\"N ={N}\", f\"X=(S,I,R,D)={euler3(f2,N)[1][-1]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Méthodes par automates cellulaires" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q15" ] }, { "cell_type": "code", "execution_count": 164, "metadata": {}, "outputs": [], "source": [ "def grille(n) :\n", " \"\"\"Prend en paramètre un entier positif n\n", " Renvoie une liste de n listes de même taille n remplies de 0\"\"\"\n", " M = []\n", " for i in range(n) :\n", " L=[ ]\n", " for j in range(n): L.append(0)\n", " M.append(L)\n", " return M" ] }, { "cell_type": "code", "execution_count": 139, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[0, 0, 0], [0, 0, 0], [0, 0, 0]]" ] }, "execution_count": 139, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grille(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q16" ] }, { "cell_type": "code", "execution_count": 183, "metadata": {}, "outputs": [], "source": [ "import random as rd \n", "\n", "def init(n:int)->[[int]]:\n", " \"\"\"Initialise une grille de taille n remplie de 0\n", " avec une cellule choisie aléatoirement qui est infectée (valeur 1)\n", " \"\"\"\n", " g = grille(n)\n", " x, y = rd.randrange(0, n), rd.randrange(0, n)\n", " g[y][x] = 1\n", " return g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q17" ] }, { "cell_type": "code", "execution_count": 184, "metadata": {}, "outputs": [], "source": [ "def compte(G:[[int]])->[int]:\n", " \"\"\"Prend en paramètre une grille G\n", " Renvoie une liste des effectifs de chaque état :\n", " 0 : sain, 1: infecté, 2: rétabli, 3 : décédé\"\"\"\n", " etat = [0 for _ in range(4)]\n", " n = len(G)\n", " for y in range(n):\n", " for x in range(n):\n", " etat[G[y][x]] += 1\n", " return etat" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Q18 et Q19" ] }, { "cell_type": "code", "execution_count": 185, "metadata": {}, "outputs": [], "source": [ "def est_exposee(G:[[int]], i:int, j:int)->True:\n", " \"\"\"Retourne un booleen indiquant si une case en ligne i et colonne j\n", " comporte au moins une case infectée dans son voisinage \"\"\"\n", " n = len(G)\n", " if i == 0 and j == 0:\n", " return (G[0][1]-1)*(G[1][1]-1)*(G[1][0]-1) == 0\n", " elif i == 0 and j == n-1:\n", " return (G[0][n-2]-1)*(G[1][n-2]-1)*(G[1][n-1]-1) == 0\n", " elif i == n-1 and j == 0:\n", " return (G[n-1][1]-1)*(G[n-2][1]-1)*(G[n-2][0]-1) == 0\n", " elif i == n-1 and j == n-1:\n", " return (G[n-1][n-2]-1)*(G[n-2][n-2]-1)*(G[n-2][n-1]-1) == 0\n", " elif i == 0:\n", " return (G[0][j+1]-1)*(G[0][j-1]-1)*(G[1][j-1]-1)*(G[1][j]-1)*(G[1][j+1]-1)== 0\n", " elif i == n-1:\n", " return (G[n-1][j-1]-1)*(G[n-2][j-1]-1)*(G[n-2][j]-1)*(G[n-2][j+1]-1)*(G[n-1][j+1]-1) == 0\n", " elif j == 0:\n", " return (G[i-1][0]-1)*(G[i-1][1]-1)*(G[i][1]-1)*(G[i+1][1]-1)*(G[i+1][0]-1) == 0\n", " elif j == n-1:\n", " return (G[i-1][n-1]-1)*(G[i-1][n-2]-1)*(G[i][n-2]-1)*(G[i+1][n-2]-1)*(G[i+1][n-1]-1) == 0\n", " else:\n", " return (G[i-1][j-1]-1)*(G[i-1][j]-1)*(G[i-1][j+1]-1)*(G[i][j-1]-1)*(G[i][j+1]-1) * (G[i+1][j-1]-1)*(G[i+1][j]-1)*(G[i+1][j+1]-1) == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q20" ] }, { "cell_type": "code", "execution_count": 186, "metadata": {}, "outputs": [], "source": [ "import random as rd\n", "\n", "def bernoulli(p:float)->int:\n", " \"\"\"Simule une va de Bernoulli de paramètre p\"\"\"\n", " if rd.random() <= p:\n", " return 1\n", " return 0" ] }, { "cell_type": "code", "execution_count": 187, "metadata": {}, "outputs": [], "source": [ "def suivant(G:[[int]], p1:float, p2:float)->None:\n", " \"\"\"Fait évoluer une grille G selon les règles de transition\n", " avec les probabilités p1 et p2\"\"\"\n", " n = len(G)\n", " for i in range(n):\n", " for j in range(n):\n", " etat = G[i][j]\n", " if etat == 1:\n", " etat += 2 - bernoulli(1 - p1)\n", " elif etat == 0 and est_exposee(G, i, j):\n", " etat = bernoulli(p2)\n", " G[i][j] = etat " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q21" ] }, { "cell_type": "code", "execution_count": 188, "metadata": {}, "outputs": [], "source": [ "def simulation(n:int, p1:float, p2:float)->[float]:\n", " \"\"\"Réalise une simulation complètee pour une grille nxn\n", " avec les probabilités p1 et p2\n", " et renvoie la liste des fréquences des 4 états\"\"\"\n", " #initialisation de la grille\n", " G = init(n)\n", " #tant qu'il y a au moins une case infectée, la grille peut évoluer\n", " while compte(G)[1] >= 1: \n", " #mise à jour de la grille\n", " suivant(G, p1, p2)\n", " #renvoie les fréquences de chaque état\n", " return [e/(n*n) for e in compte(G)]" ] }, { "cell_type": "code", "execution_count": 191, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.77, 0.0, 0.15, 0.08]" ] }, "execution_count": 191, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation(10, 0.4, 0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q22" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A la fin d'une simulation on a x1 = 0 et x0 + x1 + x2 + x3 = 1 et\n", "x_atteinte = x2 + x3 puisque les cases infectées évoluent vers l'état rétabli ou décédé qui sont des états absorbants." ] }, { "cell_type": "code", "execution_count": 207, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "p1 = 0.5\n", "n = 50\n", "nbsimul = 100\n", "pp2 = np.linspace(0, 1, 20)\n", "moy = [sum(sum(simulation(n,p1,p2)[2:]) for i in range(nbsimul))/nbsimul for p2 in pp2]\n", "plt.plot(pp2, moy)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 150, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.002500000000000002,\n", " 0.003150000000000002,\n", " 0.004350000000000003,\n", " 0.007024999999999992,\n", " 0.013599999999999984,\n", " 0.03582499999999998,\n", " 0.1369249999999999,\n", " 0.3340000000000002,\n", " 0.6687249999999999,\n", " 0.6690249999999999,\n", " 0.773125,\n", " 0.7495250000000003,\n", " 0.8457500000000004,\n", " 0.8475249999999999,\n", " 0.8710249999999996,\n", " 0.8931999999999997,\n", " 0.955525,\n", " 0.9468250000000001,\n", " 0.9462250000000005,\n", " 0.9601]" ] }, "execution_count": 150, "metadata": {}, "output_type": "execute_result" } ], "source": [ "moy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q23" ] }, { "cell_type": "code", "execution_count": 202, "metadata": {}, "outputs": [], "source": [ "def seuil(Lp2:[float], Lxa:[float], s = 0.5)->[float]:\n", " \"\"\"Meilleur encadrement possible de la valeur de x égale à s = 0.5\n", " par dichotomie à partir des listes de probabilités Lp2 et de valeurs\n", " atteintes Lxa\"\"\"\n", " debut, fin = 0, len(Lp2)\n", " while fin - debut > 1:\n", " m = (debut + fin)//2\n", " if Lxa[m] > s:\n", " fin = m\n", " else:\n", " debut = m\n", " return [Lxa[debut], Lxa[fin]], [Lp2[debut], Lp2[fin]]\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test de la fonction précédente sur un encadrement de $\\sqrt{2}$ solution de $x^2=2$ dans l'intervalle $[1;2]$" ] }, { "cell_type": "code", "execution_count": 199, "metadata": {}, "outputs": [], "source": [ "x = np.linspace(1, 2, 1001)\n", "y = x**2" ] }, { "cell_type": "code", "execution_count": 200, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([1.9993960000000004, 2.002225], [1.4140000000000001, 1.415])" ] }, "execution_count": 200, "metadata": {}, "output_type": "execute_result" } ], "source": [ "seuil(x, y, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Q24" ] }, { "cell_type": "code", "execution_count": 204, "metadata": {}, "outputs": [], "source": [ "def init_vac(n:int, q:float)->[[int]]:\n", " \"\"\"Immunise aléatoirement une fraction q\n", " d'une grille de taille n\"\"\"\n", " G = init(n)\n", " nvac = int(q * n**2)\n", " k = 0\n", " while k < nvac:\n", " i = rd.randrange(n)\n", " j = rd.randrange(n)\n", " if G[i][j] == 0:\n", " G[i][j] = 2\n", " k += 1\n", " return G" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On ne peut pas supprimer le test `if G[i][j] == 0:` car on effectue des tirages avec remise parmi les $n^2$ cases et donc on peut retomber sur une case déjà immunisée" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'appel `init_vac(5, 0.2)` retourne une grille de $25$ cases avec $25 \\times 0,2 = 5$ cases immunisées choisies aléatoirement." ] }, { "cell_type": "code", "execution_count": 205, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[0, 0, 0, 0, 2],\n", " [0, 0, 0, 0, 0],\n", " [0, 0, 1, 0, 2],\n", " [2, 0, 0, 0, 0],\n", " [0, 0, 0, 2, 2]]" ] }, "execution_count": 205, "metadata": {}, "output_type": "execute_result" } ], "source": [ "init_vac(5, 0.2)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.5 64-bit", "language": "python", "name": "python38564bit5df26436d9ea44868d95f1b30c3d2682" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 1 }