From 7301228e68d2ec31e9ca7342ea5aefbc8a6c6eef Mon Sep 17 00:00:00 2001 From: xadupre Date: Tue, 9 Sep 2025 10:29:42 +0200 Subject: [PATCH 1/6] small updates --- _doc/articles/2025/2025-09-03-ensae.rst | 4 ++-- _doc/practice/years/2025/index.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_doc/articles/2025/2025-09-03-ensae.rst b/_doc/articles/2025/2025-09-03-ensae.rst index 786dacd..4840c8c 100644 --- a/_doc/articles/2025/2025-09-03-ensae.rst +++ b/_doc/articles/2025/2025-09-03-ensae.rst @@ -1,5 +1,5 @@ -2025-09-03 : ENSAE -================== +2025-09-03 : ENSAE, Introduction et Attendus +============================================ **Objectif** diff --git a/_doc/practice/years/2025/index.rst b/_doc/practice/years/2025/index.rst index 5ef3eca..b635dd3 100644 --- a/_doc/practice/years/2025/index.rst +++ b/_doc/practice/years/2025/index.rst @@ -1,7 +1,7 @@ .. _l-notebook-2025: -2025 -==== +2025 : notebooks créés en séances +================================= .. toctree:: :maxdepth: 1 From c3e299914651b6010d8a2a455b8dde85cde8e7fc Mon Sep 17 00:00:00 2001 From: xadupre Date: Tue, 16 Sep 2025 22:24:27 +0200 Subject: [PATCH 2/6] plan --- _doc/articles/2025/2025-11-31-route2025.rst | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/_doc/articles/2025/2025-11-31-route2025.rst b/_doc/articles/2025/2025-11-31-route2025.rst index b8c2222..43649ea 100644 --- a/_doc/articles/2025/2025-11-31-route2025.rst +++ b/_doc/articles/2025/2025-11-31-route2025.rst @@ -49,6 +49,45 @@ Séance 3 * numpy, broadcasting * implémentation d'un chi-deux sans boucle +* comment implémenter la fonction `repeat_interleave + `_ + avec :epkg:`numpy` et sans boucle ? + En particulier cet exemple ``torch.repeat_interleave(y, torch.tensor([1, 2]), dim=0)`` + +Un problème... que fait la fonction suivante ? + +.. code-block:: python + + def reshape_keep0(arr, new_shape): + orig_shape = arr.shape + final_shape = [] + + for i, dim in enumerate(new_shape): + if dim == 0: + final_shape.append(orig_shape[i]) # garder dimension originale + else: + final_shape.append(dim) + return arr.reshape(tuple(final_shape)) + +Comment construire une fonction qui retourne l'argument ``new_shape`` +quand on connaît les dimensions de départ et d'arrivée ? +La fonction doit valider les exemples suivants, +chaque dimension sous forme de chaîne de caractères peut prendre n'importe +quelle valeur. + +.. code-block:: python + + self.assertEqual((0, 1024, -1), align(("d1", 4, 256, "d2"), ("d1", 1024, "d2"))) + self.assertEqual((0, 0, 1024), align(("d1", "d2", 4, 256), ("d1", "d2", 1024))) + self.assertEqual((6, -1), align((2, 3, "d1"), ("a", "d1"))) + self.assertEqual((6, -1), align((2, 3, "d1"), (6, "d1"))) + self.assertEqual((-1, 12, 196, 64), align(("d1", 196, 64), ("d2", 12, 196, 64))) + self.assertEqual((-1, 196, 64), align(("d1", 196, 64), ("d2", 196, 64))) + self.assertEqual((32, 196, 64), align((32, 196, 64), (32, 196, 64))) + self.assertEqual((4, 8, 196, 64), align((32, 196, 64), (4, 8, 196, 64))) + self.assertEqual((32, 196, 64), align((4, 8, 196, 64), (32, 196, 64))) + self.assertEqual((0, 196, 64), align(("d1", 196, 64), ("d1", 196, 64))) + self.assertEqual((0, 196, 2, 32), align(("d1", 196, 64), ("d1", 196, 2, 32))) Séance 4 ++++++++ From dee866208f998448c708c501dc47d31970ea6773 Mon Sep 17 00:00:00 2001 From: xadupre Date: Tue, 30 Sep 2025 22:22:23 +0200 Subject: [PATCH 3/6] plan --- _doc/practice/years/2025/index.rst | 1 + _doc/practice/years/2025/seance4_algo.ipynb | 306 ++++++++++++++++++ .../test_documentation_examples.py | 2 +- .../test_documentation_notebook.py | 2 +- 4 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 _doc/practice/years/2025/seance4_algo.ipynb diff --git a/_doc/practice/years/2025/index.rst b/_doc/practice/years/2025/index.rst index b635dd3..5c3413b 100644 --- a/_doc/practice/years/2025/index.rst +++ b/_doc/practice/years/2025/index.rst @@ -7,3 +7,4 @@ :maxdepth: 1 seance1_point2d + seance4_algo diff --git a/_doc/practice/years/2025/seance4_algo.ipynb b/_doc/practice/years/2025/seance4_algo.ipynb new file mode 100644 index 0000000..7adb5dd --- /dev/null +++ b/_doc/practice/years/2025/seance4_algo.ipynb @@ -0,0 +1,306 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Algorithms\n", + "\n", + "## Voyageur de commerce" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.90080623, 0.2350022 ],\n", + " [0.56755441, 0.54858335],\n", + " [0.60316886, 0.99559521],\n", + " [0.87287745, 0.22318813],\n", + " [0.21085165, 0.0701609 ]])" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "villes = np.random.rand(20, 2)\n", + "villes[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(1, 1, figsize=(3, 3))\n", + "indices = list(range(-1, villes.shape[0]))\n", + "ax.plot(villes[indices, 0], villes[indices, 1], \"o-\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def distance(v1, v2): # v1= np.array([0, 1]), v2= ....\n", + " return ((v1 - v2) ** 2).sum() ** 0.5\n", + "\n", + "\n", + "def plus_proche_non_visitee(villes, chemin):\n", + " depart = chemin[-1]\n", + " dmin, imin = None, None\n", + " for i in range(villes.shape[0]):\n", + " if i not in chemin:\n", + " d = distance(villes[depart], villes[i])\n", + " if dmin is None or d < dmin:\n", + " dmin, imin = d, i\n", + " return imin\n", + "\n", + "\n", + "def algo_proche_en_proche(villes):\n", + " chemin = [0]\n", + " while len(chemin) < villes.shape[0]:\n", + " # trouver la ville la plus proche non visitée de la dernière\n", + " # ville visitée et l'ajouter au chemin\n", + " inext = plus_proche_non_visitee(villes, chemin)\n", + " chemin.append(inext)\n", + " return chemin\n", + "\n", + "\n", + "chemin = algo_proche_en_proche(villes)\n", + "indices = chemin + chemin[:1]\n", + "fig, ax = plt.subplots(1, 1, figsize=(3, 3))\n", + "ax.plot(villes[indices, 0], villes[indices, 1], \"o-\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mieux -1 3 -0.15191965099971733 [0, 3, 14, 19] []\n", + "mieux -1 11 -0.5172511323315206 [19, 14, 3, 0, 16, 6, 10, 17, 15, 11, 18, 2] []\n", + "mieux 11 13 -0.0513745444570991 [1, 12] [12, 1]\n", + "mieux 11 17 -0.0044994455150375035 [12, 1, 7, 9, 4, 5] [5, 4, 9, 7, 1, 12]\n", + "mieux 15 17 -0.03444152981270798 [1, 12] [12, 1]\n", + "mieux 11 13 -0.12384307859548493 [5, 4] [4, 5]\n" + ] + }, + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def elimine_croisements(villes, chemin):\n", + " C = chemin\n", + " while True:\n", + " mieux = 0\n", + " for i in range(-1, villes.shape[0]):\n", + " for j in range(i + 2, villes.shape[0] - 1):\n", + " delta = (\n", + " -distance(villes[C[i]], villes[C[i + 1]])\n", + " - distance(villes[C[j]], villes[C[j + 1]])\n", + " + distance(villes[C[i]], villes[C[j]])\n", + " + distance(villes[C[i + 1]], villes[C[j + 1]])\n", + " )\n", + " if delta < 0:\n", + " mieux += 1\n", + " print(\"mieux\", i, j, delta, chemin[i + 1 : j + 1], chemin[j:i:-1])\n", + " # c'est mieux... on retourne les villes du chemin\n", + " # entre i+1 et j inclus\n", + " if i >= 0:\n", + " chemin[i + 1 : j + 1] = chemin[j:i:-1]\n", + " else:\n", + " chemin[i + 1 : j + 1] = chemin[j::-1]\n", + " if mieux == 0:\n", + " break\n", + "\n", + "\n", + "elimine_croisements(villes, chemin)\n", + "fig, ax = plt.subplots(1, 1, figsize=(3, 3))\n", + "indices = chemin + chemin[:1]\n", + "ax.plot(villes[indices, 0], villes[indices, 1], \"o-\")\n", + "ax.plot(villes[chemin[:1], 0], villes[chemin[:1], 1], \"or\")\n", + "ax.plot(villes[chemin[-1:], 0], villes[chemin[-1:], 1], \"og\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Distance d'édition" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(np.int64(1), np.int64(1)), (np.int64(2), np.int64(1)), (np.int64(3), np.int64(2)), (np.int64(4), np.int64(3)), (np.int64(4), np.int64(4)), (5, 5)]\n", + "[('E', 'E'), ('N', 'E'), ('S', 'S'), ('A', 'A'), ('A', 'N'), ('E', 'E')]\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[0., 1., 2., 3., 4., 5.],\n", + " [1., 0., 1., 2., 3., 4.],\n", + " [2., 1., 1., 2., 2., 3.],\n", + " [3., 2., 1., 2., 3., 3.],\n", + " [4., 3., 2., 1., 2., 3.],\n", + " [5., 4., 3., 2., 2., 2.]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def distance_edition(m1, m2):\n", + " cout = np.empty((len(m1) + 1, len(m2) + 1))\n", + " predi = np.empty((len(m1) + 1, len(m2) + 1), dtype=np.int64)\n", + " predj = np.empty((len(m1) + 1, len(m2) + 1), dtype=np.int64)\n", + " cout[:, 0] = np.arange(len(m1) + 1)\n", + " cout[0, :] = np.arange(len(m2) + 1)\n", + " predi[:, 0] = np.arange(len(m1) + 1) - 1\n", + " predj[:, 0] = 0\n", + " predi[0, :] = 0\n", + " predj[0, :] = np.arange(len(m2) + 1) - 1\n", + " for i in range(1, len(m1) + 1):\n", + " for j in range(1, len(m2) + 1):\n", + " c_sup = cout[i - 1, j] + 1\n", + " c_ins = cout[i, j - 1] + 1\n", + " c_cmp = cout[i - 1, j - 1] + (1 if m1[i - 1] != m2[j - 1] else 0)\n", + " if c_cmp <= min(c_sup, c_ins):\n", + " cout[i, j], predi[i, j], predj[i, j] = c_cmp, i - 1, j - 1\n", + " elif c_sup <= c_ins:\n", + " cout[i, j], predi[i, j], predj[i, j] = c_sup, i - 1, j\n", + " else:\n", + " cout[i, j], predi[i, j], predj[i, j] = c_ins, i, j - 1\n", + " # alignement\n", + " alignement = [(len(m1), len(m2))]\n", + " while min(alignement[-1]) >= 0:\n", + " i, j = alignement[-1]\n", + " i, j = predi[i, j], predj[i, j]\n", + " alignement.append((i, j))\n", + " alignement = alignement[::-1][2:]\n", + " lettres = [(m1[i - 1], m2[j - 1]) for i, j in alignement]\n", + " return cout, alignement, lettres\n", + "\n", + "\n", + "cout, alignement, lettres = distance_edition(\"ENSAE\", \"ESANE\")\n", + "print(alignement)\n", + "print(lettres)\n", + "cout" + ] + }, + { + "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.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/_unittests/ut_xrun_doc/test_documentation_examples.py b/_unittests/ut_xrun_doc/test_documentation_examples.py index c7a4a4f..ef8a32b 100644 --- a/_unittests/ut_xrun_doc/test_documentation_examples.py +++ b/_unittests/ut_xrun_doc/test_documentation_examples.py @@ -40,7 +40,7 @@ def run_test(self, fold: str, name: str, verbose=0) -> int: cmds = [sys.executable, "-u", os.path.join(fold, name)] p = subprocess.Popen(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE) res = p.communicate() - out, err = res + _out, err = res st = err.decode("ascii", errors="ignore") if "No such file or directory" in st: raise FileNotFoundError(st) # noqa: B904 diff --git a/_unittests/ut_xrun_doc/test_documentation_notebook.py b/_unittests/ut_xrun_doc/test_documentation_notebook.py index 315f3ed..3ecf8b3 100644 --- a/_unittests/ut_xrun_doc/test_documentation_notebook.py +++ b/_unittests/ut_xrun_doc/test_documentation_notebook.py @@ -74,7 +74,7 @@ def run_test(self, nb_name: str, verbose=0) -> int: cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) res = p.communicate() - out, err = res + _out, err = res st = err.decode("ascii", errors="ignore") if "No such file or directory" in st: raise FileNotFoundError(st) # noqa: B904 From 9d15303bd8acb97910a872199ce24471ff6a3029 Mon Sep 17 00:00:00 2001 From: xadupre Date: Tue, 7 Oct 2025 22:17:48 +0200 Subject: [PATCH 4/6] add notebook --- _doc/practice/years/2025/index.rst | 1 + _doc/practice/years/2025/seance4_algo.ipynb | 14 +- _doc/practice/years/2025/seance5_algo2.ipynb | 990 +++++++++++++++++++ 3 files changed, 992 insertions(+), 13 deletions(-) create mode 100644 _doc/practice/years/2025/seance5_algo2.ipynb diff --git a/_doc/practice/years/2025/index.rst b/_doc/practice/years/2025/index.rst index 5c3413b..0a22147 100644 --- a/_doc/practice/years/2025/index.rst +++ b/_doc/practice/years/2025/index.rst @@ -8,3 +8,4 @@ seance1_point2d seance4_algo + seance5_algo2 diff --git a/_doc/practice/years/2025/seance4_algo.ipynb b/_doc/practice/years/2025/seance4_algo.ipynb index 7adb5dd..bbe32af 100644 --- a/_doc/practice/years/2025/seance4_algo.ipynb +++ b/_doc/practice/years/2025/seance4_algo.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Algorithms\n", + "# Algorithmes\n", "\n", "## Voyageur de commerce" ] @@ -287,18 +287,6 @@ "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.9" } }, "nbformat": 4, diff --git a/_doc/practice/years/2025/seance5_algo2.ipynb b/_doc/practice/years/2025/seance5_algo2.ipynb new file mode 100644 index 0000000..7e7d170 --- /dev/null +++ b/_doc/practice/years/2025/seance5_algo2.ipynb @@ -0,0 +1,990 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Algorithmes\n", + "\n", + "## Mesurer le temps" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[, RuntimeError('stop')]\n" + ] + } + ], + "source": [ + "def fonction1():\n", + " raise RuntimeError(\"stop\")\n", + "\n", + "\n", + "def fonction2():\n", + " return fonction1()\n", + "\n", + "\n", + "def fonction3():\n", + " return fonction2()\n", + "\n", + "\n", + "try:\n", + " fonction3()\n", + "except Exception as e:\n", + " print([type(e), e])" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "list 0.00920867919921875\n" + ] + } + ], + "source": [ + "def recherche_list(ensemble: list, element) -> bool:\n", + " return element in ensemble\n", + "\n", + "\n", + "def recherche_set(ensemble: set, element) -> bool:\n", + " return element in ensemble\n", + "\n", + "\n", + "def recherche_dict(ensemble: dict, element) -> bool:\n", + " return element in ensemble\n", + "\n", + "\n", + "N = 10000\n", + "list_entier = list(range(N))\n", + "set_entier = set(range(N))\n", + "dict_entier = {k: 0 for k in range(N)}\n", + "\n", + "T = 100\n", + "import time\n", + "\n", + "begin = time.time()\n", + "for i in range(T):\n", + " recherche_list(list_entier, 9000)\n", + "duree = time.time() - begin\n", + "print(\"list\", duree)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "list 0.6168732643127441\n", + "set 0.0010602474212646484\n", + "dict 0.0015003681182861328\n" + ] + } + ], + "source": [ + "T = 10000\n", + "el = 9999\n", + "begin = time.time()\n", + "for i in range(T):\n", + " recherche_list(list_entier, el)\n", + "duree = time.time() - begin\n", + "print(\"list\", duree)\n", + "\n", + "begin = time.time()\n", + "for i in range(T):\n", + " recherche_set(set_entier, el)\n", + "duree = time.time() - begin\n", + "print(\"set\", duree)\n", + "\n", + "begin = time.time()\n", + "for i in range(T):\n", + " recherche_dict(dict_entier, el)\n", + "duree = time.time() - begin\n", + "print(\"dict\", duree)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b'Bonjour le mondesd\\xe3\\x83\\x8a\\xe3\\x83\\xab\\xe3\\x83\\x88'\n", + "9b158061cd\n" + ] + } + ], + "source": [ + "import hashlib\n", + "\n", + "# Texte à hacher\n", + "texte = \"Bonjour le mondesdナルト\".encode(\"utf-8\")\n", + "print(texte)\n", + "\n", + "# Création du hash SHA-256\n", + "hash_obj = hashlib.sha256(texte)\n", + "hash_hex = hash_obj.hexdigest()[:10]\n", + "\n", + "print(hash_hex)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Profiling" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def f():\n", + " for i in range(T):\n", + " recherche_list(list_entier, el)\n", + " recherche_set(set_entier, el)\n", + " recherche_dict(dict_entier, el)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " _ ._ __/__ _ _ _ _ _/_ Recorded: 22:16:49 Samples: 643\n", + " /_//_/// /_\\ / //_// / //_'/ // Duration: 0.664 CPU time: 0.669\n", + "/ _/ v5.1.1\n", + "\n", + "Profile at /tmp/ipykernel_231901/1337574655.py:4\n", + "\n", + "0.663 ZMQInteractiveShell.run_ast_nodes IPython/core/interactiveshell.py:3418\n", + "`- 0.662 /tmp/ipykernel_231901/1337574655.py:1\n", + " `- 0.662 f /tmp/ipykernel_231901/2115577803.py:1\n", + " |- 0.648 recherche_list /tmp/ipykernel_231901/3550779215.py:1\n", + " `- 0.012 [self] /tmp/ipykernel_231901/2115577803.py\n", + "\n", + "\n" + ] + } + ], + "source": [ + "from pyinstrument import Profiler\n", + "\n", + "profiler = Profiler()\n", + "profiler.start()\n", + "\n", + "# Code à profiler\n", + "f()\n", + "\n", + "profiler.stop()\n", + "print(profiler.output_text())" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 30757 function calls (30742 primitive calls) in 0.667 seconds\n", + "\n", + " Ordered by: internal time\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 10000 0.638 0.000 0.638 0.000 3550779215.py:1(recherche_list)\n", + " 1 0.007 0.007 0.459 0.459 2115577803.py:1(f)\n", + " 6/4 0.007 0.001 0.007 0.002 events.py:86(_run)\n", + " 2/1 0.005 0.003 0.459 0.459 :1()\n", + " 3/1 0.003 0.001 0.000 0.000 selectors.py:451(select)\n", + " 10000 0.002 0.000 0.002 0.000 3550779215.py:4(recherche_set)\n", + " 10000 0.002 0.000 0.002 0.000 3550779215.py:7(recherche_dict)\n", + " 14 0.001 0.000 0.001 0.000 socket.py:626(send)\n", + " 1 0.000 0.000 0.020 0.020 history.py:833(_writeout_input_cache)\n", + " 3/1 0.000 0.000 0.000 0.000 {method 'poll' of 'select.epoll' objects}\n", + " 2 0.000 0.000 0.006 0.003 socket.py:703(send_multipart)\n", + " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", + " 1 0.000 0.000 0.027 0.027 history.py:55(only_when_enabled)\n", + " 2 0.000 0.000 0.000 0.000 {method 'recv' of '_socket.socket' objects}\n", + " 2 0.000 0.000 0.000 0.000 {method '__exit__' of 'sqlite3.Connection' objects}\n", + " 2 0.000 0.000 0.000 0.000 socket.py:774(recv_multipart)\n", + " 4 0.000 0.000 0.171 0.043 base_events.py:1922(_run_once)\n", + " 5 0.000 0.000 0.000 0.000 attrsettr.py:66(_get_attr_opt)\n", + " 72 0.000 0.000 0.000 0.000 enum.py:1538(_get_value)\n", + " 2/1 0.000 0.000 0.650 0.650 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.000 0.000 {method 'execute' of 'sqlite3.Connection' objects}\n", + " 152/148 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}\n", + " 16 0.000 0.000 0.000 0.000 enum.py:1545(__or__)\n", + " 1 0.000 0.000 0.000 0.000 poll.py:80(poll)\n", + " 5 0.000 0.000 0.000 0.000 attrsettr.py:43(__getattr__)\n", + " 2/1 0.000 0.000 0.027 0.027 decorator.py:229(fun)\n", + " 31 0.000 0.000 0.000 0.000 enum.py:720(__call__)\n", + " 1 0.000 0.000 0.000 0.000 {method 'send' of '_socket.socket' objects}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:3133(_bind)\n", + " 8 0.000 0.000 0.000 0.000 enum.py:1556(__and__)\n", + " 6/4 0.000 0.000 0.001 0.000 {method 'run' of '_contextvars.Context' objects}\n", + " 1 0.000 0.000 0.000 0.000 kernelbase.py:302(poll_control_queue)\n", + " 31 0.000 0.000 0.000 0.000 enum.py:1123(__new__)\n", + " 6 0.000 0.000 0.000 0.000 typing.py:392(inner)\n", + " 2 0.000 0.000 0.006 0.003 iostream.py:278(_really_send)\n", + " 1 0.000 0.000 0.020 0.020 history.py:845(writeout_cache)\n", + " 2 0.000 0.000 0.007 0.003 zmqstream.py:583(_handle_events)\n", + " 1 0.000 0.000 0.000 0.000 selector_events.py:129(_read_from_self)\n", + " 1 0.000 0.000 0.000 0.000 traitlets.py:1527(_notify_observers)\n", + " 8 0.000 0.000 0.000 0.000 traitlets.py:676(__get__)\n", + " 3 0.000 0.000 0.000 0.000 zmqstream.py:686(_update_handler)\n", + " 3 0.000 0.000 0.000 0.000 ioloop.py:742(_run_callback)\n", + " 2 0.000 0.000 0.000 0.000 typing.py:1492(__subclasscheck__)\n", + " 1 0.000 0.000 0.000 0.000 decorator.py:199(fix)\n", + " 3 0.000 0.000 0.000 0.000 zmqstream.py:663(_rebuild_io_state)\n", + " 2 0.000 0.000 0.006 0.003 iostream.py:157(_handle_event)\n", + " 2 0.000 0.000 0.006 0.003 zmqstream.py:556(_run_callback)\n", + " 1 0.000 0.000 0.000 0.000 kernelbase.py:324(_flush)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:3631(set)\n", + " 4 0.000 0.000 0.000 0.000 queue.py:97(empty)\n", + " 7 0.000 0.000 0.000 0.000 base_events.py:738(time)\n", + " 2 0.000 0.000 0.006 0.003 zmqstream.py:624(_handle_recv)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:225(get)\n", + " 8 0.000 0.000 0.000 0.000 traitlets.py:629(get)\n", + " 3 0.000 0.000 0.000 0.000 base_events.py:818(_call_soon)\n", + " 25 0.000 0.000 0.000 0.000 {built-in method builtins.len}\n", + " 1 0.000 0.000 0.000 0.000 zmqstream.py:427(flush)\n", + " 4 0.000 0.000 0.000 0.000 typing.py:1285(__hash__)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:708(__set__)\n", + " 1 0.000 0.000 0.000 0.000 asyncio.py:225(add_callback)\n", + " 5 0.000 0.000 0.000 0.000 selector_events.py:750(_process_events)\n", + " 2 0.000 0.000 0.006 0.003 iostream.py:276()\n", + " 1 0.000 0.000 0.000 0.000 _base.py:537(set_result)\n", + " 1 0.000 0.000 0.000 0.000 iostream.py:718(_rotate_buffers)\n", + " 1 0.000 0.000 0.000 0.000 iostream.py:616(_flush)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:689(set)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:718(_validate)\n", + " 5 0.000 0.000 0.000 0.000 :1390(_handle_fromlist)\n", + " 1 0.000 0.000 0.000 0.000 threading.py:311(_acquire_restore)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2949(apply_defaults)\n", + " 2 0.000 0.000 0.000 0.000 typing.py:1221(__instancecheck__)\n", + " 5 0.000 0.000 0.000 0.000 {built-in method builtins.getattr}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:3272(bind)\n", + " 3 0.000 0.000 0.000 0.000 threading.py:299(__enter__)\n", + " 2 0.000 0.000 0.000 0.000 base_events.py:1907(_add_callback)\n", + " 10 0.000 0.000 0.000 0.000 {built-in method builtins.hasattr}\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:3474(validate)\n", + " 1 0.000 0.000 0.000 0.000 iostream.py:710(_flush_buffers)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:209(put_nowait)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:3624(validate_elements)\n", + " 7 0.000 0.000 0.000 0.000 {built-in method time.monotonic}\n", + " 1 0.000 0.000 0.000 0.000 queues.py:186(put)\n", + " 3 0.000 0.000 0.000 0.000 events.py:36(__init__)\n", + " 1 0.000 0.000 0.000 0.000 zmqstream.py:468(update_flag)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:727(_cross_validate)\n", + " 7 0.000 0.000 0.000 0.000 {built-in method builtins.max}\n", + " 3 0.000 0.000 0.000 0.000 threading.py:302(__exit__)\n", + " 1 0.000 0.000 0.000 0.000 traitlets.py:1512(_notify_trait)\n", + " 10 0.000 0.000 0.000 0.000 {method 'popleft' of 'collections.deque' objects}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2896(args)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2919(kwargs)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:2304(validate)\n", + " 2 0.000 0.000 0.000 0.000 base_events.py:789(call_soon)\n", + " 8 0.000 0.000 0.000 0.000 {method '__exit__' of '_thread.lock' objects}\n", + " 1 0.000 0.000 0.000 0.000 traitlets.py:1523(notify_change)\n", + " 9 0.000 0.000 0.000 0.000 {method 'append' of 'collections.deque' objects}\n", + " 2 0.000 0.000 0.000 0.000 iostream.py:213(_is_master_process)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:256(get_nowait)\n", + " 1 0.000 0.000 0.006 0.006 asyncio.py:200(_handle_events)\n", + " 1 0.000 0.000 0.000 0.000 futures.py:396(_call_set_state)\n", + " 1 0.000 0.000 0.000 0.000 threading.py:424(notify_all)\n", + " 2 0.000 0.000 0.000 0.000 queues.py:322(_consume_expired)\n", + " 1 0.000 0.000 0.000 0.000 threading.py:627(clear)\n", + " 28 0.000 0.000 0.000 0.000 typing.py:2187(cast)\n", + " 2 0.000 0.000 0.000 0.000 {built-in method builtins.issubclass}\n", + " 4 0.000 0.000 0.000 0.000 zmqstream.py:542(sending)\n", + " 5 0.000 0.000 0.000 0.000 {method 'upper' of 'str' objects}\n", + " 2 0.000 0.000 0.000 0.000 :121(__subclasscheck__)\n", + " 6 0.000 0.000 0.000 0.000 {built-in method builtins.next}\n", + " 2 0.000 0.000 0.000 0.000 {built-in method _abc._abc_subclasscheck}\n", + " 1 0.000 0.000 0.000 0.000 base_events.py:842(call_soon_threadsafe)\n", + " 6 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}\n", + " 2 0.000 0.000 0.000 0.000 {method 'set_result' of '_asyncio.Future' objects}\n", + " 2 0.000 0.000 0.000 0.000 {built-in method builtins.min}\n", + " 3 0.000 0.000 0.000 0.000 {method 'acquire' of '_thread.lock' objects}\n", + " 2 0.000 0.000 0.000 0.000 iostream.py:216(_check_mp_mode)\n", + " 1 0.000 0.000 0.000 0.000 history.py:839(_writeout_output_cache)\n", + " 1 0.000 0.000 0.000 0.000 selector_events.py:141(_write_to_self)\n", + " 2 0.000 0.000 0.000 0.000 {built-in method math.ceil}\n", + " 1 0.000 0.000 0.000 0.000 concurrent.py:182(future_set_result_unless_cancelled)\n", + " 1 0.000 0.000 0.000 0.000 _base.py:337(_invoke_callbacks)\n", + " 3 0.000 0.000 0.000 0.000 {method 'items' of 'mappingproxy' objects}\n", + " 1 0.000 0.000 0.000 0.000 queues.py:317(__put_internal)\n", + " 2 0.000 0.000 0.000 0.000 selectors.py:275(_key_from_fd)\n", + " 4 0.000 0.000 0.000 0.000 queue.py:209(_qsize)\n", + " 1 0.000 0.000 0.000 0.000 threading.py:308(_release_save)\n", + " 2 0.000 0.000 0.000 0.000 {built-in method _contextvars.copy_context}\n", + " 1 0.000 0.000 0.000 0.000 {built-in method _asyncio.get_running_loop}\n", + " 1 0.000 0.000 0.000 0.000 threading.py:394(notify)\n", + " 2 0.000 0.000 0.000 0.000 {built-in method posix.getpid}\n", + " 4 0.000 0.000 0.000 0.000 {method 'get' of 'dict' objects}\n", + " 1 0.000 0.000 0.000 0.000 {built-in method _heapq.heappop}\n", + " 1 0.000 0.000 0.000 0.000 {method 'values' of 'mappingproxy' objects}\n", + " 4 0.000 0.000 0.000 0.000 {built-in method builtins.hash}\n", + " 1 0.000 0.000 0.000 0.000 {method '__enter__' of '_thread.RLock' objects}\n", + " 10 0.000 0.000 0.000 0.000 inspect.py:2808(kind)\n", + " 1 0.000 0.000 0.000 0.000 {built-in method _thread.allocate_lock}\n", + " 1 0.000 0.000 0.000 0.000 unix_events.py:81(_process_self_data)\n", + " 2 0.000 0.000 0.000 0.000 traitlets.py:3486(validate_elements)\n", + " 2 0.000 0.000 0.000 0.000 {method '__enter__' of '_thread.lock' objects}\n", + " 5 0.000 0.000 0.000 0.000 zmqstream.py:538(receiving)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:173(qsize)\n", + " 1 0.000 0.000 0.000 0.000 poll.py:31(register)\n", + " 2 0.000 0.000 0.000 0.000 {built-in method builtins.iter}\n", + " 2 0.000 0.000 0.000 0.000 {method '__exit__' of '_thread.RLock' objects}\n", + " 1 0.000 0.000 0.000 0.000 zmqstream.py:694()\n", + " 3 0.000 0.000 0.000 0.000 base_events.py:543(_check_closed)\n", + " 5 0.000 0.000 0.000 0.000 base_events.py:2017(get_debug)\n", + " 2 0.000 0.000 0.000 0.000 iostream.py:255(closed)\n", + " 4 0.000 0.000 0.000 0.000 inspect.py:2796(name)\n", + " 1 0.000 0.000 0.000 0.000 {method 'items' of 'dict' objects}\n", + " 2 0.000 0.000 0.000 0.000 {method 'cancelled' of '_asyncio.Future' objects}\n", + " 1 0.000 0.000 0.000 0.000 queues.py:309(_get)\n", + " 1 0.000 0.000 0.000 0.000 zmqstream.py:659(_check_closed)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:312(_put)\n", + " 4 0.000 0.000 0.000 0.000 inspect.py:3089(parameters)\n", + " 2 0.000 0.000 0.000 0.000 {method 'extend' of 'list' objects}\n", + " 1 0.000 0.000 0.000 0.000 threading.py:314(_is_owned)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:177(empty)\n", + " 1 0.000 0.000 0.000 0.000 {method '_is_owned' of '_thread.RLock' objects}\n", + " 1 0.000 0.000 0.000 0.000 {method 'done' of '_asyncio.Future' objects}\n", + " 1 0.000 0.000 0.000 0.000 base_events.py:724(is_closed)\n", + " 1 0.000 0.000 0.000 0.000 queues.py:59(_set_timeout)\n", + " 1 0.000 0.000 0.000 0.000 {method 'release' of '_thread.lock' objects}\n", + " 1 0.000 0.000 0.000 0.000 locks.py:224(clear)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2888(__init__)" + ] + } + ], + "source": [ + "%prun f()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Optimisation d'un programme" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([[0.02609378, 0.47304915],\n", + " [0.11827469, 0.76657083],\n", + " [0.827706 , 0.26337121],\n", + " [0.56057621, 0.53610594],\n", + " [0.22134542, 0.73108227]]),\n", + " [7, 19, 0, 9, 18, 8, 17, 15, 5, 14, 2, 13, 11, 12, 6, 16, 10, 1, 4, 3])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "\n", + "def distance(v1, v2): # v1= np.array([0, 1]), v2= ....\n", + " return ((v1 - v2) ** 2).sum() ** 0.5\n", + " # return ((v1[0] - v2[0]) ** 2 + (v1[1] - v2[1]) ** 2) ** 0.5\n", + "\n", + "\n", + "def plus_proche_non_visitee(villes, chemin):\n", + " depart = chemin[-1]\n", + " dmin, imin = None, None\n", + " for i in range(villes.shape[0]):\n", + " if i not in chemin:\n", + " d = distance(villes[depart], villes[i])\n", + " if dmin is None or d < dmin:\n", + " dmin, imin = d, i\n", + " return imin\n", + "\n", + "\n", + "def algo_proche_en_proche(villes):\n", + " chemin = [0]\n", + " while len(chemin) < villes.shape[0]:\n", + " # trouver la ville la plus proche non visitée de la dernière\n", + " # ville visitée et l'ajouter au chemin\n", + " inext = plus_proche_non_visitee(villes, chemin)\n", + " chemin.append(inext)\n", + " return chemin\n", + "\n", + "\n", + "def elimine_croisements(villes, chemin):\n", + " C = chemin\n", + " while True:\n", + " mieux = 0\n", + " for i in range(-1, villes.shape[0]):\n", + " for j in range(i + 2, villes.shape[0] - 1):\n", + " delta = (\n", + " -distance(villes[C[i]], villes[C[i + 1]])\n", + " - distance(villes[C[j]], villes[C[j + 1]])\n", + " + distance(villes[C[i]], villes[C[j]])\n", + " + distance(villes[C[i + 1]], villes[C[j + 1]])\n", + " )\n", + " if delta < 0:\n", + " mieux += 1\n", + " if i >= 0:\n", + " chemin[i + 1 : j + 1] = chemin[j:i:-1]\n", + " else:\n", + " chemin[i + 1 : j + 1] = chemin[j::-1]\n", + " if mieux == 0:\n", + " break\n", + "\n", + "\n", + "villes = np.random.rand(20, 2)\n", + "chemin = algo_proche_en_proche(villes)\n", + "elimine_croisements(villes, chemin)\n", + "villes[:5], chemin" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "t= 0 N= 100\n", + "[75, 51, 15, 20, 73, 40, 82, 38, 59, 94, 36, 54, 88, 26, 97, 44, 81, 13, 96, 99, 28, 9, 14, 78, 46, 85, 83, 22, 93, 52, 2, 56, 42, 27, 49, 25, 62, 39, 5, 92, 34, 21, 66, 16, 30, 37, 70, 57, 76, 86, 63, 33, 19, 58, 43, 23, 65, 3, 45, 72, 77, 0, 60, 32, 89, 4, 61, 71, 84, 79, 18, 87, 67, 31, 24, 74, 50, 10, 91, 68, 98, 1, 64, 41, 48, 95, 80, 69, 29, 55, 12, 47, 6, 11, 35, 90, 17, 7, 53, 8]\n" + ] + } + ], + "source": [ + "def problem(N, T):\n", + " for t in range(T):\n", + " print(\"t=\", t, \"N=\", N)\n", + " villes = np.random.rand(N, 2)\n", + " chemin = algo_proche_en_proche(villes)\n", + " elimine_croisements(villes, chemin)\n", + " return chemin\n", + "\n", + "\n", + "print(problem(100, 1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python\n", + "import cProfile, pstats, io\n", + "from pstats import SortKey\n", + "pr = cProfile.Profile()\n", + "pr.enable()\n", + "\n", + "problem(10, 5)\n", + "\n", + "pr.disable()\n", + "s = io.StringIO()\n", + "sortby = SortKey.CUMULATIVE\n", + "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", + "ps.print_stats()\n", + "print(s.getvalue().replace(\"= 0:\n", + " chemin[i + 1 : j + 1] = chemin[j:i:-1]\n", + " else:\n", + " chemin[i + 1 : j + 1] = chemin[j::-1]\n", + " if mieux == 0:\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Préfixes" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'': [''], 'B': ['A', 'CA', ''], 'E': ['E', 'F', 'G'], 'A': ['B', 'BC']}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def casse_liste(liste):\n", + " premiere_lettre = set(mot[:1] for mot in liste)\n", + " res = {}\n", + " for p in premiere_lettre:\n", + " res[p] = [mot[1:] for mot in liste if mot[:1] == p]\n", + " return res\n", + "\n", + "\n", + "liste = [\"AB\", \"ABC\", \"BA\", \"BCA\", \"B\", \"EE\", \"EF\", \"EG\", \"\"]\n", + "casse_liste(liste)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'': {},\n", + " 'B': {'C': {'A': {}}, '': {}, 'A': {}},\n", + " 'E': {'E': {}, 'F': {}, 'G': {}},\n", + " 'A': {'B': {'': {}, 'C': {}}}}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def casse_liste_rec(liste):\n", + " if not liste or liste == [\"\"]:\n", + " return {}\n", + " premiere_lettre = set(mot[:1] for mot in liste)\n", + " res = {}\n", + " for p in premiere_lettre:\n", + " res[p] = casse_liste_rec([mot[1:] for mot in liste if mot[:1] == p])\n", + " return res\n", + "\n", + "\n", + "liste = [\"AB\", \"ABC\", \"BA\", \"BCA\", \"B\", \"EE\", \"EF\", \"EG\", \"\"]\n", + "casse_liste_rec(liste)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'': {},\n", + " 'A': {'B': {'': {}, 'C': {}}},\n", + " 'B': {'': {}, 'A': {}, 'C': {'A': {}}},\n", + " 'E': {'E': {}, 'F': {}, 'G': {}}}\n" + ] + } + ], + "source": [ + "import pprint\n", + "\n", + "pprint.pprint(casse_liste_rec(liste))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['', 'BCA', 'B', 'BA', 'EE', 'EF', 'EG', 'AB', 'ABC']" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def reconstruit_liste(trie, prefixe=\"\"):\n", + " mots = []\n", + " for lettre, sous_trie in trie.items():\n", + " nouveau_prefixe = prefixe + lettre\n", + " if not sous_trie: # Si le sous-trie est vide, c'est la fin d'un mot\n", + " mots.append(nouveau_prefixe)\n", + " else:\n", + " mots.extend(reconstruit_liste(sous_trie, nouveau_prefixe))\n", + " return mots\n", + "\n", + "\n", + "liste = [\"AB\", \"ABC\", \"BA\", \"BCA\", \"B\", \"EE\", \"EF\", \"EG\", \"\"]\n", + "trie = casse_liste_rec(liste)\n", + "liste_reconstruite = reconstruit_liste(trie)\n", + "liste_reconstruite" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, True, False)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def search_trie(trie, mot):\n", + " if not mot:\n", + " return True # Mot vide, considéré comme présent\n", + " if not trie:\n", + " return False # Trie vide, mot absent\n", + " premiere_lettre = mot[0]\n", + " if premiere_lettre not in trie:\n", + " return False\n", + " return search_trie(trie[premiere_lettre], mot[1:])\n", + "\n", + "\n", + "search_trie(trie, \"\"), search_trie(trie, \"BC\"), search_trie(trie, \"Z\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, True, False)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def search_trie2(trie, mot):\n", + " current = trie\n", + " for lettre in mot:\n", + " if lettre not in current:\n", + " return False\n", + " current = current[lettre]\n", + " return True\n", + "\n", + "\n", + "search_trie2(trie, \"\"), search_trie2(trie, \"BC\"), search_trie2(trie, \"Z\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['BCA', 'B', 'BA', 'EE', 'EF', 'EG', 'AB']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def intersection_tries_naive(trie1, trie2):\n", + " liste = reconstruit_liste(trie1)\n", + " return [mot for mot in liste if search_trie2(trie2, mot)]\n", + "\n", + "\n", + "liste1 = [\"AB\", \"ABC\", \"BA\", \"BCA\", \"B\", \"EE\", \"EF\", \"EG\"]\n", + "trie1 = casse_liste_rec(liste1)\n", + "liste2 = [\"AB\", \"BA\", \"BCA\", \"B\", \"EE\", \"EF\", \"EG\", \"EH\"]\n", + "trie2 = casse_liste_rec(liste2)\n", + "intersection_tries_naive(trie1, trie2)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['BCA', 'B', 'BA', 'EE', 'EF', 'EG']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def intersection_tries(trie1, trie2, prefixe=\"\"):\n", + " mots = []\n", + " # Parcourir les clés communes aux deux tries\n", + " for lettre in set(trie1.keys()) & set(trie2.keys()):\n", + " nouveau_prefixe = prefixe + lettre\n", + " # Si les deux sous-tries sont vides, c'est un mot commun\n", + " if not trie1[lettre] and not trie2[lettre]:\n", + " mots.append(nouveau_prefixe)\n", + " else:\n", + " # Sinon, continuer récursivement\n", + " mots.extend(\n", + " intersection_tries(trie1[lettre], trie2[lettre], nouveau_prefixe)\n", + " )\n", + " return mots\n", + "\n", + "\n", + "intersection_tries(trie1, trie2)" + ] + }, + { + "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.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 7f0de1dd067b0ef325fc44c1c1ade5d7497e2bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Sun, 19 Oct 2025 11:29:12 +0200 Subject: [PATCH 5/6] notebook --- _doc/practice/years/2025/index.rst | 2 + _doc/practice/years/2025/seance4_algo.ipynb | 2 +- _doc/practice/years/2025/seance5_algo2.ipynb | 2 +- _doc/practice/years/2025/seance6_regex.ipynb | 633 ++++++++++++++++++ .../years/2025/seance7_postier_chinois.ipynb | 464 +++++++++++++ 5 files changed, 1101 insertions(+), 2 deletions(-) create mode 100644 _doc/practice/years/2025/seance6_regex.ipynb create mode 100644 _doc/practice/years/2025/seance7_postier_chinois.ipynb diff --git a/_doc/practice/years/2025/index.rst b/_doc/practice/years/2025/index.rst index 0a22147..c0165bb 100644 --- a/_doc/practice/years/2025/index.rst +++ b/_doc/practice/years/2025/index.rst @@ -9,3 +9,5 @@ seance1_point2d seance4_algo seance5_algo2 + seance6_regex + seance7_postier_chinois diff --git a/_doc/practice/years/2025/seance4_algo.ipynb b/_doc/practice/years/2025/seance4_algo.ipynb index bbe32af..2a5226a 100644 --- a/_doc/practice/years/2025/seance4_algo.ipynb +++ b/_doc/practice/years/2025/seance4_algo.ipynb @@ -291,4 +291,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/_doc/practice/years/2025/seance5_algo2.ipynb b/_doc/practice/years/2025/seance5_algo2.ipynb index 7e7d170..a0b3ea5 100644 --- a/_doc/practice/years/2025/seance5_algo2.ipynb +++ b/_doc/practice/years/2025/seance5_algo2.ipynb @@ -987,4 +987,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/_doc/practice/years/2025/seance6_regex.ipynb b/_doc/practice/years/2025/seance6_regex.ipynb new file mode 100644 index 0000000..9bfb75e --- /dev/null +++ b/_doc/practice/years/2025/seance6_regex.ipynb @@ -0,0 +1,633 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Séance 6 - epressions régulières" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "texte = \"\"\"\n", + "Voici un texte intégrant 50 formules de politesse variées, adaptées à différents contextes (professionnel, amical, formel, informel, écrit, oral) :\n", + "\n", + "---\n", + "\n", + "**Objet : Remerciements et suite à notre échange**\n", + "\n", + "Chère Madame Dupont,\n", + "\n", + "Je me permets de vous adresser ce message afin de vous exprimer toute ma gratitude pour l’attention que vous avez portée à mon projet. **1. Je vous remercie sincèrement** pour le temps que vous m’avez accordé lors de notre dernière rencontre.\n", + "\n", + "**2. Veuillez agréer, Madame, l’expression de mes salutations distinguées.**\n", + "Je tiens à souligner la qualité de vos conseils, qui m’ont été d’une aide précieuse. **3. Je vous en suis profondément reconnaissant(e).**\n", + "\n", + "**4. Avec toute ma considération,**\n", + "Je vous prie de bien vouloir trouver ci-joint le document que vous m’avez demandé. **5. N’hésitez pas à me faire savoir** si vous souhaitez que j’apporte des modifications ou des précisions.\n", + "\n", + "**6. Dans l’attente de votre retour, je reste à votre disposition** pour toute information complémentaire.\n", + "**7. Je vous remercie par avance** pour l’attention que vous porterez à ce dossier.\n", + "\n", + "**8. Cordialement,**\n", + "Je souhaiterais également vous informer que l’événement aura lieu le 15 novembre prochain. **9. Seriez-vous disponible** pour y assister ?\n", + "\n", + "**10. Je serais ravi(e) de vous y retrouver.**\n", + "**11. En espérant avoir le plaisir de vous compter parmi nous,**\n", + "Je vous prie d’agréer, Cher Monsieur, **12. l’assurance de ma parfaite considération.**\n", + "\n", + "**13. Bien à vous,**\n", + "Pour revenir sur notre échange téléphonique, **14. je vous confirme** que les délais seront respectés.\n", + "**15. Merci de votre confiance.**\n", + "\n", + "**16. Avec mes sincères salutations,**\n", + "Je vous invite à consulter le rapport joint pour plus de détails. **17. Je reste à l’écoute** de vos remarques.\n", + "\n", + "**18. En vous remerciant de votre bienveillance,**\n", + "Je vous souhaite une excellente journée. **19. Prenez soin de vous.**\n", + "\n", + "**20. Amicalement,**\n", + "Je tenais à vous faire part de ma satisfaction quant à notre collaboration. **21. C’est un réel plaisir de travailler à vos côtés.**\n", + "\n", + "**22. Avec toute mon amitié,**\n", + "Je vous propose de nous retrouver la semaine prochaine pour en discuter plus en détail. **23. Qu’en pensez-vous ?**\n", + "\n", + "**24. À très bientôt,**\n", + "Je vous joins les informations demandées et **25. vous prie de m’excuser** pour le léger retard.\n", + "\n", + "**26. Avec mes excuses les plus sincères,**\n", + "Je vous remercie pour votre compréhension. **27. Je vous en suis infiniment reconnaissant(e).**\n", + "\n", + "**28. Respectueusement,**\n", + "Je vous informe que le projet avance selon le planning prévu. **29. Je vous tiendrai informé(e) des prochaines étapes.**\n", + "\n", + "**30. Dans l’attente de votre réponse,**\n", + "Je vous souhaite un excellent week-end. **31. Profitez bien de ces moments de détente.**\n", + "\n", + "**32. Avec toute ma sympathie,**\n", + "Je vous serais gré de bien vouloir me confirmer votre présence. **33. Merci d’avance pour votre retour.**\n", + "\n", + "**34. Bien cordialement,**\n", + "Je vous adresse mes plus vifs remerciements pour votre soutien. **35. Votre aide m’est précieuse.**\n", + "\n", + "**36. Avec toute ma gratitude,**\n", + "Je vous prie de croire, Madame, **37. en l’expression de mes sentiments les plus respectueux.**\n", + "\n", + "**38. Très respectueusement,**\n", + "Je vous informe que le dossier est désormais complet. **39. Je reste à votre entière disposition** pour toute question.\n", + "\n", + "**40. Avec mes meilleures pensées,**\n", + "Je vous souhaite une belle journée. **41. À très vite, j’espère.**\n", + "\n", + "**42. Avec toute mon affection,**\n", + "Je vous remercie pour votre patience. **43. Votre bienveillance me touche beaucoup.**\n", + "\n", + "**44. Avec toute ma reconnaissance,**\n", + "Je vous prie de bien vouloir excuser ce contretemps. **45. Je ferai tout mon possible pour y remédier.**\n", + "\n", + "**46. Avec mes excuses renouvelées,**\n", + "Je vous remercie pour votre confiance renouvelée. **47. C’est un honneur de collaborer avec vous.**\n", + "\n", + "**48. Avec toute mon estime,**\n", + "Je vous souhaite une excellente continuation. **49. Au plaisir de vous revoir bientôt.**\n", + "\n", + "**50. Bien à vous,**\n", + "\n", + "**51. Merci, je vous dois beaucoup.**\n", + "\n", + "Merci pour ces formules de politesse.\n", + "\n", + "---\n", + "\n", + "N’hésitez pas à me dire si vous souhaitez adapter ce texte à un contexte particulier !\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['\\n\\n',\n", + " '50. Bien à vous,',\n", + " '\\n\\n',\n", + " '51. Merci, je vous dois beaucoup.',\n", + " '\\n\\nMerci pour ces formules de politesse.\\n\\n---\\n\\nN’hésitez pas à me dire si vous souhaitez adapter ce texte à un contexte particulier !\\n']" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "morceaux = texte.split(\"**\")\n", + "morceaux[-5:]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15. Merci de votre confiance.\n", + "33. Merci d’avance pour votre retour.\n" + ] + } + ], + "source": [ + "for m in morceaux:\n", + " if \"merci\" in m.lower():\n", + " mot = m.lower().split(\" \")\n", + " if \"merci\" in mot:\n", + " print(m)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15. Merci de votre confiance.\n", + "33. Merci d’avance pour votre retour.\n", + "51. Merci, je vous dois beaucoup.\n", + "\n", + "\n", + "Merci pour ces formules de politesse.\n", + "\n", + "---\n", + "\n", + "N’hésitez pas à me dire si vous souhaitez adapter ce texte à un contexte particulier !\n", + "\n" + ] + } + ], + "source": [ + "for m in morceaux:\n", + " if \"merci\" not in m.lower():\n", + " continue\n", + " f = m.lower().replace(\",\", \" \").replace(\".\", \" \").replace(\"\\n\", \" \")\n", + " mot = f.lower().split(\" \")\n", + " if \"merci\" not in mot:\n", + " continue\n", + " print(m)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import re\n", + "\n", + "tous_les_merci = re.findall(r\"\\*\\*(merci)\\*\\*\", texte)\n", + "tous_les_merci" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['merci 1', 'merci 2']\n" + ] + } + ], + "source": [ + "motif = r\"\\*\\*(.*?merci.*?)\\*\\*\"\n", + "\n", + "resultats = re.findall(motif, \"**merci 1**, **merci 2**\", flags=re.IGNORECASE)\n", + "print(resultats)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Objet : Remerciements et suite à notre échange', '1. Je vous remercie sincèrement', '7. Je vous remercie par avance', '15. Merci de votre confiance.', '18. En vous remerciant de votre bienveillance,', '33. Merci d’avance pour votre retour.', '51. Merci, je vous dois beaucoup.']\n" + ] + } + ], + "source": [ + "resultats = re.findall(motif, texte, flags=re.IGNORECASE)\n", + "print(resultats)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['**15. Merci de votre confiance.**', '**33. Merci d’avance pour votre retour.**', '**51. Merci, je vous dois beaucoup.**']\n" + ] + } + ], + "source": [ + "motif = r\"\\*\\*(?=[^*]*merci\\b)[^*]*\\*\\*\"\n", + "resultats = re.findall(motif, texte, flags=re.IGNORECASE)\n", + "print(resultats)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import zipfile\n", + "\n", + "# Dossier contenant les fichiers ZIP\n", + "dossier_zip = \"chemin/vers/vos/fichiers_zip\" # Remplacez par votre chemin\n", + "# Dossier de destination pour les fichiers décompressés\n", + "dossier_dest = \"chemin/vers/dossier_destination\" # Remplacez par votre chemin\n", + "\n", + "# Liste tous les fichiers ZIP dans le dossier\n", + "if os.path.exists(dossier_zip):\n", + " fichiers_zip = [f for f in os.listdir(dossier_zip) if f.endswith(\".zip\")]\n", + "else:\n", + " fichiers_zip = []\n", + "\n", + "if fichiers_zip:\n", + " # Crée le dossier de destination s'il n'existe pas\n", + " os.makedirs(dossier_dest, exist_ok=True)\n", + "\n", + " print(f\"Trouvé {len(fichiers_zip)} fichiers ZIP à décompresser.\")\n", + "\n", + " for fichier in fichiers_zip:\n", + " chemin_zip = os.path.join(dossier_zip, fichier)\n", + " nom_dossier = os.path.splitext(fichier)[0] # Nom du sous-dossier = nom du ZIP\n", + " dossier_sortie = os.path.join(dossier_dest, nom_dossier)\n", + "\n", + " try:\n", + " with zipfile.ZipFile(chemin_zip, \"r\") as zip_ref:\n", + " zip_ref.extractall(dossier_sortie)\n", + " print(f\"✅ Décompression réussie : {fichier} -> {nom_dossier}\")\n", + " except zipfile.BadZipFile:\n", + " print(f\"❌ Erreur : {fichier} est corrompu ou n'est pas un ZIP valide.\")\n", + " except Exception as e:\n", + " print(f\"❌ Erreur inattendue avec {fichier} : {e}\")\n", + "\n", + " print(\"Décompression terminée !\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import pandas as pd\n", + "\n", + "# Dossier contenant vos fichiers Excel\n", + "dossier_excel = \"chemin/vers/vos/fichiers_excel\" # Remplacez par votre chemin\n", + "\n", + "if os.path.exists(dossier_excel):\n", + " # Nom du fichier Excel de sortie\n", + " fichier_sortie = \"fichier_fusionne.xlsx\" # Remplacez par le nom souhaité\n", + "\n", + " # Liste tous les fichiers Excel dans le dossier\n", + " fichiers_excel = [\n", + " f for f in os.listdir(dossier_excel) if f.endswith((\".xlsx\", \".xls\"))\n", + " ]\n", + "\n", + " print(f\"Trouvé {len(fichiers_excel)} fichiers Excel à fusionner.\")\n", + "\n", + " # Crée un objet ExcelWriter pour écrire le fichier de sortie\n", + " with pd.ExcelWriter(fichier_sortie, engine=\"openpyxl\") as writer:\n", + " for fichier in fichiers_excel:\n", + " chemin_fichier = os.path.join(dossier_excel, fichier)\n", + " # Lit chaque fichier Excel\n", + " df = pd.read_excel(chemin_fichier)\n", + " # Nom de l'onglet = nom du fichier (sans extension)\n", + " nom_onglet = os.path.splitext(fichier)[0][\n", + " :31\n", + " ] # Excel limite à 31 caractères\n", + " # Écrit dans le fichier de sortie, dans un nouvel onglet\n", + " df.to_excel(writer, sheet_name=nom_onglet, index=False)\n", + " print(f\"✅ Ajouté : {fichier} -> onglet '{nom_onglet}'\")\n", + "\n", + " print(\n", + " f\"Fusion terminée ! Le fichier '{fichier_sortie}' contient {len(fichiers_excel)} onglets.\"\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import cv2\n", + "\n", + "# Chemin du répertoire contenant vos images\n", + "dossier_images = \"chemin/vers/vos/images\" # Remplacez par votre chemin\n", + "\n", + "if os.path.exists(dossier_images):\n", + " # Chemin du répertoire de sortie (pour les images avec visages)\n", + " dossier_sortie = \"chemin/vers/images_avec_visages\" # Remplacez par votre chemin\n", + "\n", + " # Crée le dossier de sortie s'il n'existe pas\n", + " os.makedirs(dossier_sortie, exist_ok=True)\n", + "\n", + " # Charge le classificateur de visages pré-entraîné d'OpenCV\n", + " face_cascade = cv2.CascadeClassifier(\n", + " cv2.data.haarcascades + \"haarcascade_frontalface_default.xml\"\n", + " )\n", + "\n", + " # Liste des extensions d'image supportées\n", + " extensions = (\".jpg\", \".jpeg\", \".png\", \".bmp\", \".gif\")\n", + "\n", + " # Parcourt toutes les images du répertoire\n", + " for fichier in os.listdir(dossier_images):\n", + " if fichier.lower().endswith(extensions):\n", + " chemin_image = os.path.join(dossier_images, fichier)\n", + " # Lit l'image\n", + " img = cv2.imread(chemin_image)\n", + " if img is None:\n", + " continue # Ignore si l'image ne peut pas être lue\n", + "\n", + " # Convertit en niveaux de gris pour la détection\n", + " gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", + " # Détecte les visages\n", + " faces = face_cascade.detectMultiScale(\n", + " gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)\n", + " )\n", + "\n", + " # Si au moins un visage est détecté, copie l'image dans le dossier de sortie\n", + " if len(faces) > 0:\n", + " chemin_sortie = os.path.join(dossier_sortie, fichier)\n", + " cv2.imwrite(chemin_sortie, img)\n", + " print(f\"✅ Visage détecté : {fichier}\")\n", + "\n", + " print(\"Filtrage terminé ! Les images avec visages sont dans :\", dossier_sortie)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from PIL import Image\n", + "import matplotlib.pyplot as plt\n", + "import math\n", + "\n", + "# Chemin du répertoire contenant vos images\n", + "dossier_images = \"Telechargements\" # Remplacez par votre chemin\n", + "if os.path.exists(dossier_images):\n", + " # Chemin de sortie pour le poster\n", + " poster_sortie = \"poster_miniatures.jpg\" # Remplacez par le nom souhaité\n", + "\n", + " # Taille des miniatures (en pixels)\n", + " taille_miniature = (200, 200)\n", + " # Marge entre les miniatures (en pixels)\n", + " marge = 20\n", + " # Fond du poster (blanc par défaut)\n", + " fond = (255, 255, 255)\n", + "\n", + " # Liste des extensions d'image supportées\n", + " extensions = (\".jpg\", \".jpeg\", \".png\", \".bmp\", \".gif\")\n", + "\n", + " # Récupère la liste des images\n", + " images = [f for f in os.listdir(dossier_images) if f.lower().endswith(extensions)]\n", + " images.sort() # Trie par nom\n", + " print(\"nombre d'images\", len(images))\n", + "\n", + " # 1/ Zoom\n", + " zoom = []\n", + " for i, image in enumerate(images):\n", + " chemin_image = os.path.join(dossier_images, image)\n", + " img = Image.open(chemin_image)\n", + " w, h = img.size\n", + " minhw = min(w, h)\n", + " ratio = 200 / minhw\n", + " img = img.resize((int(w * ratio), int(h * ratio)))\n", + " zoom.append(img)\n", + " print(f\"image {i}: {img.size}\")\n", + "\n", + " # 2. position\n", + " print(\"-----\")\n", + " positions = []\n", + " x, y = 0, 0\n", + " miny = 1000\n", + " maxy = 0\n", + " for i, img in enumerate(zoom):\n", + " positions.append((x, y))\n", + " w, h = img.size\n", + " x += w\n", + " miny = min(h, miny)\n", + " maxy = max(maxy, y + miny)\n", + " if x >= 1200:\n", + " x = 0\n", + " y += miny\n", + " miny = 1000\n", + " print(i, (x, y), miny)\n", + "\n", + " print(positions)\n", + " largeur_poster = 1200\n", + " hauteur_poster = maxy\n", + "\n", + " # Crée une image vide pour le poster\n", + " poster = Image.new(\"RGB\", (largeur_poster, hauteur_poster), fond)\n", + "\n", + " for pos, img in zip(positions, zoom):\n", + " poster.paste(img, pos)\n", + " x = pos[0] + img.size[0]\n", + " y = pos[1]\n", + "\n", + " i = 0\n", + " while x < 1200:\n", + " poster.paste(zoom[i], (x, y))\n", + " x += zoom[i].size[0]\n", + "\n", + " # Sauvegarde le poster\n", + " poster.save(poster_sortie)\n", + " print(f\"✅ Poster généré : {poster_sortie} ({nb_images} miniatures)\")\n", + "\n", + " plt.figure(figsize=(20, 10)) # Ajustez la taille selon vos besoins\n", + " plt.imshow(poster)\n", + " plt.axis(\"off\") # Masque les axes\n", + " plt.title(f\"Poster de miniatures ({nb_images} images)\")\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'GHIZ'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def plus_grande_sequence_commune_naif(seq1, seq2):\n", + " for length in range(len(seq1), 0, -1):\n", + " for i in range(len(seq1)):\n", + " if i + length <= len(seq1):\n", + " s1 = seq1[i : i + length]\n", + " if s1 in seq2:\n", + " return s1\n", + " return \"\"\n", + "\n", + "\n", + "seq1 = \"ABCDEFGHIZERT\"\n", + "seq2 = \"ABGGHIZTJKL\"\n", + "plus_grande_sequence_commune_naif(seq1, seq2)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'GHIZ'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "import pprint\n", + "\n", + "\n", + "def distance_edition(m1, m2):\n", + " cout = np.empty((len(m1) + 1, len(m2) + 1))\n", + " predi = np.empty((len(m1) + 1, len(m2) + 1), dtype=np.int64)\n", + " predj = np.empty((len(m1) + 1, len(m2) + 1), dtype=np.int64)\n", + " cout[:, 0] = np.arange(len(m1) + 1)\n", + " cout[0, :] = np.arange(len(m2) + 1)\n", + " predi[:, 0] = np.arange(len(m1) + 1) - 1\n", + " predj[:, 0] = 0\n", + " predi[0, :] = 0\n", + " predj[0, :] = np.arange(len(m2) + 1) - 1\n", + " for i in range(1, len(m1) + 1):\n", + " for j in range(1, len(m2) + 1):\n", + " c_sup = cout[i - 1, j] + 1\n", + " c_ins = cout[i, j - 1] + 1\n", + " c_cmp = cout[i - 1, j - 1] + (1 if m1[i - 1] != m2[j - 1] else 0)\n", + " if c_cmp <= min(c_sup, c_ins):\n", + " cout[i, j], predi[i, j], predj[i, j] = c_cmp, i - 1, j - 1\n", + " elif c_sup <= c_ins:\n", + " cout[i, j], predi[i, j], predj[i, j] = c_sup, i - 1, j\n", + " else:\n", + " cout[i, j], predi[i, j], predj[i, j] = c_ins, i, j - 1\n", + " # alignement\n", + " alignement = [(len(m1), len(m2))]\n", + " while min(alignement[-1]) >= 0:\n", + " i, j = alignement[-1]\n", + " i, j = predi[i, j], predj[i, j]\n", + " alignement.append((i, j))\n", + " alignement = alignement[::-1][2:]\n", + " lettres = [(m1[i - 1], m2[j - 1]) for i, j in alignement]\n", + " return cout, alignement, lettres\n", + "\n", + "\n", + "def plus_grande_sequence_commune(seq1, seq2):\n", + " cout, alignement, lettres = distance_edition(seq1, seq2)\n", + " i0 = None\n", + " best = None\n", + " for i, (c1, c2) in enumerate(lettres):\n", + " if c1 == c2:\n", + " if i0 is None:\n", + " i0 = i\n", + " if i0 is not None and best is None or i - i0 + 1 > len(best):\n", + " best = \"\".join(c[1] for c in lettres[i0 : i + 1])\n", + " else:\n", + " i0 = None\n", + " return best\n", + "\n", + "\n", + "# cout, alignement, lettres = distance_edition(seq1, seq2)\n", + "# pprint.pprint(list(zip(alignement,lettres)))\n", + "plus_grande_sequence_commune(seq1, seq2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "celltoolbar": "Format de la Cellule Texte Brut", + "kernelspec": { + "display_name": "this312", + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/_doc/practice/years/2025/seance7_postier_chinois.ipynb b/_doc/practice/years/2025/seance7_postier_chinois.ipynb new file mode 100644 index 0000000..b02685c --- /dev/null +++ b/_doc/practice/years/2025/seance7_postier_chinois.ipynb @@ -0,0 +1,464 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Séance 7 - postier chinois" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 243 + }, + "id": "jMJh6BaUqBza", + "outputId": "7462c5b8-2545-46d6-8285-5b8702cca7eb" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Adjacency Matrix:\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1],\n", + " [0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1],\n", + " [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],\n", + " [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", + " [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", + " [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],\n", + " [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0],\n", + " [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0],\n", + " [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1],\n", + " [1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0]])" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import networkx as nx\n", + "import numpy as np\n", + "\n", + "# Create a connected graph with 12 nodes\n", + "G = nx.erdos_renyi_graph(\n", + " 12, 0.3\n", + ") # Using a random graph for simplicity, adjust probability for connectivity\n", + "\n", + "# Ensure the graph is connected, regenerate if not\n", + "while not nx.is_connected(G):\n", + " G = nx.erdos_renyi_graph(12, 0.3)\n", + "\n", + "# Get the adjacency matrix\n", + "adj_matrix = nx.adjacency_matrix(G)\n", + "\n", + "# Convert to a dense numpy array for easier viewing\n", + "adj_matrix_dense = adj_matrix.todense()\n", + "\n", + "print(\"Adjacency Matrix:\")\n", + "display(adj_matrix_dense)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 345 + }, + "id": "745eaabe", + "outputId": "53c9a82c-c2d8-40f2-8e58-fc100644683c" + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUoAAAFICAYAAAA24bcOAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAASvRJREFUeJzt3Xd4VFX6wPHvnUx6mQRCCARCS0JEQYoBgVCkBkRFbFgQRSm6oj+XIhbWrthw7SirsKgrCgiCFEPvTUPHmCAlECAJkF4mmcz9/RESiUnIzOROCbyf5/FZnTv33pPs5J1zzn3PeRVVVVWEEELUSOfsBgghhKuTQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELWQQCmEELXQO7sB4sqSX2LmbIGJ9EITRaUqpaqKm6Lg5aYQ4q0n1EePr7t8P4v6RQKlqLP0QhMJGUUkZRspMJVVFlEARfnrPaoK5TVHfPQKUQZPOjfyIsRbPoLC9SlSM0fYQlVVkrKL2ZlWyOkCEwp/BUJL6AAz0NRHT7fG3kQZPFAujaxCuBAJlMJqeSVmVqXkciSnxOoA+Xfl50cEuBMX7o+fDMuFC5JAKaySmGlkZUoexWa1TgHy7xTAQ6cwJNyP6CBPDa8sRN1JoBQW25VeyLrUfLvfp3+YLzEh3na/jxCWknGOsIijgiTA2tR8dqcXOuReQlhCAqWoVWKm0WFBstza1HwSM40OvacQNZFAKS4rr8TMypQ8p9x7ZUoe+SVmp9xbiEtJEpuokaqqrErJpdhs3TT2yUN72DzvY47v2Ul+1nk8vHwIjbiGLrfdR5db77U4DajYrLLqZB4jWvlL6pBwKnmYI2r0R5aRxcdyrTrn4NplfDdtLObSUppGd6Bh81bkZ57n+N4dmE0mrh9yByNfn2XVNW9v5U/bQHkSLpxHepSiRjvTCq3Kkyw1mfjpzWcwl5Zyz+uz6Djkjopj6UeTmPXIMPatXETM8AdoExNr0TUVyh4kSaAUziRzlKJa6YUmTheYrMqVzDieTN6FDBq1jKgUJAFCWkfRaeidAJw6tMfia6pAan7Z2nEhnEUCpahWQkYR1s4K6j08LHqfT2CQVdfVXWyPEM4igVJUKynbaPXKmwZhLWnQrCUZx4+wd+WiSsfSjyaxZ8VCvAMCufamm626rhlIzpZUIeE88jBHVJFfYuajgxdsOvf43p3896n7KcrNpml0B4LDW5N34RzH9+4gpFVb7nr5Q5pGd7Dp2hOvayBbtAmnkE+dqOJsge3zgS07dmPc7J9o0KwlpxP3sz9+CUd/3YKi6Ii8sQ8Nwlo6pV1C1IUESlFFeqHJ6vnJcntX/cinDw7G0Lgpj8/7hZe3HmfSkh10uWUkm7/+lNnjb8dUbP0wWrnYLiGcQQKlqKKoVMWW/O5zKX+y8F9P4BPYgNEffEvz6zrj4e1LcHgbbn/hPaJ7DeJ04n5+/el/Vl9bUcBYKrNEwjkkUIoqSm2ctt73yxJKTSVE9eiHp49flePtB94GwLGE7TZd3yTT6cJJJFCKKtxsXC6Yk3YaAC+/gGqPe/mXvV6Yk2XT9fWyjFE4iQRKUYWXm4ItnTe/hiEApB7eW+3x8kTzoKbhVl9bVcHTTQKlcA4JlKKKEG+9TbuXt+sbB5QNrXcsmFPpWMr+X9n6bdka7/YDbrH62urFdgnhDJJHKaqoSx7livdfYvPXnwDQuE00Ia2jyMk4S8r+X1HNZrqOeJDbX3jPpmtLHqVwFgmUolofHjhfUXrWWofWLWfnwrmkJu6nKC8HTx8/mkRdR8yIUXSMG2HTNX31ChPbN7TpXCHqSgKlqNaqlDz2nS/StICYrXRAh4ZexIVXfZIuhCPIOEZUq3MjL5cIklC21rtzIy9nN0NcxSRQimqFeOtp6qO3eYWOVhQgzFcvD3KEU0mgFDXq1tjb6b1KFegqpWuFk0mgFDWKMngQEeDutF6lAkQaPIgyWLbPpRD2IoFS1EhRFOLC/fHQKaiq46sheugU4pr7SWEx4XQSKMVl+eoVMrcuRVEc/1EZEu4neZPCJcinUNTIbDbz1FNP8eo/xuCWvNuh9+4f5kt0kBQUE65BAqWoVmlpKWPHjuXjjz9m1qxZTLl7CP3DfO16T7O5bHjfP8yHGHmAI1yI5FyIKkpKSnjwwQf54Ycf+O9//8uoUaMAiAnxxt9dx8qUPIrNqqZPxBVAr5r5eupY3AbFEjNlikXn5ZeYOVtQVqWxqFSlVFVxUxS83BRCvPWE+uhl+C7qTAKlqKSoqIh77rmHlStX8sMPP3DHHZXLzkYHedLMz51VKbkcySmxqu53dcrPjzB4ENe8AVkx1zJt2jQ6dOjA4MGDqz0nvdBEQkYRSdnGimWWClTabFhV/2qXj14hyuBJ50Zeko8pbCJLGEWFgoIChg8fzubNm1m0aBFDhw6t8b2qqpKUXczOtEJOF5jQUbaCxlLl7w/z1dM1xJsogweKolBaWsqtt97Ktm3b2L17NxEREdXez9oAXX6/pj56ujX+635CWEICpQAgJyeHYcOGkZCQwLJly7jpppssPre8h5ecbSRfgx5eVlYW3bp1w93dne3bt6N4+Wrfgw1wJy7cHz8ZlgsLSKAUXLhwgbi4OJKSkli5ciXdu3e3+VqXzhkaS1VMqopeUfB0U8g4msh9wwazZd1qOnbseNnr/P7773Tr1o27Jj7DtXdPoMQOc6IeOoUh4X7ydF3USgLlVS4tLY2BAwdy5swZ4uPj6dSpk93uVVRUhMFg4L333uOJJ56o9f1z1u0mLagVqmq2ax5n/zBfecouLkvGHVexU6dO0adPH86dO8fGjRvtGiQBvLy86NKlC1u3bq31vbvSC0kLagVg92T3tan57E4vtOs9RP0mgfIqdfToUXr16kVhYSGbNm2iXbt2DrlvbGwsmzdv5nIDmcRMI+tS8x3SnnJrU/NJzLS+3ri4OkigvAolJibSu3dv9Ho9mzdvrniy7AixsbGkpqaSkpJS7fG8EjMrU/Ic1p5LrUzJI7/E8WvaheuTpLKrzP79+xkwYAAhISGsXr2aJk2aOPT+PXr0AGDLli20aNGi0jFVVVmVkkuxuXJvM/XwPpJ3buDUwT2cPJRATvoZAN5MyLjsvX5b+h07Fswh/egfuLl70Lx9F/o9+k9aXN+12vcXm1VWncxjRCt/SR0SlUigvIrs2rWLuLg4WrVqxS+//EJwcLDD2xAcHMw111zDli1buP/++ysdS8ou5khOSZVz1v3nPQ5vWGnVfZa98zzbvvsCdy9vIm/sS4mxiCM7N3Jkxwbue/srrr2pao6oCiRnF5OUXUzbQHkSLv4igfIqsWnTJoYNG0b79u1ZsWIFBoPBaW3p2bMnW7ZsqfL6zrTCavMkwzvcQGhkO5q160Szazvy9rAumIprnk88snMj2777Ap/ABjw2dwXB4W0AOLFvN7PHDWfhS0/S+oaeePtX/R0olD1IkkApLiVzlFeB+Ph44uLiiImJ4ZdffnFqkISyecpDhw6RmZlZ8Vp6oYnTBaZqcyX7PPQkAx+bxjV9BuMf3LjW62/+5jMAbnrk6YogCdDi+hi63Tmaotxsfl3ybbXnqkBqflkeqBDlJFC6kPwSM39mF7P9bAHrU/NZcyqP9an5bD9bwJ/ZxTY9aPjpp5+45ZZb6NevHz///DN+fs6vZBgbG4uqqmzfvr3itYSMIk12Ui8pKuTo7rLeavsBt1Y5fl3/WwD4fdMvNV5Dd7E9QpSTobeT2XODh++++45Ro0Zx++238+233+Lh4RolFVq3bk1oaChbtmypWE+elG3UZOVNxokjmIqN+AYFY2jctMrxsGs6AHA2+XCN1zADydlG4nD+l4pwDRIonaC2DR5UyoJjdQpMKvvPF7H3fNFlN3j46quvePTRRxk1ahRffvkler3r/F+tKAqxsbEV85T5JeaKL4m6yjqbCoChcfVP8z28ffHyN1CYk4UxPw9P3+qDYb5JJb/ELFu0CUCG3g6XV2Jm0dEcFh/L5UxB2TyYtSGifAB+psDE4mO5LDqaQ94lw/KPPvqIRx55hPHjxzNnzhyXCpLlYmNj2bVrF0ajkbMF2s0HFheUJaq7e9W8JNHD2wcAY8Hl8zW1bJeo3yRQOlBippHZhzP582IKTF37UOXn/5lTwuzDmSRmGnnzzTd58sknmTRpEp9++ik6nWv+X9yzZ0+MRiO//fYb6YUmp9cP/zsF5IGOqOCaf0VXoF3phSw5notR411woCxgGs0qS47nsvzgCV588UXeeecdl06a7tixI76+vmzdupWiUhWtmurhU1auoqSo5rXbxYUFAHj61DwHqShgLJX9YkQZCZQOsCu90GFrl4dNfo2bH3/GpYMkgF6v58Ybb2TLli2UariBVWBoGADZaWeqPV5cmE9RbjbeAYE1zk+WM8nGWuIiCZR2Jhs81Cw2NpatW7dq+iFs1CICvYcn+ZnnyE6vGixTf98PQGhk7ZuA6F38y0Y4jgRKO5INHi4vNjaW8+fPk5t5rsan/NZy9/KmdUwsAAdW/1Tl+MG1ywC4pnf19XjKqSp4ukmgFGVc73HoFaKmDR6qU1xYQPKODSRu+oXje3eSdeYUis6Nhs1bcV3/YcQ+MOGy82nVXrMebPDQrVs33NzcOPX7ftTIHppdt9cDj5G0dS3rv3yf6F4DKy1h3LVoHl7+Bm4Yfv9lr6GCFCITFWSHczv5I8vI4mO5Fr139+Kv+fHVfwIQ0iqKxhHRFOXlkrJ/N8b8PBq1jGTcf37Cr0Ejq9txeyt/l1633KVLFzp2607k2JdqfE/i5njWzZ5Z8d+nDiWgqirNr+tS8Vq/sf8kutegiv/+a1MMHyJv7IOppJgjOzeCqta4KcbfTbyugeRRCkB6lHZT0wYP1dHp3ek64kF63jeekNZRFa/nZJzlv0/dx+nEA/z87guMfONzq9pQHzZ4iI2NZfny5Vz/2Ms1Jp3nZ57n5MHfqrx+6Wv5mecrHbtlyus0bXsd27//kuQdG3Fzdyeia2/6jZ1U4zZrl/LVKxIkRQXpUdpBeqGJrxKzNLnWiX27mfXwUPQenry4+Sh6d+uXIY6JDnTZYeSCBQu4++67WfT7WZIL3TRPnbKFDujQ0Iu4cFnCKMrIV6YdaLXBA0CTqGsBMBUbKci6YPX5rr7BQ8+ePQEoTEpwiSAJZSufOjfycnYzhAuRQGkHWm3wAHAh9QQAbnp3fAxBVp9fvsGDq2ratCmtW7dm97pfaOqjd/oKHQUI89W7bA9cOIcESo1pucEDwLbvvgAgqkc/9B62zTWWb/Dgqso38u3W2NvpvUoV6Cqla8XfSKDUmJYbKSRuWc2vS77FTe/OwMen1elarrzBQ2xsLHv37qWpWzERAe5O61UqQKTBgyiDa2xHJ1yHBEqNabXBQ/qxZH544XFUVWXI/71Ik6jrbL6Wq2/wEBsbS2lpaVlNn3B/PHTOCZUeOoW45n4um3cqnEcCpca02OAhO/0Mc564h8KcLGIfeIye942v0/VcfYOH6OhoGjRowJYtW/Bz1zHESU+bh4T7SUqQqJZ8KjRW1w0eCrIz+erxu8g6c5Iut97L0Kdf1qRdrrzBg06nq1RwLDrIk/5hvg5tQ/8wX6KDXDffVDiXBEqNudWhO2ksyGPOxJGkH/2Da/vdzIjp72s2DHT1DR5iY2PZvn07JlPZFEFMiDcBpy+Wa7BzkO8f5kuMPMARlyGBUmNebopNf9emYiNfP/0gpw4mENn9Jka++QU6NzdN2lQfNnjo2bMn+fn57Nu3D4D9+/cz+a44Tq/8Gk83neYPeBTAU6cwvKW/BElRK0kW01iIt9760g6lpcx/djx/7t5My0438sC7c21agVOT+rDBww033ICnpydbt24lIiKCO+64g6ioKN56egKlek9WpeRyJKfE4mWhNSk/P8LgQVxzmZMUlnHtv556KNTH+l/p9u//w6H1ywHwDWzITzOmVvu+of/3Mr5BDR3WLkfy9PQkJiaGzZs3s379ejIyMli1ahXe3mW9vTtaB1QqyKbjr9pBlih/f1NfPV1Dqi/IJkRNXPuvpx7yddfho1esSjovzMmu+PfygFmdAeOn2hQo68sGD7GxsXzyySfk5uby008/0aZNm4pjiqLQNtCTtoGepBea+C2jkK1Jp/BrWLaj0uVK/PrqFSItLPErRHXkU2MHUQZP9p0vsniIOGDCVAZMqL4XWVc6INJQP57mBgQEkJuby2OPPcatt95a4/tCvPW0zD/F0IHtWLl2A5FdupNeaMJYqmJSVfSKgqebQoi3nlAffb34khCuTQKlHVzfwJ29511jI4r6ssHD6dOn+fe//w1ATExMre/ftWsXAN27dMRg8KCNrKYRdiRftRpSVZUVK1YwuEcMJ/btRjWXOrU99WWDh5KSEu655x70ej1t27Zlx44dtZ6ze/duoqOjMRgMDmihuNpJoNTIjh076Nu3LzfffDMNGjRgaLtmKDpt0ntsVV82eJg2bRo7duxgwYIF9O3btyLx/HJ27dplUc9TCC1IoKyjxMRERowYQffu3cnMzGTFihWsX7+eYTHXyQYPFli4cCEzZ85k5syZ9OjRg9jYWA4fPsz58+drPMdoNLJ37166dq19p3IhtCCB0kapqamMGzeOa6+9loSEBObNm8eePXsYMmQIiqKgKIps8FCLP/74g4cffpiRI0fyxBNPAGVPvgG2bdtW43n79++npKREAqVwGAmUVsrKyuLZZ58lIiKCH3/8kffee48//viDUaNG4fa3lTSywUPN8vLyGDFiBM2bN2f27NkVAb1FixaEhYVddvi9a9cu3N3duf766x3VXHGVc+1ZfhdSVFTExx9/zBtvvIHRaGTy5MlMnjy51ocJ0UGe9C8xszY130Etdf0NHlRVZdy4caSkpLB79278/P76MlEUhZ49e7Jr3wH+zC4mvdBEUalKqaripih4uSkcSs+ha2wfPD1d92cUVxYpLlaL0tJS5s2bx4svvsjp06cZN24c06dPp0mTJlZdZ3d6oUOCZX3Y4OGTTz7hiSee4Pvvv+fuu++ueD290ERCRhF7z2SCR9nPcLlEch+9QpQkkgsHkEBZA1VVWbZsGc899xyHDh3irrvu4rXXXiMqKqr2k2uQmGlkZUoexWZV05IHpSYTnnodw1oaXLonCWXZAb179+Yf//gH77//PqqqVlqaaO1a7oqliT56ujWWpYnCPlwiUOaXmDlbYKp2mOWM1RVbt27lmWeeYevWrdx000289dZbmqWi5JWYNd/gIeXXzSR88yGbVv+Ch4frPuXOyMigc+fOtGjRgvXr12PETfvNLgLciQv3x8+F52dF/eO0QFk+zErKNlasi3b2MOvw4cM8++yzLF26lI4dOzJjxgwGDRqkeQ/l770oWzd4CLu4wUPe0UPc2K0b06ZN49VXX9W0rVopLS0lLi6O/fv3k5CQQK5PsF161wplT/yHhPu5fO9a1B8ODZSuOsw6efIkL774Iv/9739p0aIFr7/+Ovfccw86nf17JeVfGMnZRvIt+MKoaYOHV155hVdeeYVt27a5ZNrM9OnTeeONN1izZg2+197IOpmvFfWIwwKlPYacdR1mXbhwgRkzZvDhhx8SEBDA9OnTGT9+vNOGr5dOQVi7wUNJSQk9evQgLy+PhISEiu3JXMHy5csZNmwYM2bM4KaHn3RIkCwnwVJowSGB0l4PMWwdZhUWFvLhhx8yY8YMSkpKmDx5MpMmTcLf31/D1jne4cOH6dy5M48//jgzZ850dnMAOHbsGJ07d6ZPnz68OWc+Px3Pc3gbhrf0l2G4qBO7B8pd6YUuM8wymUzMnTuXl156ibS0NMaPH8/06dNp3Lix3dvnKDNnzmTy5MmsX7+ePn36OLUtRUVF9OjRg5ycHDbt2M33qWaMZsdPiXvqFMa1C3LpBHzh2uwaKB0VJMvVFCxVVWXJkiU899xzJCYmMnLkSF599VUiIiIc1jZHKS0t5aabbuLkyZPs37/fqb3kRx99lG+//Zbt23dwxL8lf+aUWDSiOPrrVmaPG17r+wZMeIb+4ybX+j6FstIPI1r5S+qQsIndsnQTM40ODZIAa1Pz8XfXVRpmbdq0iWeeeYYdO3YwcOBAvv32Wzp37uzQdjmSm5sbc+fOpUOHDkyePJnPP//cKe348ssv+fLLL5k7dy7eLaM5cizX4nP9GobQ+ZZ7qj1mLjWzd8UCAFp2utGi66lAcnYxSdnFtA2UIbiwnl16lHklZmYfznTqMOto4iGeffZZli9fTpcuXZgxYwYDBgxweHuc5fPPP2fChAmsWLGCIUOGOPTee/bsoXv37owePZrPP/+ceX9kcabApMn89B9b1zB34r0YQsN4Zvkei3uICmX1ckZFBWrQCnG10bxHqaoqq1JyKbYySKYfTWLdlzM5unszBdlZ+Ac3JrrXQKvrxBSbzbzx00bevLs/rVu3Zv78+dx1110OSfVxJePGjWPx4sU88sgjHDx4kAYNGjjkvpmZmdxxxx1cd911fPDBB6QXmjhdYNLs+ntWLASg45A7rBpGq0BqfllGgSx3FNbSPHokZRdzxMK5qHJ/7trMxw8MZN/KRXj5GYjuNRC9hwc7fviKj+7rR3baaYuvpaLg36Y97/9vMYcPH3ZYPqSrURSFL7/8ksLCQiZOnOiQe5rNZh588EGysrJYuHAhXl5eJGQUabYnZ3FhPr9vWAlAp5vvruXdVemAhAzXKNEh6hfNI8jOtEKr/jCKCwuY//x4SooK6Dd2Mv/8cRsPvDuXf/64nV6j/kF22mkWvfyUVW1QgAad+7j0cj5HCAsL46OPPuJ///sfCxcutPv9ZsyYwfLly/n2229p2bIlAEnZRs1Swg6uXU5xYQFNo9vTuHVbq883A8nZRo1aI64mmgbK8mGWNX8Yh9YtJ+98Bo1aRtB//JSK1xVFYfATzxPUNJzkHRs4k3TQ4mteOsy62t1///2MGDGCCRMmkJaWZrf7rFmzhunTpzN9+vSKOdH8ErNVZXtrU/4Qp9NQ63uT5fJNKvkl1iwYFULjQGnLMCv1930AtOzUvcoQ2c3dnRbXly3HO7xhlVXXlWFWGUVRmDVrFjqdjnHjxmGPbLBTp05x7733MmDAAP71r39VvH5Ww7nJnIyz/Ll7Mzo3N66Pu71O19KyXeLqoGmgtGWYVVxYAIB3QGC1x30CgwCs6lGCDLMu1ahRI7744guWLl3K119/rem1i4uLueuuu/D29ubbb7+ttMt7eqFJs/nJfb8sxlxaSkS3PvgH275AQLnYLiGsoVmgtHWYVf5EO+vMyWqPZ6amXDx+yvo2yTCrwvDhwxk1ahQTJ07k5Mnqf9e2mDx5Mr/99hsLFy4kODi40rGiUhWt8rsrht02PMS5lKKAsdTpOwuKekazQGnrcKZV5+4AJG5ZTX5m5cp72elnSN65EQBjgW1rhGWY9ZcPP/wQf39/xowZo8kQ/LvvvuOjjz7igw8+qHbHolKNhvnpR5M4nXgADx9f2vWte06oyflbsIp6RrNAaeswK7L7TTSN7kBxQT5zJo7k5MEEjAV5nNi3m7lPjMRcWhboFMX6psowq7LAwEC++uor1qxZw2effVanax06dIhHH32UBx54gAkTJlT7HjeNupN7lv8AwLX9bsbD26fO19PLMkZhJc0Cpa3DLEVReODduTRuE03q4b18+uBgXoptxayHh5KXmcGAcWVPwmuaw7z8tWWY9XeDBg1iwoQJTJkyhSNHjth0jdzcXO644w5at27NrFmzakz89nJTqGvnTVVV9q76EYDOdRx2l10PPN0kUArraLZEoS7DrKCmzZn43XoOr1/OiX27KTEW0bhNWzoOuZND634GoHEb6/PmQIZZ1XnnnXeIj4/noYceYuPGjVXK7F6Oqqo88sgjnD59ml9//RVfX98a3xvira9zDuXxhO1knTlJQEgTWsf0quPVylLHZGWOsJZmn5i6DrPc9HraD7yN9gNvq/T6iX27AWjVpadN15VhVlV+fn7MnTuXPn36MHPmTKZMmVL7SRd98MEHLFiwgEWLFtVaaC3Up+4fr4oli3F3aLbCSot2iauLZkNvLYZZf5d7Lo2Da5fhE9iA6/rdbPX5MsyqWa9evZg0aRIvvPACBw9alnq1ZcsWpkyZwuTJkxkxYkSt7/d11+Gjt/33byo2cnDtMgA6Dr3T5utUapNekX0phdU02z3oz+xiFhzNsencs0d+p2HzVrh7elW8lp12mm+mPMypgwnc+fJHdLllpE3Xvqt1AG0MV/dSxpoUFRXRpUsXPD092blzJ+7u7jW+Ny0tjU6dOhEZGcnatWvR6y3rla1KyWPf+SJNd7a3lQ7o0NCLuHA/ZzdF1DOajUHqMpzZ/PUnHFq/grDoDvgHNybvwjlO7N2JqdhIv7GTbA6SdW3XleJy5YDfm/cD9wzpz+uvv85LL71U7fkmk4mRI0eiqirz58+3OEgCdG7kxd7zrrFCykxZe4SwlmZRpHyYZUvSebu+Q8k9l87Z5EOc2LsL74BAonr0o+d942l9g21zk3B1D7MsLgesa8yzvxwk73wGX/92jMHtmld52PHCCy+wefNm1q1bR5MmTaxqR4i3nqY+es32o7RV+X6U8iBH2ELTjXtlmOVcdS0HbC41oXPTVyoH/NNPP3H77bfz7rvvMmnSJJva9UeWkcVW7HBuL7e38pcdzoVNNA2U6YUmvkrM0upydTYmOvCq6UHYoxxwE7dinr2tF907d2ThwoU215tRVZVFR3MsrpmjNamZI+pK81IQWm77b6urbdt/e5UDNpeWYioqZFjrQDo3DazTtVyhPMjVOg0j6k7zT063xt5OH3qrQNerpOj9rvRClhzPxahxkATQubnh4etLfJqJ3emFdbqWn7uOIU6aBhkS7idBUtSJ5p+eKIMHEQHumm2vZS0FiDR4EHUVpAQ5phxw2f+Ta1Pz6xwso4M86R9W80oee+gf5lupKqcQttA8UCqKQly4Px4654RKD51CXHO/K34uylnlgBMz67bHZ0yI9yXB0r5jj5rqvAthLbuMR2SYZV95JWZWpti27VxdrUzJq/MenzEh3gxv6Y+pqLBidyitKJTNSQ5v6S9BUmjGbo+Eo4M86V9iZq0Dez0/v/sC+a0b8corr1yxPcqaygGnHt5H8s4NnDq4h5OHEshJPwPAmwkZ1V4n62wqv2/6hVOHEjh5IIFzJ46gqipjv1hy2dzVYrPKqpN5dX6CfHj9ct4a9xivL95AgV8jzZ7URxg8iGt+5X9ZCseya+5M+Te6I4Jl/zBf3Dq2YerUqWRkZPDJJ59YtStOfVFeDvjv1v3nPQ5fLOVqiYNrl7H8velW318FkrOLScoutjknMSsriyeeeIKbenTjiZ5tSc4pqcj91FG2gsZS5e9v6quna0hZ7ueV+iUpnMfuSYYxId74u+vskr6iUDYnOSTcj+ggT2KmTKFhw4aMHTuWCxcu8PXXX+PpeWVN5JeXA/777zG8ww2ERrajWbtONLu2I28P64KpuOb5xAbNWtLzvvE0u7bs/UtnTCN5xwaL2qBQ9iDJ1kA5bdo08vLy+PTTT9HpdLQN9KRtoGfFaqJdJ9Lw8DNU3KvKaqKL/+6rV4g0eNK5kddVky8rnMMhn67oIE+a+blrnhBd3TBrzJgxNGjQgJEjRzJs2DAWL16Mn59t86WXWyMd4q0n1Efv0CFeeTng6vR56EmrrtWuTxzt+sT99YIVvbBLywFbG6A2bdrE559/zscff0yzZs0qHQvx1jO4uS8Pd4tlzITHGfN/z5BeaMJYqmJSVfSKgqeTfvfi6uawr2E/dx13tA6otMTO2mFWqakEN717rcOs4cOHs2rVKm699Vb69+/P8uXLqxS+qonFa6Qv/ruPXiHKQb2a8nLAzs5Thb/KAVuzRLSoqIhx48bRvXt3HnvssWrfc/z4cc6ePUv3Lp1oY/CQnZ+ES3DoeEVRlCrDrORsI/kWBqRdK5fQsCCdaa+9WOu9+vbty4YNG4iLi6NXr17Ex8fTvHnzat9b2xpp9WJbqlNgUtl/voi954sqrZG2xzyZLeWA7aW8HHAclgfKN954g6NHj7Jo0aIaN+Hdtm0bADfeeKMWzRRCE06b2Anx1hMX7kccfpWGuJcbZj333Uk+++wz3nrhGby8at8uq3PnzmzZsoVBgwbRs2dP4uPjiY6OrvSev6+RBut7bOW94jMFJhYfyyUiwJ24cH/8NBwa2loO2J7KywFbMgQ+ePAgb775Js899xzXXnttje/bvn07UVFRFo8AhHAEl5jk8XXX0cbgQfdQH/qG+TKgmR99w3zpHupDG4NHxR/iQw89RFZWFj/99JPF146KimLr1q0EBAQQGxvL7t27K44lZhqZfTiTPy8+Ra5rGCo//8+cEmYfzqxzcvalXLXsriXtKi0tZezYsURERPDcc89d9r3btm2jR48eWjVPCE24RKC0VFRUFD169GDu3LlWnRcWFsamTZuIjIykX79+rFmzxq5rpFXAaFZZcjy3zsv+ytlaDtieLC0H/Nlnn7Fjxw5mz5592SyEvLw89u3bJ4FSuJx6FSihrFcZHx9PamqqVec1aNCANWvWEBsby2tfL3HY8j8t1kiD7eWA7cmScsAnT57k2WefZcKECcTGxl72vbt378ZsNtO9e3ctmylEndW7QHn33Xfj6enJ119/bfW5vr6+vDNvIXH/95L2DbsMLdZI16UcsL2YS0svWw5YVVUef/xxAgICmDFjRq3X27ZtGwEBAbRr107LZgpRZ/UuUBoMBkaMGMGcOXOwdivNvBIzq087p35LXddI17UcsD2YSkvJunC+xuM//PADP//8M5988gkGg6HW623bto3u3btrVpZWCK3Uy0/kww8/TFJSEjt27LD4nJrWSF/O5m8+45tJD/HubV15qXdrXugWxltDO/HD9H9wNvmwVW0uXyNt6z7J9igHXFc6nY7FC36gpKTqksoLFy7w5JNPcscddzB8+PBar2U2m9mxY4cMu4VLqpeB8qabbiI8PJw5c+ZYfE75GmlrYs2Gr/7NH9vW4m0IIiKmN9GxA9F7erJn+Q98fP8Aft8Ub/G1Ll0jbYsQb73L5FCW07npSdi4mjfffLPKsSlTpmA0Gvnoo48sulZSUhIXLlyQBznCJWleCsJR/vWvf/HBBx9w5swZfHx8an2/LSUqju/dSdg111eqNw6w/YevWDrjGfwaNmLayv24WVi+tS4lKvJLzHx08EKNxxM3x7Nu9syK/z51KAFVVWl+XZeK1/qN/SfRvQYBkJNxlm8mPVRxLON4MkV5OYS0isLT1x+Atr0G0n/s5QuKFSyfzZsv/4sdO3bQpUvZvdatW0f//v35/PPPGTdunEU/31dffcWjjz5KVlYWAQEBFp0jhKPU250ERo8ezauvvsrixYu5//77L/vey62RvpyWHbtV+3r3u8ew5ZvPuHDqOOlH/6BJVM0J1Jeqyxrp2soB52ee5+TB36q8fulr+Zl/zSeWlhRX+/70Y0kV/96oVcTl26RX+OfUSfz84wJGjx7Nr7/+iqqqjBs3jt69e/Poo49WbuNl1s7vS73ADT16SZAULqne9igB+vTpg4eHB6tXr77s++xRRnfmiB5kHE/m6UXbCGkVafF5dSmj66rlgA8cOMANN9zAU089hU6n49///jf79u2jbdu2Lr12XghL1etP4sMPP8yYMWNISUkhPDy8xvdpvUY64ecfOHfiCA3DWxMc3tqqc21ZI12ucyMv9p53zlP7vzNT1h6A9u3b88orrzBt2jTc3Nx4+eWXoXFL5v2R5dJr54WwVL3uUebl5REaGsq0adN44YUXqn1PbXN7ltj0349JO5pIcWEBGceSSfszkYBGoTz4/jeEtbvepmtOvK6BTduEuWo5YKPRSMOGDfH0D+Tj9Xs5UYh22+nZYe28ENao1588Pz8/7rrrLubOnVtj2o0Wa6STtq8nYdn3HFyzjLQ/Ewls0pyRb3xuc5CsS7uuD3D+NmvVlQP+5JNPaN2jPxN/2MTx/NKK99X1PmCftfNCWKNeB0ooW9L4559/smXLlmqPa7FG+tFZi3gzIYN/bTzCuP8sJTi8NV+MvY31/5lZ+8nVsHSN9N9t2LCB4T068ceW1aDWrcCXrcylJgxFmZXKAR87doyfDxznvre+xMvXH0WnbQkOe6ydF8Ia9T5Q9urVi9atW9eYU6nlGmlvfwOtOnfnoQ+/I+ya61n92QxOHtpj9XUsWSN9qcLCQp5++umK/NEpQ7vj6ZR6QCrmkmKmDuvJM888Q3FxMaqq8to3Sxj05L/K3mLnuUSt1s4LYY16Hyh1Oh2jR4/mhx9+IC+vaglXe6yRdnN3p8Og4aiqSuKmX2y6xuXWSF9q165ddOrUic8++4yZM2eyfv162rVp6aRywAoj2obw0nPP8P7779OrVy/e++ZHIoeNcmgrtFg7L4Q16n2ghLKcyvz8fBYtWlTlmL3WSPsENgAq5yZaQ19Lu4qLi5k+fTo9evTA39+fPXv28PTTT1esg44O8qR/mK9N97ZV/zBf2jXwYtKkSWzdupXsohLyWnRCNTt+GkCL+uJCWKpepweVa9GiBf369WPOnDmMHj260jF7rZE+llBWsqBBs5ZWn1taWsqGNfH8abpAZGQkERERNGnSpCIF5sCBAzz44IMcPHiQF198kWeffRZ9Nat/HF0OOOaSBzgxMTEMf+4d3L19UCzcxMLa2uOXo1V9cSEscUUESijLqRw1ahRHjx6ldeu/chttXSN9fO9OjPl5RHa/qdJuNqUlJexcNJc9yxfg7uVNh0HDrb62onNj7U8L2LpkfsXTeh8fHyIiIjCbzRw+fJjQ0FA+/fRTbr755svWJ3dkOeBL/bBhF4FR1j31t7b2+OVoUV9cCEvV6zzKSxUUFBAaGsrTTz9dlvB8ka15lL8t/Y6FLz2Jb2BDml7TAZ/ABhRknufskd/JPZeG3tOLu17+yKZACWV5lG6lxRw7dozk5GS2b9/OnDlzSEtLIyAggNzc3CpBNCIioqIHWv6/TZs2RVGUKrV/tMhfjKymHDBAfn4+zy/dSUjUteiseMK9ce6HFBcWVKk9bkuPsrydtq6dF8IaV0ygBBg7diyrV6/m6NGjlXqBHx44b3VhrgupJ9i9+BuOJWzjwqkTFGRdwM3dnaCm4bSOiaXHyLFWr8op56tXmNi+IVC2vdinn37K1KlTadq0KfPmzaNHjx4YjUaOHj3KkSNHSE5OrvS/J06cqAii3t7elQJneExv1BbtydP7WB0wy8sHh9VSDnjqqzNoMOzRKq9ba/qNzeoUKMuNiQ6U5Y7Crq6oQLl161ZiY2NZu3Yt/fr1q3jdVddIp6SkMGbMGNauXcvjjz/O22+/ja9v7Q9ojEZjRU/074E0JSUFs9lMaGQ7et47lmv7DsX74oMnc2lZ7qbezQ0UpdIaa1+9QqQFa6x//fVX3liyka63j4I6brCrRaCsy9p5ISx1RX0N9+jRg8jISObOnVspULrcGulgT+bOnctTTz1FQEAA8fHxDBw40OJreHp6Eh0dXaX0LvwVRCsC6MIPOH46jTydJ4qhEV5+Aeg9PFDMZnw93fE2FRLipaNheBieEREU6yIxN21a7S7jJSUlPProowz/94I6B0mt1GXtvBCWuqICpaIoPPTQQ7z22mt8/PHHFVt2hXjraeqjd4k10sHuKmPvvZOlS5cyevRo/v3vfxMYGKjZPWoKosXFxXh6evLGG2/Qvn37Sj3RjcnJnDhxAvPFNB9vb2/atGlTZU40Pj6eo6ln8TIEadZeLVhTX1wIW1xRgRLgwQcfZPr06SxYsIBHHnmk4vVujb1ZfCzXiS0rG+bOfn4ix3bsYPHixRaVSNBKZmYmANdeey3Dhg2rcry4uLhyT/Ti/y5atIjjx49XBNFrLm7862rOFphoc8mySiG0dMUFymbNmjFw4EDmzJlTKVBGGTyICHDnTyvLQWhFNZdyeOMvhOlLWHbwII0aNXLo/S9cKHvy36BBg2qPe3h40LZtW9q2bVvlmNFopG/fvhw7dozRTzyN2Wy2OHfSEcrXzkugFPbiOp92DT300ENs3bqV5OTkitcURSEu3B8PneOTk81mM8aCfAY29WbhwoUOD5JQe6C8nP/973/s2LGDefPm0bVnL9zcXOtjY+3aeSGs5VqfeI0MHz4cg8HA3LlzK17LLzGTVmCiTYC7w9uj0+kY1NSbB0fe5bRVJLYGyrS0NCZNmsSoUaMYNGiQS9YXB8vXzgthiytu6A3g5eXFvffey/JN24k9kUNyTknlMgQ4dk/Hfk196Nq49gJo9lQ+RxkUZN2DmKeeego3NzdmzizbUs4V64tD7WvnhaiLKy5QqqpKUnYx7R99nhY6L/adN1ba+stRAVK9OI/39zXSznLhwgV8fX3x9LR8ud/PP//M999/zzfffENwcDDgmvXFVRU83SRQCvu5ogJlpWV8uoslZp3R0zCb8dTrGBruX2WNtLNcuHDBqmF3bm4ujz32GIMHD+a+++6reN0V64urICtzhF1dMZ+uxExjxcYQ4JxyCebSUnRubkQGeVW7RtqZLly4YNWw+/nnn+fChQvMmjWr0rxqqI/tH5m/1x4vLSkG4NMH4ypeu7T2uDXq0i4hanNFfLp2pReyzgFbjdWk1GTCTa+nmZ8H3UJ9XLJqoDU9yu3bt/Pxxx/z3nvv0bJly0rHaqsvfjnW1h63lK9ecakvJXHlqfdrvR0dJMvDX/kvrTDrPBEGDwZf09ylh39xcXH4+vpWu7nxpYqLi+ncuTM+Pj5s37692i3eXHXtvBD24rp/2RZIzDQ6vCepAqd2b2TNvM+47aZYXn5+Gl5eXg5tgyXyS8ycLTCRXmiiqFQlrP8dBDdowPazBYR46wn10VfbC3vrrbdITEzkt99+q3EfTJdbO9/I9X7/4spSb3uUeSVmZh/OxGh2bPPNZjMlhfn04iz9Yrs79N61SS80kZBRRFK2sXI6lFK2oYVO0aFzc6voCfroFaIu2TEoMTGR66+/nn/+85+8+eabl72Xq9YXF8Ie6mWgVFWVRUdzrFqOWFJUyIY5H7Dvl8Vkn03FOyCQqB79GPj4sxhCmlh1fwWIMHi4RBmC8nSonWmFnC4w2bwHZVMfPcs+ep29vyxh//79eHtfPqXpjyyj09fOA9zeyl92OBd2Vy8DpbV/pCXGImaPu52TB37FP7gxLTvdSOaZk5w6mIBvUDCP/3elTbVvnP1HquWu5qhmUHQEFufwQOeW+NXycMSWLystudKXlbjy1ctHhTvTCrHmT2P9f2Zy8sCvhHeIYdKSHdz31n/4x7xfGPrPV8jPPMfCl5+yug0KZQ+SnCUx08jsw5n8mVMCaJAOpZR9FLI9Aph9OLPWcrDOXDsPZbV84pr7SZAUDlHvAmV6oYnTVsyNmUqK2f79lwDcNm0Gnj5/PR3t9cBjhEZey7HftpF6eJ9V7VCB1PyyhyWOtiu9kCXHczFqXEwMyn4uo1llyfFcdtfyReDnrnNSfXEYEu5aeariylbvPmkJGUVW9SZP7N1FUV4ODZq1pGl0hyrHrxtwCwC/b/rF6rboLrbHkRyZDrU2Nb/WYOmM+uJ7588iuNT586Pi6lHvAmVSttGqXtSZpIMAhF1TNUgChEW3B+Bs8mGr21JehsBRnJEOtTY1v9ZheEyIt8OCZTRZrJ/7Eb179yY1NdUh9xSiXgXK/BKz1StCss6W/TEFhDSt9rihcdnrmWdO2tami2UI7C2vxMzKlDy736c6K1Pyav0ZY0K8Gd7SH0+dYlWP3xIK4KlTGN7Sn+GdIti8eTN5eXnExsby559/anw3IaqqVwnnZwusnw8sLijrgXl4VZ/u4u5Vtv2ZscD2IGTvMgSqqrIqJbdiHbul8jLPsWnuR/y+6Reyzqbi7ulFUNPmtInpzdCnX7L4OsVmlVUn82p9whwd5EkzP3fN64tH/K2+eFRUFFu2bGHAgAH06tWL+Ph4rrvuujrcSYjLq1c9yvRCk+a9lboqL0NgT0nZxRyxMg0n9fA+3r+jJ5u//hQ3vTvt+sTRvH0XCrKz2Pq/WVbdXwWSs4tJyi6u9b1+7jruaB3A7a38aXJxowprP2Tl72/qq+f2Vv6MaOVf5cFNeHg4mzdvplGjRvTp04ddu3ZZeRchLFevepRFpSqKglX7IXr4lM2dFRdV/1CipKgAoNLTcGs4ogxBeTqUpXfJyzzHnCfuoaSoiFHvf027PnGVjp88mGB1G8rToSzJG1UUhbaBnrQN9KxYLZScbST/b6uFytlSXxygcePGbNiwgZtvvpn+/fuzbNky+vbta/XPJkRt6lWgtKUMQWBoGAA56aerPZ6dVvZ6UJPmNrfLnmUIytOhrLFm1tvkZ53n1mlvVQmSAM2v62x1Oy5Nh7Jm848Qbz1x4X7E4Vdp/bmxVMWkqugVBU835bLrzy8nKCiI+Ph4br/9duLi4li4cGG1VSaFqIt6FShtKUPQJKps7ir19/3VHk9NPABAaGQ7m9pkMpnYsnEjf2QdJzw8vOKfwMBATZKhy9OhrFmquXfFAjy8fbjh1nvrfP9LladD2bpTj6+7jjYGD83nc/38/Fi2bBn33nsvt99+O/PmzePee7X92cXVrV4FSlvKELTo2BUvvwAunDrO6T8O0LRt+0rHD65ZBsA1vQfb2CqF/Xt+Y/lHr1Nc/Nccnq+vb6XA+fd/mjVrhodH7QHD2nSoU4f3YszPo2XHbrh7efPH1jUk79iIqdhIcHhrOgwaTkCjUBt+zr/SoeJwvS3NvLy8WLBgAWPGjOH+++8nJyeH8ePHO7tZ4gpRrwKlLWUI9O4edL/nEdZ/+T5LZzzDmE8X4OFdNm+5+ZvPOJt8iFZdehDW7nqb2qRzc+Od6dNY+PYLpKenk5KSUuWfhIQElixZQkZGRsV5iqIQGhp62WDqFRBkdTpU+tEkAHwbBPP1Px/k8IaVlY7Hf/IGI/71bzrGjbDp5y1Ph3LFVTF6vZ65c+diMBiYMGEC2dnZTJ061dnNEleAehUobd3u/6ZH/8mRnZs4sW83797WjZadbiTrzClOHvwN36Bg7nzxgzq3S6fTERoaSmhoKF27dq32fQUFBZw6daraYLp3715SUlIwGv9K7m7fbyj3vftfq9pSmJsFlK000uncuHXaW7QfeCslhYVs//5LNn/9CQv/9QQhrSKr9K4tZe90qLrQ6XR8+OGHGAwGnnnmGbKzs3nttddkTbiok3oVKG0tQ+Du6cXYLxazYc4H7F25iMMbVuJjCKTLLSPLtllrXH0yukVtsqIMgY+PD1FRUURFRVV7XFVVMjIyKoLnUdWfkovVHC2lmssSw80mE4OefI7ud48pOxAEQ59+iayzJzmweimb5n3CyNetSxOCv9KhXDVQQllv/bXXXsNgMDB16lSys7P58MMP0VnxexTiUvUqUAJEGTxtKkPg7uXNwMemMfCxaZq1RQdEGrTbZk1RFEJCQggJCeGGG25gfWo+uzMKsSbPvDwdCqDLbVUfaHS59V4OrF7Ksd+22dhG+6dDaWXKlCkEBgYyfvx4srOzmTNnDnp9vfvICxdQ7z41V1MZAlvSocrTnNy9fPALCq7meDgA+RfO2dwue6ZDaW3s2LH4+/szatQocnNzmT9/vkuW7hCurd6NRUK89TT10Tt9hY4ChPnq7VpQzJZ0qPJ5R5OxEFNx1c0sCnIygco9T2vp69l838iRI1myZAm//PILw4YNIy/POWvmRf1V7wIlQLfG3k6vAKgCXUMuXy6hrmxJhwps0owmUdeiqipHqxlelw+5bX2Qo6rg6Va/AiXAzTffzKpVq9i5cycDBw4kMzPT2U0S9Ui9DJRRBg8iAtyd1qtUgEiDB1F2fqBhSzoUQO/REwFY+f5L5GScrXj99B8H2PzNZwB0u3O0TW1SL7arPurTpw/r1q0jKSmJvn37kpaW5uwmiXqiXtbMAedVYYSyLb/GtQuyey5hfomZjw5esOncBS8+QcKy7/HyN9Di+hhKiopI2b8bU7GRmNtHMWL6TJvbNfG6Bi6ZR2mpQ4cOMXDgQPz8/Fi9ejUtWrRwdpOEi6u3gRLKNrJdctzxO10Pb+lPdJBjiop9eOC81elQUJZqtHvxN+xa9F/SjyWjKBAaeS1d73iQLreMtLk9vnqFie0b2ny+qzh69CgDBgzAZDKxevVq2rZt6+wmCRdWrwMlwO70QtY6cNfv/mG+xNh5bvJSq1LybEqHsgcd0KGhl81rvV1NamoqgwYNIiMjg/j4eDp27OjsJgkXVX/HTxc5sgyBo4MklKUfuUKQBPunQzlaWFgYGzdupEWLFvTt25dt22zLLRVXvnofKMFxZQgcHSTh6kqHcobg4GDWrl3L9ddfz8CBA1m9erWzmyRc0BURKKGsDMHYdkG0CXAHqHNgKT8/wuDBuHZBDpuTrM7Vkg7lLAEBAaxatYq+ffsybNgwfvzxR2c3SbiYej9H+XeqqpKUXczOtEJOF5jQUTZktFT5+8N89XQN8SbK4OH0DRVUVWXR0Rz+tLIchFYUyr4waquZU98VFxfz4IMPsmDBAr766itGj7YthUpcea6scRSOK0PgSIqiEBfu77R0KA+dQlxzvys6SAJ4eHjw7bffEhAQwEMPPUROTg4TJ050drOEC3CdaGAH9i5D4Eh+7jqGhPs5JR1qSLifS/9utOTm5sbnn3+OwWDgySefJDs7m+eff/6K/5IQl3dFB8pL2asMgSNFB3nSv8Ts8HQoZ87POoOiKLz99tsEBgbywgsvkJWVxTvvvCPB8ip21QTKK0X5k3dHBEtnpEO5CkVReP755wkICKjoWc6aNQs3NzdnN004gQTKeigmxBt/dx0rU/IoNquaPuBRKJuTHBLud9X1JKszceJEDAYDDz/8MLm5ucybN8+iWkfiynLFPfW+muSVmFmVksuRnBKrKjVWp/z8SIMHcc2vnjlJSy1evJiRI0cyYMAAFixYgI+Pj7ObJBxIAmU9dyWmQ7mq1atXM3z4cG644QaWLVtGQECAs5skHEQC5RXkSkmHcmXbtm1j6NChREREsGrVKoKDq+4iL648EiivUPU9HcqV7d27l8GDBxMcHEx8fDxhYWHObpKwMwmUQtggKSmJAQMGoNfrWbNmDa1bt3Z2k4QdSZdCCBtERUWxZcsW9Ho9sbGxHDp0yNlNEnYkgVIIG4WHh7N582YaNWpE79692b17t7ObJOxEAqUQddC4cWM2bNhA27Zt6devHxs2bHB2k4QdSKAUoo6CgoKIj4/nxhtvZMiQISxfvtzZTRIak0AphAb8/PxYtmwZcXFxDB8+nPnz5zu7SUJDEiiF0IiXlxcLFizg3nvv5b777uOLL75wdpOERiTLWAgN6fV65s6di8FgYPz48eTk5DB58mSbr3dpPmxRqUqpquKmKHhJPqxDSaAUQmM6nY4PP/wQg8HAlClTyMrK4tVXX7V4aWj5CqukbGNFqeLLrbDy0StEyQoru5LfqhB2oCgKr732GgaDgalTp5Kdnc0HH3yATld97+/va/b/vsmJSllwrE6BSWX/+SL2ni+iqY+ebo1lzb7WZGWOEHb2xRdfMGHCBEaNGsWXX36JXl+5f2KPXaAiAtyJC/fHT4blmpBAKYQDzJ8/n1GjRjFs2DDmz5+Pp2fZXp+JmUbZV7QekEAphIMsX76cO++8k9jYWJYsWcKhfB3rZKf6ekECpRAOtGHDBm655RZue/J5rrvzUYfdV4Jl3UigFMLBfv71EAfdGjv8vsNb+ssw3EYy0yuEA+WVmEl2D6Vuj2xsszIlj/wSa/a/F+UkPUgIB1FVlVUpuRSbVcoet9Tui7G3cey3bTUef+ij+bTt2d+iaxWbVVadzGNEK39JHbKSBEohHCQpu5gjOSU2nXtd/2F4+PhWed0Q0sTia6hAcnYxSdnFtA2UIbg1JFAK4SA70wptzpMc+vTLBDUNr3MbFGBXeqEESivJHKUQDpBeaOJ0gckJM5OVqUBqftnacWE5CZRCOEBCRpGFs5L2p6OsPcJyMvQWwgGSso116k3uXvItBdmZKIpCcIs2XNt3KIFNmtl0LTOQnG0kDr86tOjqIoFSCDvLLzFX7AJkq/X/mVnpv1e+/xI3jZ1E/7GTbGuTSSW/xCxbtFlIAqUQdna2wPb5wFaduxMz/AFaXB+Df3BjstJOc3DNUtZ/+T5rPpuBl68fPe8bb3O72hg8bG7b1URW5ghhZ9vPFrDpTIGmD3KStq9nzj/uxsvfwHO/HMDdy7rliQrQu4kP3UN9NGzVlUv63ULYWVGpitb53VHdbyKsXUeKcrM5eTDB6vMVBYyl0keylARKIeys1E6DtuDw1gDknEuz6XyTDCYtJoFSCDtzs9NywcKcLAA8vG0bPutlGaPFJFAKYWdebkqNZRxslZd5juN7dgAQFt3B6vNVFTzdJFBaSgKlEHYW4q236UHOiX27OLR+BebS0kqvZ55O4ZtJoykuLOCaPnEYGje1+trqxXYJy8hvSgg7C/Wx7c/s3Ik/WfjSk/gHh9A0ugNe/gayzpwk9ff9mIxFNG4TzYjpM2u/kMbtuhrJb0oIO/N11+GjV6xOOm9+XRe63fUwJw/8xqlDeynMzcLDy4cmUdfRfuCt3HjnQ1anBVW0Sa9IsrkVJI9SCAdYlZLHvvNFTt8UA8rm2zo09CIuXJYwWkq+UoRwgM6NvFwiSELZWu/Ojbyc3Yx6RQKlEA4Q4q2nqY/e6TsIKUCYr14e5FhJAqUQDtKtsbfTe5Uq0FWqMVpNAqUQDhJl8CAiwN1pvUoFiDR4ECUbYVhNAqUQDqIoCnHh/njonBMqPXQKcc39pLCYDSRQCuFAfu46hjjpafOQcD9JCbKR/NaEcLDoIE/6h1WtqGhPBxf+hxA136H3vJJIoBTCCWJCvB0WLCNLz7Hq83fp06cPqampDrnnlUYSzoVwosRMIytT8ig2q5o+EVcom5McEu5HdJAnv//+O4MGDUKv1xMfH09kZKSGd7vySaAUwsnySsysSsnlSE6JzXW/y5WfH2nwIK555TnJkydPMmjQIC5cuMCqVavo1KlTHVt+9ZBAKYQLUFWVpOxidqYVcrrAhI6yFTSWKn9/mK+eriHeRBk8qn26fe7cOYYOHUpiYiJLly6lb9++2vwAVzgJlEK4mPRCEwkZRSRnG8m/uJGGApXKSajqXz1PX71CpMGTzo28LFpxk5uby4gRI9i8eTPz589n+PDhmv8MVxoJlEK4sPwSM2cLTKQXmjCWqphUFb2i4OmmEOKtJ9RHb1PKj9FoZNSoUSxatIjZs2czZswYO7T+yiGBUoirVGlpKU888QSzZs3irbfeYurUqc5uksuSlfFCXKXc3Nz49NNPadSoEc888wwZGRm8/fbbsnKnGhIohbiKKYrCK6+8QnBwME899RTnzp1j9uzZ6PUSGi4lvw0hBE8++SQNGzbkoYce4sKFC8yfPx9vb9llqJzMUQohKqxYsYI777yTmJgYli5disFgcHaTXIIESiFEJVu3bmXYsGG0bNmSVatW0bhxY2c3yekkUAohqjhw4ACDBw/Gx8eH1atX06pVK2c3yalkUwwhRBXt27dn69atKIpCz549OXDggLOb5FQSKIUQ1WrVqhVbtmwhNDSU3r17s2XLFmc3yWkkUAohatS4cWPWr1/P9ddfz6BBg1i+fLmzm+QUEiiFEJdlMBhYtWoVgwcP5rbbbuObb75xdpMcTgKlEKJWXl5eLFiwgNGjRzNq1Cg++OADZzfJoSThXAhhEb1ez3/+8x+Cg4P5v//7PzIyMnj11VeviiWPEiiFEBZTFIW33nqL4OBgpk6dyrlz5/jkk09wc3NzdtPsSgKlEMJqU6ZMITg4mLFjx3L+/Hm++eYbPD09bbrWpVvJFZWqlKoqboqCVx23ktOSJJwLIWz2008/cc899xAbG8vixYvx9/e36LzyzYmTso0UWLA5sY9eIcqKzYm1JoFSCFEnGzdu5NZbbyUqKooVK1bQqFGjat/393IX1tYHKi930dRHT7fGNZe7sAcJlEKIOtuzZw9xcXEEBQURHx9PeHh4peP2KKAWEeBOXLg/fg4YlkugFEJoIjk5mUGDBmEymYiPj+eaa64BHFeS154kUAohNHP69GkGDx7M6dOnWbFiBUqrDqxLzbf7ffuH+RITYr/9MyVQCiE0lZmZybBhw/BsewODJk532H3tGSwlUAohNLcvLYeVp4sdft/hLf3tMgyXJYxCCE3llZhZd7bEKfdemZJHfolZ8+tKoBRCaEZVVVal5FJstm2gmp91gdf6X8OznRvxzq0xVp9fbFZZdTIPrQfKEiiFEJpJyi7mSE6JzU+3V7z/Lwqyztt8fxVIzi4mKVvbYb8ESiGEZnamFWJrCviRnZtIWPY9MbePqlMbFGBXemGdrvF3EiiFEJpILzRxusBkU2+ypKiQxa9PIqR1W3o9+Hid2qECqflla8e1IoFSCKGJhIwim3uTa794h8zUEwx/7h3c9O51bovuYnu0IoFSCKGJpGyjTb3JM0mH2PzNZ3S59V5ade6uSVvMQHK2UZNrgQRKIYQG8kvMFbsAWcNsNvPjq0/j7Wcg7qkXtW2TSdUsVUgCpRCizs4W2DYfuH3+bE4d2sOQ/3sR38AGGrfK9nb9nQRKIUSdpRearJ6fzDpzivhP36RVlx50ufVezdukXGyXFiRQCiHqrKhUxdqtIX+a8QylJSUMf+5du7RJUcBYqk3iuZSCEELUWakNK2ESN8fj5W9gyRuTK71uMpY9hMnJOMsXY28D4N43v8A/uLHV9zBptEJHAqUQos7cbNxpvCg3m2O/bav2mMlYVHHMVGzbE2y9RjugS6AUQtSZl5uCtZ23NxMyqn0983QKbw/rQoNmLZmydLfNbVJV8HTTJlDKHKUQos5CvPWa7l6uBRU0K0QmgVIIUWehPq45ONWqXRIohRB15uuuw0fvmIqIlvLVK5rVA5cdzoUQmliVkse+80UuMQTXAR0aehEX7qfZ9YQQos46N/JyiSAJZWu9Ozfy0ux6EiiFEJoI8dbT1Edv8w5CWlGAMF+9Zg9yQAKlEEJD3Rp7O71XqQJdNa7GKIFSCKGZKIMHEQHuTutVKkCkwYMog4em15VAKYTQjKIoxIX746FzTqj00CnENfdD0WhFTjkJlEIITfm56xii0dNmaw0J99MsJehSEiiFEJqLDvKkf5ivQ+/ZP8yX6CBPu1xbAqUQwi5iQrwdFiz7h/kSo/EDnEtJwrkQwq4SM42sTMmj2Kxq+kRcoWxOcki4n916khX3kkAphLC3vBIzq1JyOZJTggJ1Cpjl50caPIhrbp85ySr3lEAphHAEVVVJyi5mZ1ohpwtM6ChbQWOp8veH+erpGuJNlMFD86fbNZFAKYRwuPRCEwkZRSRnG8m/WL1RgUrlJFT1r56nr14h0uBJ50Zemq64sZQESiGEU+WXmDlbYCK90ISxVMWkqugVBU83hRBvPaE+eocMry9HAqUQQtRC0oOEEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIWEiiFEKIW/w8u9m0+2MhGzgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Draw the graph\n", + "pos = nx.spring_layout(G) # positions for all nodes - seed for reproducibility\n", + "fig, ax = plt.subplots(figsize=(4, 4))\n", + "nx.draw(\n", + " G,\n", + " pos,\n", + " with_labels=True,\n", + " node_color=\"skyblue\",\n", + " node_size=700,\n", + " edge_color=\"k\",\n", + " linewidths=1,\n", + " font_size=15,\n", + " ax=ax,\n", + ")\n", + "\n", + "# Display the plot\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "GHcplBDDqpU4", + "outputId": "5608ce1a-75b8-4dd7-ec68-f0f7ca428734" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([4, 5, 3, 3, 1, 2, 3, 4, 3, 3, 3, 4])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def degre_noeuds(adj_matrix_dense):\n", + " return adj_matrix_dense.sum(axis=1)\n", + "\n", + "\n", + "degre_noeuds(adj_matrix_dense)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9ATMw4THrnWT", + "outputId": "1283378b-5327-4a44-9b53-58c5089cad17" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def tous_noeuds_degre_impair_sauf_deux(adj_matrix_dense):\n", + " deg = degre_noeuds(adj_matrix_dense)\n", + " impairs = (deg % 2).sum()\n", + " return bool(impairs <= 2)\n", + "\n", + "\n", + "tous_noeuds_degre_impair_sauf_deux(adj_matrix_dense)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "23W4Bn5jvwGN", + "outputId": "2d38f735-7f17-4dae-a5a4-d38551167a3c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(np.float64(1.0), [0, 3, 1])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def plus_court_chemin(adj_matrix, debut, fin):\n", + " distance = np.array([np.inf for i in range(len(adj_matrix))])\n", + " predecessors = np.array([-1 for i in range(len(adj_matrix))])\n", + " distance[debut] = 0\n", + " for t in range(len(adj_matrix)):\n", + " for i in range(len(adj_matrix)):\n", + " for j in range(len(adj_matrix)):\n", + " d = distance[i] + adj_matrix[i, j]\n", + " if adj_matrix[i, j] != 0 and distance[j] > d:\n", + " distance[j] = d\n", + " predecessors[j] = i\n", + " chemin = []\n", + " while fin != -1:\n", + " chemin.append(int(fin))\n", + " fin = predecessors[fin]\n", + " return distance[fin], chemin[::-1]\n", + "\n", + "\n", + "plus_court_chemin(adj_matrix_dense, 0, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "T8bQZmj2wWWn", + "outputId": "9dc51332-be09-4b69-9208-db3458c628f1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(np.int64(2), np.int64(1)),\n", + " (np.int64(4), np.int64(3)),\n", + " (np.int64(8), np.int64(6)),\n", + " (np.int64(10), np.int64(9))]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def appariement_approche(adj_matrix):\n", + " degre = degre_noeuds(adj_matrix)\n", + " impair = np.arange(degre.shape[0])[degre % 2 == 1]\n", + " paires = []\n", + " for i in impair:\n", + " for j in impair:\n", + " if i <= j:\n", + " continue\n", + " paires.append((i, j, plus_court_chemin(adj_matrix, i, j)[0]))\n", + " paires.sort()\n", + " appariement = []\n", + " selectionne = set()\n", + " for i, j, d in paires:\n", + " if i not in selectionne and j not in selectionne:\n", + " selectionne.add(i)\n", + " selectionne.add(j)\n", + " appariement.append((i, j))\n", + " return appariement\n", + "\n", + "\n", + "appariement = appariement_approche(adj_matrix_dense)\n", + "appariement" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "krmGWY-T0bZh", + "outputId": "30617cbf-12b1-47ab-fab3-85f379a32e68" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 2],\n", + " [0, 0, 2, 2, 0, 2, 0, 1, 0, 0, 0, 1],\n", + " [0, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],\n", + " [1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", + " [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],\n", + " [0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1],\n", + " [0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 1, 0],\n", + " [0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0],\n", + " [2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2],\n", + " [2, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0]])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def ajout_arc(adj_matrix):\n", + " copie = adj_matrix.copy()\n", + " appariement = appariement_approche(adj_matrix_dense)\n", + " for i, j in appariement:\n", + " chemin = plus_court_chemin(adj_matrix, i, j)[1]\n", + " for k in range(len(chemin) - 1):\n", + " copie[chemin[k], chemin[k + 1]] += 1\n", + " copie[chemin[k + 1], chemin[k]] += 1\n", + " return copie\n", + "\n", + "\n", + "matrice_paire = ajout_arc(adj_matrix_dense)\n", + "matrice_paire" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VXXei49I17IY", + "outputId": "832c5fb0-ec65-40d3-b511-83a48be40f92" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([6, 8, 4, 4, 2, 4, 4, 6, 4, 4, 4, 6])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "degre_noeuds(matrice_paire)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dGGJiXVr2MpZ", + "outputId": "4d4ea4b5-0bc2-44b5-f7f5-bbf6ec6b1222" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 11, 10, 8, 7, 6, 11, 1, 3, 9, 0, 3, 6, 2, 1, 8, 5, 4, 7, 10]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def chemin_passant_par_tous_les_arcs(matrice):\n", + " \"\"\"\n", + " Retourne un chemin passant par tous les arcs d'un graphe non orienté,\n", + " représenté par une matrice d'adjacence.\n", + " Retourne None si le graphe n'est pas eulérien.\n", + " \"\"\"\n", + " # Conversion matrice -> liste d'adjacence\n", + " n = len(matrice)\n", + " graphe = {}\n", + " for i in range(n):\n", + " for j in range(i + 1, n):\n", + " if matrice[i][j] > 0:\n", + " if i not in graphe:\n", + " graphe[i] = []\n", + " if j not in graphe:\n", + " graphe[j] = []\n", + " graphe[i].append(j)\n", + " graphe[j].append(i)\n", + "\n", + " # Vérifie si le graphe est eulérien\n", + " def est_eulerien(g):\n", + " degres = [0] * n\n", + " for u in g:\n", + " degres[u] = len(g[u])\n", + " degres_impairs = [u for u in range(n) if degres[u] % 2 != 0]\n", + " if len(degres_impairs) == 0 or len(degres_impairs) == 2:\n", + " return True, degres_impairs\n", + " return False, degres_impairs\n", + "\n", + " # Algorithme de Hierholzer\n", + " def hierholzer(g):\n", + " stack = []\n", + " chemin = []\n", + " sommet_courant = 0\n", + " stack.append(sommet_courant)\n", + "\n", + " while stack:\n", + " u = stack[-1]\n", + " if g[u]:\n", + " v = g[u].pop()\n", + " g[v].remove(u) # Supprime l'arc dans les deux sens\n", + " stack.append(v)\n", + " else:\n", + " chemin.append(stack.pop())\n", + " return chemin[::-1]\n", + "\n", + " # Copie du graphe pour ne pas le modifier\n", + " g = {}\n", + " for u in graphe:\n", + " g[u] = graphe[u].copy()\n", + "\n", + " chemin = hierholzer(g)\n", + " return chemin\n", + "\n", + "\n", + "chemin_passant_par_tous_les_arcs(matrice_paire)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "2ldG9xEz4Cw8" + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "this312", + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From d688d13bc23db7ffc1ed0c327c06020350622e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Sun, 19 Oct 2025 12:01:39 +0200 Subject: [PATCH 6/6] fix --- .../years/2025/seance7_postier_chinois.ipynb | 108 ++++++++---------- requirements-dev.txt | 1 + 2 files changed, 51 insertions(+), 58 deletions(-) diff --git a/_doc/practice/years/2025/seance7_postier_chinois.ipynb b/_doc/practice/years/2025/seance7_postier_chinois.ipynb index b02685c..037088a 100644 --- a/_doc/practice/years/2025/seance7_postier_chinois.ipynb +++ b/_doc/practice/years/2025/seance7_postier_chinois.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -23,28 +23,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "Adjacency Matrix:\n" + "Adjacency Matrix:\n", + "[[0 1 0 1 0 0 0 0 1 1 1 0]\n", + " [1 0 1 0 0 0 1 0 1 0 0 1]\n", + " [0 1 0 0 1 0 0 1 0 1 1 0]\n", + " [1 0 0 0 0 0 0 0 1 0 0 0]\n", + " [0 0 1 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 1 1 1 0 0]\n", + " [0 1 0 0 0 0 0 0 0 1 0 0]\n", + " [0 0 1 0 0 1 0 0 1 1 1 1]\n", + " [1 1 0 1 0 1 0 1 0 0 0 0]\n", + " [1 0 1 0 0 1 1 1 0 0 0 0]\n", + " [1 0 1 0 0 0 0 1 0 0 0 0]\n", + " [0 1 0 0 0 0 0 1 0 0 0 0]]\n" ] - }, - { - "data": { - "text/plain": [ - "array([[0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1],\n", - " [0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1],\n", - " [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],\n", - " [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", - " [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", - " [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],\n", - " [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0],\n", - " [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0],\n", - " [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1],\n", - " [1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0]])" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ @@ -67,12 +59,12 @@ "adj_matrix_dense = adj_matrix.todense()\n", "\n", "print(\"Adjacency Matrix:\")\n", - "display(adj_matrix_dense)" + "print(adj_matrix_dense)" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -84,7 +76,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -117,7 +109,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -129,10 +121,10 @@ { "data": { "text/plain": [ - "array([4, 5, 3, 3, 1, 2, 3, 4, 3, 3, 3, 4])" + "array([5, 5, 5, 2, 1, 3, 2, 6, 5, 5, 3, 2])" ] }, - "execution_count": 3, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -147,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -162,7 +154,7 @@ "False" ] }, - "execution_count": 4, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -179,7 +171,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -191,10 +183,10 @@ { "data": { "text/plain": [ - "(np.float64(1.0), [0, 3, 1])" + "(np.float64(2.0), [0, 1])" ] }, - "execution_count": 5, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -223,7 +215,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -235,13 +227,13 @@ { "data": { "text/plain": [ - "[(np.int64(2), np.int64(1)),\n", - " (np.int64(4), np.int64(3)),\n", - " (np.int64(8), np.int64(6)),\n", + "[(np.int64(1), np.int64(0)),\n", + " (np.int64(4), np.int64(2)),\n", + " (np.int64(8), np.int64(5)),\n", " (np.int64(10), np.int64(9))]" ] }, - "execution_count": 6, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -273,7 +265,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -285,21 +277,21 @@ { "data": { "text/plain": [ - "array([[0, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 2],\n", - " [0, 0, 2, 2, 0, 2, 0, 1, 0, 0, 0, 1],\n", - " [0, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],\n", - " [1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", - " [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],\n", - " [0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1],\n", - " [0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 1, 0],\n", - " [0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0],\n", - " [2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2],\n", - " [2, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0]])" + "array([[0, 2, 0, 1, 0, 0, 0, 0, 1, 2, 2, 0],\n", + " [2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1],\n", + " [0, 1, 0, 0, 2, 0, 0, 1, 0, 1, 1, 0],\n", + " [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],\n", + " [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0],\n", + " [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", + " [0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1],\n", + " [1, 1, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0],\n", + " [2, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n", + " [2, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],\n", + " [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]])" ] }, - "execution_count": 7, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -322,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -334,10 +326,10 @@ { "data": { "text/plain": [ - "array([6, 8, 4, 4, 2, 4, 4, 6, 4, 4, 4, 6])" + "array([8, 6, 6, 2, 2, 4, 2, 6, 6, 6, 4, 2])" ] }, - "execution_count": 8, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -348,7 +340,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -360,10 +352,10 @@ { "data": { "text/plain": [ - "[0, 11, 10, 8, 7, 6, 11, 1, 3, 9, 0, 3, 6, 2, 1, 8, 5, 4, 7, 10]" + "[0, 10, 7, 11, 1, 8, 7, 9, 6, 1, 2, 9, 5, 7, 2, 4, 8, 3, 0, 1, 8, 9, 10]" ] }, - "execution_count": 9, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } diff --git a/requirements-dev.txt b/requirements-dev.txt index 96d1a55..ac15ba5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -22,6 +22,7 @@ matplotlib mutagen # mp3 nbsphinx networkx +opencv-python openpyxl pandas patsy