diff --git a/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb b/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
index 011be66b3..6065b6784 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
@@ -77,87 +77,330 @@
},
"outputs": [
{
- "output_type": "display_data",
"data": {
- "text/markdown": "# Sudoku-0 : Environnement et Classes de Base (C#)\n\n**Navigation** : [Index](README.md) | [Sudoku-1 Backtracking C# >>](Sudoku-1-Backtracking-Csharp.ipynb)\n\n## Objectifs d'apprentissage\n\nA la fin de ce notebook, vous saurez :\n1. Comprendre la structure de donnees `SudokuGrid` et ses methodes principales\n2. Utiliser `ISudokuSolver` pour implementer un solveur de Sudoku\n3. Exploiter `SudokuHelper` pour charger des grilles et tester des solveurs\n4. Comparer les performances de plusieurs solveurs sur differentes difficultes\n\n**Prerequis** : Notions de base en C# (.NET Interactive) \n**Duree estimee** : ~15 min"
+ "text/html": [
+ "\r\n",
+ "
\r\n",
+ "
\r\n",
+ " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
+ "
\r\n",
+ " \r\n",
+ "
"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/html": ""
+ "text/markdown": [
+ "# Sudoku-0 : Environnement et Classes de Base (C#)\n",
+ "\n",
+ "**Navigation** : [Index](README.md) | [Sudoku-1 Backtracking C# >>](Sudoku-1-Backtracking-Csharp.ipynb)\n",
+ "\n",
+ "## Objectifs d'apprentissage\n",
+ "\n",
+ "A la fin de ce notebook, vous saurez :\n",
+ "1. Comprendre la structure de donnees `SudokuGrid` et ses methodes principales\n",
+ "2. Utiliser `ISudokuSolver` pour implementer un solveur de Sudoku\n",
+ "3. Exploiter `SudokuHelper` pour charger des grilles et tester des solveurs\n",
+ "4. Comparer les performances de plusieurs solveurs sur differentes difficultes\n",
+ "\n",
+ "**Prerequis** : Notions de base en C# (.NET Interactive) \n",
+ "**Duree estimee** : ~15 min"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "## Définition de la classe SudokuGrid\n\nNous définissons ici la classe SudokuGrid qui représente une grille de Sudoku et fournit des méthodes pour manipuler et afficher les grilles.\n"
+ "text/html": [
+ ""
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "## Définition de la classe SudokuGrid\n",
+ "\n",
+ "Nous définissons ici la classe SudokuGrid qui représente une grille de Sudoku et fournit des méthodes pour manipuler et afficher les grilles.\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "SudokuGrid defini.\r\n"
+ "output_type": "stream",
+ "text": [
+ "SudokuGrid defini.\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "### Interpretation : Structure de donnees pour la grille Sudoku\n\n**Sortie obtenue** : La classe `SudokuGrid` encapsule toutes les operations de manipulation, validation et affichage d'une grille de Sudoku 9x9.\n\n| Aspect | Valeur | Signification |\n|--------|--------|---------------|\n| `Cells[9,9]` | int[,] | Stockage interne des valeurs (0 = vide) |\n| `AllNeighbours` | 27 x 9 positions | Pre-calcul des voisins ligne/colonne/bloc |\n| `CellNeighbours[9][9]` | ~20 positions chacune | Voisins directs de chaque cellule |\n| `GetAvailableNumbers()` | int[] | Candidats valides pour une cellule |\n| `NbErrors()` | int | Nombre de conflits + modifications erronees |\n\n**Points cles** :\n1. **Pre-calcul des voisins** : `AllNeighbours` et `CellNeighbours` sont calcules une seule fois a l'initialisation, evitant les recalculs couteux\n2. **Conversion flexible** : Methodes pour convertir entre tableaux 1D, 2D et jagged arrays (utile pour differents formats de fichiers)\n3. **Validation robuste** : `NbErrors` compte a la fois les doublons (ligne/colonne/bloc) et les modifications de indices pre-remplis\n4. **Parsing tolerant** : `ReadMultiSudoku` accepte plusieurs formats (`.`, `X`, `-`, espaces)\n\n> **Note technique** : La structure `CellNeighbours[i][j]` contient environ 20 positions (8 ligne + 8 colonne + 4 bloc, moins les doublons). Ce pre-calcul est crucial pour les performances des algorithmes de backtracking et de propagation de contraintes."
+ "text/markdown": [
+ "### Interpretation : Structure de donnees pour la grille Sudoku\n",
+ "\n",
+ "**Sortie obtenue** : La classe `SudokuGrid` encapsule toutes les operations de manipulation, validation et affichage d'une grille de Sudoku 9x9.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `Cells[9,9]` | int[,] | Stockage interne des valeurs (0 = vide) |\n",
+ "| `AllNeighbours` | 27 x 9 positions | Pre-calcul des voisins ligne/colonne/bloc |\n",
+ "| `CellNeighbours[9][9]` | ~20 positions chacune | Voisins directs de chaque cellule |\n",
+ "| `GetAvailableNumbers()` | int[] | Candidats valides pour une cellule |\n",
+ "| `NbErrors()` | int | Nombre de conflits + modifications erronees |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Pre-calcul des voisins** : `AllNeighbours` et `CellNeighbours` sont calcules une seule fois a l'initialisation, evitant les recalculs couteux\n",
+ "2. **Conversion flexible** : Methodes pour convertir entre tableaux 1D, 2D et jagged arrays (utile pour differents formats de fichiers)\n",
+ "3. **Validation robuste** : `NbErrors` compte a la fois les doublons (ligne/colonne/bloc) et les modifications de indices pre-remplis\n",
+ "4. **Parsing tolerant** : `ReadMultiSudoku` accepte plusieurs formats (`.`, `X`, `-`, espaces)\n",
+ "\n",
+ "> **Note technique** : La structure `CellNeighbours[i][j]` contient environ 20 positions (8 ligne + 8 colonne + 4 bloc, moins les doublons). Ce pre-calcul est crucial pour les performances des algorithmes de backtracking et de propagation de contraintes."
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "## Définition de l'interface ISudokuSolver\n\nNous définissons ici l'interface ISudokuSolver qui sera implémentée par les différentes stratégies de résolution de Sudoku.\n"
+ "text/markdown": [
+ "## Définition de l'interface ISudokuSolver\n",
+ "\n",
+ "Nous définissons ici l'interface ISudokuSolver qui sera implémentée par les différentes stratégies de résolution de Sudoku.\n"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "ISudokuSolver defini.\r\n"
+ "output_type": "stream",
+ "text": [
+ "ISudokuSolver defini.\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "### Interpretation : Interface de strategie\n\n**Sortie obtenue** : L'interface `ISudokuSolver` definit le contrat que tous les solveurs doivent respecter.\n\n| Aspect | Valeur | Signification |\n|--------|--------|---------------|\n| `Solve(SudokuGrid)` | SudokuGrid | Methode unique de resolution |\n| Pattern | Strategie | Permuter les algorithmes sans modifier le code client |\n\n**Points cles** :\n1. **Simplicite** : Une seule methode `Solve` prenant une grille et retournant une grille resolue\n2. **Flexibilite** : N'importe quel algorithme (backtracking, CSP, metaheuristique) peut implementer cette interface\n3. **Composabilite** : Les solveurs peuvent etre passes en parametre, stockes dans des listes, testes unitairement\n4. **Extensibilite** : Ajouter un nouveau solver ne necessite que d'implementer l'interface\n\n> **Note technique** : Ce design pattern permet a `SudokuHelper.TestSolvers` d'accepter une liste de `(string, ISudokuSolver)` pour comparer tous les algorithmes avec le meme code de test."
+ "text/markdown": [
+ "### Interpretation : Interface de strategie\n",
+ "\n",
+ "**Sortie obtenue** : L'interface `ISudokuSolver` definit le contrat que tous les solveurs doivent respecter.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `Solve(SudokuGrid)` | SudokuGrid | Methode unique de resolution |\n",
+ "| Pattern | Strategie | Permuter les algorithmes sans modifier le code client |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Simplicite** : Une seule methode `Solve` prenant une grille et retournant une grille resolue\n",
+ "2. **Flexibilite** : N'importe quel algorithme (backtracking, CSP, metaheuristique) peut implementer cette interface\n",
+ "3. **Composabilite** : Les solveurs peuvent etre passes en parametre, stockes dans des listes, testes unitairement\n",
+ "4. **Extensibilite** : Ajouter un nouveau solver ne necessite que d'implementer l'interface\n",
+ "\n",
+ "> **Note technique** : Ce design pattern permet a `SudokuHelper.TestSolvers` d'accepter une liste de `(string, ISudokuSolver)` pour comparer tous les algorithmes avec le meme code de test."
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "## Définition de la classe SudokuHelper\n\nNous ajoutons ici la classe SudokuHelper qui contient des méthodes utilitaires pour charger des grilles de Sudoku et tester des solvers.\n\n- `GetSudokus` : Renvoie des listes de Sudoku issues de fichiers de 3 difficultés différentes.\n- `SolveSudoku` : effectue un test simple d'un solver sur un sudoku donné.\n- `TestSolvers` : exécute les tests de performance sur plusieurs solveurs.\n- `DisplayResults` : affiche les résultats des tests sous forme de graphiques.\n\n"
+ "text/markdown": [
+ "## Définition de la classe SudokuHelper\n",
+ "\n",
+ "Nous ajoutons ici la classe SudokuHelper qui contient des méthodes utilitaires pour charger des grilles de Sudoku et tester des solvers.\n",
+ "\n",
+ "- `GetSudokus` : Renvoie des listes de Sudoku issues de fichiers de 3 difficultés différentes.\n",
+ "- `SolveSudoku` : effectue un test simple d'un solver sur un sudoku donné.\n",
+ "- `TestSolvers` : exécute les tests de performance sur plusieurs solveurs.\n",
+ "- `DisplayResults` : affiche les résultats des tests sous forme de graphiques.\n",
+ "\n"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "SudokuHelper defini.\r\n"
+ "output_type": "stream",
+ "text": [
+ "SudokuHelper defini.\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "### Interpretation : Infrastructure de test et benchmark\n\n**Sortie obtenue** : La classe `SudokuHelper` fournit une infrastructure complete pour tester et comparer les solveurs de Sudoku.\n\n| Aspect | Valeur | Signification |\n|--------|--------|---------------|\n| `GetSudokus()` | 51/95/100 grilles | Trois niveaux de difficulte (Easy/Medium/Hard) |\n| `TestSolvers()` | Performance multi-solveurs | Execution parallele avec timeout |\n| `DisplayResults()` | Graphiques Plotly.NET | Visualisation des temps de resolution |\n| `SolveSudoku()` | Test unitaire | Resolution individuelle avec affichage |\n\n**Points cles** :\n1. **Chargement intelligent** : Recherche recursive du dossier `Puzzles` dans l'arborescence\n2. **Robustesse** : Gestion des timeouts (3000ms par defaut) et exceptions\n3. **Mesures** : Temps d'execution total + nombre de grilles resolues\n4. **Disqualification** : Un solver echouant sur une grille est disqualifie pour la difficulte\n\n> **Note technique** : La methode `TestSolvers` utilise `Interlocked.Increment` pour un thread-safe increment du compteur de solutions. Le `CancellationToken` permet d'interrompre proprement les solveurs trop lents."
+ "text/markdown": [
+ "### Interpretation : Infrastructure de test et benchmark\n",
+ "\n",
+ "**Sortie obtenue** : La classe `SudokuHelper` fournit une infrastructure complete pour tester et comparer les solveurs de Sudoku.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `GetSudokus()` | 51/95/100 grilles | Trois niveaux de difficulte (Easy/Medium/Hard) |\n",
+ "| `TestSolvers()` | Performance multi-solveurs | Execution parallele avec timeout |\n",
+ "| `DisplayResults()` | Graphiques Plotly.NET | Visualisation des temps de resolution |\n",
+ "| `SolveSudoku()` | Test unitaire | Resolution individuelle avec affichage |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Chargement intelligent** : Recherche recursive du dossier `Puzzles` dans l'arborescence\n",
+ "2. **Robustesse** : Gestion des timeouts (3000ms par defaut) et exceptions\n",
+ "3. **Mesures** : Temps d'execution total + nombre de grilles resolues\n",
+ "4. **Disqualification** : Un solver echouant sur une grille est disqualifie pour la difficulte\n",
+ "\n",
+ "> **Note technique** : La methode `TestSolvers` utilise `Interlocked.Increment` pour un thread-safe increment du compteur de solutions. Le `CancellationToken` permet d'interrompre proprement les solveurs trop lents."
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/markdown": "## Exercice : Validation d'une grille Sudoku\n\n### Enonce\n\nImplementez une methode `IsValidSolution` qui verifie qu'une grille est une solution valide de Sudoku, c'est-a-dire que chaque ligne, chaque colonne et chaque bloc 3x3 contient exactement une fois chaque chiffre de 1 a 9.\n\nUtilisez cette methode pour valider les resultats de `SudokuHelper.SolveSudoku`.\n\n### Indices\n\n- Parcourez les 9 lignes, 9 colonnes et 9 blocs\n- Pour chaque unite, verifiez que les 9 chiffres sont tous presents sans doublon\n- `SudokuGrid.AllNeighbours` contient deja les indices des unites"
+ "text/markdown": [
+ "## Exercice : Validation d'une grille Sudoku\n",
+ "\n",
+ "### Enonce\n",
+ "\n",
+ "Implementez une methode `IsValidSolution` qui verifie qu'une grille est une solution valide de Sudoku, c'est-a-dire que chaque ligne, chaque colonne et chaque bloc 3x3 contient exactement une fois chaque chiffre de 1 a 9.\n",
+ "\n",
+ "Utilisez cette methode pour valider les resultats de `SudokuHelper.SolveSudoku`.\n",
+ "\n",
+ "### Indices\n",
+ "\n",
+ "- Parcourez les 9 lignes, 9 colonnes et 9 blocs\n",
+ "- Pour chaque unite, verifiez que les 9 chiffres sont tous presents sans doublon\n",
+ "- `SudokuGrid.AllNeighbours` contient deja les indices des unites"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Exercice a completer\r\n"
+ "output_type": "stream",
+ "text": [
+ "Exercice a completer\r\n"
+ ]
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "## Resume et perspectives\n",
+ "\n",
+ "Ce notebook a pose les fondations de toute la serie Sudoku en definissant trois composants essentiels. La classe `SudokuGrid` encapsule la representation d'une grille 9x9 avec le pre-calcul des voisins (`AllNeighbours`, `CellNeighbours`), ce qui evite les recalculs couteux lors de la resolution. L'interface `ISudokuSolver` implante le pattern Strategie, permettant de permuter les algorithmes de resolution sans modifier le code client. Enfin, la classe `SudokuHelper` fournit une infrastructure de benchmark complete avec chargement de puzzles, mesures de performance et visualisation Plotly.NET.\n",
+ "\n",
+ "L'infrastructure de test (`TestSolvers`, `DisplayResults`) permet de comparer objectivement les solveurs sur trois niveaux de difficulte (Easy, Medium, Hard) avec gestion des timeouts et des disqualifications. Ce cadre de benchmark sera utilise dans tous les notebooks suivants pour mesurer les performances de chaque algorithme.\n",
+ "\n",
+ "Le notebook suivant, [Sudoku-1-Backtracking](Sudoku-1-Backtracking-Csharp.ipynb), utilise ces classes pour implementer le premier algorithme de resolution : le backtracking recursif avec ses heuristiques d'amelioration."
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
}
],
"source": [
@@ -211,25 +454,70 @@
},
"outputs": [
{
- "output_type": "display_data",
"data": {
- "text/plain": "Puzzle Facile:\n-------------------------------\n| 9 2 | 5 | 4 3 | \n| 1 | 6 3 | 2 5 | \n| 5 8 | 4 7 | 6 | \n-------------------------------\n| 2 6 | 3 9 | 1 | \n| 5 7 | 1 | 2 9 | \n| 9 | 6 7 | 5 3 | \n-------------------------------\n| 2 4 | 5 3 | 6 | \n| 7 5 | 2 | 3 4 | \n| 8 | 4 1 | 9 5 | \n-------------------------------"
+ "text/plain": [
+ "Puzzle Facile:\n",
+ "-------------------------------\n",
+ "| 9 2 | 5 | 4 3 | \n",
+ "| 1 | 6 3 | 2 5 | \n",
+ "| 5 8 | 4 7 | 6 | \n",
+ "-------------------------------\n",
+ "| 2 6 | 3 9 | 1 | \n",
+ "| 5 7 | 1 | 2 9 | \n",
+ "| 9 | 6 7 | 5 3 | \n",
+ "-------------------------------\n",
+ "| 2 4 | 5 3 | 6 | \n",
+ "| 7 5 | 2 | 3 4 | \n",
+ "| 8 | 4 1 | 9 5 | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Puzzle Moyen:\n-------------------------------\n| 8 5 | 2 | 4 | \n| 7 2 | | 9 | \n| 4 | | | \n-------------------------------\n| | 1 7 | 2 | \n| 3 5 | | 9 | \n| 4 | | | \n-------------------------------\n| | 8 | 7 | \n| 1 7 | | | \n| | 3 6 | 4 | \n-------------------------------"
+ "text/plain": [
+ "Puzzle Moyen:\n",
+ "-------------------------------\n",
+ "| 8 5 | 2 | 4 | \n",
+ "| 7 2 | | 9 | \n",
+ "| 4 | | | \n",
+ "-------------------------------\n",
+ "| | 1 7 | 2 | \n",
+ "| 3 5 | | 9 | \n",
+ "| 4 | | | \n",
+ "-------------------------------\n",
+ "| | 8 | 7 | \n",
+ "| 1 7 | | | \n",
+ "| | 3 6 | 4 | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Puzzle Difficile:\n-------------------------------\n| 4 | | 8 5 | \n| 3 | | | \n| | 7 | | \n-------------------------------\n| 2 | | 6 | \n| | 8 | 4 | \n| | 1 | | \n-------------------------------\n| | 6 3 | 7 | \n| 5 | 2 | | \n| 1 4 | | | \n-------------------------------"
+ "text/plain": [
+ "Puzzle Difficile:\n",
+ "-------------------------------\n",
+ "| 4 | | 8 5 | \n",
+ "| 3 | | | \n",
+ "| | 7 | | \n",
+ "-------------------------------\n",
+ "| 2 | | 6 | \n",
+ "| | 8 | 4 | \n",
+ "| | 1 | | \n",
+ "-------------------------------\n",
+ "| | 6 3 | 7 | \n",
+ "| 5 | 2 | | \n",
+ "| 1 4 | | | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
}
],
"source": [
@@ -328,7 +616,15 @@
},
"tags": []
},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "BacktrackingDotNetSolver class defined\r\n"
+ ]
+ }
+ ],
"source": [
"public class BacktrackingDotNetSolver : ISudokuSolver\n",
"{\n",
@@ -375,7 +671,9 @@
"\n",
" return true;\n",
" }\n",
- "}\n"
+ "}\n",
+ "Console.WriteLine(\"BacktrackingDotNetSolver class defined\");\n",
+ ""
]
},
{
@@ -425,76 +723,184 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "Puzzle Sudoku Facile Initial:\r\n"
+ "output_type": "stream",
+ "text": [
+ "Puzzle Sudoku Facile Initial:\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n -------------------------------\n| 9 2 | 5 | 4 3 | \n| 1 | 6 3 | 2 5 | \n| 5 8 | 4 7 | 6 | \n-------------------------------\n| 2 6 | 3 9 | 1 | \n| 5 7 | 1 | 2 9 | \n| 9 | 6 7 | 5 3 | \n-------------------------------\n| 2 4 | 5 3 | 6 | \n| 7 5 | 2 | 3 4 | \n| 8 | 4 1 | 9 5 | \n-------------------------------"
+ "text/plain": [
+ "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n",
+ " -------------------------------\n",
+ "| 9 2 | 5 | 4 3 | \n",
+ "| 1 | 6 3 | 2 5 | \n",
+ "| 5 8 | 4 7 | 6 | \n",
+ "-------------------------------\n",
+ "| 2 6 | 3 9 | 1 | \n",
+ "| 5 7 | 1 | 2 9 | \n",
+ "| 9 | 6 7 | 5 3 | \n",
+ "-------------------------------\n",
+ "| 2 4 | 5 3 | 6 | \n",
+ "| 7 5 | 2 | 3 4 | \n",
+ "| 8 | 4 1 | 9 5 | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "BacktrackingDotNetSolver: 122 search calls\r\n"
+ "output_type": "stream",
+ "text": [
+ "BacktrackingDotNetSolver: 122 search calls\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Sudoku renvoyé:\n-------------------------------\n| 9 6 2 | 1 8 5 | 4 7 3 | \n| 1 7 4 | 9 6 3 | 8 2 5 | \n| 5 3 8 | 4 2 7 | 1 6 9 | \n-------------------------------\n| 8 2 6 | 3 5 9 | 7 4 1 | \n| 3 5 7 | 8 1 4 | 2 9 6 | \n| 4 9 1 | 6 7 2 | 5 3 8 | \n-------------------------------\n| 2 4 9 | 5 3 8 | 6 1 7 | \n| 7 1 5 | 2 9 6 | 3 8 4 | \n| 6 8 3 | 7 4 1 | 9 5 2 | \n-------------------------------\nNombre d'erreurs réstantes: 0\nTemps de résolution: 0,6802 ms"
+ "text/plain": [
+ "Sudoku renvoyé:\n",
+ "-------------------------------\n",
+ "| 9 6 2 | 1 8 5 | 4 7 3 | \n",
+ "| 1 7 4 | 9 6 3 | 8 2 5 | \n",
+ "| 5 3 8 | 4 2 7 | 1 6 9 | \n",
+ "-------------------------------\n",
+ "| 8 2 6 | 3 5 9 | 7 4 1 | \n",
+ "| 3 5 7 | 8 1 4 | 2 9 6 | \n",
+ "| 4 9 1 | 6 7 2 | 5 3 8 | \n",
+ "-------------------------------\n",
+ "| 2 4 9 | 5 3 8 | 6 1 7 | \n",
+ "| 7 1 5 | 2 9 6 | 3 8 4 | \n",
+ "| 6 8 3 | 7 4 1 | 9 5 2 | \n",
+ "-------------------------------\n",
+ "Nombre d'erreurs réstantes: 0\n",
+ "Temps de résolution: 0,4354 ms"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Puzzle Sudoku Moyen Initial:\r\n"
+ "output_type": "stream",
+ "text": [
+ "Puzzle Sudoku Moyen Initial:\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n -------------------------------\n| 8 5 | 2 | 4 | \n| 7 2 | | 9 | \n| 4 | | | \n-------------------------------\n| | 1 7 | 2 | \n| 3 5 | | 9 | \n| 4 | | | \n-------------------------------\n| | 8 | 7 | \n| 1 7 | | | \n| | 3 6 | 4 | \n-------------------------------"
+ "text/plain": [
+ "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n",
+ " -------------------------------\n",
+ "| 8 5 | 2 | 4 | \n",
+ "| 7 2 | | 9 | \n",
+ "| 4 | | | \n",
+ "-------------------------------\n",
+ "| | 1 7 | 2 | \n",
+ "| 3 5 | | 9 | \n",
+ "| 4 | | | \n",
+ "-------------------------------\n",
+ "| | 8 | 7 | \n",
+ "| 1 7 | | | \n",
+ "| | 3 6 | 4 | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "BacktrackingDotNetSolver: 490304 search calls\r\n"
+ "output_type": "stream",
+ "text": [
+ "BacktrackingDotNetSolver: 490304 search calls\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Sudoku renvoyé:\n-------------------------------\n| 8 5 9 | 6 1 2 | 4 3 7 | \n| 7 2 3 | 8 5 4 | 1 6 9 | \n| 1 6 4 | 3 7 9 | 5 2 8 | \n-------------------------------\n| 9 8 6 | 1 4 7 | 3 5 2 | \n| 3 7 5 | 2 6 8 | 9 1 4 | \n| 2 4 1 | 5 9 3 | 7 8 6 | \n-------------------------------\n| 4 3 2 | 9 8 1 | 6 7 5 | \n| 6 1 7 | 4 2 5 | 8 9 3 | \n| 5 9 8 | 7 3 6 | 2 4 1 | \n-------------------------------\nNombre d'erreurs réstantes: 0\nTemps de résolution: 254,1017 ms"
+ "text/plain": [
+ "Sudoku renvoyé:\n",
+ "-------------------------------\n",
+ "| 8 5 9 | 6 1 2 | 4 3 7 | \n",
+ "| 7 2 3 | 8 5 4 | 1 6 9 | \n",
+ "| 1 6 4 | 3 7 9 | 5 2 8 | \n",
+ "-------------------------------\n",
+ "| 9 8 6 | 1 4 7 | 3 5 2 | \n",
+ "| 3 7 5 | 2 6 8 | 9 1 4 | \n",
+ "| 2 4 1 | 5 9 3 | 7 8 6 | \n",
+ "-------------------------------\n",
+ "| 4 3 2 | 9 8 1 | 6 7 5 | \n",
+ "| 6 1 7 | 4 2 5 | 8 9 3 | \n",
+ "| 5 9 8 | 7 3 6 | 2 4 1 | \n",
+ "-------------------------------\n",
+ "Nombre d'erreurs réstantes: 0\n",
+ "Temps de résolution: 141,0824 ms"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Puzzle Sudoku Difficile Initial:\r\n"
+ "output_type": "stream",
+ "text": [
+ "Puzzle Sudoku Difficile Initial:\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n -------------------------------\n| 4 | | 8 5 | \n| 3 | | | \n| | 7 | | \n-------------------------------\n| 2 | | 6 | \n| | 8 | 4 | \n| | 1 | | \n-------------------------------\n| | 6 3 | 7 | \n| 5 | 2 | | \n| 1 4 | | | \n-------------------------------"
+ "text/plain": [
+ "Résolution par le solver BacktrackingDotNetSolver du Sudoku:\n",
+ " -------------------------------\n",
+ "| 4 | | 8 5 | \n",
+ "| 3 | | | \n",
+ "| | 7 | | \n",
+ "-------------------------------\n",
+ "| 2 | | 6 | \n",
+ "| | 8 | 4 | \n",
+ "| | 1 | | \n",
+ "-------------------------------\n",
+ "| | 6 3 | 7 | \n",
+ "| 5 | 2 | | \n",
+ "| 1 4 | | | \n",
+ "-------------------------------"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "BacktrackingDotNetSolver: 12625368 search calls\r\n"
+ "output_type": "stream",
+ "text": [
+ "BacktrackingDotNetSolver: 12625368 search calls\r\n"
+ ]
},
{
- "output_type": "display_data",
"data": {
- "text/plain": "Sudoku renvoyé:\n-------------------------------\n| 4 1 7 | 3 6 9 | 8 2 5 | \n| 6 3 2 | 1 5 8 | 9 4 7 | \n| 9 5 8 | 7 2 4 | 3 1 6 | \n-------------------------------\n| 8 2 5 | 4 3 7 | 1 6 9 | \n| 7 9 1 | 5 8 6 | 4 3 2 | \n| 3 4 6 | 9 1 2 | 7 5 8 | \n-------------------------------\n| 2 8 9 | 6 4 3 | 5 7 1 | \n| 5 7 3 | 2 9 1 | 6 8 4 | \n| 1 6 4 | 8 7 5 | 2 9 3 | \n-------------------------------\nNombre d'erreurs réstantes: 0\nTemps de résolution: 10338,992 ms"
+ "text/plain": [
+ "Sudoku renvoyé:\n",
+ "-------------------------------\n",
+ "| 4 1 7 | 3 6 9 | 8 2 5 | \n",
+ "| 6 3 2 | 1 5 8 | 9 4 7 | \n",
+ "| 9 5 8 | 7 2 4 | 3 1 6 | \n",
+ "-------------------------------\n",
+ "| 8 2 5 | 4 3 7 | 1 6 9 | \n",
+ "| 7 9 1 | 5 8 6 | 4 3 2 | \n",
+ "| 3 4 6 | 9 1 2 | 7 5 8 | \n",
+ "-------------------------------\n",
+ "| 2 8 9 | 6 4 3 | 5 7 1 | \n",
+ "| 5 7 3 | 2 9 1 | 6 8 4 | \n",
+ "| 1 6 4 | 8 7 5 | 2 9 3 | \n",
+ "-------------------------------\n",
+ "Nombre d'erreurs réstantes: 0\n",
+ "Temps de résolution: 4127,7309 ms"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
}
],
"source": [
@@ -610,9 +1016,11 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "TODO: Implementez BacktrackingMRVSolver pour comparer les performances\r\n"
+ "output_type": "stream",
+ "text": [
+ "TODO: Implementez BacktrackingMRVSolver pour comparer les performances\r\n"
+ ]
}
],
"source": [
@@ -762,4 +1170,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb b/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb
index a876b13bb..57ad4ab6e 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb
@@ -75,17 +75,132 @@
},
"outputs": [
{
- "output_type": "stream",
+ "data": {
+ "text/html": [
+ "\r\n",
+ "\r\n",
+ "
\r\n",
+ " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
+ "
\r\n",
+ " \r\n",
+ "
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
"name": "stdout",
+ "output_type": "stream",
"text": [
"Choco-solver JAR deja present: choco-solver-4.10.17-jar-with-dependencies.jar\r\n"
]
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
- "Repertoire de travail: d:\\dev\\CoursIA\\MyIA.AI.Notebooks\\Sudoku\r\n"
+ "Repertoire de travail: D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\r\n"
]
}
],
@@ -115,8 +230,27 @@
"languageId": "polyglot-notebook"
}
},
- "outputs": [],
- "source": "// Charger les DLLs IKVM runtime (requis pour Choco-solver)\n// Les DLLs doivent etre dans le meme repertoire que le notebook\n#r \"IKVM.Runtime.dll\"\n#r \"IKVM.Java.dll\"\n#r \"IKVM.CoreLib.dll\"\n\n// Charger la DLL Choco-solver pré-compilée\n#r \"org.chocosolver.solver.dll\""
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "IKVM runtime DLLs loaded for Choco-solver\r\n"
+ ]
+ }
+ ],
+ "source": [
+ "// Charger les DLLs IKVM runtime (requis pour Choco-solver)\n",
+ "// Les DLLs doivent etre dans le meme repertoire que le notebook\n",
+ "#r \"IKVM.Runtime.dll\"\n",
+ "#r \"IKVM.Java.dll\"\n",
+ "#r \"IKVM.CoreLib.dll\"\n",
+ "\n",
+ "// Charger la DLL Choco-solver pré-compilée\n",
+ "#r \"org.chocosolver.solver.dll\"\n",
+ "Console.WriteLine(\"IKVM runtime DLLs loaded for Choco-solver\");\n",
+ ""
+ ]
},
{
"cell_type": "markdown",
@@ -138,8 +272,8 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Choco-solver via IKVM 7.2.4630.5 - Pret pour resolution Sudoku\r\n"
]
@@ -183,60 +317,215 @@
},
"outputs": [
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "# Sudoku-0 : Environnement et Classes de Base (C#)\n",
+ "\n",
+ "**Navigation** : [Index](README.md) | [Sudoku-1 Backtracking C# >>](Sudoku-1-Backtracking-Csharp.ipynb)\n",
+ "\n",
+ "## Objectifs d'apprentissage\n",
+ "\n",
+ "A la fin de ce notebook, vous saurez :\n",
+ "1. Comprendre la structure de donnees `SudokuGrid` et ses methodes principales\n",
+ "2. Utiliser `ISudokuSolver` pour implementer un solveur de Sudoku\n",
+ "3. Exploiter `SudokuHelper` pour charger des grilles et tester des solveurs\n",
+ "4. Comparer les performances de plusieurs solveurs sur differentes difficultes\n",
+ "\n",
+ "**Prerequis** : Notions de base en C# (.NET Interactive) \n",
+ "**Duree estimee** : ~15 min"
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
- "metadata": {},
"data": {
"text/html": [
- ""
+ ""
]
- }
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "## Définition de la classe SudokuGrid\n",
+ "\n",
+ "Nous définissons ici la classe SudokuGrid qui représente une grille de Sudoku et fournit des méthodes pour manipuler et afficher les grilles.\n"
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "SudokuGrid defini.\r\n"
+ ]
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "### Interpretation : Structure de donnees pour la grille Sudoku\n",
+ "\n",
+ "**Sortie obtenue** : La classe `SudokuGrid` encapsule toutes les operations de manipulation, validation et affichage d'une grille de Sudoku 9x9.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `Cells[9,9]` | int[,] | Stockage interne des valeurs (0 = vide) |\n",
+ "| `AllNeighbours` | 27 x 9 positions | Pre-calcul des voisins ligne/colonne/bloc |\n",
+ "| `CellNeighbours[9][9]` | ~20 positions chacune | Voisins directs de chaque cellule |\n",
+ "| `GetAvailableNumbers()` | int[] | Candidats valides pour une cellule |\n",
+ "| `NbErrors()` | int | Nombre de conflits + modifications erronees |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Pre-calcul des voisins** : `AllNeighbours` et `CellNeighbours` sont calcules une seule fois a l'initialisation, evitant les recalculs couteux\n",
+ "2. **Conversion flexible** : Methodes pour convertir entre tableaux 1D, 2D et jagged arrays (utile pour differents formats de fichiers)\n",
+ "3. **Validation robuste** : `NbErrors` compte a la fois les doublons (ligne/colonne/bloc) et les modifications de indices pre-remplis\n",
+ "4. **Parsing tolerant** : `ReadMultiSudoku` accepte plusieurs formats (`.`, `X`, `-`, espaces)\n",
+ "\n",
+ "> **Note technique** : La structure `CellNeighbours[i][j]` contient environ 20 positions (8 ligne + 8 colonne + 4 bloc, moins les doublons). Ce pre-calcul est crucial pour les performances des algorithmes de backtracking et de propagation de contraintes."
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "## Définition de l'interface ISudokuSolver\n",
+ "\n",
+ "Nous définissons ici l'interface ISudokuSolver qui sera implémentée par les différentes stratégies de résolution de Sudoku.\n"
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "ISudokuSolver defini.\r\n"
+ ]
},
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "### Interpretation : Interface de strategie\n",
+ "\n",
+ "**Sortie obtenue** : L'interface `ISudokuSolver` definit le contrat que tous les solveurs doivent respecter.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `Solve(SudokuGrid)` | SudokuGrid | Methode unique de resolution |\n",
+ "| Pattern | Strategie | Permuter les algorithmes sans modifier le code client |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Simplicite** : Une seule methode `Solve` prenant une grille et retournant une grille resolue\n",
+ "2. **Flexibilite** : N'importe quel algorithme (backtracking, CSP, metaheuristique) peut implementer cette interface\n",
+ "3. **Composabilite** : Les solveurs peuvent etre passes en parametre, stockes dans des listes, testes unitairement\n",
+ "4. **Extensibilite** : Ajouter un nouveau solver ne necessite que d'implementer l'interface\n",
+ "\n",
+ "> **Note technique** : Ce design pattern permet a `SudokuHelper.TestSolvers` d'accepter une liste de `(string, ISudokuSolver)` pour comparer tous les algorithmes avec le meme code de test."
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "## Définition de la classe SudokuHelper\n",
+ "\n",
+ "Nous ajoutons ici la classe SudokuHelper qui contient des méthodes utilitaires pour charger des grilles de Sudoku et tester des solvers.\n",
+ "\n",
+ "- `GetSudokus` : Renvoie des listes de Sudoku issues de fichiers de 3 difficultés différentes.\n",
+ "- `SolveSudoku` : effectue un test simple d'un solver sur un sudoku donné.\n",
+ "- `TestSolvers` : exécute les tests de performance sur plusieurs solveurs.\n",
+ "- `DisplayResults` : affiche les résultats des tests sous forme de graphiques.\n",
+ "\n"
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "SudokuHelper defini.\r\n"
+ ]
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "### Interpretation : Infrastructure de test et benchmark\n",
+ "\n",
+ "**Sortie obtenue** : La classe `SudokuHelper` fournit une infrastructure complete pour tester et comparer les solveurs de Sudoku.\n",
+ "\n",
+ "| Aspect | Valeur | Signification |\n",
+ "|--------|--------|---------------|\n",
+ "| `GetSudokus()` | 51/95/100 grilles | Trois niveaux de difficulte (Easy/Medium/Hard) |\n",
+ "| `TestSolvers()` | Performance multi-solveurs | Execution parallele avec timeout |\n",
+ "| `DisplayResults()` | Graphiques Plotly.NET | Visualisation des temps de resolution |\n",
+ "| `SolveSudoku()` | Test unitaire | Resolution individuelle avec affichage |\n",
+ "\n",
+ "**Points cles** :\n",
+ "1. **Chargement intelligent** : Recherche recursive du dossier `Puzzles` dans l'arborescence\n",
+ "2. **Robustesse** : Gestion des timeouts (3000ms par defaut) et exceptions\n",
+ "3. **Mesures** : Temps d'execution total + nombre de grilles resolues\n",
+ "4. **Disqualification** : Un solver echouant sur une grille est disqualifie pour la difficulte\n",
+ "\n",
+ "> **Note technique** : La methode `TestSolvers` utilise `Interlocked.Increment` pour un thread-safe increment du compteur de solutions. Le `CancellationToken` permet d'interrompre proprement les solveurs trop lents."
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "display_data",
+ "data": {
+ "text/markdown": [
+ "## Exercice : Validation d'une grille Sudoku\n",
+ "\n",
+ "### Enonce\n",
+ "\n",
+ "Implementez une methode `IsValidSolution` qui verifie qu'une grille est une solution valide de Sudoku, c'est-a-dire que chaque ligne, chaque colonne et chaque bloc 3x3 contient exactement une fois chaque chiffre de 1 a 9.\n",
+ "\n",
+ "Utilisez cette methode pour valider les resultats de `SudokuHelper.SolveSudoku`.\n",
+ "\n",
+ "### Indices\n",
+ "\n",
+ "- Parcourez les 9 lignes, 9 colonnes et 9 blocs\n",
+ "- Pour chaque unite, verifiez que les 9 chiffres sont tous presents sans doublon\n",
+ "- `SudokuGrid.AllNeighbours` contient deja les indices des unites"
+ ]
+ },
"metadata": {},
- "data": {}
+ "output_type": "display_data"
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Exercice a completer\r\n"
]
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "## Resume et perspectives\n",
+ "\n",
+ "Ce notebook a pose les fondations de toute la serie Sudoku en definissant trois composants essentiels. La classe `SudokuGrid` encapsule la representation d'une grille 9x9 avec le pre-calcul des voisins (`AllNeighbours`, `CellNeighbours`), ce qui evite les recalculs couteux lors de la resolution. L'interface `ISudokuSolver` implante le pattern Strategie, permettant de permuter les algorithmes de resolution sans modifier le code client. Enfin, la classe `SudokuHelper` fournit une infrastructure de benchmark complete avec chargement de puzzles, mesures de performance et visualisation Plotly.NET.\n",
+ "\n",
+ "L'infrastructure de test (`TestSolvers`, `DisplayResults`) permet de comparer objectivement les solveurs sur trois niveaux de difficulte (Easy, Medium, Hard) avec gestion des timeouts et des disqualifications. Ce cadre de benchmark sera utilise dans tous les notebooks suivants pour mesurer les performances de chaque algorithme.\n",
+ "\n",
+ "Le notebook suivant, [Sudoku-1-Backtracking](Sudoku-1-Backtracking-Csharp.ipynb), utilise ces classes pour implementer le premier algorithme de resolution : le backtracking recursif avec ses heuristiques d'amelioration."
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
}
],
"source": [
@@ -272,8 +561,8 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"ChocoSimpleSolver defini.\r\n"
]
@@ -392,8 +681,8 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"ChocoSolverVariableSelector defini avec strategie FirstFail.\r\n"
]
@@ -650,15 +939,15 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Puzzle initial:\r\n"
]
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"-------------------------------\n",
"| 9 2 | 5 | 4 3 | \n",
@@ -721,29 +1010,29 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
- "[IKVM Runtime] Could not locate ikvm home path.\r\n"
+ "[IKVM Runtime] Could not load file or assembly 'System.Text.Json, Version=8.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. Le fichier spécifié est introuvable.\r\n"
]
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Le solveur Choco via IKVM ne peut pas s'initialiser dans dotnet-interactive.\r\n"
]
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Cause : IKVM necessite un runtime Java/.NET specifique non disponible ici.\r\n"
]
},
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Le code est correct et fonctionnerait avec un runtime IKVM complet.\r\n"
]
@@ -810,8 +1099,8 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"TODO: Implementez NQueensChocoSolver.CountSolutions() pour le probleme des 8-Reines\r\n"
]
diff --git a/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb b/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
index be541ea3a..03bc7bf9d 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
@@ -163,34 +163,161 @@
},
"outputs": [
{
- "output_type": "stream",
- "name": "stdout",
- "text": "Classe BDDNode definie avec succes.\r\n"
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": "Operations disponibles :\r\n"
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": " - True/False : Terminaux (feuilles)\r\n"
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": " - Create(var, low, high) : Cree un noeud de decision\r\n"
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": " - Evaluate(assign) : Evalue le BDD\r\n"
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": " - CountNodes() : Compte les noeuds\r\n"
+ "data": {
+ "text/html": [
+ "\r\n",
+ "\r\n",
+ "
\r\n",
+ " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
+ "
\r\n",
+ " \r\n",
+ "
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Classe BDDNode definie avec succes.\r\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Operations disponibles :\r\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " - True/False : Terminaux (feuilles)\r\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " - Create(var, low, high) : Cree un noeud de decision\r\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " - Evaluate(assign) : Evalue le BDD\r\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " - CountNodes() : Compte les noeuds\r\n"
+ ]
}
],
"source": [
@@ -342,84 +469,122 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Exemple 1 : Constante TRUE ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Exemple 1 : Constante TRUE ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 1\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 1\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Valeur : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Valeur : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Exemple 2 : Variable x ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Exemple 2 : Variable x ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "x?\r\n |-> |(True)\r\n |-> |(False)\r\n"
+ "output_type": "stream",
+ "text": [
+ "x?\r\n",
+ " |-> |(True)\r\n",
+ " |-> |(False)\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 3\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 3\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Eval(x=true) : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Eval(x=true) : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Eval(x=false) : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Eval(x=false) : False\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Exemple 3 : x AND y ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Exemple 3 : x AND y ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "x?\r\n |-> |y?\r\n | |-> | |(True)\r\n | |-> | |(False)\r\n |-> |(False)\r\n"
+ "output_type": "stream",
+ "text": [
+ "x?\r\n",
+ " |-> |y?\r\n",
+ " | |-> | |(True)\r\n",
+ " | |-> | |(False)\r\n",
+ " |-> |(False)\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 5\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 5\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Eval(x=true, y=true) : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Eval(x=true, y=true) : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Eval(x=true, y=false) : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Eval(x=true, y=false) : False\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Eval(x=false, y=true) : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Eval(x=false, y=true) : False\r\n"
+ ]
}
],
"source": [
@@ -530,9 +695,11 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "BDDOperations OK (Apply/And/Or/Not).\r\n"
+ "output_type": "stream",
+ "text": [
+ "BDDOperations OK (Apply/And/Or/Not).\r\n"
+ ]
}
],
"source": [
@@ -650,74 +817,102 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test 1 : x AND NOT x ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test 1 : x AND NOT x ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Resultat : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Resultat : False\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Attendu : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Attendu : False\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 1\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 1\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test 2 : x OR NOT x ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test 2 : x OR NOT x ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Resultat : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Resultat : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Attendu : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Attendu : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 1\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 1\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test 3 : Distributivite ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test 3 : Distributivite ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds (gauche) : 7\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds (gauche) : 7\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds (droite) : 7\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds (droite) : 7\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Equivalent (x=T,y=T,z=F) : True == True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Equivalent (x=T,y=T,z=F) : True == True\r\n"
+ ]
}
],
"source": [
@@ -808,9 +1003,11 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDDNode OK (Pretty/ToString/Evaluate).\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDDNode OK (Pretty/ToString/Evaluate).\r\n"
+ ]
}
],
"source": [
@@ -938,9 +1135,11 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "RowMDDBuilder OK (memoization bitmask).\r\n"
+ "output_type": "stream",
+ "text": [
+ "RowMDDBuilder OK (memoization bitmask).\r\n"
+ ]
}
],
"source": [
@@ -1035,64 +1234,88 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "Construction du MDD pour une ligne Sudoku...\r\n"
+ "output_type": "stream",
+ "text": [
+ "Construction du MDD pour une ligne Sudoku...\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Attention: 9! = 362880 permutations valides\r\n"
+ "output_type": "stream",
+ "text": [
+ "Attention: 9! = 362880 permutations valides\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDD construit!\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDD construit!\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Nombre de noeuds : 5611771\r\n"
+ "output_type": "stream",
+ "text": [
+ "Nombre de noeuds : 5611771\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test 1 : Ligne valide ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test 1 : Ligne valide ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Resultat : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Resultat : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Attendu : True\r\n"
+ "output_type": "stream",
+ "text": [
+ "Attendu : True\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test 2 : Ligne invalide (doublon de 1) ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test 2 : Ligne invalide (doublon de 1) ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Resultat : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Resultat : False\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Attendu : False\r\n"
+ "output_type": "stream",
+ "text": [
+ "Attendu : False\r\n"
+ ]
}
],
"source": [
@@ -1212,9 +1435,11 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDDOperations OK (Product).\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDDOperations OK (Product).\r\n"
+ ]
}
],
"source": [
@@ -1329,69 +1554,97 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Test du Produit MDD ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Test du Produit MDD ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Grille 2x2 (valeurs 1-2)\r\n"
+ "output_type": "stream",
+ "text": [
+ "Grille 2x2 (valeurs 1-2)\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDD Ligne 0 (2 cellules, valeurs 1-2) :\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDD Ligne 0 (2 cellules, valeurs 1-2) :\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 7\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 7\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDD Contrainte (r0_c0 != 1) :\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDD Contrainte (r0_c0 != 1) :\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "r0_c0?\n 1 -> | (INVALID)\n 2 -> | (VALID)\r\n"
+ "output_type": "stream",
+ "text": [
+ "r0_c0?\n",
+ " 1 -> | (INVALID)\n",
+ " 2 -> | (VALID)\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDD Produit (ligne 0 INTERSECT r0_c0 != 1) :\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDD Produit (ligne 0 INTERSECT r0_c0 != 1) :\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Noeuds : 5\r\n"
+ "output_type": "stream",
+ "text": [
+ "Noeuds : 5\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Test (r0_c0=1, r0_c1=2) : False (attendu: False)\r\n"
+ "output_type": "stream",
+ "text": [
+ "Test (r0_c0=1, r0_c1=2) : False (attendu: False)\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Test (r0_c0=2, r0_c1=1) : True (attendu: True)\r\n"
+ "output_type": "stream",
+ "text": [
+ "Test (r0_c0=2, r0_c1=1) : True (attendu: True)\r\n"
+ ]
}
],
"source": [
@@ -1542,19 +1795,25 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "Classe SudokuMDDSolver definie avec succes.\r\n"
+ "output_type": "stream",
+ "text": [
+ "Classe SudokuMDDSolver definie avec succes.\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "Note: Cette implementation utilise le backtracking classique\r\n"
+ "output_type": "stream",
+ "text": [
+ "Note: Cette implementation utilise le backtracking classique\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "car les MDD complets pour Sudoku seraient trop volumineux.\r\n"
+ "output_type": "stream",
+ "text": [
+ "car les MDD complets pour Sudoku seraient trop volumineux.\r\n"
+ ]
}
],
"source": [
@@ -1720,574 +1979,803 @@
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "=== Puzzle Sudoku Facile ===\r\n"
+ "output_type": "stream",
+ "text": [
+ "=== Puzzle Sudoku Facile ===\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\nSolution trouve en 0,61 ms :\r\n"
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "Solution trouve en 0,46 ms :\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "-------+-------+-------\r\n"
+ "output_type": "stream",
+ "text": [
+ "-------+-------+-------\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "-------+-------+-------\r\n"
+ "output_type": "stream",
+ "text": [
+ "-------+-------+-------\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "-------+-------+-------\r\n"
+ "output_type": "stream",
+ "text": [
+ "-------+-------+-------\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "6 "
+ "output_type": "stream",
+ "text": [
+ "6 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "9 "
+ "output_type": "stream",
+ "text": [
+ "9 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "5 "
+ "output_type": "stream",
+ "text": [
+ "5 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "4 "
+ "output_type": "stream",
+ "text": [
+ "4 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "1 "
+ "output_type": "stream",
+ "text": [
+ "1 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "7 "
+ "output_type": "stream",
+ "text": [
+ "7 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "| "
+ "output_type": "stream",
+ "text": [
+ "| "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "3 "
+ "output_type": "stream",
+ "text": [
+ "3 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "8 "
+ "output_type": "stream",
+ "text": [
+ "8 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "2 "
+ "output_type": "stream",
+ "text": [
+ "2 "
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "\r\n"
+ "output_type": "stream",
+ "text": [
+ "\r\n"
+ ]
},
{
- "output_type": "stream",
"name": "stdout",
- "text": "-------+-------+-------\r\n"
+ "output_type": "stream",
+ "text": [
+ "-------+-------+-------\r\n"
+ ]
}
],
"source": [
@@ -2600,7 +3088,15 @@
},
"tags": []
},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "BDDConstraintPropagator class defined (exercice a completer)\r\n"
+ ]
+ }
+ ],
"source": [
"// A COMPLETER : Solveur BDD avec propagation de contraintes\n",
"\n",
@@ -2645,6 +3141,7 @@
" return null; // TODO etudiant : a completer\n",
" }\n",
"}\n",
+ "Console.WriteLine(\"BDDConstraintPropagator class defined (exercice a completer)\");\n",
"\n",
"// Test : Verifier que votre solveur trouve la meme solution que le solveur de reference\n",
"// string puzzle = \"003020600900305001001806400008102900700000008006708200002609500800203009005010300\";\n",
diff --git a/scripts/notebook_tools/generate_catalog.py b/scripts/notebook_tools/generate_catalog.py
index 85102eda2..d353225f6 100644
--- a/scripts/notebook_tools/generate_catalog.py
+++ b/scripts/notebook_tools/generate_catalog.py
@@ -349,8 +349,27 @@ def _is_outputless_by_design(cell: dict) -> bool:
outputless = (
ast.Assign, ast.AnnAssign,
ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef,
+ ast.Import, ast.ImportFrom,
)
- return all(isinstance(node, outputless) for node in ast.iter_child_nodes(tree))
+ # Also accept Expr nodes that are bare Call expressions for configuration
+ # (plt.style.use, warnings.filterwarnings, np.set_printoptions, etc.).
+ # These produce no visible output and are purely side-effect configuration.
+ # Exclude print()/display() which DO produce output.
+ _OUTPUT_FUNCS = {"print", "display", "pprint", "show", "render"}
+ for node in ast.iter_child_nodes(tree):
+ if not isinstance(node, outputless):
+ if isinstance(node, ast.Expr) and isinstance(node.value, ast.Call):
+ # Get the function name (simple or attribute)
+ func = node.value.func
+ fname = ""
+ if isinstance(func, ast.Name):
+ fname = func.id
+ elif isinstance(func, ast.Attribute):
+ fname = func.attr
+ if fname not in _OUTPUT_FUNCS:
+ continue # config call, no output expected
+ return False
+ return True
except SyntaxError:
return False