diff --git a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals-CSharp.ipynb b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals-CSharp.ipynb index 69b5e2221c..546b3c5a4b 100644 --- a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals-CSharp.ipynb +++ b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals-CSharp.ipynb @@ -3,7 +3,16 @@ { "cell_type": "markdown", "id": "5393fa40", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.006383, + "end_time": "2026-09-27T07:23:30.395308+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:30.388925+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "# CSP-1 : Fondamentaux des CSP - Version .NET (Choco-solver 4.10.17 via IKVM 8.15.0)\n", "\n", @@ -39,7 +48,16 @@ { "cell_type": "markdown", "id": "9104ce9b", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.00534, + "end_time": "2026-09-27T07:23:30.406153+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:30.400813+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -64,34 +82,156 @@ "id": "fa887f4c", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:10.900846Z", - "iopub.status.busy": "2026-07-03T23:16:10.896421Z", - "iopub.status.idle": "2026-07-03T23:16:12.097200Z", - "shell.execute_reply": "2026-07-03T23:16:12.095489Z" - } + "iopub.execute_input": "2026-09-27T07:23:30.436869Z", + "iopub.status.busy": "2026-09-27T07:23:30.425312Z", + "iopub.status.idle": "2026-09-27T07:23:33.631695Z", + "shell.execute_reply": "2026-09-27T07:23:33.627320Z" + }, + "papermill": { + "duration": 3.220182, + "end_time": "2026-09-27T07:23:33.631928+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:30.411746+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "display_data", "data": { - "text/html": "" + "text/html": [ + "\r\n", + "
\r\n", + " \r\n", + " \r\n", + "
" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" }, { - "output_type": "stream", "name": "stdout", - "text": "DLL Choco trouvee : org.chocosolver.solver.dll\r\n" + "output_type": "stream", + "text": [ + "DLL Choco trouvee : org.chocosolver.solver.dll\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Taille : 11,4 MB\r\n" + "output_type": "stream", + "text": [ + "Taille : 11.4 MB\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Date de build : 2026-08-19\r\n" + "output_type": "stream", + "text": [ + "Date de build : 2026-09-24\n" + ] } ], "source": [ @@ -127,40 +267,56 @@ "id": "2488ea57", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:12.098945Z", - "iopub.status.busy": "2026-07-03T23:16:12.098765Z", - "iopub.status.idle": "2026-07-03T23:16:12.661265Z", - "shell.execute_reply": "2026-07-03T23:16:12.660663Z" - } + "iopub.execute_input": "2026-09-27T07:23:33.647476Z", + "iopub.status.busy": "2026-09-27T07:23:33.647133Z", + "iopub.status.idle": "2026-09-27T07:23:39.779014Z", + "shell.execute_reply": "2026-09-27T07:23:39.778630Z" + }, + "papermill": { + "duration": 6.140149, + "end_time": "2026-09-27T07:23:39.779164+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:33.639015+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "display_data", "data": { - "text/html": "
Installing Packages
" + "text/html": [ + "
Installed Packages
" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" }, { - "output_type": "stream", "name": "stdout", - "text": "IKVM 8.15.0 pret (home=ikvm-home-8.15.0-win-x64, tzdb=True) - Choco-solver charge\r\n" + "output_type": "stream", + "text": [ + "IKVM 8.15.0 pret (home=ikvm-home-8.15.0-linux-x64, tzdb=True) - Choco-solver charge\n" + ] } ], "source": [ "// Configuration IKVM 8.15.0 pour Choco-solver -- recette #4711 (IkvmCopyMerge récursif)\n", "// Leve \"Could not locate ikvm home path\" : IKVM 8.15 lit AppContext[\"IKVM.Home\"], pas la variable\n", "// d'environnement. On assemble le home complet (fusion image arch-indépendante any/any + native\n", - "// win-x64) via copie RÉCURSIVE (la copie plate rate les sous-dossiers lib/ et tzdb.dat), AVANT\n", + "// de la plateforme) via copie RÉCURSIVE (la copie plate rate les sous-dossiers lib/ et tzdb.dat), AVANT\n", "// tout premier appel Java (l'init JVM se declenche au premier type java.*, cellule suivante).\n", "// See #4667, See #3801, See #4956.\n", "#r \"nuget: IKVM, 8.15.0\"\n", "#r \"nuget: IKVM.Image, 8.15.0\"\n", - "#r \"nuget: IKVM.Image.runtime.win-x64, 8.15.0\"\n", "\n", "using System.IO;\n", + "using System.Runtime.InteropServices;\n", "\n", - "string ikvmVer = \"8.15.0\", ikvmRid = \"win-x64\";\n", + "// RID de la machine courante (win-x64, linux-x64, osx-arm64, ...) : le paquet IKVM.Image\n", + "// tire deja l'image native de chaque plateforme, il suffit de choisir la bonne.\n", + "string ikvmOs = OperatingSystem.IsWindows() ? \"win\" : OperatingSystem.IsMacOS() ? \"osx\" : \"linux\";\n", + "string ikvmRid = ikvmOs + \"-\" + RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();\n", + "string ikvmVer = \"8.15.0\";\n", "string nugetRoot = Environment.GetEnvironmentVariable(\"NUGET_PACKAGES\")\n", " ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), \".nuget\", \"packages\");\n", "string ikvmBaseAny = Path.Combine(nugetRoot, \"ikvm.image\", ikvmVer, \"ikvm\", \"any\", \"any\");\n", @@ -197,17 +353,27 @@ "id": "d88eae78", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:12.663094Z", - "iopub.status.busy": "2026-07-03T23:16:12.662712Z", - "iopub.status.idle": "2026-07-03T23:16:12.735669Z", - "shell.execute_reply": "2026-07-03T23:16:12.735091Z" - } + "iopub.execute_input": "2026-09-27T07:23:39.797105Z", + "iopub.status.busy": "2026-09-27T07:23:39.796874Z", + "iopub.status.idle": "2026-09-27T07:23:39.876454Z", + "shell.execute_reply": "2026-09-27T07:23:39.876060Z" + }, + "papermill": { + "duration": 0.090044, + "end_time": "2026-09-27T07:23:39.876593+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:39.786549+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Choco-solver 4.10.17 charge -- Model, IntVar, arithm, allDifferent disponibles\r\n" + "output_type": "stream", + "text": [ + "Choco-solver 4.10.17 charge -- Model, IntVar, arithm, allDifferent disponibles\n" + ] } ], "source": [ @@ -225,7 +391,16 @@ { "cell_type": "markdown", "id": "9f051749", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.005301, + "end_time": "2026-09-27T07:23:39.887423+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:39.882122+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -255,7 +430,16 @@ { "cell_type": "markdown", "id": "743cde31", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.005207, + "end_time": "2026-09-27T07:23:39.898087+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:39.892880+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "Implémentons une classe CSP générique en C# (équivalent direct de la classe Python du notebook source). Elle servira pour les sections 3 et 4 (implémentation manuelle), avant de basculer sur Choco en section 5." ] @@ -266,17 +450,27 @@ "id": "129f2a8c", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:12.737888Z", - "iopub.status.busy": "2026-07-03T23:16:12.737464Z", - "iopub.status.idle": "2026-07-03T23:16:12.928162Z", - "shell.execute_reply": "2026-07-03T23:16:12.926000Z" - } + "iopub.execute_input": "2026-09-27T07:23:39.912540Z", + "iopub.status.busy": "2026-09-27T07:23:39.912132Z", + "iopub.status.idle": "2026-09-27T07:23:40.151425Z", + "shell.execute_reply": "2026-09-27T07:23:40.150786Z" + }, + "papermill": { + "duration": 0.248336, + "end_time": "2026-09-27T07:23:40.151589+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:39.903253+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Classe CSP C# définie.\r\n" + "output_type": "stream", + "text": [ + "Classe CSP C# définie.\n" + ] } ], "source": [ @@ -333,7 +527,16 @@ { "cell_type": "markdown", "id": "c59de729", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.006202, + "end_time": "2026-09-27T07:23:40.163975+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.157773+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -358,82 +561,118 @@ "id": "eb8596f9", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:12.931625Z", - "iopub.status.busy": "2026-07-03T23:16:12.930865Z", - "iopub.status.idle": "2026-07-03T23:16:13.166695Z", - "shell.execute_reply": "2026-07-03T23:16:13.166343Z" - } + "iopub.execute_input": "2026-09-27T07:23:40.180495Z", + "iopub.status.busy": "2026-09-27T07:23:40.180027Z", + "iopub.status.idle": "2026-09-27T07:23:40.391761Z", + "shell.execute_reply": "2026-09-27T07:23:40.391423Z" + }, + "papermill": { + "duration": 0.221802, + "end_time": "2026-09-27T07:23:40.391866+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.170064+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Problème de coloration de l Australie\r\n" + "output_type": "stream", + "text": [ + "Problème de coloration de l Australie\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=============================================\r\n" + "output_type": "stream", + "text": [ + "=============================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Variables : WA, NT, SA, Q, NSW, V, T\r\n" + "output_type": "stream", + "text": [ + "Variables : WA, NT, SA, Q, NSW, V, T\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Taille dom. : 3 couleurs\r\n" + "output_type": "stream", + "text": [ + "Taille dom. : 3 couleurs\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Espace brut : 2187 combinaisons\r\n" + "output_type": "stream", + "text": [ + "Espace brut : 2187 combinaisons\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Adjacences :\r\n" + "output_type": "stream", + "text": [ + "Adjacences :\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " WA -> [NT, SA]\r\n" + "output_type": "stream", + "text": [ + " WA -> [NT, SA]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NT -> [WA, SA, Q]\r\n" + "output_type": "stream", + "text": [ + " NT -> [WA, SA, Q]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " SA -> [WA, NT, Q, NSW, V]\r\n" + "output_type": "stream", + "text": [ + " SA -> [WA, NT, Q, NSW, V]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Q -> [NT, SA, NSW]\r\n" + "output_type": "stream", + "text": [ + " Q -> [NT, SA, NSW]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NSW -> [Q, SA, V]\r\n" + "output_type": "stream", + "text": [ + " NSW -> [Q, SA, V]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " V -> [SA, NSW]\r\n" + "output_type": "stream", + "text": [ + " V -> [SA, NSW]\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " T -> []\r\n" + "output_type": "stream", + "text": [ + " T -> []\n" + ] } ], "source": [ @@ -474,7 +713,16 @@ { "cell_type": "markdown", "id": "e1f7a3c9", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.00814, + "end_time": "2026-09-27T07:23:40.409606+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.401466+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Lecture de l'instance** (cellule ci-dessus) :\n", "\n", @@ -492,122 +740,174 @@ "id": "1484605f", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:13.168846Z", - "iopub.status.busy": "2026-07-03T23:16:13.168426Z", - "iopub.status.idle": "2026-07-03T23:16:13.302852Z", - "shell.execute_reply": "2026-07-03T23:16:13.301556Z" - } + "iopub.execute_input": "2026-09-27T07:23:40.423932Z", + "iopub.status.busy": "2026-09-27T07:23:40.423648Z", + "iopub.status.idle": "2026-09-27T07:23:40.608444Z", + "shell.execute_reply": "2026-09-27T07:23:40.608139Z" + }, + "papermill": { + "duration": 0.192994, + "end_time": "2026-09-27T07:23:40.608556+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.415562+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Graphe de contraintes - Australie (vue texte)\r\n" + "output_type": "stream", + "text": [ + "Graphe de contraintes - Australie (vue texte)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=============================================\r\n" + "output_type": "stream", + "text": [ + "=============================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NT (deg 3 - Territoire du Nord)\r\n" + "output_type": "stream", + "text": [ + " NT (deg 3 - Territoire du Nord)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " /|\\\r\n" + "output_type": "stream", + "text": [ + " /|\\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " WA | Q (deg 3 - Queensland)\r\n" + "output_type": "stream", + "text": [ + " WA | Q (deg 3 - Queensland)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " \\ | /\r\n" + "output_type": "stream", + "text": [ + " \\ | /\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " \\ | /\r\n" + "output_type": "stream", + "text": [ + " \\ | /\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " \\ | /\r\n" + "output_type": "stream", + "text": [ + " \\ | /\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " SA (deg 5 - noeud le plus contraint, hub)\r\n" + "output_type": "stream", + "text": [ + " SA (deg 5 - noeud le plus contraint, hub)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " /|\\\r\n" + "output_type": "stream", + "text": [ + " /|\\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " / | \\\r\n" + "output_type": "stream", + "text": [ + " / | \\\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NSW | V (deg 2 - Victoria, au sud de NSW)\r\n" + "output_type": "stream", + "text": [ + " NSW | V (deg 2 - Victoria, au sud de NSW)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " |\r\n" + "output_type": "stream", + "text": [ + " |\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " T (deg 0 - Tasmanie, ile isolee au sud)\r\n" + "output_type": "stream", + "text": [ + " T (deg 0 - Tasmanie, ile isolee au sud)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Arêtes : 9 paires de contraintes binaires (régions adjacentes != même couleur)\r\n" + "output_type": "stream", + "text": [ + "Arêtes : 9 paires de contraintes binaires (régions adjacentes != même couleur)\n" + ] } ], "source": [ @@ -645,7 +945,16 @@ { "cell_type": "markdown", "id": "72e0ef68", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.0064, + "end_time": "2026-09-27T07:23:40.622147+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.615747+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : le graphe de contraintes de l'Australie a 7 noeuds et 9 arêtes. SA (Australie-Méridionale) est le noeud le plus contraint (5 voisins) -- c est lui qui elimine le plus de combinaisons. T (Tasmanie) est isolee : n importe quelle couleur lui convient.\n", "\n", @@ -658,7 +967,16 @@ { "cell_type": "markdown", "id": "b1406284", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.006285, + "end_time": "2026-09-27T07:23:40.635153+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.628868+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -689,42 +1007,62 @@ "id": "a1718468", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:13.307014Z", - "iopub.status.busy": "2026-07-03T23:16:13.306339Z", - "iopub.status.idle": "2026-07-03T23:16:13.453159Z", - "shell.execute_reply": "2026-07-03T23:16:13.451836Z" - } + "iopub.execute_input": "2026-09-27T07:23:40.651976Z", + "iopub.status.busy": "2026-09-27T07:23:40.651663Z", + "iopub.status.idle": "2026-09-27T07:23:40.740785Z", + "shell.execute_reply": "2026-09-27T07:23:40.740590Z" + }, + "papermill": { + "duration": 0.099302, + "end_time": "2026-09-27T07:23:40.740888+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.641586+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Brute force - Coloration Australie\r\n" + "output_type": "stream", + "text": [ + "Brute force - Coloration Australie\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=============================================\r\n" + "output_type": "stream", + "text": [ + "=============================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Combinaisons testees : 2187\r\n" + "output_type": "stream", + "text": [ + "Combinaisons testees : 2187\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Solutions trouvees : 18\r\n" + "output_type": "stream", + "text": [ + "Solutions trouvees : 18\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Ratio solutions : 0,82 %\r\n" + "output_type": "stream", + "text": [ + "Ratio solutions : 0.82 %\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Temps brute force : 3,9 ms\r\n" + "output_type": "stream", + "text": [ + "Temps brute force : 1.2 ms\n" + ] } ], "source": [ @@ -768,28 +1106,46 @@ { "cell_type": "markdown", "id": "d0e6f2b8", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.006394, + "end_time": "2026-09-27T07:23:40.754811+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.748417+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Lecture du brute force** (cellule ci-dessus) :\n", "\n", "La sortie quantifie le coût de l'approche exhaustive : **2187 combinaisons testées pour 18 solutions**, soit un ratio de **0,82 %** — les solutions sont rares dans l'espace brut, l'essentiel du travail de l'énumération est rejeté par le filtre de cohérence.\n", "\n", - "Les **3,9 ms** mesurés semblent négligeables, mais la croissance est en 3ⁿ : chaque variable ajoutée triple l'espace. À 15 variables, le même balayage vaut ~14 millions de combinaisons ; à 20, ~3,5 milliards — là où le backtracking de la cellule suivante, en coupant des sous-arbres entiers dès la première incohérence partielle, reste dans des tailles polynomiales en pratique sur ces instances.\n", + "Les quelques millisecondes mesurées (valeur qui dépend de la machine, lue dans la sortie ci-dessus) semblent négligeables, mais la croissance est en 3ⁿ : chaque variable ajoutée triple l'espace. À 15 variables, le même balayage vaut ~14 millions de combinaisons ; à 20, ~3,5 milliards — là où le backtracking de la cellule suivante, en coupant des sous-arbres entiers dès la première incohérence partielle, reste dans des tailles polynomiales en pratique sur ces instances.\n", "\n", "Les **18 solutions** serviront d'étalon : c'est exactement le compte que Choco-solver énumérera en section 6 (cf. la sortie d'énumération complète), ce qui validera la chaîne brute force → backtracking → solveur industriel sur une même instance." ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "fa31c9c5", + "metadata": { + "papermill": { + "duration": 0.006973, + "end_time": "2026-09-27T07:23:40.768366+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.761393+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Du brute force au backtracking\n", "\n", "Le brute force ci-dessus est **correct mais exhaustif** : il énumère tout le produit cartésien des domaines, puis filtre les combinaisons valides. Sur la coloration de l'Australie (7 territoires, 3 couleurs), cela fait $3^7 = 2187$ combinaisons — gérable. Mais sur un graphe à 30 variables et 5 couleurs, on passe à $5^{30} \\approx 9{,}3 \\times 10^{20}$ : l'explosion combinatoire rend le brute force inutilisable en pratique.\n", "\n", "Le **backtracking** est la première amélioration fondamentale : au lieu d'énumérer puis de filtrer, on **assigne les variables une par une** et on **vérifie les contraintes dès qu'une variable est fixée**. Dès qu'une assignation viole une contrainte, on remonte (*backtrack*) sans explorer les sous-arbres invalides — on élague ainsi l'immense majorité de l'espace de recherche." - ], - "id": "fa31c9c5" + ] }, { "cell_type": "code", @@ -797,42 +1153,62 @@ "id": "48e72ae3", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:13.456135Z", - "iopub.status.busy": "2026-07-03T23:16:13.455476Z", - "iopub.status.idle": "2026-07-03T23:16:13.687450Z", - "shell.execute_reply": "2026-07-03T23:16:13.686748Z" - } + "iopub.execute_input": "2026-09-27T07:23:40.783760Z", + "iopub.status.busy": "2026-09-27T07:23:40.783415Z", + "iopub.status.idle": "2026-09-27T07:23:40.919805Z", + "shell.execute_reply": "2026-09-27T07:23:40.919616Z" + }, + "papermill": { + "duration": 0.14487, + "end_time": "2026-09-27T07:23:40.919894+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.775024+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Backtracking simple - Coloration Australie\r\n" + "output_type": "stream", + "text": [ + "Backtracking simple - Coloration Australie\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=============================================\r\n" + "output_type": "stream", + "text": [ + "=============================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Solution : WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Rouge\r\n" + "output_type": "stream", + "text": [ + "Solution : WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Rouge\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Assignations : ~11\r\n" + "output_type": "stream", + "text": [ + "Assignations : ~11\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Temps : 1,21 ms\r\n" + "output_type": "stream", + "text": [ + "Temps : 0.53 ms\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Validation : VALIDE\r\n" + "output_type": "stream", + "text": [ + "Validation : VALIDE\n" + ] } ], "source": [ @@ -893,7 +1269,16 @@ { "cell_type": "markdown", "id": "f73333ce", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.00668, + "end_time": "2026-09-27T07:23:40.933914+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.927234+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : le backtracking C# trouve une solution en explorant beaucoup moins de combinaisons que la brute force.\n", "\n", @@ -910,7 +1295,16 @@ { "cell_type": "markdown", "id": "742479ab", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.006522, + "end_time": "2026-09-27T07:23:40.947027+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.940505+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -936,17 +1330,27 @@ "id": "ec03ac6e", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:13.692080Z", - "iopub.status.busy": "2026-07-03T23:16:13.691510Z", - "iopub.status.idle": "2026-07-03T23:16:14.151756Z", - "shell.execute_reply": "2026-07-03T23:16:14.143767Z" - } + "iopub.execute_input": "2026-09-27T07:23:40.962430Z", + "iopub.status.busy": "2026-09-27T07:23:40.962079Z", + "iopub.status.idle": "2026-09-27T07:23:41.029889Z", + "shell.execute_reply": "2026-09-27T07:23:41.029581Z" + }, + "papermill": { + "duration": 0.076423, + "end_time": "2026-09-27T07:23:41.030028+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:40.953605+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Heuristique MRV définie.\r\n" + "output_type": "stream", + "text": [ + "Heuristique MRV définie.\n" + ] } ], "source": [ @@ -965,15 +1369,24 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "68deec77", + "metadata": { + "papermill": { + "duration": 0.01089, + "end_time": "2026-09-27T07:23:41.051905+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.041015+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Pourquoi MRV réduit l'arbre de recherche\n", "\n", "L'heuristique **MRV (Minimum Remaining Values)** choisit, à chaque étape, la variable non encore assignée qui a le **moins de valeurs viables** dans son domaine. L'intuition : la variable la plus contrainte est celle qui risque le plus d'échouer — l'assigner en premier fait remonter les échecs plus tôt et élague l'arbre.\n", "\n", "La cellule suivante montre comment, après quelques assignations sur l'Australie, MRV sélectionne automatiquement le territoire le plus contraint (celui dont les voisins déjà colorés réduisent le plus son domaine), plutôt que de suivre l'ordre naturel de déclaration des variables." - ], - "id": "68deec77" + ] }, { "cell_type": "code", @@ -981,57 +1394,83 @@ "id": "4e434bcb", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:14.169652Z", - "iopub.status.busy": "2026-07-03T23:16:14.167498Z", - "iopub.status.idle": "2026-07-03T23:16:14.688015Z", - "shell.execute_reply": "2026-07-03T23:16:14.687453Z" - } + "iopub.execute_input": "2026-09-27T07:23:41.069774Z", + "iopub.status.busy": "2026-09-27T07:23:41.069453Z", + "iopub.status.idle": "2026-09-27T07:23:41.149273Z", + "shell.execute_reply": "2026-09-27T07:23:41.148897Z" + }, + "papermill": { + "duration": 0.089575, + "end_time": "2026-09-27T07:23:41.149419+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.059844+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Assignation partielle : WA=Rouge, NT=Vert\r\n" + "output_type": "stream", + "text": [ + "Assignation partielle : WA=Rouge, NT=Vert\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Variable Valeurs viables MRV Deg\r\n" + "output_type": "stream", + "text": [ + "Variable Valeurs viables MRV Deg\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "-------------------------------------------------------\r\n" + "output_type": "stream", + "text": [ + "-------------------------------------------------------\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "SA Bleu 1 3 <-- MRV\r\n" + "output_type": "stream", + "text": [ + "SA Bleu 1 3 <-- MRV\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Q Rouge,Bleu 2 2\r\n" + "output_type": "stream", + "text": [ + "Q Rouge,Bleu 2 2\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "NSW Rouge,Vert,Bleu 3 3\r\n" + "output_type": "stream", + "text": [ + "NSW Rouge,Vert,Bleu 3 3\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "V Rouge,Vert,Bleu 3 2\r\n" + "output_type": "stream", + "text": [ + "V Rouge,Vert,Bleu 3 2\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "T Rouge,Vert,Bleu 3 0\r\n" + "output_type": "stream", + "text": [ + "T Rouge,Vert,Bleu 3 0\n" + ] } ], "source": [ @@ -1058,7 +1497,16 @@ { "cell_type": "markdown", "id": "c5p1tr4n", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.010544, + "end_time": "2026-09-27T07:23:41.169363+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.158819+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : MRV choisit **SA** (Southern Australia) parce qu'il ne lui reste qu'**une seule valeur viable** (`Bleu`) -- c'est la variable la plus contrainte du graphe. C'est le principe **fail-fast** : traiter en priorite la variable la plus susceptible de provoquer une impasse, afin de detecter l'échec tot dans l'arbre de recherche et d'éviter d'explorer de larges sous-arbres voués à l'échec.\n", "\n", @@ -1071,6 +1519,16 @@ { "cell_type": "markdown", "id": "3757c66b", + "metadata": { + "papermill": { + "duration": 0.007835, + "end_time": "2026-09-27T07:23:41.185353+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.177518+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### 5.2 Value Ordering : LCV (Least Constraining Value)\n", "\n", @@ -1081,8 +1539,7 @@ "$$\\text{LCV}(v) = \\sum_{\\text{voisin } Y \\text{ non assigné}} |\\{w \\in D_Y : \\text{contrainte}(X, v, Y, w) \\text{ violée}\\}|$$\n", "\n", "On trie les valeurs de $D_X$ par $\\text{LCV}(v)$ **croissant** (la moins contraignante d'abord). L'implémentation C# correspondante est la méthode `OrderLCV` dans la cellule suivante." - ], - "metadata": {} + ] }, { "cell_type": "code", @@ -1090,17 +1547,27 @@ "id": "51b6440b", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:14.689912Z", - "iopub.status.busy": "2026-07-03T23:16:14.689561Z", - "iopub.status.idle": "2026-07-03T23:16:15.045632Z", - "shell.execute_reply": "2026-07-03T23:16:15.045020Z" - } + "iopub.execute_input": "2026-09-27T07:23:41.202758Z", + "iopub.status.busy": "2026-09-27T07:23:41.202484Z", + "iopub.status.idle": "2026-09-27T07:23:41.254834Z", + "shell.execute_reply": "2026-09-27T07:23:41.254641Z" + }, + "papermill": { + "duration": 0.061877, + "end_time": "2026-09-27T07:23:41.254924+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.193047+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Heuristique LCV définie.\r\n" + "output_type": "stream", + "text": [ + "Heuristique LCV définie.\n" + ] } ], "source": [ @@ -1127,7 +1594,17 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "c0258755", + "metadata": { + "papermill": { + "duration": 0.00731, + "end_time": "2026-09-27T07:23:41.271551+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.264241+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Combiner les heuristiques : MRV + LCV\n", "\n", @@ -1136,8 +1613,7 @@ "- **LCV (Least Constraining Value)** décide *quelle valeur* tester en premier — celle qui élimine le moins d'options pour les voisins.\n", "\n", "Un backtracking efficace les **combine** : MRV pour le choix de variable, LCV pour l'ordre des valeurs. Les deux réduisent l'arbre de façon complémentaire — MRV en accélérant les échecs, LCV en privilégiant les branches qui aboutissent. La cellule suivante implémente cette combinaison." - ], - "id": "c0258755" + ] }, { "cell_type": "code", @@ -1145,17 +1621,27 @@ "id": "858509d3", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:15.049741Z", - "iopub.status.busy": "2026-07-03T23:16:15.048033Z", - "iopub.status.idle": "2026-07-03T23:16:15.120523Z", - "shell.execute_reply": "2026-07-03T23:16:15.120269Z" - } + "iopub.execute_input": "2026-09-27T07:23:41.294996Z", + "iopub.status.busy": "2026-09-27T07:23:41.294756Z", + "iopub.status.idle": "2026-09-27T07:23:41.361860Z", + "shell.execute_reply": "2026-09-27T07:23:41.361687Z" + }, + "papermill": { + "duration": 0.080085, + "end_time": "2026-09-27T07:23:41.361948+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.281863+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Backtracking amélioré défini (variantes contrôlées par useMRV/useLCV booléens).\r\n" + "output_type": "stream", + "text": [ + "Backtracking amélioré défini (variantes contrôlées par useMRV/useLCV booléens).\n" + ] } ], "source": [ @@ -1212,7 +1698,17 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "1628d0c4", + "metadata": { + "papermill": { + "duration": 0.007488, + "end_time": "2026-09-27T07:23:41.377261+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.369773+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Comparaison empirique des variantes\n", "\n", @@ -1222,8 +1718,7 @@ "3. **Backtracking MRV + LCV** — backtracking enrichi des deux heuristiques.\n", "\n", "La comparaison suivante mesure le **nombre d'assignations testées** par chaque variante. C'est la métrique qui révèle le gain réel des heuristiques : moins d'assignations = moins de nœuds explorés = arbre plus petit. Sur un petit graphe l'écart peut sembler modeste, mais il devient drastique quand le nombre de variables croît." - ], - "id": "1628d0c4" + ] }, { "cell_type": "code", @@ -1231,47 +1726,69 @@ "id": "e02b0c4f", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:15.122524Z", - "iopub.status.busy": "2026-07-03T23:16:15.121931Z", - "iopub.status.idle": "2026-07-03T23:16:15.343215Z", - "shell.execute_reply": "2026-07-03T23:16:15.342624Z" - } + "iopub.execute_input": "2026-09-27T07:23:41.394724Z", + "iopub.status.busy": "2026-09-27T07:23:41.394476Z", + "iopub.status.idle": "2026-09-27T07:23:41.492393Z", + "shell.execute_reply": "2026-09-27T07:23:41.492159Z" + }, + "papermill": { + "duration": 0.107001, + "end_time": "2026-09-27T07:23:41.492486+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.385485+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Comparaison des variantes - Coloration Australie\r\n" + "output_type": "stream", + "text": [ + "Comparaison des variantes - Coloration Australie\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=======================================================\r\n" + "output_type": "stream", + "text": [ + "=======================================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Variante Assignations Temps (ms)\r\n" + "output_type": "stream", + "text": [ + "Variante Assignations Temps (ms)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "--------------------------------------------------\r\n" + "output_type": "stream", + "text": [ + "--------------------------------------------------\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Backtracking simple 102 8,83\r\n" + "output_type": "stream", + "text": [ + "Backtracking simple 102 1.08\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "+ MRV 102 1,32\r\n" + "output_type": "stream", + "text": [ + "+ MRV 102 0.41\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "+ MRV + LCV 102 3,44\r\n" + "output_type": "stream", + "text": [ + "+ MRV + LCV 102 1.03\n" + ] } ], "source": [ @@ -1305,7 +1822,16 @@ { "cell_type": "markdown", "id": "f691a71f", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.007676, + "end_time": "2026-09-27T07:23:41.508559+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.500883+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : sur ce petit graphe, les heuristiques n amelioresent pas le compte d assignations.\n", "\n", @@ -1326,7 +1852,16 @@ { "cell_type": "markdown", "id": "b40856f3", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.007722, + "end_time": "2026-09-27T07:23:41.523667+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.515945+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -1351,72 +1886,104 @@ "id": "28460e99", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:15.346323Z", - "iopub.status.busy": "2026-07-03T23:16:15.345618Z", - "iopub.status.idle": "2026-07-03T23:16:17.021222Z", - "shell.execute_reply": "2026-07-03T23:16:17.020031Z" - } + "iopub.execute_input": "2026-09-27T07:23:41.540935Z", + "iopub.status.busy": "2026-09-27T07:23:41.540527Z", + "iopub.status.idle": "2026-09-27T07:23:42.214500Z", + "shell.execute_reply": "2026-09-27T07:23:42.214271Z" + }, + "papermill": { + "duration": 0.683291, + "end_time": "2026-09-27T07:23:42.214613+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:41.531322+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Choco-solver - Coloration Australie\r\n" + "output_type": "stream", + "text": [ + "Choco-solver - Coloration Australie\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "=============================================\r\n" + "output_type": "stream", + "text": [ + "=============================================\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Solution : {\r\n" + "output_type": "stream", + "text": [ + "Solution : {\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " WA = Rouge (0)\r\n" + "output_type": "stream", + "text": [ + " WA = Rouge (0)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NT = Vert (1)\r\n" + "output_type": "stream", + "text": [ + " NT = Vert (1)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " SA = Bleu (2)\r\n" + "output_type": "stream", + "text": [ + " SA = Bleu (2)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Q = Rouge (0)\r\n" + "output_type": "stream", + "text": [ + " Q = Rouge (0)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " NSW = Vert (1)\r\n" + "output_type": "stream", + "text": [ + " NSW = Vert (1)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " V = Rouge (0)\r\n" + "output_type": "stream", + "text": [ + " V = Rouge (0)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " T = Rouge (0)\r\n" + "output_type": "stream", + "text": [ + " T = Rouge (0)\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "}\r\n" + "output_type": "stream", + "text": [ + "}\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Temps : 463,19 ms\r\n" + "output_type": "stream", + "text": [ + "Temps : 55.56 ms\n" + ] } ], "source": [ @@ -1462,7 +2029,16 @@ { "cell_type": "markdown", "id": "d2d3ac0d", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008962, + "end_time": "2026-09-27T07:23:42.232884+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.223922+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : Choco-solver résout la coloration de l'Australie en un temps mesuré en sortie au premier appel, puis beaucoup plus rapidement une fois la JVM chaude (cf. énumération cellule suivante). Le premier appel paie le demarrage de la JVM Java (IKVM) sous-jacente ; en regime etabli, le coeur metier (propagation + backtracking) est quasi-instantane (runtime *machine-dep*, cf. la mesure en sortie de la cellule suivante).\n", "\n", @@ -1485,57 +2061,83 @@ "id": "e32623d6", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:17.027955Z", - "iopub.status.busy": "2026-07-03T23:16:17.027358Z", - "iopub.status.idle": "2026-07-03T23:16:17.211376Z", - "shell.execute_reply": "2026-07-03T23:16:17.210931Z" - } + "iopub.execute_input": "2026-09-27T07:23:42.251953Z", + "iopub.status.busy": "2026-09-27T07:23:42.251614Z", + "iopub.status.idle": "2026-09-27T07:23:42.362560Z", + "shell.execute_reply": "2026-09-27T07:23:42.362344Z" + }, + "papermill": { + "duration": 0.121429, + "end_time": "2026-09-27T07:23:42.362663+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.241234+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Nombre total de solutions : 18\r\n" + "output_type": "stream", + "text": [ + "Nombre total de solutions : 18\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Temps énumération : 30,40 ms\r\n" + "output_type": "stream", + "text": [ + "Temps énumération : 3.85 ms\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Premières 5 solutions :\r\n" + "output_type": "stream", + "text": [ + "Premières 5 solutions :\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Solution 1 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Rouge }\r\n" + "output_type": "stream", + "text": [ + " Solution 1 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Rouge }\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Solution 2 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Vert }\r\n" + "output_type": "stream", + "text": [ + " Solution 2 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Vert }\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Solution 3 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Bleu }\r\n" + "output_type": "stream", + "text": [ + " Solution 3 : { WA=Rouge, NT=Vert, SA=Bleu, Q=Rouge, NSW=Vert, V=Rouge, T=Bleu }\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Solution 4 : { WA=Rouge, NT=Bleu, SA=Vert, Q=Rouge, NSW=Bleu, V=Rouge, T=Rouge }\r\n" + "output_type": "stream", + "text": [ + " Solution 4 : { WA=Rouge, NT=Bleu, SA=Vert, Q=Rouge, NSW=Bleu, V=Rouge, T=Rouge }\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Solution 5 : { WA=Rouge, NT=Bleu, SA=Vert, Q=Rouge, NSW=Bleu, V=Rouge, T=Vert }\r\n" + "output_type": "stream", + "text": [ + " Solution 5 : { WA=Rouge, NT=Bleu, SA=Vert, Q=Rouge, NSW=Bleu, V=Rouge, T=Vert }\n" + ] } ], "source": [ @@ -1581,7 +2183,16 @@ { "cell_type": "markdown", "id": "c7271b01", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008632, + "end_time": "2026-09-27T07:23:42.381524+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.372892+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : Choco énumère les 18 solutions valides (comme la brute force, mais avec propagation de contraintes en interne).\n", "\n", @@ -1597,7 +2208,16 @@ { "cell_type": "markdown", "id": "7c5476d1", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008306, + "end_time": "2026-09-27T07:23:42.398454+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.390148+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### 6.1 Démonstration SOTA : N-Reines avec Choco\n", "\n", @@ -1610,77 +2230,111 @@ "id": "4a683ace", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:17.214032Z", - "iopub.status.busy": "2026-07-03T23:16:17.213558Z", - "iopub.status.idle": "2026-07-03T23:16:17.500528Z", - "shell.execute_reply": "2026-07-03T23:16:17.500034Z" - } + "iopub.execute_input": "2026-09-27T07:23:42.417689Z", + "iopub.status.busy": "2026-09-27T07:23:42.417456Z", + "iopub.status.idle": "2026-09-27T07:23:42.619220Z", + "shell.execute_reply": "2026-09-27T07:23:42.618907Z" + }, + "papermill": { + "duration": 0.212456, + "end_time": "2026-09-27T07:23:42.619335+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.406879+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Solution 8-Reines :\r\n" + "output_type": "stream", + "text": [ + "Solution 8-Reines :\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " (col -> ligne) : 0->4, 1->6, 2->1, 3->5, 4->2, 5->0, 6->3, 7->7\r\n" + "output_type": "stream", + "text": [ + " (col -> ligne) : 0->4, 1->6, 2->1, 3->5, 4->2, 5->0, 6->3, 7->7\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Temps : 23,16 ms\r\n" + "output_type": "stream", + "text": [ + "Temps : 18.68 ms\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "\r\n" + "output_type": "stream", + "text": [ + "\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Echiquier (Q = reine) :\r\n" + "output_type": "stream", + "text": [ + "Echiquier (Q = reine) :\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 7 | . . . . . . . Q \r\n" + "output_type": "stream", + "text": [ + " Ligne 7 | . . . . . . . Q \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 6 | . Q . . . . . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 6 | . Q . . . . . . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 5 | . . . Q . . . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 5 | . . . Q . . . . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 4 | Q . . . . . . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 4 | Q . . . . . . . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 3 | . . . . . . Q . \r\n" + "output_type": "stream", + "text": [ + " Ligne 3 | . . . . . . Q . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 2 | . . . . Q . . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 2 | . . . . Q . . . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 1 | . . Q . . . . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 1 | . . Q . . . . . \n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": " Ligne 0 | . . . . . Q . . \r\n" + "output_type": "stream", + "text": [ + " Ligne 0 | . . . . . Q . . \n" + ] } ], "source": [ @@ -1745,7 +2399,16 @@ { "cell_type": "markdown", "id": "4bdd51fe", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.009353, + "end_time": "2026-09-27T07:23:42.638578+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.629225+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Interprétation** : Choco-solver résout les 8-Reines quasi-instantanément (runtime *machine-dep*, temps mesure en sortie de la cellule précédente).\n", "\n", @@ -1767,7 +2430,16 @@ { "cell_type": "markdown", "id": "f7b629b0", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.009256, + "end_time": "2026-09-27T07:23:42.656636+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.647380+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### 6.2 Contrainte globale : `AllDifferent` avec Choco\n", "\n", @@ -1775,14 +2447,22 @@ "\n", "**Pourquoi \"globale\" ?** Au lieu de coder $O(n^2)$ contraintes binaires `xi != xj` (qui laissent le solveur explorer tout l'espace par backtracking), `allDifferent` est traitée comme **une seule contrainte** par Choco via une **structure de couplage** (matching biparti, complexité $O(n\\sqrt{n})$ -- cf. [Regin 1994, *A Filtering Algorithm for Constraints of Difference in CSPs*, JAIR](https://www.jair.org/index.php/jair/article/view/10357)). Sur 4 variables de domaine `{1..4}`, le nombre de solutions tombe directement à $4! = 24$ **sans aucun backtracking** sur cette contrainte.\n", "\n", - "**Parité pédagogique avec le twin Python** : la jumeau Python ([CSP-1-Fundamentals.ipynb, section *AllDifferentConstraint*](CSP-1-Fundamentals.ipynb)) utilise la bibliothèque `python-constraint` et expose la même contrainte via `Problem.addConstraint(AllDifferentConstraint(), variables)`. La formulation Choco est plus déclarative (un seul appel) et intégrée au solveur ; la formulation Python est plus pédagogique (le constructeur `AllDifferentConstraint` est explicite, on voit comment il s'instancie). Même concept, deux implémentations SOTA.\n", - "" + "**Parité pédagogique avec le twin Python** : la jumeau Python ([CSP-1-Fundamentals.ipynb, section *AllDifferentConstraint*](CSP-1-Fundamentals.ipynb)) utilise la bibliothèque `python-constraint` et expose la même contrainte via `Problem.addConstraint(AllDifferentConstraint(), variables)`. La formulation Choco est plus déclarative (un seul appel) et intégrée au solveur ; la formulation Python est plus pédagogique (le constructeur `AllDifferentConstraint` est explicite, on voit comment il s'instancie). Même concept, deux implémentations SOTA.\n" ] }, { "cell_type": "markdown", "id": "c514399d", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008991, + "end_time": "2026-09-27T07:23:42.675225+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.666234+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "**Exemple illustratif** -- `allDifferent` sur 4 variables `{A, B, C, D}` de domaine `{1, 2, 3, 4}` (les **24 permutations**) :\n", "\n", @@ -1824,14 +2504,22 @@ "2. Sudoku (lignes/colonnes/blocs), N-Reines (lignes), coloration équitable, planning de personnel, ordre de passage : c'est la **première contrainte globale** à apprendre\n", "3. Choco expose aussi `model.allDifferentExcept` (relaxation avec liste d'exceptions) -- utile pour les variantes pedagogiques\n", "\n", - "> **Référence** : Choco-solver 4.10.17 documentation, [section Global Constraints](https://choco-solver.org/2021/04/08/global-constraints/) ; implémentation par matching biparti (cf. Regin 1994, *A Filtering Algorithm for Constraints of Difference in CSPs*, J. Artif. Intell. Res. 1).\n", - "" + "> **Référence** : Choco-solver 4.10.17 documentation, [section Global Constraints](https://choco-solver.org/2021/04/08/global-constraints/) ; implémentation par matching biparti (cf. Regin 1994, *A Filtering Algorithm for Constraints of Difference in CSPs*, J. Artif. Intell. Res. 1).\n" ] }, { "cell_type": "markdown", "id": "1ad348f6", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008913, + "end_time": "2026-09-27T07:23:42.693323+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.684410+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -1862,7 +2550,16 @@ { "cell_type": "markdown", "id": "c7e38188", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.014654, + "end_time": "2026-09-27T07:23:42.720201+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.705547+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Exercice 1 : 4-Reines avec backtracking manuel C#\n", "\n", @@ -1879,22 +2576,34 @@ "id": "9643c3e5", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:17.503747Z", - "iopub.status.busy": "2026-07-03T23:16:17.503177Z", - "iopub.status.idle": "2026-07-03T23:16:17.587914Z", - "shell.execute_reply": "2026-07-03T23:16:17.587426Z" - } + "iopub.execute_input": "2026-09-27T07:23:42.754591Z", + "iopub.status.busy": "2026-09-27T07:23:42.754176Z", + "iopub.status.idle": "2026-09-27T07:23:42.818106Z", + "shell.execute_reply": "2026-09-27T07:23:42.817849Z" + }, + "papermill": { + "duration": 0.082437, + "end_time": "2026-09-27T07:23:42.818210+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.735773+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Exercice à compléter : 4-Reines avec backtracking manuel C#\r\n" + "output_type": "stream", + "text": [ + "Exercice à compléter : 4-Reines avec backtracking manuel C#\n" + ] }, { - "output_type": "stream", "name": "stdout", - "text": "Solution attendue : 2 solutions symetriques.\r\n" + "output_type": "stream", + "text": [ + "Solution attendue : 2 solutions symetriques.\n" + ] } ], "source": [ @@ -1912,7 +2621,16 @@ { "cell_type": "markdown", "id": "d6f9e788", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.009479, + "end_time": "2026-09-27T07:23:42.837970+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.828491+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Exercice 2 : Comparer MRV sur les 4-Reines (manuel vs Choco)\n", "\n", @@ -1929,17 +2647,27 @@ "id": "6060993d", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:17.590085Z", - "iopub.status.busy": "2026-07-03T23:16:17.589646Z", - "iopub.status.idle": "2026-07-03T23:16:17.634729Z", - "shell.execute_reply": "2026-07-03T23:16:17.634010Z" - } + "iopub.execute_input": "2026-09-27T07:23:42.857951Z", + "iopub.status.busy": "2026-09-27T07:23:42.857643Z", + "iopub.status.idle": "2026-09-27T07:23:42.893414Z", + "shell.execute_reply": "2026-09-27T07:23:42.893180Z" + }, + "papermill": { + "duration": 0.046551, + "end_time": "2026-09-27T07:23:42.893510+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.846959+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Exercice de benchmark - decommentez pour tester\r\n" + "output_type": "stream", + "text": [ + "Exercice de benchmark - decommentez pour tester\n" + ] } ], "source": [ @@ -1956,7 +2684,16 @@ { "cell_type": "markdown", "id": "753a31f5", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.009996, + "end_time": "2026-09-27T07:23:42.913258+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.903262+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Exercice 3 : SEND + MORE = MONEY avec Choco-solver\n", "\n", @@ -1986,17 +2723,27 @@ "id": "4d01fd8f", "metadata": { "execution": { - "iopub.execute_input": "2026-07-03T23:16:17.637279Z", - "iopub.status.busy": "2026-07-03T23:16:17.636866Z", - "iopub.status.idle": "2026-07-03T23:16:17.682017Z", - "shell.execute_reply": "2026-07-03T23:16:17.681698Z" - } + "iopub.execute_input": "2026-09-27T07:23:42.933642Z", + "iopub.status.busy": "2026-09-27T07:23:42.933413Z", + "iopub.status.idle": "2026-09-27T07:23:42.968855Z", + "shell.execute_reply": "2026-09-27T07:23:42.968670Z" + }, + "papermill": { + "duration": 0.046322, + "end_time": "2026-09-27T07:23:42.968959+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.922637+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { - "output_type": "stream", "name": "stdout", - "text": "Exercice SEND + MORE = MONEY - decommentez pour tester\r\n" + "output_type": "stream", + "text": [ + "Exercice SEND + MORE = MONEY - decommentez pour tester\n" + ] } ], "source": [ @@ -2015,7 +2762,16 @@ { "cell_type": "markdown", "id": "6bd4bdcf", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.008898, + "end_time": "2026-09-27T07:23:42.987243+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.978345+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "### Et ensuite ?\n", "\n", @@ -2038,7 +2794,16 @@ { "cell_type": "markdown", "id": "08476ffa", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.009187, + "end_time": "2026-09-27T07:23:43.005429+00:00", + "exception": false, + "start_time": "2026-09-27T07:23:42.996242+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "***\n", "\n", @@ -2081,6 +2846,23 @@ } ], "metadata": { + "cost": { + "api_provider": "none", + "api_usd_est": 0.0, + "cpu_min": 2, + "external_account": "none", + "free_alternative": "self", + "gpu_min": 0, + "gpu_required": false, + "metadata_written": "2026-07-28", + "network": false, + "qcc_tokens_est": 0, + "reduced_pedagogical": null, + "reproducibility": "HIGH", + "validator": "manual", + "vram_gb": 0, + "vram_tier": "NONE" + }, "coursia": { "epic": "#4956", "ikvm": "8.15.0", @@ -2098,26 +2880,21 @@ "mimetype": "text/x-csharp", "name": "C#", "pygments_lexer": "csharp", - "version": "12.0" + "version": "13.0" }, - "cost": { - "api_usd_est": 0.0, - "api_provider": "none", - "qcc_tokens_est": 0, - "cpu_min": 2, - "gpu_min": 0, - "gpu_required": false, - "vram_gb": 0, - "vram_tier": "NONE", - "network": false, - "external_account": "none", - "free_alternative": "self", - "reduced_pedagogical": null, - "reproducibility": "HIGH", - "metadata_written": "2026-07-28", - "validator": "manual" + "papermill": { + "default_parameters": {}, + "duration": 15.217674, + "end_time": "2026-09-27T07:23:43.131096+00:00", + "environment_variables": {}, + "exception": null, + "input_path": "CSP-1-Fundamentals-CSharp.ipynb", + "output_path": "CSP-1-Fundamentals-CSharp.ipynb", + "parameters": {}, + "start_time": "2026-09-27T07:23:27.913422+00:00", + "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-2-Consistency-CSharp.ipynb b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-2-Consistency-CSharp.ipynb index 3f6ec33c3d..c2531ac105 100644 --- a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-2-Consistency-CSharp.ipynb +++ b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-2-Consistency-CSharp.ipynb @@ -5,10 +5,10 @@ "id": "ff8c1476", "metadata": { "papermill": { - "duration": 0.004218, - "end_time": "2026-07-31T19:43:29.035464", + "duration": 0.009571, + "end_time": "2026-09-27T07:23:49.998909+00:00", "exception": false, - "start_time": "2026-07-31T19:43:29.031246", + "start_time": "2026-09-27T07:23:49.989338+00:00", "status": "completed" }, "tags": [] @@ -56,16 +56,16 @@ "id": "f5e3a0d6", "metadata": { "execution": { - "iopub.execute_input": "2026-07-31T19:43:29.052207Z", - "iopub.status.busy": "2026-07-31T19:43:29.046692Z", - "iopub.status.idle": "2026-07-31T19:43:30.527525Z", - "shell.execute_reply": "2026-07-31T19:43:30.520815Z" + "iopub.execute_input": "2026-09-27T07:23:50.038872Z", + "iopub.status.busy": "2026-09-27T07:23:50.026734Z", + "iopub.status.idle": "2026-09-27T07:23:52.661554Z", + "shell.execute_reply": "2026-09-27T07:23:52.656588Z" }, "papermill": { - "duration": 1.488155, - "end_time": "2026-07-31T19:43:30.527640", + "duration": 2.654102, + "end_time": "2026-09-27T07:23:52.661735+00:00", "exception": false, - "start_time": "2026-07-31T19:43:29.039485", + "start_time": "2026-09-27T07:23:50.007633+00:00", "status": "completed" }, "tags": [] @@ -76,10 +76,11 @@ "text/html": [ "\r\n", "
\r\n", - "