{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f590881f",
   "metadata": {},
   "source": [
    "# Séance 5\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "```{admonition} Objectifs\n",
    "* Introduction à Sagemath\n",
    "* Calcul exact : entiers, rationnels, complexes\n",
    "* Notions sur le calcul symbolique\n",
    "* Notion de méthode et de classe\n",
    "```\n",
    "\n",
    "\n",
    "## Sagemath\n",
    "\n",
    "Sagemath est un **logiciel** de **calcul formel** dont la syntaxe est celle du langage python. Les notions vues dans 4 premières séances de cours vous seront donc essentielles pour utiliser ce logiciel.\n",
    "\n",
    "Sagemath peut être utilisé en **ligne de commande** (comme python), mais également dans un **notebook Jupyter.** C'est ce dernier choix qui a été effectué pour ce cours. Vous utiliserez donc le même environnement de travail que lors des 4 premières séances.\n",
    "\n",
    "\n",
    "```{note}\n",
    "Lorsque vous ouvrez un notebook Jupyter, pour vérifier que c'est bien le \"noyau\" Sagemath (et non python) qui est lancé, observez ce qui est indiqué en haut à droite de votre fichier.\n",
    "```\n",
    "\n",
    "Sagemath **regroupe** de nombreuses bibliothèques et de nombreux logiciels sous un même envrionnement. En particulier, les bibliothèques  `math`, `matplotlib` et `random` de python sont déjà incluses dans Sagemath, et importées à son ouverture. **Vous n'aurez donc pas besoin de les importer, ni de les mentionner.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2856d4f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(randint(0, 1000))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47d12281",
   "metadata": {},
   "source": [
    "```{warning}\n",
    "Certaines de ces fonctions (par exemple, `plot` ou `sqrt`) ont été modifiées pour les simplifier, ou pour permettre d'accéder à d'autres fonctionnalités.\n",
    "```\n",
    "\n",
    "Par exemple, l'affichage graphique d'une liste de points ne se fera plus sous la forme suivante (qui provoque une erreur) :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87b830f0",
   "metadata": {
    "tags": [
     "hide-output"
    ]
   },
   "outputs": [],
   "source": [
    "X = [ i for i in range(12) ]\n",
    "Y = [ 2*x-5 for x in X ]\n",
    "plot(X, Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb29da94",
   "metadata": {},
   "source": [
    "mais peut se faire sous la forme suivante :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b31a9710",
   "metadata": {},
   "outputs": [],
   "source": [
    "points = [ (X[i],Y[i]) for i in range(len(X))] \n",
    "list_plot(points)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73cf5b99",
   "metadata": {},
   "source": [
    "Nous verrons ces subtilités dans une prochaine séance (ce n'est pas nécessaire de retenir la syntaxe ci-dessus pour l'instant).\n",
    "\n",
    "\n",
    "## Entiers\n",
    "\n",
    "### Déclaration et manipulation élémentaire\n",
    "\n",
    "Avec Sagemath, on peut déclarer et utiliser les **entiers** comme en python."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f2c3f5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 1\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ab79c1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 17\n",
    "print(((x % 5)**123 + 3*x - 2)//8)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36905463",
   "metadata": {},
   "source": [
    "On peut également appliquer des **fonctions externes** sur ces entiers, par exemple la fonction `gcd` qui calcule un pgcd, ou la fonction `xgcd` qui calcule également les coefficients de Bezout. En revanche, **contrairement à python, ces fonctions ne nécessitent pas d'import**, elles sont directement incluses dans Sagemath."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e874f61c",
   "metadata": {},
   "outputs": [],
   "source": [
    "gcd(12, 27)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55a9b58c",
   "metadata": {},
   "outputs": [],
   "source": [
    "xgcd(12, 27)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "386b4a0e",
   "metadata": {},
   "source": [
    "**Remarque importante :** Pour savoir comment utiliser une fonction, on peut s'aider de l'aide interactive de Sagemath. Pour cela, il faut taper le nom de la fonction suivi de `?`. Une mini-fenêtre s'ouvre alors, avec l'aide (en anglais) associée à la fonction. Exemple (ne s'affiche pas sur la page web) :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62af0153",
   "metadata": {},
   "outputs": [],
   "source": [
    "xgcd?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "826dbf2b",
   "metadata": {},
   "source": [
    "### Fonctions spécifiques à Sagemath\n",
    "\n",
    "\n",
    "Un avantage de Sagemath est qu'il contient une quantité importante de fonctions  qui sont **absentes de la bibliothèque** `math` de python. Prenons l'exemple de la fonction `factor`, qui permet d'obtenir la factorisation d'un entier :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3b0ffef",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(factor(12))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81a3b192",
   "metadata": {},
   "outputs": [],
   "source": [
    "factor(1234567890)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "737d1a92",
   "metadata": {},
   "source": [
    "On peut également penser à la fonction `next_prime(a)` qui retourne le plus petit nombre premier strictement supérieur à `a` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c07a0b7d",
   "metadata": {},
   "outputs": [],
   "source": [
    "next_prime(100)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5380681f",
   "metadata": {},
   "source": [
    "Il existe beaucoup d'autres fonctions à appliquer directement sur des entiers... à vous de les chercher/tester !\n",
    "\n",
    "\n",
    "\n",
    "### Retour aux entiers : la classe `Integer`\n",
    "\n",
    "Un changement majeur entre python et sagemath provient de la **manière dont les entiers sont créés et stockés**. Leur **type** a changé : ce sont maintenant des objets provenant d'une **classe** appelée `Integer`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "36020a4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "type(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fa22fa4",
   "metadata": {},
   "source": [
    "```{note}\n",
    "En informatique, la notion de classe permet de représenter une catégorie d'objets ayant des attributs, des propriétés ou des méthodes (au sens de fonction applicable à un objet) en commun. La classe est une sorte de \"moule\" dans lequel on peut créer des objets similares, qu'on appelle **instances** de classe.\n",
    "```\n",
    "\n",
    "\n",
    "La classe `Integer` est donc le \"moule\" des entiers, et elle attache à ses objets (les entiers) de nombreuses propriétés et fonctions. On peut s'en apercevoir en tapant `a.<Tab>` après avoir créé un entier `a`. Sagemath va alors lister tous les attributs de `a` et toutes les méthodes que l'on peut lui appliquer. Exemple :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1450a0cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 12\n",
    "# a.<Tab>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e65ee30",
   "metadata": {},
   "source": [
    "```{note}\n",
    "Cette technique vous sera très utile, pour retrouver le nom d'une méthode, ou pour compléter automatiquement (et correctement !) un nom de méthode déjà entamé.\n",
    "```\n",
    "\n",
    "\n",
    "Pour des raisons de commodité, Sagemath a créé des **fonctions du même nom** que certaines méthodes de la classe `Integer`. L'intérêt est de pouvoir les appliquer directement sur l'écriture entière, sans passer par une variable. Par exemple, l'instruction `factorial(4)` existe et a le même comportement que `a.factorial()` où la variable `a` a été assignée à la valeur $4$.\n",
    "\n",
    "**Autre exemple :** on obtient le **coefficient binomial** $\\binom{n}{k}$ par l'appel à la fonction `binomial(n, k)`, mais également par l'utilisation de la méthode de classe `n.binomial(k)` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3ead768",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 5\n",
    "k = 2\n",
    "print(n.binomial(k))\n",
    "print(binomial(n, k))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93050f4e",
   "metadata": {},
   "source": [
    "Néanmoins, si ces \"raccourcis\" sont assez fréquents pour les entiers, ils le seront beaucoup moins pour les objets que nous verrons par la suite. Retenez-donc plutôt l'approche par **méthode de classe**.\n",
    "\n",
    "\n",
    "**Tableau récapitulatif des méthodes ou fonctions sur les entiers :**\n",
    "\n",
    "|   Méthode (où `n` est de type `Integer`)  | Description | Syntaxe équivalente |\n",
    "|:---:|:---:|:---:|\n",
    "| `n.factorial()` | Calcule $n!$, la factorielle de l'entier $n$. | `factorial(n)` |\n",
    "| `n.binomial(k)` | Calcule le coefficient binomial $\\binom{n}{k}$. | `binomial(n, k)` |\n",
    "| `n.gcd(k)` | Retourne le pgcd de la paire $(n, k)$. | `gcd(n, k)` |\n",
    "| `n.xgcd(k)` | Retourne le triplet formé du pgcd et des coefficients de Bezout de la paire $(n, k)$. | `xgcd(n, k)` |\n",
    "| `n.quo_rem(k)` | Calcule la paire (quotient, reste) de la division euclidienne de $n$ par $k$. | `divmod(n, k)` |\n",
    "| `n.inverse_mod(k)` | Calcule l'inverse de $n$ modulo $k$. | `inverse_mod(n, k)` |\n",
    "| `n.divides(k)` | Teste si l'entier $n$ est divisible par $k$. | `n % k == 0` |\n",
    "| `n.is_prime()` | Teste si $n$ est premier. | `is_prime(n)` |\n",
    "| `n.is_square()` | Teste si $n$ est un carré parfait. | `is_square(n)` |\n",
    "| `n.factor()` | Retourne la factorisation de $n$. | `factor(n)` |\n",
    "| `n.divisors()` | Retourne la liste des diviseurs de $n$. | `divisors(n)` |\n",
    "| `n.bits()` | Retourne la liste des coefficients de la décomposition binaire de $n$ (en commençant par le bit de poids faible). | pas d'équivalent direct |\n",
    "\n",
    "\n",
    "Quelques exemples :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "945d23fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 9\n",
    "print(n.factorial())\n",
    "print(n.divides(36))\n",
    "print(n.is_prime())\n",
    "print(n.is_square())\n",
    "print(n.inverse_mod(17))\n",
    "print(n.quo_rem(4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23eb11bb",
   "metadata": {},
   "source": [
    "Observons ici que Sagemath  n'est pas gêné pour le calcul d'entiers de taille importante."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "663b2184",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = 100\n",
    "print(m.factorial())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c26a8fe0",
   "metadata": {},
   "source": [
    "### Notion de classe parente\n",
    "\n",
    "Pour finir, Sagemath permet de manipuler non seulement les entiers, mais également **l'ensemble** des entiers, vus comme une structure algébrique (on sait que cet ensemble a une structure **d'anneau**). \n",
    "\n",
    "La variable `ZZ` a été prédéfinie dans Sagemath pour stocker cet anneau. L'instruction `IntegerRing()` permet aussi d'y accéder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a68967b",
   "metadata": {},
   "outputs": [],
   "source": [
    "ZZ"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "134de801",
   "metadata": {},
   "source": [
    "<!-- Remarquons que  Sagemath \"sait\" que `ZZ` est un anneau, et qu'il est infini : -->\n",
    "\n",
    "<!-- ```{code-cell} -->\n",
    "<!-- print(\"Anneau ?\", ZZ.is_ring()) -->\n",
    "<!-- print(\"Fini ?  \", ZZ.is_finite()) -->\n",
    "<!-- ``` -->\n",
    "\n",
    "\n",
    "Sagemath a donc **lié** les entiers à leur anneau par une relation de **parenté** : l'anneau `ZZ` est un parent de tout objet de la classe `Integer`. C'est une manière de représenter la **relation d'appartenance à une structure**.\n",
    "\n",
    "Pour observer cela, on peut demander à Sagemath le parent d'un entier `a` quelconque, ou simplement tester l'appartenance de `a` à l'objet `ZZ` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acbee2c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = -2\n",
    "print(a.parent())\n",
    "print(a in ZZ)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a9c7888",
   "metadata": {},
   "source": [
    " \n",
    "\n",
    "\n",
    "## Nombres rationnels\n",
    "\n",
    "### Création et classes associées\n",
    "\n",
    "**Contrairement à python**, Sagemath permet de stocker des nombres rationnels sous forme **exacte** et **réduite**. Si `a` et `b` sont deux entiers, alors le rationnel $\\frac{a}{b}$ peut être construit avec `a/b`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e64a19fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 4/6\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91378045",
   "metadata": {},
   "source": [
    "```{warning}\n",
    "L'opérateur `/` a donc un comportement différent sous Sagemath et sous python !\n",
    "```\n",
    "\n",
    "\n",
    "Un rationnel est un élément de la **classe** `Rational`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "737869b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(type(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "503fb865",
   "metadata": {},
   "source": [
    "Sa **classe parente** est le corps des rationnels, affiché `Rational Field`, à laquelle on accède par la variable prédéfinie `QQ` ou par le constructeur `RationalField()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad32a1a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(parent(x))\n",
    "print(x in QQ)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37da0e11",
   "metadata": {},
   "source": [
    "<!-- Une nouvelle fois, l'objet `QQ` contient des informations sur la structure algébrique des rationnels, et peut fournir des fonctions utiles. -->\n",
    "\n",
    "<!-- ```{code-cell} -->\n",
    "<!-- QQ.is_ring() and QQ.is_field() -->\n",
    "<!-- ``` -->\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "### Opérations élémentaires\n",
    "\n",
    "On peut effectuer des opérations élémentaires sur les rationnels, et ce, avec les **mêmes** opérateurs  que sur les entiers :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd2b9fc1",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 2/3\n",
    "print(x + 1/2)\n",
    "print(3*x)\n",
    "print(x**2)\n",
    "print(-3/x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "495c2475",
   "metadata": {},
   "source": [
    "Comme pour les entiers, il existe des méthodes à appliquer aux rationnels. Par exemple, on peut accéder au **numérateur** et au **dénominateur** de la fraction réduite :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8df016fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 4/-6\n",
    "p = a.numerator()\n",
    "q = a.denominator()\n",
    "print(p)\n",
    "print(q)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22037573",
   "metadata": {},
   "source": [
    "On observe que le numérateur et le dénominateur sont des objets de la classe `Integer` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fee732d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(type(p))\n",
    "print(isinstance(p, Integer))      # teste si p est une instance de la classe Integer "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5db27eef",
   "metadata": {},
   "source": [
    "### Conversion de type\n",
    "\n",
    "Enfin, il peut être utile de **convertir** un objet de la classe `Rational` en un objet de la class `Integer`. On parle de **coercion**.\n",
    "\n",
    "Attention, ce n'est pas un arrondi : on transfère les informations d'une classe à une autre, autrement dit, on **transforme simplement le type de l'objet**. \n",
    "\n",
    "Dans l'exemple suivant, la variable `b` contient la valeur $1$, vue comme un rationnel :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "07d6585d",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 1/3\n",
    "b = a + 2/3\n",
    "print(b)\n",
    "print(isinstance(b, Rational))\n",
    "print(isinstance(b, Integer))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66d55432",
   "metadata": {},
   "source": [
    "On peut ensuite la convertir en un entier :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e045ee4",
   "metadata": {},
   "outputs": [],
   "source": [
    "c = Integer(b)\n",
    "print(c)\n",
    "print(isinstance(c, Integer))\n",
    "print(b == c)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9aefac4d",
   "metadata": {},
   "source": [
    "Bien entendu, pour être effective, cette conversion doit être possible, sinon on obtient une erreur :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b5c4f03",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 1/3\n",
    "y = Integer(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b170f57c",
   "metadata": {},
   "source": [
    "**Tableau récapitulatif des méthodes ou fonctions sur les rationnels :**\n",
    "\n",
    "|   Méthode (où `r` est de type `Rational`)  | Description | \n",
    "|:---:|:---:|\n",
    "| `r.denominator()` | Retourne de dénominateur de $r \\in \\mathbb{Q}$ | \n",
    "| `r.numerator()` | Retourne de numérateur de $r \\in \\mathbb{Q}$ | \n",
    "\n",
    "\n",
    "\n",
    "<!-- **Remarque importante :** la classe dont est issu un objet est importante. Par exemple, l'opérateur `//` agit différemment si on l'utilise sur un entier et sur un rationnel : -->\n",
    "<!-- ```{code-cell} -->\n",
    "<!-- print(Integer(1)//2) -->\n",
    "<!-- print(Rational(1)//2) -->\n",
    "<!-- ``` -->\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Nombres complexes\n",
    "\n",
    "Dans Sagemath, on peut également manipuler des **nombres complexes** sous une forme **exacte**. Pour cela, il suffit d'avoir accès à une variable qui stocke $i$, le nombre imaginaire pur. Dans Sagemath, c'est la variable prédéfinie `I`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51973976",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(I)\n",
    "print(I**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d3e987a",
   "metadata": {},
   "source": [
    "La **classe parente** de la variable prédéfinie `I` a varié suivant les versions de Sagemath, et peut vous paraître obscure pour certaines (\"corps de nombres défini par le polynôme $x^2+1$\" pour la version 10.1), mais pourra peut-être s'expliquer dans vos prochaines années d'études en mathématiques."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77c05a29",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(parent(I))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac7edf4a",
   "metadata": {},
   "source": [
    "```{warning}\n",
    "Il faut donc faire attention à ne jamais écraser la variable `I` !\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "### Opérations élémentaires\n",
    "\n",
    "On peut effectuer des opérations élémnentaires sur les complexes d'une manière similaire à celles faites sur les entiers ou les rationnels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2e93a9c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 3 - I/2\n",
    "print(I * (x - 1))\n",
    "print(x**2)\n",
    "print(x / (2 + I))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9a00ee1",
   "metadata": {},
   "source": [
    "Certaines méthodes permettent d'accéder à la **partie réelle**, la **partie imaginaire**, le **conjugué** et le **module** (au carré ou non) d'un nombre complexe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ad4c391",
   "metadata": {},
   "outputs": [],
   "source": [
    "z = 1 - 2*I\n",
    "print(z.real_part())\n",
    "print(z.imag_part())\n",
    "print(z.conjugate())\n",
    "print(z.norm())\n",
    "print(z.abs())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32f7d7ac",
   "metadata": {},
   "source": [
    "Enfin, on peut accéder à l'argument principal d'un nombre complexe $z$ grâce à la **fonction** `arg`. Il n'existe pas de **méthode** équivalente, car la classe parente `I` manipule aussi des éléments qui n'ont pas d'argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a734f50",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(arg(z))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52c2eead",
   "metadata": {},
   "source": [
    "**Tableau récapitulatif des méthodes ou fonctions sur les rationnels :**\n",
    "\n",
    "|   Méthode ou fonction  | Description |\n",
    "|:---:|:---:|\n",
    "| `z.real_part()` | Retourne la partie réelle de $z$. |\n",
    "| `z.imag_part()` | Retourne la partie imaginaire de $z$. |\n",
    "| `z.conjugate()` | Retourne la conjugué complexe de $z$. |\n",
    "| `z.norm()` | Retourne le module **au carré** de $z$. |\n",
    "| `z.abs()` | Retourne le module de $z$. |\n",
    "| `arg(z)` | Retourne l'argument de $z$. |\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Fonctions et constantes classiques\n",
    "\n",
    "Sagemath permet la manipulation exacte de fonctions et de constantes classiques en mathématiques. Pour cela, certains de ces objets **doivent** être vus de manière symbolique (et non numérique).\n",
    "\n",
    "Prenons l'exemple de la fonction sinus et de la constante $\\pi$. Lorsqu'on demande la valeur de $\\sin(\\pi)$ à Sagemath, aucun calcul numérique n'est effectué ; simplement, on applique les propriétés symboliques de ces objets, parmi lesquelles on retrouve le fait que $\\sin(\\pi)$ vaut **exactement** $0$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cebc4fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "sin(pi)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25dc0eaa",
   "metadata": {},
   "source": [
    "De la même manière, $\\sqrt{2}$ n'est pas stockée comme sa valeur approchée $1.414...$ mais comme le nombre positif qui, lorsqu'il est élevé au carré, donne $2$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ae30120",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = sqrt(2)\n",
    "print(a)\n",
    "print(a**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "437435a5",
   "metadata": {},
   "source": [
    "On peut d'ailleurs remarquer que la classe parente de tous ces nombres ($\\pi$, $e$, $\\zeta(3)$, $\\sqrt{2}$, etc.) est `Symbolic Ring`. Cela signifie qu'on manipule bien des **expressions symboliques**, qui ne sont donc pas des valeurs numériques."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb695b7f",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(a.parent())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5640967",
   "metadata": {},
   "source": [
    "Nous verrons dans une **séance future** les subtilités de cette distinction. Gardons néanmoins en mémoire la particularité suivante. Grâce à ces expessions symboliques (et donc, contrairement à la bibliothèque standard de python), Sagemath sait que certaines fonctions ne sont pas définies en des points singuliers. Par exemple :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ede2ef76",
   "metadata": {},
   "outputs": [],
   "source": [
    "tan(pi/2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04ddf202",
   "metadata": {},
   "source": [
    "Pour finir, voici une liste de fonctions courantes en mathématiques (il en manque certainement, n'hésitez pas à chercher ou demander !).\n",
    "\n",
    "\n",
    "**Tableau récapitulatif de fonctions ou objets symboliques dans Sagemath.**\n",
    "\n",
    "|   Fonction ou objet   | Description |\n",
    "|:---:|:---:|\n",
    "| `exp(x, b)` et `log(x, b)` | Exponentielle et logarithme de $x$ en base $b$. |\n",
    "| `exp(x)` et `log(x)` | Exponentielle et logarithme de $x$ en base $e$. |\n",
    "| `sin(t)`, `cos(t)`, `tan(t)` | Sinus, cosinus et tangente de $t$. |\n",
    "| `asin(y)`, `acos(y)`, `atan(y)` | Arcsinus, arccosinus et arctangente de $y$. |\n",
    "| `sqrt(x)`, `x**(p/q)` | Racine carrée et puissance rationnelle $(p/q)$-ème de $x$. |\n",
    "| `pi`, `e`, `I` | Nombres $\\pi$, $e$ et $i$. |"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Sagemath",
   "language": "python",
   "name": "sagemath"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
