{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Variabilité\n", "===========\n", "\n", "**Date:** vendredi 6 septembre 2024\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Capacité numérique:\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "Simuler, à l’aide d’un langage de programmation ou d’un tableur,
\n", "un processus aléatoire permettant de caractériser la variabilité
\n", "de la valeur d’une grandeur composée
\n", "

\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Outils\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On rappelle quelques bases fondamentales pour l'utilisation de python\n", "en sciences physiques. En préambule, rappelons que `python` utilise\n", "des règles d'**indentation** strictes.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Modules\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On aura besoin de charger des bibliothèques nommées `modules` pour\n", "accéder à certaines fonctions.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les fonctions qu'elle apporte seront appelées par `math.nom_de_la_fonction`\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Variables et affectation\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut manipuler des entiers, des flottants, sur lesquels on peut\n", "utiliser les opérations usuelles et qu'on affecte à des variables par\n", "`=`. La structure avec `f'` permet par exemple de former une chaîne de\n", "caractères utilisant les valeurs des variables.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5 7\n", "la valeur de d est: 5\n", "le quotient par / de deux entiers est un flottant \"d/2\": 2.5\n", "la division euclidienne est obtenue par \"d//2\": 2\n", "son reste est obtenu par \"d%2\": 1\n", "on élève à une puissance en utilisant \"pow\" ou \"**\": 16 ou 32\n", "on peut préciser l'approximation décimale des flottants: ln(12) = 2.485\n", "on utilise une notation scientifique avec \".2e\" = 2.48e+00" ] } ], "source": [ "a = 2\n", "b,c = 3,5\n", "d = a + b\n", "print(d, a + c)\n", "print(f'la valeur de d est: {d}')\n", "print(f'le quotient par / de deux entiers est un flottant \"d/2\": {d/2}')\n", "print(f'la division euclidienne est obtenue par \"d//2\": {d//2}')\n", "print(f'son reste est obtenu par \"d%2\": {d%2}')\n", "print(f'on élève à une puissance en utilisant \"pow\" ou \"**\": {pow(a,4)} ou {a**5}')\n", "\n", "print(f'on peut préciser l\\'approximation décimale des flottants: ln(12) = {math.log(12):.3f}')\n", "print(f'on utilise une notation scientifique avec \".2e\" = {math.log(12):.2e}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sur les chaînes de caractères, on utilisera par exemples les\n", "opérations suivantes:\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"+\" désigne la concaténation: bonjour la HX2\n", "\"*\" n désigne la répétition n fois: bonjourbonjourbonjourbonjourbonjour" ] } ], "source": [ "a = \"bonjour\"\n", "b = \" \"\n", "c = \"la HX2\"\n", "print(f'\"+\" désigne la concaténation: {a+b+c}')\n", "print(f'\"*\" n désigne la répétition n fois: {a*5}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Listes et slicing\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On manipulera souvent des listes de variables, de types\n", "variables. Comme tous les objets en `python`, elles possèdent des\n", "`méthodes` accessibles par la notation `objet.methode`:\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "on accède à un élément de position donnée par liste[0]: \"bonjour\n", "liste[-1] désigne le dernier élément: \"2\n", "les opérateurs + et * n joignent ou dupliquent les éléments d'une liste:(['bonjour', 3.5, 2, 'bonjour', 3.5, 2], ['bonjour', 3.5, 2, 'bonjour', 3.5, 2, 'bonjour', 3.5, 2])\n", "le nombre d'éléments est donné par \"len\": 3" ] } ], "source": [ "a = \"bonjour\"\n", "b = 3.5\n", "c = 2\n", "liste = [a,b]\n", "liste.append(c)\n", "print(f'on accède à un élément de position donnée par liste[0]: \"{liste[0]}')\n", "print(f'liste[-1] désigne le dernier élément: \"{liste[2]}')\n", "print(f'les opérateurs + et * n joignent ou dupliquent les éléments d\\'une liste:{liste+liste, 3*liste}')\n", "print(f'le nombre d\\'éléments est donné par \"len\": {len(liste)}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut former des listes en utilisant des boucles `for`, des\n", "conditions `if`.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]" ] } ], "source": [ "autre_liste = [3*i for i in range(10) if 2*i<19]\n", "print(autre_liste)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut «trancher» les listes (slice en anglais) pour n'en prendre que\n", "certains éléments en choisissant le premier, le dernier, et\n", "l'incrément.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "un élément sur deux entre le deuxième et le septième: [3, 9, 15]\n", "un élément sur trois entre le premier et l'avant dernier: [0, 9, 18]\n", "tous les éléments supérieurs à 13: [15, 18, 21, 24, 27]" ] } ], "source": [ "print(f'un élément sur deux entre le deuxième et le septième: {autre_liste[1:6:2]}')\n", "print(f'un élément sur trois entre le premier et l\\'avant dernier: {autre_liste[:-2:3]}')\n", "print(f'tous les éléments supérieurs à 13: {[ i for i in autre_liste if i > 13]}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Numpy\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour manipuler des données numériques, tracer des courbes, on\n", "utilisera un type de liste particulier, les `numpy.array` facilitant\n", "les manipulations d'un grand nombre de données en parallèle. On en\n", "fait ici un alias `np` plus court à écrire.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "les opérateurs usuels comme \"+,*\" s'appliquent à chacun des éléments de la liste: [ 2 3 4 5 6 7 8 9 10 11]\n", "3.0 4 0" ] } ], "source": [ "import numpy as np\n", "\n", "abscisses = np.array(range(10))\n", "ordonnees = abscisses + 2\n", "ordonnees2 = abscisses *2\n", "ordonnees3 = abscisses * abscisses\n", "ordonnees4 = np.sqrt(abscisses)\n", "print(f'les opérateurs usuels comme \"+,*\" s\\'appliquent à chacun des éléments de la liste: {ordonnees}' )\n", "print(ordonnees4[-1],ordonnees3[2],ordonnees2[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fonctions et boucles\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On définit des fonctions avec `def`, le corps de la fonction doit\n", "ensuite être indenté de 4 espaces, tout comme les éléments des\n", "boucles et structures conditionnelles.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "12\n", "trop petit\n", "8" ] } ], "source": [ "def ma_fonction(ma_variable):\n", " seuil = 8\n", " if ma_variable > seuil:\n", " return ma_variable\n", " else:\n", " print(\"trop petit\")\n", " return seuil\n", "print(ma_fonction(12))\n", "print(ma_fonction(5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Courbes\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le module `matplotlib` permet de tracer des ensembles de points: on\n", "utilisera le plus souvent des `np.array` pour les abscisses et les\n", "ordonnées. La méthode `np.linspace` permet d'utiliser un grand nombre\n", "de points d'abscisses, uniformément répartis dans un intervalle.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# Out[28]:" ] }, { "data": { "image/png": "", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "xmin = 0\n", "xmax = 12\n", "Npoints = 200\n", "AbscissesII = np.linspace(xmin,xmax,Npoints)\n", "OrdonneesII = np.power(AbscissesII,3)\n", "OrdonneesIII = np.power(AbscissesII,.5)\n", "\n", "fig,(axeII,axeIII) = plt.subplots(2,1) # pour organiser plusieurs graphes sur unemême figure \n", "axeII.plot(AbscissesII,OrdonneesII,label=\"cube\")\n", "axeII.legend()\n", "axeIII.plot(AbscissesII,OrdonneesIII,label=\"racine\")\n", "axeIII.legend()\n", "fig.suptitle(\"Ceci est un titre\")\n", "axeII.set_xlabel(\"abscisses\")\n", "axeII.set_xlabel(None)\n", "axeIII.set_xlabel(\"abscisses\")\n", "axeII.set_ylabel(\"ordonnees\")\n", "axeIII.set_ylabel(\"ordonnees\")\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On pourra consulter [https://matplotlib.org/cheatsheets/>](https://matplotlib.org/cheatsheets/>)pour plus de\n", "précisions.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chute libre\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dispositif expérimental\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On cherche à mesurer l'accélération de la pesanteur $g$ en étudiant la\n", "chute libre d'un corps dans le vide. Le dispositif consiste en:\n", "\n", "- un objet de masse $m$ en chute libre dans le vide;\n", "- est lâché sans vitesse initiale d'une altitude $h_1$;\n", "- sa vitesse $v$ est mesurée par un capteur spécifique quand il passe\n", " en un point d'altitude $h_2 < h_1$.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Modèle\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Montrer qu'on a:\n", "\n", "\\begin{equation*}\n", "v^2 = 2 g (h_1 -h_2)\n", "\\end{equation*}\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Incertitudes\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On cherche à observer l'effet sur l'incertitude sur la mesure de $g$ des\n", "sources d'incertitude suivantes:\n", "\n", "- incertitude sur les lectures des altitudes $h_1$ et $h_2$ sur une règle;\n", "\n", "- incertitude sur la mesure de la vitesse par un capteur.\n", "\n", "On **simule** ici numériquement les répartitions des valeurs mesurées\n", "pour ces grandeurs si on reproduisait un grand nombre de fois la\n", "manipulation, en supposant connue la loi de répartition des erreurs.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Lecture des altitudes sur une règle\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On suppose une répartition uniforme d'erreurs entre deux graduations\n", "de la règle distantes de $2 \\Delta h$.\n", "\n", "On rappelle que l'incertitude-type vaut alors:\n", "\n", "\\begin{equation*}\n", " \\Delta h/(\\sqrt{3})\n", "\\end{equation*}\n", "\n", "On utilisera la fonction `random.random_sample` pour tirer un nombre\n", "flottant aléatoire correspondant à une altitude lue entre deux\n", "graduations de la règle.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Mesure de la vitesse\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On suppose une répartition d'erreurs autour d'une vitesse $v$ donnée\n", "par une loi normale d'incertitude-type $\\Delta v$.\n", "\n", "On utilisera la fonction `random.normal` pour tirer un nombre flottant\n", "aléatoire correspondant cette loi normale.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fonctions permettant de réaliser les tirages aléatoires\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On utilise les fonctions offertes par `numpy.random`\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# tirage aléatoire pour une loi normale de moyenne X[0] et d'incertitude-type X[1]\n", "def tirage_normal(X):\n", " return X[0] + X[1]*np.random.normal()\n", "\n", "# tirage aléatoire pour une répartition uniforme entre X[0] et X[1]\n", "def tirage_uniforme(X):\n", " return X[0] + (X[1]-X[0])*np.random.random_sample()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Paramètres\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On suppose pour cette simulation connue les valeurs vraies de $g$,\n", "$h_1$ et $h_2$. On en déduit celle de $v$.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Accélération de la pesanteur\n", "g = 9.80665 #en m/s, valeur normale de la CGPM\n", "\n", "# Hauteur de chute\n", "h1 = 3 # en m\n", "h2 = 2 # en m\n", "h0 = h1-h2\n", "Deltah = 5e-3 # en m, demi-largeur de la lecture de h\n", "\n", "# Vitesse atteinte\n", "v0 = np.sqrt(2* g * h0) # en m/s\n", "Deltav = 1e-2 # en m/s, incertitude-type sur la mesure de v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simulation des mesures\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On crée des listes `numpy array` de mesures de $h_1$, $h_2$ et $v$\n", "pour faciliter leur manipulation.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Mesures\n", "N = 10000 # nombre de points de mesure\n", "g_calculee = np.array([])\n", "\n", "h1min = h1-Deltah\n", "h1max = h1+Deltah\n", "h2min = h2-Deltah\n", "h2max = h2+Deltah\n", "\n", "MesuresV = np.array([tirage_normal([v0,Deltav]) for i in range(N)])\n", "MesuresH1 = np.array([tirage_uniforme([h1min,h1max]) for i in range(N)])\n", "MesuresH2 = np.array([tirage_uniforme([h2min,h2max]) for i in range(N)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Étude de $g$\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On calcule les valeurs de $g$, leur valeur moyenne et l'écart-type de\n", "leur distribution.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "moyenne des valeurs calculées de g: 9.807e+00\n", "incertitude-type sur les valeurs calculées de g: 5.988e-02" ] } ], "source": [ "# Valeurs de $h = h1-h2\n", "MesuresH = MesuresH1 - MesuresH2\n", "# On pourrait faire la même chose sans numpy array avec:\n", "# MesuresH = [MesuresH1[i] - MesuresH2[i] for i in range(N)]\n", "# ou\n", "# for i in range(N)\n", "# MesuresH[i] = MesuresH1[i] - MesuresH2[i]\n", "\n", "# Valeurs calculées de g = v^2/(2h)\n", "g_calculees = MesuresV**2/(2*MesuresH)\n", "g_moyenne = np.average(g_calculees)\n", "Stdevg = np.std(g_calculees,ddof=1)\n", "print(f'moyenne des valeurs calculées de g: {g_moyenne:.3e}')\n", "print(f'incertitude-type sur les valeurs calculées de g: {Stdevg:.3e}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'argument `ddof=1` passé à la méthode `std` de `numpy` est\n", "nécessaire pour utiliser le terme en $\\sqrt{N-1}$ dans la\n", "définition de l'écart-type corrigé:\n", "\n", "\\begin{equation*}\n", " \\sigma = \\sqrt{\\frac{1}{N-1}{\\sum_{i=1}^N \\left(m_i-\\overline{m}\\right)^2}},\n", "\\end{equation*}\n", "\n", "On affiche un histogramme de ces valeurs.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# Out[14]:" ] }, { "data": { "image/png": "", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "histo,(axehisto)=plt.subplots(1,1)\n", "axehisto.hist(g_calculees, bins = 50, color = 'blue', edgecolor = 'black')\n", "axehisto.set_xlabel('g (m/s^2)')\n", "axehisto.set_ylabel('effectif')\n", "histo.suptitle(f'Pour {N} iterations')\n", "histo.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Questions\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manipulations élémentaires\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Créer une liste nommée `liste1` contenant les entiers pairs entre\n", " $4 et 20$.\n", "\n", "1. Créer une liste `liste2` contenant leurs produits par $3$.\n", "\n", "2. Transformer ces listes en `numpy.array` et en déduire leurs\n", " produits termes à terme de leurs éléments.\n", "\n", "1. Créer une fonction `somme(n)` qui renvoie la somme des $1/p^2$\n", " pour $p \\in [1;n]$. On peut montrer que `somme(n)` tend vers\n", " $\\pi^2/6$ quand $n\\to\\infty$.\n", " \n", " Calculer la différence relative pour quelques grandeurs valeurs de $n$, et\n", " l'afficher en notation scientifique. La valeur de $\\pi$ est\n", " accessible par `np.pi`.\n", "\n", "2. Tracer la courbe représentative de $x\\mapsto e^{\\left(-x/2\\right)}\n", " \\cos{\\left(2\\pi x\\right)}$ pour $x \\in [0;5]$. On utilisera les\n", " fonctions `np.exp` et `np.cos` (dont les arguments sont des\n", " radians).\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Incertitudes composées\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Afficher l'écart-type relative des mesures de $g$.\n", "\n", "2. Afficher les incertitudes-types et les incertitudes-types relatives\n", " sur $v$, $h1$, $h2$.\n", "\n", "3. Afficher l'écart-type des valeurs mesurées de $h$ et comparer à\n", " l'incertitude-type composée à partir des incertitudes-types de\n", " $h_1$ et $h_2$. Calculer l'incertitude-type relative sur $h$.\n", "\n", "4. Déterminer et afficher l'incertitude-type relative composée sur $g$\n", " en fonction des incertitudes-types relatives précédentes et\n", " comparer à l'écart-type relatif sur $g$.\n", " \n", " On a $g = v^2/(2 h)$, soit $\\Delta g/g = \\sqrt{4 (\\Delta v/v)^2 +\n", " (\\Delta h/h)^2}$, qu'on compare à l'écart-type des valeurs\n", " calculées de $g$.\n", "\n", "5. Augmenter d'un facteur 10 la précision sur la vitesse? Quel est\n", " l'effet sur la précision de la détermination de $g$. Commenter.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Effet du nombre de mesures\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Changer le nombre d'itérations $N$ d'un facteur 100 dans un sens ou\n", " dans l'autre. Cela change-t-il les résultats précédents?\n", " \n", " On passe de $N=1e4$ à $Np=100$:\n", "\n", "1. Pour un jeu de $N = 1e4$ mesures, effectuer des moyennes de $m =\n", " 100$ et étudier l'incertitude-type des $N/m = 100$ mesures\n", " obtenues. Vérifier qu'il est réduit d'un rapport $\\sqrt{m}$.\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.12.3" }, "org": null }, "nbformat": 4, "nbformat_minor": 1 }