{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "aa8dec41",
   "metadata": {},
   "source": [
    "# Séance 7\n",
    "\n",
    "\n",
    "```{admonition} Objectifs\n",
    "* Vecteurs\n",
    "* Matrices\n",
    "* Résolution de systèmes linéaires\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "## Vecteurs et espaces vectoriels\n",
    "\n",
    "Commençons par essayer de représenter des **espaces vectoriels** (de dimension finie) et leurs éléments, des **vecteurs**.\n",
    "\n",
    "### Création et classe parente\n",
    "\n",
    "\n",
    "En mathématiques, un **vecteur** est un élément d'un espace vectoriel. L'espace vectoriel canonique est $\\mathbb{K}^n$, où $\\mathbb{K}$ est un corps (par exemple, $\\mathbb{K} = \\mathbb{Q}, \\mathbb{R}, \\mathbb{C}$, etc.) et $n \\ge 1$ est un entier.\n",
    "\n",
    "Avec Sagemath, on peut créer un objet de type **vecteur** avec la commande `vector()`. Cette commande prend comme arguments :\n",
    "1. de manière optionnelle (mais fortement conseillée), le **corps** de définition des coefficients,\n",
    "1. de manière obligatoire, la **liste des coefficients** du vecteur.\n",
    "\n",
    "Par exemple, pour créer le vecteur $(1, \\frac{1}{2}, -3) \\in \\mathbb{Q}^3$, on exécute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb5c2661",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = vector(QQ, [1, 1/2, -3])\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "272f662b",
   "metadata": {},
   "source": [
    "De même, pour créer le vecteur $(1.2, \\pi/2, -\\sqrt{2})$ dans le corps des nombres flottants (à $53$ bits de précision), on peut écrire simplement :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aa315e74",
   "metadata": {},
   "outputs": [],
   "source": [
    "w = vector(RR, [1.2, pi/2, -sqrt(2)])\n",
    "print(w)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18f20bfd",
   "metadata": {},
   "source": [
    "**Remarque :** il existe une fonction spéciale pour créer un vecteur nul, `zero_vector`, qui s'utilise ainsi (dans l'exemple, pour créer $\\mathbf{0} \\in \\mathbb{Q}^{20}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b79dc6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "z = zero_vector(QQ, 20)\n",
    "print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5327fae",
   "metadata": {},
   "source": [
    "Observons que les **classes parentes** de ces éléments sont bien des espaces vectoriels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6018a5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(parent(v))\n",
    "print(parent(w))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14b2ac48",
   "metadata": {},
   "source": [
    "### Opérations élémentaires\n",
    "\n",
    "Avec Sagemath, on peut facilement **manipuler** les vecteurs. Les opérations usuelles de l'espace vectoriel (**addition** et **multiplication scalaire**) sont déjà écrites."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "267ac445",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = vector(QQ, [1, 1/2, -3])\n",
    "b = vector(QQ, [0, -7/3, 2])\n",
    "c = a + b\n",
    "d = (-1/2)*a\n",
    "print(c)\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c82e40fd",
   "metadata": {},
   "source": [
    "On retrouve également le **produit scalaire** entre les deux vecteurs `a` et `b`, sous la forme d'une méthode `a.inner_product(b)`, mais également avec l'opérateur `a * b`. Il faudra néanmoins prendre garde à l'utilisation de l'opérateur `*` qui peut parfois être trompeuse, notamment si l'un  des deux opérandes n'est pas un objet de **type vecteur**.\n",
    "\n",
    "Notons enfin que la **classe parente** du résultat de ce calcul est bien le corps de définition des coefficients."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b6c420fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = vector(QQ, [1, 1/2, -3])\n",
    "b = vector(QQ, [0, -7/3, 2])\n",
    "x = a.inner_product(b)\n",
    "print(x)\n",
    "print(x == a * b)\n",
    "print(parent(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6883199",
   "metadata": {},
   "source": [
    "On peut **accéder** aux coefficients d'un vecteur comme on le ferait avec une liste. Par exemple, pour avoir la deuxième coordonnée (celle d'indice $1$) du vecteur `v`, on entre `v[1]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f71dc987",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = vector(QQ, [1, 1/2, -3])\n",
    "print(v[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a4d77b0",
   "metadata": {},
   "source": [
    "### Espace vectoriel\n",
    "\n",
    "La classe parente des vecteurs pourra vous être utile, par exemple pour **tirer aléatoirement** des vecteurs, ou pour effectuer des **coercions**.\n",
    "\n",
    "On peut directement créer un espace vectoriel grâce à la commande `VectorSpace(K, n)`, qui prend en entrée un corps `K` et un entier positif `n`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "44c2b987",
   "metadata": {},
   "outputs": [],
   "source": [
    "E = VectorSpace(QQ, 5)\n",
    "print(E)\n",
    "e = E.random_element()\n",
    "print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76183c1b",
   "metadata": {},
   "source": [
    "## Matrices\n",
    "\n",
    "Passons désormais aux matrices.\n",
    "\n",
    "### Création et manipulation de matrices\n",
    "\n",
    "La création et la manipulation de **matrices** est assez similaire à celle des vecteurs. On utilise pour cela le constructeur `matrix`, qui prend comme argument :\n",
    "1. de manière optionnelle, le corps (ou l'anneau) sur lequel sont définis les coefficients de la matrice à créer,\n",
    "1. les coefficients de la matrice sous la forme d'une **liste `L` de sous-listes toutes de même longueur**, où la sous-liste `L[i]` de `L` correspond aux coefficients de la ligne d'indice $i+1$ de la matrice. \n",
    "\n",
    "Par exemple, si l'on souhaite créer la matrice :\n",
    "\n",
    "$$\n",
    "    M = \\begin{pmatrix} 1 & 2 & 3 \\\\ 4 & 5 & 6 \\end{pmatrix}\\,,\n",
    "$$\n",
    "\n",
    "on écrira"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc434228",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, [ [1, 2, 3], [4, 5, 6] ] )\n",
    "print(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd30a3a6",
   "metadata": {},
   "source": [
    "Il existe une **seconde manière** de créer une matrice, toujours avec le mot-clef `matrix`. Cette fois-ci, on donne $4$ arguments :\n",
    "1. de manière optionnelle, le corps (ou l'anneau) de définition des coefficients,\n",
    "1. le nombre $m$ de lignes de la matrice,\n",
    "1. le nombre $n$ de colonnes de la matrice, \n",
    "1. la liste des $nm$ coefficients de la matrice, en commençant par les coefficients de la première ligne (décrits de gauche à droite), puis ceux de la deuxième, etc. jusqu'à la dernière.\n",
    "\n",
    "En reprenant l'exemple précédent on obtient :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b24fcbce",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, 2, 3, [ 1, 2, 3, 4, 5, 6 ] )\n",
    "print(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c7c7292",
   "metadata": {},
   "source": [
    "Avec l'interface **jupyter** (mais pas sur le rendu de la page web), on peut obtenir un meilleur affichage des matrices avec la fonction `show()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d1a1626",
   "metadata": {},
   "outputs": [],
   "source": [
    "# show(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d8d86fd",
   "metadata": {},
   "source": [
    "Cela fonctionne également pour d'autres objets (polynômes, expressions symboliques, etc.).\n",
    "On peut également générer le **code LaTeX** correspondant à une matrice (ou un auttre objet), ce qui est pratique pour l'édition de documents scientifiques avec des objets mathématiques de grande taille."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac9faa43",
   "metadata": {},
   "outputs": [],
   "source": [
    "latex(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "201bcdd3",
   "metadata": {},
   "source": [
    "La **classe parente** des matrices est un espace de matrices nommé généralement `MatrixSpace`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "339f9c8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(M.parent())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12060a76",
   "metadata": {},
   "source": [
    "Comme pour les vecteurs, on peut **additionner** ou **soustraire** deux matrices de même taille, et **multiplier** une d'entre elles **par un scalaire** :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46f11f91",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, 2, 3, [ 1, 2, 3, 4, 5, 6 ] )\n",
    "N = matrix(QQ, 2, 3, [ 0, 1/2, -1, 2, 1/3, 0 ] )\n",
    "print(M - 2*N)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5bf5a69c",
   "metadata": {},
   "source": [
    "On peut enfin les **multiplier entre elles** si leurs tailles concordent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41976fe6",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, 2, 3, [ 1, 2, 3, 4, 5, 6 ] )\n",
    "A = matrix(QQ, 3, 2, [ 0, 1/2, -1, 2, 1/3, 0 ] )\n",
    "\n",
    "print(\"M = \")\n",
    "print(M)\n",
    "print(\"\\nA = \")\n",
    "print(A)\n",
    "print(\"\\nLe produit donne\")\n",
    "print(M * A)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad819ff5",
   "metadata": {},
   "source": [
    "Il est également possible de calculer les **puissances** d'une matrice et son **inverse** :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd9b9c11",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(QQ, 3, 3, [ 1, 1, 1, 0, 1, 2, 0, 1, 4 ] )\n",
    "print(\"A = \")\n",
    "print(A)\n",
    "print(\"\\nA^2 = \")\n",
    "print(A**2)\n",
    "print(\"\\nA^10 = \")\n",
    "print(A**10)\n",
    "print(\"\\nA^(-1) = \")\n",
    "print(A**(-1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72cfe508",
   "metadata": {},
   "source": [
    "### Accès aux coefficients, aux lignes et aux colonnes\n",
    "\n",
    "Pour **accéder au coefficient** situé sur la ligne d'indice $i$ et la colonne d'indice $j$  d'une matrice `M`, on utilisera la syntaxe `M[i,j]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a429411",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, 2, 3, [ 1, 2, 3, 4, 5, 6 ] )\n",
    "print(\"Sur la matrice M =\")\n",
    "print(M)\n",
    "print(\"le coefficient de coordonnées (0,1) est :\", M[0,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37866293",
   "metadata": {},
   "source": [
    "Pour **accéder à une ligne ou une colonne spécifique** d'une matrice, il existe les méthodes `row(i)` et `column(j)`, qui retournent la ligne ou la colonne attendue, sous la forme d'un **vecteur** (pour les colonnes, l'affichage se fait donc en ligne)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a23101f",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(M.row(0))\n",
    "print(M.column(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68c5fa3e",
   "metadata": {},
   "source": [
    "### Autres propriétés et opérations\n",
    "\n",
    "On peut obtenir différentes propriétés ou paramètres d'une matrice. Par exemple, son **rang** avec la méthode `rank()`, ou (si la matrice est carrée), son **déterminant** et sa **trace** avec les méthodes `det()` et `rank()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f010d04",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(QQ, 3, 3, [ 1, 1, 1, 2, 2, 2, 3, 4, 5 ] )\n",
    "print(A)\n",
    "\n",
    "print(\"Rang  :\", A.rank())\n",
    "print(\"Det   :\", A.det())\n",
    "print(\"Trace :\", A.trace())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73add6bb",
   "metadata": {},
   "source": [
    "Également, on obtient la **transposée** d'une matrice par la méthode `.transpose()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "273b7184",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(A.transpose())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13ab4af6",
   "metadata": {},
   "source": [
    "### Espaces vectoriels associés\n",
    "\n",
    "\n",
    "\n",
    "Les **espaces vectoriels engendrés** par les lignes et les colonnes sont accessibles avec les commandes `.row_space()` et `.column_space()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "495fccfe",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, [[1, 2, 3], [4, 5, 6]])\n",
    "print(\"M = \")\n",
    "print(M)\n",
    "\n",
    "V = M.row_space()\n",
    "print(\"\\n--- Espace lignes ---\")\n",
    "print(V)\n",
    "\n",
    "W = M.column_space()\n",
    "print(\"\\n--- Espace colonnes ---\")\n",
    "print(W)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1eca796",
   "metadata": {},
   "source": [
    "On peut accéder à une **base** d'un espace vectoriel avec `.basis()`, à sa **dimension** avec `.dimension()`, et à la **longueur** de ses vecteurs (en nombre de coordonnées) avec `.degree()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b34bf52a",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Base de l'espace ligne :\")\n",
    "print(V.basis())\n",
    "\n",
    "print(\"\\nDimension et longueur des vecteurs :\", (V.dimension(), V.degree()))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61d8e97a",
   "metadata": {},
   "source": [
    "On peut obtenir les **noyaux** à gauche et à droite d'une matrice $M$ avec `.left_kernel()` et `.right_kernel()`. Ce sont des espaces vectoriels si la matrice $M$ est bien définie sur un corps (par exemple, `QQ` ou `RR`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c00a4be7",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = matrix(QQ, [[1,1,1,1], [2,2,2,2], [3,4,5,6]])\n",
    "print(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2af06b1a",
   "metadata": {},
   "source": [
    "Pour le **noyau à gauche** :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b33592fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(M.left_kernel())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e352fade",
   "metadata": {},
   "source": [
    "Pour le **noyau à droite** :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "457a4947",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(M.right_kernel())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27f37f69",
   "metadata": {},
   "source": [
    "### Création de matrices spécifiques\n",
    "\n",
    "\n",
    "\n",
    "Quelques matrices spécifiques possèdent leurs constructeurs propres. Cela permet un gain de temps non-négligeable dans la construction de ces matrices.\n",
    "\n",
    "La **matrice nulle**, avec `matrix.zero(K, m, n)` ou son alias `zero_matrix(K, m, n)`, où `K` est le corps (ou l'anneau) de définition, `m` est le nombre de lignes et `n` le nombre de colonnes :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52db88e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "Z = zero_matrix(QQ, 3, 5)\n",
    "print(Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d19e13e",
   "metadata": {},
   "source": [
    "La **matrice pleine de $1$**, avec `matrix.ones(K, m, n)` ou son alias `ones_matrix(K, m, n)`, où `K` est le corps (ou l'anneau) de définition, `m` est le nombre de lignes et `n` le nombre de colonnes :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "081d6037",
   "metadata": {},
   "outputs": [],
   "source": [
    "J = ones_matrix(QQ, 2, 2)\n",
    "print(J)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c2c1640",
   "metadata": {},
   "source": [
    "La **matrice identité**, avec `matrix.identity(K, n)` ou son alias `identity_matrix(K, n)`, où `K` est le corps (ou l'anneau) de définition, et `n` est le nombre de lignes et de colonnes :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7e3b52d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "I = identity_matrix(QQ, 3)\n",
    "print(I)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5714383",
   "metadata": {},
   "source": [
    "## Résolution de systèmes linéaires\n",
    "\n",
    "\n",
    "Supposons que l'on souhaite résoudre, sur le corps $\\mathbb{Q}$, le système linéaire\n",
    "\n",
    "$$\n",
    "    \\left\\{\\begin{array}{cccccccc}\n",
    "    &x &+ & y &+ & z &= & 0 \\\\\n",
    "    &2x &+ &y &- &z &= &1 \\\\\n",
    "    &3x& + &2y&&& = &1\n",
    "    \\end{array}\\right.\n",
    "$$\n",
    "\n",
    "\n",
    "Rappelons que, mathématiquement, la méthode générique est la suivante :\n",
    "1. on construit la matrice $A$ associée  au système,\n",
    "1. on construit le vecteur $b$ associé au système,\n",
    "1. on \"résout\" l'équation $Au = b$ pour avoir une **solution particulière** $u = (x, y, z)$ du système,\n",
    "1. on cherche l'ensemble des **solutions homogènes** du système, c'est-à-dire le **noyau à droite** de la matrice $A$.\n",
    "\n",
    "**Attention !** Par défaut, Sagemath écrit les vecteurs comme des vecteurs lignes. Si vous souhaitez afficher un vecteur `v` sous forme de colonne, tapez `v.column()`.\n",
    "\n",
    "\n",
    "La seule opération qui nous manque pour effectuer les $4$ étapes ci-dessus est le **calcul d'une solution particulière**. Sagemath nous propose pour cela la méthode `A.solve_right(b)`, qui s'applique sur une matrice `A` avec comme paramètre un vecteur `b`, et qui retourne **un** vecteur `u` tel que `A * u == b`.\n",
    "\n",
    "\n",
    "Exemple ci-dessous :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "53edb94e",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = matrix(QQ, [[1, 1, 1], [2, 1, -1], [3, 2, 0]])\n",
    "b = vector(QQ, [0, 1, 1])\n",
    "u = A.solve_right(b)        # on peut aussi écrire :    u = A \\ b\n",
    "V = A.right_kernel()\n",
    "\n",
    "print(\"Les solutions du système sont les vecteurs de la forme u + v avec\")\n",
    "print(\"  u =\", u)\n",
    "print(\"et v un élément de l'espace vectoriel de dimension\", V.dimension(), \"dont une base est :\")\n",
    "print(V.basis())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6038ce2e",
   "metadata": {},
   "source": [
    "On peut faire une petite **vérification**, par exemple que, si $v$ est un vecteur de la base du noyau, alors $u + 6v$ est bien une solution du système :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2272ae71",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = V.basis()[0]\n",
    "A*(u + 6*v) == b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01fb1c4d",
   "metadata": {},
   "source": [
    "## Récapitulatif des instructions à connaître\n",
    "\n",
    "\n",
    "\n",
    "**Tableau récapitulatif** des instructions à connaître sur les matrices :\n",
    "\n",
    "| Méthode, fonction, instruction | Description |\n",
    "|:---:|:---:|\n",
    "| `matrix(K, L)` | Crée une matrice sur un corps `K` de liste de coefficients `L` (liste de sous-listes) |\n",
    "| `matrix(K, m, n, L)` | Crée une matrice sur un corps `K` de taille `m` x `n`, et de liste de coefficients `L` |\n",
    "| `zero_matrix(K, m, n)` | Crée la matrice nulle de taille `m` x `n` sur un corps `K`  |\n",
    "| `identity_matrix(K, n)` | Crée la matrice idnetité de taille `n` x `n` sur un corps `K`  |\n",
    "| `M[i,j]` | Accès au coefficient $(i,j)$ de `M` |\n",
    "| `M.nrows()` | Nombre de lignes de la matrice `M` |\n",
    "| `M.ncols()` | Nombre de colonnes de la matrice `M` |\n",
    "| `M.rows()` | Liste des lignes et des colonnes de la matrice `M` |\n",
    "| `M.columns()` | Liste des colonnes de la matrice `M` |\n",
    "| `M.row(i)` | Ligne numéro `i` de `M`, donnée comme un vecteur |\n",
    "| `M.column(j)` | Colonne numéro `j` de `M`, donnée comme un vecteur |\n",
    "| `M.rank()` | Rang de la matrice `M` |\n",
    "| `M.det()` | Déterminant de la matrice `M` |\n",
    "| `M.trace()` | Trace de la matrice `M` |\n",
    "| `M.transpose()` | Transposée de la matrice `M`  |\n",
    "| `M.left_kernel()` | Noyau à gauche de la matrice `M`  |\n",
    "| `M.solve_right(y)` | Une solution $x$ de l'équation $Mx = y$ (où `M` est une matrice et `y` un vecteur) |\n",
    "\n",
    "\n",
    "\n",
    "**Tableau récapitulatif** des instructions à connaître sur les vecteurs et espaces vectoriels :\n",
    "\n",
    "\n",
    "| Méthode, fonction, instruction | Description |\n",
    "|:---:|:---:|\n",
    "| `vector(K, L)` | Crée un vecteur sur un corps `K` de liste de coefficients `L` |\n",
    "| `zero_vector(K, n)` | Crée le vecteur nul de l'espace vectoriel sur `K` de dimension `n` |\n",
    "| `a.inner_product(b)` ou `a * b` | Produit scalaire des vecteurs `a` et `b` |\n",
    "| `a[i]` | Coefficient d'indice `i` du vecteur `a` |\n",
    "| `VectorSpace(K, n)` | Crée l'espace vectoriel canonique sur `K` de dimension `n` |\n",
    "| `V.basis()` | Base de l'espace vectoriel `V`, donné comme une liste de vecteurs |\n",
    "| `V.dimension()` | Dimension de l'espace vectoriel `V` |\n",
    "| `V.degree()` | Dimension de l'espace vectoriel dans lequel est plongé `V` en tant que sous-espace (autrement dit, longueur des vecteurs de `V`) |\n",
    "| `M.row_space()` | Espace vectoriel engendré par les lignes de `M` |\n",
    "| `M.column_space()` | Espace vectoriel engendré par les colonnes de `M` |\n",
    "| `M.right_kernel()` | Noyau à droite de la matrice `M`, donné comme un espace vectoriel  |\n",
    "| `M.left_kernel()` | Noyau à gauche de la matrice `M`, donné comme un espace vectoriel  |\n",
    "\n",
    "\n",
    "**D'autres méthodes :**\n",
    "\n",
    "\n",
    "| Méthode | Description |\n",
    "|:---:|:---:|\n",
    "| `M.is_invertible()` | Teste si la matrice `M`  est inversible (sur l'anneau des coefficients donné !) |\n",
    "| `M.is_symmetric()` | Teste si la matrice `M`  est symétrique |\n",
    "| `M.rref()` | Forme échelonnée réduite (par les lignes) de la matrice `M` |"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Sagemath",
   "language": "python",
   "name": "sagemath"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
