{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TP0 Introduction\n",
    "\n",
    "### Table of Contents\n",
    "\n",
    "* [1. Introduction to Jupyter notebooks](#chapter1)\n",
    "    * [1.1 Markdown cell](#section_1_1)\n",
    "    * [1.2  Python cell](sSection_1_2)\n",
    "    \n",
    "* [2. Introduction to Python](#chapter2)\n",
    "    * [2.1 Variables and types, list and np.array](#section_2_1)\n",
    "        * [2.1.1. Variable](#section_2_1_1)\n",
    "        * [2.1.2. List](#section_2_1_2)\n",
    "        * [2.1.3. Type `array`](#section_2_1_3)\n",
    "    * [2.2  basic operations](#section_2_2)\n",
    "        * [2.2.1 Operations on figures](#section_2_2_1)\n",
    "        * [2.2.2 Operations on a matrix](#section_2_2_2)\n",
    "    * [2.3 `for`-loop and `if...else`](#section_2_3)\n",
    "    * [2.4 Define your function](#section_2_4)\n",
    "    * [2.5 Graphs](#section_2_5)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Introduction to Jupyter notebook<a class=\"anchor\" id=\"chapter1\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To launch Jupyter, you need to run the command in a terminal:\n",
    "\n",
    "`jupyter notebook`\n",
    "\n",
    "This will automatically open a web browser where you can work. The main tab represents the file tree starting from the directory where the command was executed.\n",
    "\n",
    "Notebooks are composed of cells containing code (in Python) or text (plain or formatted with Markdown markup). These notebooks allow for interactive calculations in Python and are an excellent tool for teaching.\n",
    "\n",
    "You can edit a cell by double-clicking on it, and evaluate it by pressing **Ctrl+Enter** (you will also often use **Shift+Enter** to evaluate and move to the next cell). The buttons in the toolbar will be very useful; hover over them to display a tooltip if their icon is not clear enough.\n",
    "\n",
    "Don't forget to save your work from time to time, even though Jupyter performs regular automatic saves."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can click on *Help -> User Interface Tour* or *Help -> Keyboard Shortcuts* to get explanations[5]."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 1** : Delete the following cell:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 2** : Add a Python cell below"
   ]
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:11:15.477711Z",
     "start_time": "2025-01-22T09:11:15.474249Z"
    }
   },
   "cell_type": "code",
   "source": "print(\"Hello World\")",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello World\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1  Markdown cell <a class=\"anchor\" id=\"section_1_1\"></a>\n",
    "*Markdown* is a text format that allows minimal formatting. It enables you to quickly:\n",
    "- create lists.\n",
    "- make *italics*, **bold**, ~~strikethrough~~, etc.\n",
    "- create [links](https://fr.wikipedia.org/wiki/Markdown)\n",
    "- write mathematical formulas using $$\\LaTeX$$ (see [here](http://www.tuteurs.ens.fr/logiciels/latex/maths.html#s2) for a quick introduction to $$\\LaTeX$$).\n",
    "\n",
    "Citations:\n",
    "[1] https://fr.wikipedia.org/wiki/Markdown"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 3** : change the first word to *italics* and the second word to **bold** "
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "*first word*\n",
    "\n",
    "**second word**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 4** : Type a simple formula in $$\\LaTeX$$ (for example :  integration, expectation of a random variable)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "$\\mathbb{E}[X]=\\frac{1}{\\lambda}$\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.2 Python cell<a class=\"anchor\" id=\"section_1_2\"></a>\n",
    "The following cell is a python cell. You can run it with maj+ Enter (or the triangular icon : \"run the selected cell and advance\" or go to the run tab)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 5** : Run the next cell. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:13:39.085033Z",
     "start_time": "2025-01-22T09:13:39.081416Z"
    }
   },
   "source": [
    "# This is a Python comment. \n",
    "# Comment your code :\n",
    "# Code should be readable and understandable by other users\n",
    "#\n",
    "\n",
    "print(\"hello world !\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world !\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 6** : Next cell is formatted in markdown. Switch to a Python cell. "
   ]
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:14:10.188568Z",
     "start_time": "2025-01-22T09:14:10.185558Z"
    }
   },
   "cell_type": "code",
   "source": "print(\"hello world !\")",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world !\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 7** : Turn the next cell into a markdown cell. "
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "Oops! This is a Markdown cell"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Introduction to Python<a class=\"anchor\" id=\"chapter2\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Possible resources (mostly for numpy and matplotlib) : \n",
    "-  https://numpy.org/doc/2.2/user/absolute_beginners.html\n",
    "-  https://file.cz123.top/5textbook/CODING/Numerical_Python.pdf\n",
    "-  https://cs231n.github.io/python-numpy-tutorial/\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import a library. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:14:38.458151Z",
     "start_time": "2025-01-22T09:14:37.524456Z"
    }
   },
   "source": [
    "# Import the library numpy\n",
    "import numpy\n",
    "\n",
    "# Import the  library numpy and give it a diminutive \n",
    "import numpy as np\n",
    "\n",
    "# Import  part of a  library\n",
    "from scipy.stats import norm, multivariate_normal"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 Variables and types, list and np.array<a class=\"anchor\" id=\"section_2_1\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.1. Variable <a class=\"anchor\" id=\"section_2_1_1\"></a> "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:14:40.801476Z",
     "start_time": "2025-01-22T09:14:40.798177Z"
    }
   },
   "source": [
    "#Integer\n",
    "a = 4\n",
    "print(\"a = \", a, \"\\t\\t\\t\\t its type is\", type(a))\n",
    "\n",
    "# Float\n",
    "a = 3.5\n",
    "print(\"a = \", a, \"\\t\\t\\t its  type is\", type(a))\n",
    "a = 1e7  # = 10^7, --> float\n",
    "print(\"a = \", a, \"\\t\\t its type is\", type(a))\n",
    "a = np.pi\n",
    "print(\"a = \", a, \"\\t\\t its type is\", type(a))\n",
    "\n",
    "# Boolean\n",
    "a = True\n",
    "print(\"a = \", a, \"\\t\\t\\t its type is\", type(a))\n",
    "\n",
    "# String\n",
    "a = \"Hello World!\"\n",
    "print(\"a = \", a, \"\\t\\t its type is\", type(a))\n",
    "\n",
    "# Lists (mutable)\n",
    "a = [1, 2, 3]\n",
    "print(\"a = \", a, \"\\t\\t\\t its type is\", type(a))\n",
    "\n",
    "# Tuples (immutable)\n",
    "a = (1.5, [1, 2], \"coucou\")\n",
    "print(\"a = \", a, \"\\t its type is\", type(a))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a =  4 \t\t\t\t its type is <class 'int'>\n",
      "a =  3.5 \t\t\t its  type is <class 'float'>\n",
      "a =  10000000.0 \t\t its type is <class 'float'>\n",
      "a =  3.141592653589793 \t\t its type is <class 'float'>\n",
      "a =  True \t\t\t its type is <class 'bool'>\n",
      "a =  Hello World! \t\t its type is <class 'str'>\n",
      "a =  [1, 2, 3] \t\t\t its type is <class 'list'>\n",
      "a =  (1.5, [1, 2], 'coucou') \t its type is <class 'tuple'>\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.2. List   <a class=\"anchor\" id=\"section_2_1_2\"></a>\n",
    "Run the following cells : "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:15:47.717601Z",
     "start_time": "2025-01-22T09:15:47.714511Z"
    }
   },
   "source": [
    "#Empty list\n",
    "L = []\n",
    "print(\"The empty list : L =\", L, \"\\n\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The empty list : L = [] \n",
      "\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:15:49.504901Z",
     "start_time": "2025-01-22T09:15:49.502Z"
    }
   },
   "source": [
    "L = [1, 2, 3, 4, 5]\n",
    "print(\"L =\", L)\n",
    "\n",
    "#Indices in Python start at zero !\n",
    "print(\"the first element is\", L[0])\n",
    "\n",
    "#Another way to to access the last element of a list :\n",
    "print(\"The last element is \", L[-1])\n",
    "\n",
    "# Access to a sublist \n",
    "print(\"L contains the sublist\", L[1:4])"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L = [1, 2, 3, 4, 5]\n",
      "the first element is 1\n",
      "The last element is  5\n",
      "L contains the sublist [2, 3, 4]\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:15:51.173918Z",
     "start_time": "2025-01-22T09:15:51.170290Z"
    }
   },
   "source": [
    "L = [1, 2, 3, 4, 5]\n",
    "print(\"L =\", L)\n",
    "\n",
    "# my_liste.append()\n",
    "L.append(100)\n",
    "print(\"L =\", L)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L = [1, 2, 3, 4, 5]\n",
      "L = [1, 2, 3, 4, 5, 100]\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.3. Type `array` :  <a class=\"anchor\" id=\"section_2_1_3\"></a>\n",
    "In addition to these basic types, we work with the numpy library, which introduces the array type. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 8** : import numpy and use  `np.array` to define a  matrix $a$\n",
    "\n",
    "$a=\\begin{pmatrix}\n",
    "1 & 2 \\\\\n",
    "3 & 4 \\\\\n",
    "\\end{pmatrix}$\n",
    "\n",
    "Display the matrix and its type."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:16:18.283762Z",
     "start_time": "2025-01-22T09:16:18.280869Z"
    }
   },
   "source": [
    "# Your answer for Q8:\n",
    "a = np.array([[1, 2], [3, 4]])\n",
    "print(a)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 Basic operations <a class=\"anchor\" id=\"section_2_2\"></a>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.1 Operations on numbers<a class=\"anchor\" id=\"section_2_2_1\"></a>\n",
    "\n",
    "Operators :  `+,-,/,*`, and many other ones using the packages `math` and `numpy`.\n",
    "\n",
    "Package `math`: https://docs.python.org/3/library/math.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 9** : display $e$ and  $log(e)$. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:01.140658Z",
     "start_time": "2025-01-22T09:17:01.138212Z"
    }
   },
   "source": [
    "import math\n",
    "\n",
    "print(\"e = \", math.exp(1))\n",
    "print(\"log(e) = \", math.log(math.exp(1)))\n",
    "\n",
    "print(\"e = \", np.exp(1))\n",
    "print(\"log(e) = \", np.log(np.exp(1)))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "e =  2.718281828459045\n",
      "log(e) =  1.0\n",
      "e =  2.718281828459045\n",
      "log(e) =  1.0\n"
     ]
    }
   ],
   "execution_count": 14
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.2 Operations on an array<a class=\"anchor\" id=\"section_2_2_2\"></a>"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:03.680124Z",
     "start_time": "2025-01-22T09:17:03.675137Z"
    }
   },
   "source": [
    "# Creation of a 2 x 3 array filled with zeroes:\n",
    "A = np.zeros([2, 3])\n",
    "print(\"A = \\n\", A)\n",
    "\n",
    "# Creation of a 2 x 3 array filled with ones\n",
    "B = np.ones([2, 3])\n",
    "print(\"\\nB = \\n\", B)\n",
    "\n",
    "# Identity matrix\n",
    "C = np.eye(3)  # alternative :  np.identity(3)\n",
    "print(\"\\n C = \\n\", A)\n",
    "\n",
    "# arange \n",
    "print('np.arange(3) =', np.arange(3))\n",
    "print('np.arange(2,5)=', np.arange(2, 5))\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A = \n",
      " [[0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "\n",
      "B = \n",
      " [[1. 1. 1.]\n",
      " [1. 1. 1.]]\n",
      "\n",
      " C = \n",
      " [[0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "np.arange(3) = [0 1 2]\n",
      "np.arange(2,5)= [2 3 4]\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 10**\n",
    "Create an array that contains 10 evenly spaced numbers over [3,9].\n",
    "<details>\n",
    "<summary>Click here for a hint</summary>\n",
    "Use linspace https://numpy.org/doc/2.1/reference/generated/numpy.linspace.html\n",
    "</details>\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:27.970224Z",
     "start_time": "2025-01-22T09:17:27.966232Z"
    }
   },
   "source": [
    "space = np.linspace(3, 9, 10)\n",
    "print(space)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3.         3.66666667 4.33333333 5.         5.66666667 6.33333333\n",
      " 7.         7.66666667 8.33333333 9.        ]\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Matrix multiplication \n",
    "**Beware**, `a*b` , where `a` and `b` are 2-dimensional arrays, corresponds to  elementwise multiplication whereas matrix multiplication can be performed with  `np.dot` or `@`.\n",
    "The official documentation says `@`is to be preferred. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:44.926867Z",
     "start_time": "2025-01-22T09:17:44.922056Z"
    }
   },
   "source": [
    "a = np.array([[1, 2], [3, 4]])\n",
    "b = np.eye(2)\n",
    "\n",
    "print(\"a=\\n\", a)\n",
    "print(\"b=\\n\", b)\n",
    "\n",
    "print(\" a*b = \\n \", a * b)\n",
    "print(\" np.dot(a,b) = \\n\", np.dot(a, b))\n",
    "print(\" a@b = \\n\", a @ b)  # equivalent to np.matmul(a,b)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a=\n",
      " [[1 2]\n",
      " [3 4]]\n",
      "b=\n",
      " [[1. 0.]\n",
      " [0. 1.]]\n",
      " a*b = \n",
      "  [[1. 0.]\n",
      " [0. 4.]]\n",
      " np.dot(a,b) = \n",
      " [[1. 2.]\n",
      " [3. 4.]]\n",
      " a@b = \n",
      " [[1. 2.]\n",
      " [3. 4.]]\n"
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Inner product for one dimensional arrays**"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:48.202259Z",
     "start_time": "2025-01-22T09:17:48.198663Z"
    }
   },
   "source": [
    "a = np.arange(3)\n",
    "b = np.arange(4, 7)\n",
    "c = np.dot(a, b)\n",
    "d = np.inner(a, b)\n",
    "print('a = ', a)\n",
    "print('b = ', b)\n",
    "print('np.dot(a,b)=', c)\n",
    "print('np.inner(a,b)=', d)  # alternative to np.dot for the inner product\n",
    "# of one-dimensional arrays"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a =  [0 1 2]\n",
      "b =  [4 5 6]\n",
      "np.dot(a,b)= 17\n",
      "np.inner(a,b)= 17\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Reshaping**"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:17:50.913721Z",
     "start_time": "2025-01-22T09:17:50.910196Z"
    }
   },
   "source": [
    "#Turning a one-dimensional array with 6 elements into a \n",
    "#2x3 dimensional array \n",
    "a = np.arange(6)\n",
    "b = a.reshape(2, 3)\n",
    "print('a = ', a)\n",
    "print('b =\\n', b)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a =  [0 1 2 3 4 5]\n",
      "b =\n",
      " [[0 1 2]\n",
      " [3 4 5]]\n"
     ]
    }
   ],
   "execution_count": 20
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 11**\n",
    "Turn the previous 2X3 dimensional array `b` into a 3x2 dimensional array using `reshape`:"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:18:51.612181Z",
     "start_time": "2025-01-22T09:18:51.609302Z"
    }
   },
   "source": [
    "b2 = b.copy().reshape(3, 2)\n",
    "print(b2)\n",
    "print(b2.shape)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1]\n",
      " [2 3]\n",
      " [4 5]]\n",
      "(3, 2)\n"
     ]
    }
   ],
   "execution_count": 27
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 12** Does the new array corresponds to the transpose of `b`? In case it does not, display the transpose of `b`.  "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:19:31.699357Z",
     "start_time": "2025-01-22T09:19:31.697031Z"
    }
   },
   "source": [
    "print(b.transpose())\n",
    "print(b.transpose() == b2)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 3]\n",
      " [1 4]\n",
      " [2 5]]\n",
      "[[ True False]\n",
      " [False False]\n",
      " [False  True]]\n"
     ]
    }
   ],
   "execution_count": 30
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 `for`-loop and `if...else`<a class=\"anchor\" id=\"section_2_3\"></a>\n",
    "\n",
    "Python code is structured by *indentation*.\n",
    "\n",
    "**Beware** :  Python indices start at **ZERO** !"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 13** : Write a  `for` loop that displays every integer `i` from 2 to 12. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:19:43.363208Z",
     "start_time": "2025-01-22T09:19:43.359985Z"
    }
   },
   "source": [
    "for i in range(2, 13):\n",
    "    print(i)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n"
     ]
    }
   ],
   "execution_count": 31
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 14** : Write a program to check if a number is divisible by both 3 and 13 or not, using if-else. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:20:24.414268Z",
     "start_time": "2025-01-22T09:20:24.410942Z"
    }
   },
   "source": [
    "def divisible_by_3_and13(n):\n",
    "    if n % 3 == 0 and n % 13 == 0:\n",
    "        print(n, \"is divisible by 3 and 13\")\n",
    "    else:\n",
    "        print(n, \"is not divisible by 3 and 13\")\n",
    "\n",
    "\n",
    "print(divisible_by_3_and13(39))\n",
    "print(divisible_by_3_and13(26))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "39 is divisible by 3 and 13\n",
      "None\n",
      "26 is not divisible by 3 and 13\n",
      "None\n"
     ]
    }
   ],
   "execution_count": 33
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4 Functions <a class=\"anchor\" id=\"section_2_4\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To define a function, use the keyword `def`. To let a function return a value, use the return statement. "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:20:41.546944Z",
     "start_time": "2025-01-22T09:20:41.542979Z"
    }
   },
   "source": [
    "# Example\n",
    "def my_function(x):\n",
    "    return x + 3\n",
    "\n",
    "\n",
    "print(my_function(2))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "execution_count": 34
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 15** : Define a function named *square_cube*. The input is a integer, the output is its square and its  cube. Diplay the result of carre_cube(2)."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:20:59.887492Z",
     "start_time": "2025-01-22T09:20:59.884773Z"
    }
   },
   "source": [
    "def square_cube(x):\n",
    "    return x ** 2, x ** 3\n",
    "\n",
    "\n",
    "print(square_cube(2))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(4, 8)\n"
     ]
    }
   ],
   "execution_count": 35
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.5 Graphs <a class=\"anchor\" id=\"section_2_5\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matplotlib tutorial :\n",
    "https://matplotlib.org/stable/tutorials/introductory/pyplot.html"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:21:02.381191Z",
     "start_time": "2025-01-22T09:21:02.126204Z"
    }
   },
   "source": [
    "import matplotlib.pyplot as plt"
   ],
   "outputs": [],
   "execution_count": 36
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The basic command is `plt.plot(x,y)` where $x$ and $y$ are lists/arrays of the same size. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 16** : Plot the graph of the standard normal distribution density on [-5,5]. You can use `scipy.stats.norm`. \n",
    "https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.norm.html"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:22:37.451301Z",
     "start_time": "2025-01-22T09:22:37.386127Z"
    }
   },
   "source": [
    "xx = np.linspace(-5, 5, 100)\n",
    "yy = norm.pdf(xx)\n",
    "plt.plot(xx, yy)\n",
    "plt.ylabel('Density')\n",
    "plt.xlabel('x')\n",
    "plt.title('Standard normal distribution')\n",
    "plt.show()"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "[encoded data, 33916 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 39
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 17** : Plot the graph of the density of  the two-dimensional standard normal distribution $\\mathcal{N}(0, I_2)$ on [-3,3]$\\times$[-3,3].\n",
    "\n",
    "We will use `plot_surface`. You can find an example here https://matplotlib.org/stable/gallery/mplot3d/surface3d.html\n",
    "\n",
    "For the PDF (probability density function), you can use `scipy.stats.multivariate_normal`. \n",
    "https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.multivariate_normal.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<details>\n",
    "<summary>Click here for a hint</summary>\n",
    "Use `meshgrid`. See below for more info about `meshgrid`.  \n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:31:03.547534Z",
     "start_time": "2025-01-22T09:31:03.467548Z"
    }
   },
   "source": [
    "from scipy.stats import multivariate_normal\n",
    "\n",
    "fig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\n",
    "\n",
    "X = np.arange(-3, 3, 0.25)\n",
    "Y = np.arange(-3, 3, 0.25)\n",
    "X, Y = np.meshgrid(X, Y)\n",
    "R = multivariate_normal([0, 0], np.eye(2))\n",
    "\n",
    "surf = ax.plot_surface(X, Y, R.pdf(np.dstack((X, Y))), cmap='coolwarm', linewidth=0, antialiased=False)\n",
    "\n",
    "fig.colorbar(surf, shrink=0.5, aspect=5)\n",
    "plt.show()"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ],
      "image/png": "[encoded data, 78872 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 56
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you feel you need to practice more, there are lots of resources online, for instance : https://github.com/rougier/numpy-100/blob/master/100_Numpy_exercises.ipynb (exercises with solutions !)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Details about `meshgrid`: "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:31:27.147136Z",
     "start_time": "2025-01-22T09:31:27.142313Z"
    }
   },
   "source": [
    "x = np.arange(3)\n",
    "y = np.arange(3)\n",
    "\n",
    "\n",
    "def f(x, y):\n",
    "    return x ** 2 + y ** 2\n",
    "\n",
    "\n",
    "f(x, y)\n"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 2, 8])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 57
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output is  [f(0,0),f(1,1),f(2,2)]\n",
    "Now if the desired output is [f(0,0),f(0,1),f(0,2),f(1,0),f(1,1), etc. jusqu'à f(2,2)], \n",
    "i.e.  the  f(i,j)'s for every  (i,j) where i=0,1,2 and j=0,1,2, then you should use \n",
    " `meshgrid`(or `mgrid`) instead. The output is two arrays :"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:31:53.126413Z",
     "start_time": "2025-01-22T09:31:53.120541Z"
    }
   },
   "source": [
    "X, Y = np.meshgrid(x, y)\n",
    "X, Y"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 1, 2],\n",
       "        [0, 1, 2],\n",
       "        [0, 1, 2]]),\n",
       " array([[0, 0, 0],\n",
       "        [1, 1, 1],\n",
       "        [2, 2, 2]]))"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 58
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:32:24.722840Z",
     "start_time": "2025-01-22T09:32:24.717892Z"
    }
   },
   "source": "X ** 2 + Y ** 2  # gives the desired output",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 4],\n",
       "       [1, 2, 5],\n",
       "       [4, 5, 8]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 59
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:32:27.491058Z",
     "start_time": "2025-01-22T09:32:27.486755Z"
    }
   },
   "source": [
    "#same calculation, except here  Z is a list of  lists \n",
    "Z = [[x ** 2 + y ** 2 for x in range(3)] for y in range(3)]\n",
    "Z"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0, 1, 4], [1, 2, 5], [4, 5, 8]]"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 60
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:32:34.752570Z",
     "start_time": "2025-01-22T09:32:34.747781Z"
    }
   },
   "source": [
    "#Alternative : using mgrid (vu qu'on utilise une grille uniforme)\n",
    "X, Y = np.mgrid[0:3, 0:3]  # equivalent to np.meshgrid(np.arange(3),np.arange(3))\n",
    "X, Y"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 0, 0],\n",
       "        [1, 1, 1],\n",
       "        [2, 2, 2]]),\n",
       " array([[0, 1, 2],\n",
       "        [0, 1, 2],\n",
       "        [0, 1, 2]]))"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 61
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-22T09:32:36.382070Z",
     "start_time": "2025-01-22T09:32:36.377342Z"
    }
   },
   "source": [
    "# from -1 to 1, in steps of 0.5\n",
    "X, Y = np.mgrid[-1:1:.5, -1:1:.5]\n",
    "X, Y"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[-1. , -1. , -1. , -1. ],\n",
       "        [-0.5, -0.5, -0.5, -0.5],\n",
       "        [ 0. ,  0. ,  0. ,  0. ],\n",
       "        [ 0.5,  0.5,  0.5,  0.5]]),\n",
       " array([[-1. , -0.5,  0. ,  0.5],\n",
       "        [-1. , -0.5,  0. ,  0.5],\n",
       "        [-1. , -0.5,  0. ,  0.5],\n",
       "        [-1. , -0.5,  0. ,  0.5]]))"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 62
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
