diff --git a/COURSE_CATALOG.generated.json b/COURSE_CATALOG.generated.json
index cd1b8704d..4614fe329 100644
--- a/COURSE_CATALOG.generated.json
+++ b/COURSE_CATALOG.generated.json
@@ -88,7 +88,7 @@
"cells_code": 8,
"cells_markdown": 13,
"cells_with_outputs": 4,
- "cells_without_outputs": 3,
+ "cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -111,7 +111,7 @@
"cells_total": 66,
"cells_code": 20,
"cells_markdown": 46,
- "cells_with_outputs": 20,
+ "cells_with_outputs": 18,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -135,7 +135,7 @@
"cells_total": 34,
"cells_code": 14,
"cells_markdown": 20,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 9,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -159,7 +159,7 @@
"cells_total": 47,
"cells_code": 15,
"cells_markdown": 32,
- "cells_with_outputs": 9,
+ "cells_with_outputs": 5,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -207,7 +207,7 @@
"cells_total": 38,
"cells_code": 14,
"cells_markdown": 24,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
@@ -255,7 +255,7 @@
"cells_total": 51,
"cells_code": 24,
"cells_markdown": 27,
- "cells_with_outputs": 24,
+ "cells_with_outputs": 21,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -303,7 +303,7 @@
"cells_total": 29,
"cells_code": 13,
"cells_markdown": 16,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 12,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -352,7 +352,7 @@
"cells_code": 10,
"cells_markdown": 22,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -375,7 +375,7 @@
"cells_total": 45,
"cells_code": 16,
"cells_markdown": 29,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 13,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -447,7 +447,7 @@
"cells_total": 30,
"cells_code": 12,
"cells_markdown": 18,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 10,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -519,7 +519,7 @@
"cells_total": 27,
"cells_code": 12,
"cells_markdown": 15,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 10,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -591,7 +591,7 @@
"cells_total": 32,
"cells_code": 14,
"cells_markdown": 18,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 8,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -615,7 +615,7 @@
"cells_total": 39,
"cells_code": 12,
"cells_markdown": 27,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -664,7 +664,7 @@
"cells_code": 16,
"cells_markdown": 27,
"cells_with_outputs": 13,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -687,7 +687,7 @@
"cells_total": 67,
"cells_code": 21,
"cells_markdown": 46,
- "cells_with_outputs": 21,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -1383,7 +1383,7 @@
"cells_total": 21,
"cells_code": 10,
"cells_markdown": 11,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
@@ -1503,7 +1503,7 @@
"cells_total": 26,
"cells_code": 10,
"cells_markdown": 16,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
@@ -1695,7 +1695,7 @@
"cells_total": 25,
"cells_code": 13,
"cells_markdown": 12,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": true,
@@ -1719,7 +1719,7 @@
"cells_total": 31,
"cells_code": 16,
"cells_markdown": 15,
- "cells_with_outputs": 16,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
@@ -1791,7 +1791,7 @@
"cells_total": 40,
"cells_code": 16,
"cells_markdown": 24,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 14,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": true,
@@ -1840,7 +1840,7 @@
"cells_code": 12,
"cells_markdown": 13,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
"requires_cloud": false,
@@ -1864,7 +1864,7 @@
"cells_code": 12,
"cells_markdown": 13,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
"requires_cloud": false,
@@ -2032,7 +2032,7 @@
"cells_code": 5,
"cells_markdown": 8,
"cells_with_outputs": 2,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": true,
"requires_cloud": false,
@@ -2824,7 +2824,7 @@
"cells_code": 17,
"cells_markdown": 39,
"cells_with_outputs": 16,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
"requires_cloud": false,
@@ -3327,7 +3327,7 @@
"cells_total": 29,
"cells_code": 14,
"cells_markdown": 15,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 10,
"cells_without_outputs": 1,
"requires_api": true,
"requires_gpu": true,
@@ -3352,7 +3352,7 @@
"cells_code": 13,
"cells_markdown": 16,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
"requires_cloud": false,
@@ -3423,7 +3423,7 @@
"cells_total": 28,
"cells_code": 14,
"cells_markdown": 14,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
@@ -3592,7 +3592,7 @@
"cells_code": 11,
"cells_markdown": 15,
"cells_with_outputs": 10,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -3615,7 +3615,7 @@
"cells_total": 11,
"cells_code": 4,
"cells_markdown": 7,
- "cells_with_outputs": 4,
+ "cells_with_outputs": 3,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -3639,7 +3639,7 @@
"cells_total": 13,
"cells_code": 5,
"cells_markdown": 8,
- "cells_with_outputs": 5,
+ "cells_with_outputs": 4,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -3663,7 +3663,7 @@
"cells_total": 26,
"cells_code": 10,
"cells_markdown": 16,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 1,
"requires_api": true,
"requires_gpu": false,
@@ -3711,7 +3711,7 @@
"cells_total": 24,
"cells_code": 11,
"cells_markdown": 13,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -3783,7 +3783,7 @@
"cells_total": 22,
"cells_code": 10,
"cells_markdown": 12,
- "cells_with_outputs": 4,
+ "cells_with_outputs": 3,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -3903,7 +3903,7 @@
"cells_total": 18,
"cells_code": 8,
"cells_markdown": 10,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 6,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4263,7 +4263,7 @@
"cells_total": 18,
"cells_code": 7,
"cells_markdown": 11,
- "cells_with_outputs": 7,
+ "cells_with_outputs": 6,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4455,7 +4455,7 @@
"cells_total": 36,
"cells_code": 11,
"cells_markdown": 25,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4527,7 +4527,7 @@
"cells_total": 19,
"cells_code": 8,
"cells_markdown": 11,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4575,7 +4575,7 @@
"cells_total": 14,
"cells_code": 6,
"cells_markdown": 8,
- "cells_with_outputs": 6,
+ "cells_with_outputs": 5,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4599,7 +4599,7 @@
"cells_total": 21,
"cells_code": 9,
"cells_markdown": 12,
- "cells_with_outputs": 9,
+ "cells_with_outputs": 8,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4623,7 +4623,7 @@
"cells_total": 31,
"cells_code": 13,
"cells_markdown": 18,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4647,7 +4647,7 @@
"cells_total": 27,
"cells_code": 12,
"cells_markdown": 15,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4671,7 +4671,7 @@
"cells_total": 18,
"cells_code": 8,
"cells_markdown": 10,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4695,7 +4695,7 @@
"cells_total": 31,
"cells_code": 14,
"cells_markdown": 17,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -4719,7 +4719,7 @@
"cells_total": 29,
"cells_code": 13,
"cells_markdown": 16,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 12,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -6592,7 +6592,7 @@
"cells_code": 11,
"cells_markdown": 41,
"cells_with_outputs": 0,
- "cells_without_outputs": 11,
+ "cells_without_outputs": 10,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": true,
@@ -7047,7 +7047,7 @@
"cells_total": 27,
"cells_code": 13,
"cells_markdown": 14,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -7335,7 +7335,7 @@
"cells_total": 19,
"cells_code": 10,
"cells_markdown": 9,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -7983,7 +7983,7 @@
"cells_total": 59,
"cells_code": 25,
"cells_markdown": 34,
- "cells_with_outputs": 24,
+ "cells_with_outputs": 21,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8001,12 +8001,12 @@
"maturity": "PRODUCTION",
"duree_estimee": "45min",
"owner_logique": "po-2025",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1901",
- "cells_total": 62,
+ "issue_pr_associee": "#1931",
+ "cells_total": 63,
"cells_code": 25,
- "cells_markdown": 37,
+ "cells_markdown": 38,
"cells_with_outputs": 20,
"cells_without_outputs": 0,
"requires_api": false,
@@ -8031,7 +8031,7 @@
"cells_total": 47,
"cells_code": 20,
"cells_markdown": 27,
- "cells_with_outputs": 17,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8319,7 +8319,7 @@
"cells_total": 49,
"cells_code": 18,
"cells_markdown": 31,
- "cells_with_outputs": 18,
+ "cells_with_outputs": 12,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8343,7 +8343,7 @@
"cells_total": 39,
"cells_code": 18,
"cells_markdown": 21,
- "cells_with_outputs": 9,
+ "cells_with_outputs": 5,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -8367,7 +8367,7 @@
"cells_total": 41,
"cells_code": 17,
"cells_markdown": 24,
- "cells_with_outputs": 17,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8415,7 +8415,7 @@
"cells_total": 49,
"cells_code": 18,
"cells_markdown": 31,
- "cells_with_outputs": 18,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8487,7 +8487,7 @@
"cells_total": 67,
"cells_code": 29,
"cells_markdown": 38,
- "cells_with_outputs": 21,
+ "cells_with_outputs": 20,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -8535,7 +8535,7 @@
"cells_total": 62,
"cells_code": 23,
"cells_markdown": 39,
- "cells_with_outputs": 23,
+ "cells_with_outputs": 19,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8583,7 +8583,7 @@
"cells_total": 38,
"cells_code": 14,
"cells_markdown": 24,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 7,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -8607,7 +8607,7 @@
"cells_total": 42,
"cells_code": 16,
"cells_markdown": 26,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8631,7 +8631,7 @@
"cells_total": 52,
"cells_code": 17,
"cells_markdown": 35,
- "cells_with_outputs": 17,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -8823,7 +8823,7 @@
"cells_total": 53,
"cells_code": 20,
"cells_markdown": 33,
- "cells_with_outputs": 16,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
@@ -8913,12 +8913,12 @@
"maturity": "DRAFT",
"duree_estimee": "30min",
"owner_logique": "po-2025",
- "last_validation": "2026-05-29",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1769",
- "cells_total": 25,
+ "issue_pr_associee": "#1931",
+ "cells_total": 26,
"cells_code": 11,
- "cells_markdown": 14,
+ "cells_markdown": 15,
"cells_with_outputs": 5,
"cells_without_outputs": 3,
"requires_api": false,
@@ -8958,7 +8958,7 @@
"sous_serie": "",
"kernel": ".NET (C#)",
"status": "READY",
- "maturity": "BETA",
+ "maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2023",
"last_validation": "2026-05-17",
@@ -8967,8 +8967,8 @@
"cells_total": 13,
"cells_code": 5,
"cells_markdown": 8,
- "cells_with_outputs": 3,
- "cells_without_outputs": 1,
+ "cells_with_outputs": 4,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -9054,7 +9054,7 @@
"sous_serie": "",
"kernel": ".NET (C#)",
"status": "READY",
- "maturity": "BETA",
+ "maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2023",
"last_validation": "2026-05-30",
@@ -9063,8 +9063,8 @@
"cells_total": 23,
"cells_code": 9,
"cells_markdown": 14,
- "cells_with_outputs": 8,
- "cells_without_outputs": 1,
+ "cells_with_outputs": 9,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -9087,7 +9087,7 @@
"cells_total": 33,
"cells_code": 10,
"cells_markdown": 23,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -9135,7 +9135,7 @@
"cells_total": 23,
"cells_code": 8,
"cells_markdown": 15,
- "cells_with_outputs": 8,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -9183,8 +9183,8 @@
"cells_total": 33,
"cells_code": 12,
"cells_markdown": 21,
- "cells_with_outputs": 11,
- "cells_without_outputs": 1,
+ "cells_with_outputs": 12,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -9231,7 +9231,7 @@
"cells_total": 28,
"cells_code": 10,
"cells_markdown": 18,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -9255,8 +9255,8 @@
"cells_total": 55,
"cells_code": 22,
"cells_markdown": 33,
- "cells_with_outputs": 19,
- "cells_without_outputs": 1,
+ "cells_with_outputs": 17,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
"requires_cloud": false,
@@ -9297,13 +9297,13 @@
"maturity": "BETA",
"duree_estimee": "45min",
"owner_logique": "po-2023",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1871",
- "cells_total": 59,
+ "issue_pr_associee": "#1931",
+ "cells_total": 60,
"cells_code": 21,
- "cells_markdown": 38,
- "cells_with_outputs": 18,
+ "cells_markdown": 39,
+ "cells_with_outputs": 17,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -9399,7 +9399,7 @@
"cells_total": 26,
"cells_code": 9,
"cells_markdown": 17,
- "cells_with_outputs": 9,
+ "cells_with_outputs": 8,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -9495,7 +9495,7 @@
"cells_total": 39,
"cells_code": 12,
"cells_markdown": 27,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -9880,7 +9880,7 @@
"cells_code": 26,
"cells_markdown": 47,
"cells_with_outputs": 24,
- "cells_without_outputs": 2,
+ "cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
"requires_cloud": false,
@@ -9903,7 +9903,7 @@
"cells_total": 46,
"cells_code": 15,
"cells_markdown": 31,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": true,
@@ -9921,9 +9921,9 @@
"maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1870",
+ "issue_pr_associee": "#1843, #1940",
"cells_total": 34,
"cells_code": 10,
"cells_markdown": 24,
@@ -10168,7 +10168,7 @@
"cells_code": 17,
"cells_markdown": 20,
"cells_with_outputs": 13,
- "cells_without_outputs": 3,
+ "cells_without_outputs": 1,
"requires_api": true,
"requires_gpu": false,
"requires_cloud": false,
@@ -10254,17 +10254,17 @@
"sous_serie": "",
"kernel": ".NET (C#)",
"status": "READY",
- "maturity": "BETA",
+ "maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-25",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1455",
+ "issue_pr_associee": "#1946, #1948",
"cells_total": 20,
"cells_code": 7,
"cells_markdown": 13,
- "cells_with_outputs": 5,
- "cells_without_outputs": 1,
+ "cells_with_outputs": 6,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -10311,7 +10311,7 @@
"cells_total": 43,
"cells_code": 13,
"cells_markdown": 30,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 12,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10408,7 +10408,7 @@
"cells_code": 18,
"cells_markdown": 38,
"cells_with_outputs": 15,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -10425,13 +10425,13 @@
"maturity": "PRODUCTION",
"duree_estimee": "45min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-24",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1455, #1547",
+ "issue_pr_associee": "#1946, #1951",
"cells_total": 47,
"cells_code": 16,
"cells_markdown": 31,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10455,7 +10455,7 @@
"cells_total": 74,
"cells_code": 21,
"cells_markdown": 53,
- "cells_with_outputs": 21,
+ "cells_with_outputs": 20,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10473,9 +10473,9 @@
"maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1899",
+ "issue_pr_associee": "#1934",
"cells_total": 42,
"cells_code": 12,
"cells_markdown": 30,
@@ -10503,7 +10503,7 @@
"cells_total": 44,
"cells_code": 15,
"cells_markdown": 29,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 12,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10527,7 +10527,7 @@
"cells_total": 48,
"cells_code": 12,
"cells_markdown": 36,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10545,9 +10545,9 @@
"maturity": "PRODUCTION",
"duree_estimee": "45min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1899",
+ "issue_pr_associee": "#1946, #1951",
"cells_total": 44,
"cells_code": 16,
"cells_markdown": 28,
@@ -10575,7 +10575,7 @@
"cells_total": 57,
"cells_code": 17,
"cells_markdown": 40,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10593,9 +10593,9 @@
"maturity": "PRODUCTION",
"duree_estimee": "45min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1899",
+ "issue_pr_associee": "#1934",
"cells_total": 53,
"cells_code": 11,
"cells_markdown": 42,
@@ -10671,7 +10671,7 @@
"cells_total": 64,
"cells_code": 19,
"cells_markdown": 45,
- "cells_with_outputs": 19,
+ "cells_with_outputs": 17,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10695,7 +10695,7 @@
"cells_total": 92,
"cells_code": 31,
"cells_markdown": 61,
- "cells_with_outputs": 31,
+ "cells_with_outputs": 24,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10719,7 +10719,7 @@
"cells_total": 53,
"cells_code": 18,
"cells_markdown": 35,
- "cells_with_outputs": 18,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
@@ -10743,8 +10743,8 @@
"cells_total": 72,
"cells_code": 25,
"cells_markdown": 47,
- "cells_with_outputs": 21,
- "cells_without_outputs": 4,
+ "cells_with_outputs": 18,
+ "cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -10863,7 +10863,7 @@
"cells_total": 47,
"cells_code": 16,
"cells_markdown": 31,
- "cells_with_outputs": 16,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -10983,7 +10983,7 @@
"cells_total": 44,
"cells_code": 16,
"cells_markdown": 28,
- "cells_with_outputs": 16,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11007,7 +11007,7 @@
"cells_total": 52,
"cells_code": 19,
"cells_markdown": 33,
- "cells_with_outputs": 19,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11031,7 +11031,7 @@
"cells_total": 77,
"cells_code": 30,
"cells_markdown": 47,
- "cells_with_outputs": 30,
+ "cells_with_outputs": 27,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11056,7 +11056,7 @@
"cells_code": 12,
"cells_markdown": 24,
"cells_with_outputs": 11,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11103,7 +11103,7 @@
"cells_total": 28,
"cells_code": 9,
"cells_markdown": 19,
- "cells_with_outputs": 9,
+ "cells_with_outputs": 8,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11381,13 +11381,13 @@
"serie": "SymbolicAI",
"sous_serie": "SmartContracts",
"kernel": "Python (SmartContracts + Foundry)",
- "status": "DEMO",
+ "status": "READY",
"maturity": "PRODUCTION",
"duree_estimee": "30min",
"owner_logique": "po-2024",
- "last_validation": "2026-05-30",
+ "last_validation": "2026-05-31",
"last_validator": "jsboige@gmail.com",
- "issue_pr_associee": "#1887",
+ "issue_pr_associee": "#1946, #1951",
"cells_total": 26,
"cells_code": 9,
"cells_markdown": 17,
@@ -11416,7 +11416,7 @@
"cells_code": 10,
"cells_markdown": 25,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11439,7 +11439,7 @@
"cells_total": 38,
"cells_code": 10,
"cells_markdown": 28,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11464,7 +11464,7 @@
"cells_code": 9,
"cells_markdown": 22,
"cells_with_outputs": 8,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11512,7 +11512,7 @@
"cells_code": 11,
"cells_markdown": 30,
"cells_with_outputs": 10,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11536,7 +11536,7 @@
"cells_code": 10,
"cells_markdown": 24,
"cells_with_outputs": 9,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11632,7 +11632,7 @@
"cells_code": 9,
"cells_markdown": 24,
"cells_with_outputs": 8,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11656,7 +11656,7 @@
"cells_code": 5,
"cells_markdown": 16,
"cells_with_outputs": 4,
- "cells_without_outputs": 1,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11679,8 +11679,8 @@
"cells_total": 28,
"cells_code": 5,
"cells_markdown": 23,
- "cells_with_outputs": 3,
- "cells_without_outputs": 2,
+ "cells_with_outputs": 2,
+ "cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
"requires_cloud": false,
@@ -11703,7 +11703,7 @@
"cells_total": 38,
"cells_code": 12,
"cells_markdown": 26,
- "cells_with_outputs": 12,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11727,7 +11727,7 @@
"cells_total": 41,
"cells_code": 15,
"cells_markdown": 26,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11799,7 +11799,7 @@
"cells_total": 31,
"cells_code": 10,
"cells_markdown": 21,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 7,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11823,7 +11823,7 @@
"cells_total": 40,
"cells_code": 13,
"cells_markdown": 27,
- "cells_with_outputs": 13,
+ "cells_with_outputs": 11,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11847,7 +11847,7 @@
"cells_total": 38,
"cells_code": 16,
"cells_markdown": 22,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": true,
"requires_gpu": false,
@@ -11871,7 +11871,7 @@
"cells_total": 40,
"cells_code": 15,
"cells_markdown": 25,
- "cells_with_outputs": 15,
+ "cells_with_outputs": 14,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11895,7 +11895,7 @@
"cells_total": 51,
"cells_code": 17,
"cells_markdown": 34,
- "cells_with_outputs": 17,
+ "cells_with_outputs": 16,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11919,7 +11919,7 @@
"cells_total": 40,
"cells_code": 14,
"cells_markdown": 26,
- "cells_with_outputs": 14,
+ "cells_with_outputs": 13,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11943,7 +11943,7 @@
"cells_total": 34,
"cells_code": 11,
"cells_markdown": 23,
- "cells_with_outputs": 11,
+ "cells_with_outputs": 10,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -11991,7 +11991,7 @@
"cells_total": 23,
"cells_code": 8,
"cells_markdown": 15,
- "cells_with_outputs": 7,
+ "cells_with_outputs": 6,
"cells_without_outputs": 1,
"requires_api": false,
"requires_gpu": false,
@@ -12015,7 +12015,7 @@
"cells_total": 33,
"cells_code": 10,
"cells_markdown": 23,
- "cells_with_outputs": 10,
+ "cells_with_outputs": 9,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -12039,7 +12039,7 @@
"cells_total": 17,
"cells_code": 6,
"cells_markdown": 11,
- "cells_with_outputs": 6,
+ "cells_with_outputs": 5,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -12063,7 +12063,7 @@
"cells_total": 21,
"cells_code": 6,
"cells_markdown": 15,
- "cells_with_outputs": 5,
+ "cells_with_outputs": 4,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
@@ -12087,7 +12087,7 @@
"cells_total": 21,
"cells_code": 7,
"cells_markdown": 14,
- "cells_with_outputs": 6,
+ "cells_with_outputs": 5,
"cells_without_outputs": 0,
"requires_api": false,
"requires_gpu": false,
diff --git a/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb b/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
index 011be66b3..5951167d5 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-1-Backtracking-Csharp.ipynb
@@ -5,10 +5,10 @@
"id": "e7eb1226",
"metadata": {
"papermill": {
- "duration": 0.002419,
- "end_time": "2026-05-02T18:17:35.443018+00:00",
+ "duration": 0.002429,
+ "end_time": "2026-05-31T21:12:51.011859",
"exception": false,
- "start_time": "2026-05-02T18:17:35.440599+00:00",
+ "start_time": "2026-05-31T21:12:51.009430",
"status": "completed"
},
"tags": []
@@ -58,16 +58,16 @@
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-05-02T18:17:35.457153Z",
- "iopub.status.busy": "2026-05-02T18:17:35.451410Z",
- "iopub.status.idle": "2026-05-02T18:17:37.678395Z",
- "shell.execute_reply": "2026-05-02T18:17:37.675884Z"
+ "iopub.execute_input": "2026-05-31T21:12:51.027748Z",
+ "iopub.status.busy": "2026-05-31T21:12:51.021628Z",
+ "iopub.status.idle": "2026-05-31T21:12:53.369379Z",
+ "shell.execute_reply": "2026-05-31T21:12:53.367105Z"
},
"papermill": {
- "duration": 2.233247,
- "end_time": "2026-05-02T18:17:37.678516+00:00",
+ "duration": 2.355327,
+ "end_time": "2026-05-31T21:12:53.369488",
"exception": false,
- "start_time": "2026-05-02T18:17:35.445269+00:00",
+ "start_time": "2026-05-31T21:12:51.014161",
"status": "completed"
},
"polyglot_notebook": {
@@ -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": [
@@ -169,10 +412,10 @@
"id": "50d4e0cf",
"metadata": {
"papermill": {
- "duration": 0.00258,
- "end_time": "2026-05-02T18:17:37.684085+00:00",
+ "duration": 0.002656,
+ "end_time": "2026-05-31T21:12:53.374884",
"exception": false,
- "start_time": "2026-05-02T18:17:37.681505+00:00",
+ "start_time": "2026-05-31T21:12:53.372228",
"status": "completed"
},
"tags": []
@@ -192,16 +435,16 @@
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-05-02T18:17:37.691555Z",
- "iopub.status.busy": "2026-05-02T18:17:37.691313Z",
- "iopub.status.idle": "2026-05-02T18:17:37.775233Z",
- "shell.execute_reply": "2026-05-02T18:17:37.774996Z"
+ "iopub.execute_input": "2026-05-31T21:12:53.381774Z",
+ "iopub.status.busy": "2026-05-31T21:12:53.381582Z",
+ "iopub.status.idle": "2026-05-31T21:12:53.463081Z",
+ "shell.execute_reply": "2026-05-31T21:12:53.462903Z"
},
"papermill": {
- "duration": 0.088429,
- "end_time": "2026-05-02T18:17:37.775317+00:00",
+ "duration": 0.085386,
+ "end_time": "2026-05-31T21:12:53.463148",
"exception": false,
- "start_time": "2026-05-02T18:17:37.686888+00:00",
+ "start_time": "2026-05-31T21:12:53.377762",
"status": "completed"
},
"polyglot_notebook": {
@@ -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": [
@@ -251,10 +539,10 @@
"id": "54e213c3",
"metadata": {
"papermill": {
- "duration": 0.005613,
- "end_time": "2026-05-02T18:17:37.784139+00:00",
+ "duration": 0.002461,
+ "end_time": "2026-05-31T21:12:53.468489",
"exception": false,
- "start_time": "2026-05-02T18:17:37.778526+00:00",
+ "start_time": "2026-05-31T21:12:53.466028",
"status": "completed"
},
"tags": []
@@ -286,10 +574,10 @@
"id": "ef6a308c",
"metadata": {
"papermill": {
- "duration": 0.003752,
- "end_time": "2026-05-02T18:17:37.791985+00:00",
+ "duration": 0.002357,
+ "end_time": "2026-05-31T21:12:53.473267",
"exception": false,
- "start_time": "2026-05-02T18:17:37.788233+00:00",
+ "start_time": "2026-05-31T21:12:53.470910",
"status": "completed"
},
"tags": []
@@ -311,16 +599,16 @@
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-05-02T18:17:37.800380Z",
- "iopub.status.busy": "2026-05-02T18:17:37.800155Z",
- "iopub.status.idle": "2026-05-02T18:17:37.855405Z",
- "shell.execute_reply": "2026-05-02T18:17:37.855211Z"
+ "iopub.execute_input": "2026-05-31T21:12:53.479405Z",
+ "iopub.status.busy": "2026-05-31T21:12:53.479236Z",
+ "iopub.status.idle": "2026-05-31T21:12:53.522659Z",
+ "shell.execute_reply": "2026-05-31T21:12:53.522522Z"
},
"papermill": {
- "duration": 0.059582,
- "end_time": "2026-05-02T18:17:37.855478+00:00",
+ "duration": 0.046745,
+ "end_time": "2026-05-31T21:12:53.522725",
"exception": false,
- "start_time": "2026-05-02T18:17:37.795896+00:00",
+ "start_time": "2026-05-31T21:12:53.475980",
"status": "completed"
},
"polyglot_notebook": {
@@ -328,7 +616,15 @@
},
"tags": []
},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Classe BacktrackingDotNetSolver definie\r\n"
+ ]
+ }
+ ],
"source": [
"public class BacktrackingDotNetSolver : ISudokuSolver\n",
"{\n",
@@ -375,7 +671,9 @@
"\n",
" return true;\n",
" }\n",
- "}\n"
+ "}\n",
+ "\n",
+ "Console.WriteLine(\"Classe BacktrackingDotNetSolver definie\");"
]
},
{
@@ -383,10 +681,10 @@
"id": "023237a1",
"metadata": {
"papermill": {
- "duration": 0.002875,
- "end_time": "2026-05-02T18:17:37.861387+00:00",
+ "duration": 0.002463,
+ "end_time": "2026-05-31T21:12:53.528007",
"exception": false,
- "start_time": "2026-05-02T18:17:37.858512+00:00",
+ "start_time": "2026-05-31T21:12:53.525544",
"status": "completed"
},
"tags": []
@@ -406,16 +704,16 @@
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-05-02T18:17:37.869242Z",
- "iopub.status.busy": "2026-05-02T18:17:37.868672Z",
- "iopub.status.idle": "2026-05-02T18:17:42.721785Z",
- "shell.execute_reply": "2026-05-02T18:17:42.721538Z"
+ "iopub.execute_input": "2026-05-31T21:12:53.534101Z",
+ "iopub.status.busy": "2026-05-31T21:12:53.533931Z",
+ "iopub.status.idle": "2026-05-31T21:12:58.177539Z",
+ "shell.execute_reply": "2026-05-31T21:12:58.177375Z"
},
"papermill": {
- "duration": 4.85771,
- "end_time": "2026-05-02T18:17:42.721871+00:00",
+ "duration": 4.647063,
+ "end_time": "2026-05-31T21:12:58.177617",
"exception": false,
- "start_time": "2026-05-02T18:17:37.864161+00:00",
+ "start_time": "2026-05-31T21:12:53.530554",
"status": "completed"
},
"polyglot_notebook": {
@@ -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,4305 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: 154,5594 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: 4422,7117 ms"
+ ]
},
- "metadata": {}
+ "metadata": {},
+ "output_type": "display_data"
}
],
"source": [
@@ -522,10 +928,10 @@
"id": "4261aa01",
"metadata": {
"papermill": {
- "duration": 0.003266,
- "end_time": "2026-05-02T18:17:42.728671+00:00",
+ "duration": 0.003373,
+ "end_time": "2026-05-31T21:12:58.184837",
"exception": false,
- "start_time": "2026-05-02T18:17:42.725405+00:00",
+ "start_time": "2026-05-31T21:12:58.181464",
"status": "completed"
},
"tags": []
@@ -560,10 +966,10 @@
"id": "486520ad",
"metadata": {
"papermill": {
- "duration": 0.003354,
- "end_time": "2026-05-02T18:17:42.735489+00:00",
+ "duration": 0.003146,
+ "end_time": "2026-05-31T21:12:58.191358",
"exception": false,
- "start_time": "2026-05-02T18:17:42.732135+00:00",
+ "start_time": "2026-05-31T21:12:58.188212",
"status": "completed"
},
"tags": []
@@ -594,25 +1000,27 @@
"id": "c83254e4",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-05-02T18:17:42.743125Z",
- "iopub.status.busy": "2026-05-02T18:17:42.742921Z",
- "iopub.status.idle": "2026-05-02T18:17:42.792177Z",
- "shell.execute_reply": "2026-05-02T18:17:42.792012Z"
+ "iopub.execute_input": "2026-05-31T21:12:58.198430Z",
+ "iopub.status.busy": "2026-05-31T21:12:58.198246Z",
+ "iopub.status.idle": "2026-05-31T21:12:58.240608Z",
+ "shell.execute_reply": "2026-05-31T21:12:58.240476Z"
},
"papermill": {
- "duration": 0.053508,
- "end_time": "2026-05-02T18:17:42.792253+00:00",
+ "duration": 0.046411,
+ "end_time": "2026-05-31T21:12:58.240671",
"exception": false,
- "start_time": "2026-05-02T18:17:42.738745+00:00",
+ "start_time": "2026-05-31T21:12:58.194260",
"status": "completed"
},
"tags": []
},
"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": [
@@ -683,10 +1091,10 @@
"id": "dde7cf46",
"metadata": {
"papermill": {
- "duration": 0.003419,
- "end_time": "2026-05-02T18:17:42.799175+00:00",
+ "duration": 0.003494,
+ "end_time": "2026-05-31T21:12:58.247220",
"exception": false,
- "start_time": "2026-05-02T18:17:42.795756+00:00",
+ "start_time": "2026-05-31T21:12:58.243726",
"status": "completed"
},
"tags": []
@@ -737,14 +1145,14 @@
},
"papermill": {
"default_parameters": {},
- "duration": 9.89454,
- "end_time": "2026-05-02T18:17:42.932787+00:00",
+ "duration": 10.335153,
+ "end_time": "2026-05-31T21:12:58.371052",
"environment_variables": {},
"exception": null,
- "input_path": "d:\\dev\\CoursIA\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-1-Backtracking-Csharp.ipynb",
- "output_path": "d:\\dev\\CoursIA\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-1-Backtracking-Csharp.ipynb",
+ "input_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-1-Backtracking-Csharp.ipynb",
+ "output_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-1-Backtracking-Csharp_output.ipynb",
"parameters": {},
- "start_time": "2026-05-02T18:17:33.038247+00:00",
+ "start_time": "2026-05-31T21:12:48.035899",
"version": "2.7.0"
},
"polyglot_notebook": {
@@ -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..62b876f6d 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-11-Choco-Csharp.ipynb
@@ -2,7 +2,17 @@
"cells": [
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "0941cf3e",
+ "metadata": {
+ "papermill": {
+ "duration": 0.016064,
+ "end_time": "2026-05-31T21:13:38.421877",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:38.405813",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"# Sudoku-11-Choco-Csharp : Solveur Choco via IKVM\n",
"\n",
@@ -38,7 +48,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "0d75d2cf",
+ "metadata": {
+ "papermill": {
+ "duration": 0.015551,
+ "end_time": "2026-05-31T21:13:38.446458",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:38.430907",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## Configuration IKVM\n",
"\n",
@@ -65,35 +85,221 @@
{
"cell_type": "code",
"execution_count": 1,
+ "id": "0a36ae28",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:38.610335Z",
- "iopub.status.busy": "2026-04-21T00:17:38.601508Z",
- "iopub.status.idle": "2026-04-21T00:17:40.928323Z",
- "shell.execute_reply": "2026-04-21T00:17:40.917342Z"
- }
+ "iopub.execute_input": "2026-05-31T21:13:38.466945Z",
+ "iopub.status.busy": "2026-05-31T21:13:38.462855Z",
+ "iopub.status.idle": "2026-05-31T21:13:40.339079Z",
+ "shell.execute_reply": "2026-05-31T21:13:40.328121Z"
+ },
+ "papermill": {
+ "duration": 1.888222,
+ "end_time": "2026-05-31T21:13:40.339438",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:38.451216",
+ "status": "completed"
+ },
+ "tags": []
},
"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"
+ "Telechargement de choco-solver-4.10.17-jar-with-dependencies.jar depuis Maven...\r\n"
]
},
{
+ "name": "stdout",
"output_type": "stream",
+ "text": [
+ "Telecharge: choco-solver-4.10.17-jar-with-dependencies.jar (11043898 bytes)\r\n"
+ ]
+ },
+ {
"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"
]
}
],
- "source": "// Configuration du repertoire de travail\n// Recherche le repertoire Sudoku depuis le repertoire courant\nusing System;\nusing System.IO;\nusing System.Net.Http;\n\nstring FindSudokuDir()\n{\n var dir = new DirectoryInfo(Directory.GetCurrentDirectory());\n while (dir != null)\n {\n // Check if we're in the Sudoku directory\n if (File.Exists(Path.Combine(dir.FullName, \"Sudoku-0-Environment-Csharp.ipynb\")))\n return dir.FullName;\n // Check if Sudoku is a subdirectory\n var candidate = Path.Combine(dir.FullName, \"MyIA.AI.Notebooks\", \"Sudoku\");\n if (Directory.Exists(candidate) && File.Exists(Path.Combine(candidate, \"Sudoku-0-Environment-Csharp.ipynb\")))\n return candidate;\n dir = dir.Parent;\n }\n return Directory.GetCurrentDirectory();\n}\n\nvar sudokuDir = FindSudokuDir();\nDirectory.SetCurrentDirectory(sudokuDir);\n\nconst string ChocoVersion = \"4.10.17\";\nconst string ChocoJar = $\"choco-solver-{ChocoVersion}-jar-with-dependencies.jar\";\nconst string ChocoUrl = $\"https://repo1.maven.org/maven2/org/choco-solver/choco-solver/{ChocoVersion}/{ChocoJar}\";\n\nif (!File.Exists(ChocoJar))\n{\n Console.WriteLine($\"Telechargement de {ChocoJar} depuis Maven...\");\n using var client = new HttpClient();\n var data = client.GetByteArrayAsync(ChocoUrl).Result;\n File.WriteAllBytes(ChocoJar, data);\n Console.WriteLine($\"Telecharge: {ChocoJar} ({data.Length} bytes)\");\n}\nelse\n{\n Console.WriteLine($\"Choco-solver JAR deja present: {ChocoJar}\");\n}\n\nConsole.WriteLine($\"Repertoire de travail: {sudokuDir}\");"
+ "source": [
+ "// Configuration du repertoire de travail\n",
+ "// Recherche le repertoire Sudoku depuis le repertoire courant\n",
+ "using System;\n",
+ "using System.IO;\n",
+ "using System.Net.Http;\n",
+ "\n",
+ "string FindSudokuDir()\n",
+ "{\n",
+ " var dir = new DirectoryInfo(Directory.GetCurrentDirectory());\n",
+ " while (dir != null)\n",
+ " {\n",
+ " // Check if we're in the Sudoku directory\n",
+ " if (File.Exists(Path.Combine(dir.FullName, \"Sudoku-0-Environment-Csharp.ipynb\")))\n",
+ " return dir.FullName;\n",
+ " // Check if Sudoku is a subdirectory\n",
+ " var candidate = Path.Combine(dir.FullName, \"MyIA.AI.Notebooks\", \"Sudoku\");\n",
+ " if (Directory.Exists(candidate) && File.Exists(Path.Combine(candidate, \"Sudoku-0-Environment-Csharp.ipynb\")))\n",
+ " return candidate;\n",
+ " dir = dir.Parent;\n",
+ " }\n",
+ " return Directory.GetCurrentDirectory();\n",
+ "}\n",
+ "\n",
+ "var sudokuDir = FindSudokuDir();\n",
+ "Directory.SetCurrentDirectory(sudokuDir);\n",
+ "\n",
+ "const string ChocoVersion = \"4.10.17\";\n",
+ "const string ChocoJar = $\"choco-solver-{ChocoVersion}-jar-with-dependencies.jar\";\n",
+ "const string ChocoUrl = $\"https://repo1.maven.org/maven2/org/choco-solver/choco-solver/{ChocoVersion}/{ChocoJar}\";\n",
+ "\n",
+ "if (!File.Exists(ChocoJar))\n",
+ "{\n",
+ " Console.WriteLine($\"Telechargement de {ChocoJar} depuis Maven...\");\n",
+ " using var client = new HttpClient();\n",
+ " var data = client.GetByteArrayAsync(ChocoUrl).Result;\n",
+ " File.WriteAllBytes(ChocoJar, data);\n",
+ " Console.WriteLine($\"Telecharge: {ChocoJar} ({data.Length} bytes)\");\n",
+ "}\n",
+ "else\n",
+ "{\n",
+ " Console.WriteLine($\"Choco-solver JAR deja present: {ChocoJar}\");\n",
+ "}\n",
+ "\n",
+ "Console.WriteLine($\"Repertoire de travail: {sudokuDir}\");"
+ ]
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "126f24c0",
+ "metadata": {
+ "papermill": {
+ "duration": 0.007273,
+ "end_time": "2026-05-31T21:13:40.353338",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:40.346065",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"Chargement des references au solveur Choco (directives #r en premier)."
]
@@ -101,26 +307,64 @@
{
"cell_type": "code",
"execution_count": 2,
+ "id": "eb2f7777",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:40.930416Z",
- "iopub.status.busy": "2026-04-21T00:17:40.930116Z",
- "iopub.status.idle": "2026-04-21T00:17:40.984059Z",
- "shell.execute_reply": "2026-04-21T00:17:40.983398Z"
+ "iopub.execute_input": "2026-05-31T21:13:40.370673Z",
+ "iopub.status.busy": "2026-05-31T21:13:40.370280Z",
+ "iopub.status.idle": "2026-05-31T21:13:46.406542Z",
+ "shell.execute_reply": "2026-05-31T21:13:46.405489Z"
+ },
+ "papermill": {
+ "duration": 6.044612,
+ "end_time": "2026-05-31T21:13:46.407041",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:40.362429",
+ "status": "completed"
},
+ "tags": [],
"vscode": {
"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": [
+ "DLLs IKVM + Choco-solver chargees\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",
+ "\n",
+ "Console.WriteLine(\"DLLs IKVM + Choco-solver chargees\");"
+ ]
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "89de0442",
+ "metadata": {
+ "papermill": {
+ "duration": 0.024506,
+ "end_time": "2026-05-31T21:13:46.453386",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:46.428880",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"Import des espaces de noms Java Choco via IKVM."
]
@@ -128,18 +372,27 @@
{
"cell_type": "code",
"execution_count": 3,
+ "id": "692440c3",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:40.985963Z",
- "iopub.status.busy": "2026-04-21T00:17:40.985573Z",
- "iopub.status.idle": "2026-04-21T00:17:41.019270Z",
- "shell.execute_reply": "2026-04-21T00:17:41.019681Z"
- }
+ "iopub.execute_input": "2026-05-31T21:13:46.553601Z",
+ "iopub.status.busy": "2026-05-31T21:13:46.552687Z",
+ "iopub.status.idle": "2026-05-31T21:13:46.912292Z",
+ "shell.execute_reply": "2026-05-31T21:13:46.911701Z"
+ },
+ "papermill": {
+ "duration": 0.40941,
+ "end_time": "2026-05-31T21:13:46.912606",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:46.503196",
+ "status": "completed"
+ },
+ "tags": []
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"Choco-solver via IKVM 7.2.4630.5 - Pret pour resolution Sudoku\r\n"
]
@@ -165,7 +418,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "3111a042",
+ "metadata": {
+ "papermill": {
+ "duration": 0.007461,
+ "end_time": "2026-05-31T21:13:46.935743",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:46.928282",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"Import des classes de base depuis le notebook d'environnement."
]
@@ -173,70 +436,234 @@
{
"cell_type": "code",
"execution_count": 4,
+ "id": "98fd108f",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.021615Z",
- "iopub.status.busy": "2026-04-21T00:17:41.021380Z",
- "iopub.status.idle": "2026-04-21T00:17:41.082219Z",
- "shell.execute_reply": "2026-04-21T00:17:41.081272Z"
- }
+ "iopub.execute_input": "2026-05-31T21:13:46.949018Z",
+ "iopub.status.busy": "2026-05-31T21:13:46.948465Z",
+ "iopub.status.idle": "2026-05-31T21:13:48.533584Z",
+ "shell.execute_reply": "2026-05-31T21:13:48.533102Z"
+ },
+ "papermill": {
+ "duration": 1.592885,
+ "end_time": "2026-05-31T21:13:48.533692",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:46.940807",
+ "status": "completed"
+ },
+ "tags": []
},
"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"
+ },
+ {
+ "name": "stdout",
+ "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** :\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"
+ },
+ {
+ "name": "stdout",
+ "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** :\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": [
@@ -246,7 +673,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "91f73654",
+ "metadata": {
+ "papermill": {
+ "duration": 0.006678,
+ "end_time": "2026-05-31T21:13:48.546834",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.540156",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## 1. Implementation Simple : ChocoSimpleSolver\n",
"\n",
@@ -256,24 +693,33 @@
{
"cell_type": "code",
"execution_count": 5,
+ "id": "c882b364",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.083984Z",
- "iopub.status.busy": "2026-04-21T00:17:41.083715Z",
- "iopub.status.idle": "2026-04-21T00:17:41.481975Z",
- "shell.execute_reply": "2026-04-21T00:17:41.481415Z"
+ "iopub.execute_input": "2026-05-31T21:13:48.562149Z",
+ "iopub.status.busy": "2026-05-31T21:13:48.561813Z",
+ "iopub.status.idle": "2026-05-31T21:13:48.646676Z",
+ "shell.execute_reply": "2026-05-31T21:13:48.646357Z"
},
+ "papermill": {
+ "duration": 0.093508,
+ "end_time": "2026-05-31T21:13:48.646789",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.553281",
+ "status": "completed"
+ },
+ "tags": [],
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"ChocoSimpleSolver defini.\r\n"
]
@@ -363,7 +809,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "d12a2720",
+ "metadata": {
+ "papermill": {
+ "duration": 0.006556,
+ "end_time": "2026-05-31T21:13:48.659323",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.652767",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## 2. Implementation Optimisee : ChocoSolverVariableSelector\n",
"\n",
@@ -376,24 +832,33 @@
{
"cell_type": "code",
"execution_count": 6,
+ "id": "07446ee2",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.535819Z",
- "iopub.status.busy": "2026-04-21T00:17:41.483508Z",
- "iopub.status.idle": "2026-04-21T00:17:41.711435Z",
- "shell.execute_reply": "2026-04-21T00:17:41.710678Z"
+ "iopub.execute_input": "2026-05-31T21:13:48.673918Z",
+ "iopub.status.busy": "2026-05-31T21:13:48.673342Z",
+ "iopub.status.idle": "2026-05-31T21:13:48.867358Z",
+ "shell.execute_reply": "2026-05-31T21:13:48.866603Z"
},
+ "papermill": {
+ "duration": 0.202059,
+ "end_time": "2026-05-31T21:13:48.867684",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.665625",
+ "status": "completed"
+ },
+ "tags": [],
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"ChocoSolverVariableSelector defini avec strategie FirstFail.\r\n"
]
@@ -621,12 +1086,46 @@
},
{
"cell_type": "markdown",
- "metadata": {},
- "source": "> **Note technique** : Le solveur Choco via IKVM ne peut pas s'executer dans l'environnement\n> dotnet-interactive actuel. Deux problemes d'environnement ont ete identifies :\n>\n> 1. **Assembly System.Text.Json v8.0.0.5** : Les DLL IKVM reference cette version (NuGet 8.0.5\n> target net462), mais le runtime dotnet-interactive fournit la version 8.0.0.0 (.NET 8).\n> 2. **IKVM_HOME non configure** : Le runtime IKVM requiert un repertoire home specifique avec\n> une structure de fichiers Java/.NET qui n'est pas disponible dans le kernel notebook.\n>\n> Le code Choco (modeles, contraintes, strategies de recherche) est correct et suit l'API\n> Choco-solver 4.10.x. Pour l'executer, il faudrait recompiler les DLL IKVM pour .NET 10\n> ou utiliser un environnement IKVM complet en dehors du notebook interactif.\n>\n> **Statut** : toutes les cellules code executent sans erreur (catch sur l'initialisation IKVM)."
+ "id": "f7423d67",
+ "metadata": {
+ "papermill": {
+ "duration": 0.039676,
+ "end_time": "2026-05-31T21:13:48.927181",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.887505",
+ "status": "completed"
+ },
+ "tags": []
+ },
+ "source": [
+ "> **Note technique** : Le solveur Choco via IKVM ne peut pas s'executer dans l'environnement\n",
+ "> dotnet-interactive actuel. Deux problemes d'environnement ont ete identifies :\n",
+ ">\n",
+ "> 1. **Assembly System.Text.Json v8.0.0.5** : Les DLL IKVM reference cette version (NuGet 8.0.5\n",
+ "> target net462), mais le runtime dotnet-interactive fournit la version 8.0.0.0 (.NET 8).\n",
+ "> 2. **IKVM_HOME non configure** : Le runtime IKVM requiert un repertoire home specifique avec\n",
+ "> une structure de fichiers Java/.NET qui n'est pas disponible dans le kernel notebook.\n",
+ ">\n",
+ "> Le code Choco (modeles, contraintes, strategies de recherche) est correct et suit l'API\n",
+ "> Choco-solver 4.10.x. Pour l'executer, il faudrait recompiler les DLL IKVM pour .NET 10\n",
+ "> ou utiliser un environnement IKVM complet en dehors du notebook interactif.\n",
+ ">\n",
+ "> **Statut** : toutes les cellules code executent sans erreur (catch sur l'initialisation IKVM)."
+ ]
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "86b81912",
+ "metadata": {
+ "papermill": {
+ "duration": 0.03612,
+ "end_time": "2026-05-31T21:13:49.011185",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:48.975065",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## 3. Test avec une Grille Exemple"
]
@@ -634,31 +1133,40 @@
{
"cell_type": "code",
"execution_count": 7,
+ "id": "e3d9701b",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.713613Z",
- "iopub.status.busy": "2026-04-21T00:17:41.713194Z",
- "iopub.status.idle": "2026-04-21T00:17:41.768222Z",
- "shell.execute_reply": "2026-04-21T00:17:41.767282Z"
+ "iopub.execute_input": "2026-05-31T21:13:49.068130Z",
+ "iopub.status.busy": "2026-05-31T21:13:49.066368Z",
+ "iopub.status.idle": "2026-05-31T21:13:49.187001Z",
+ "shell.execute_reply": "2026-05-31T21:13:49.186686Z"
},
+ "papermill": {
+ "duration": 0.143201,
+ "end_time": "2026-05-31T21:13:49.187145",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.043944",
+ "status": "completed"
+ },
+ "tags": [],
"vscode": {
"languageId": "polyglot-notebook"
}
},
"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",
@@ -697,7 +1205,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "ec5aa75c",
+ "metadata": {
+ "papermill": {
+ "duration": 0.007205,
+ "end_time": "2026-05-31T21:13:49.201860",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.194655",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"Test du solveur Choco optimise sur la grille de validation."
]
@@ -705,55 +1223,97 @@
{
"cell_type": "code",
"execution_count": 8,
+ "id": "e6276ce8",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.770357Z",
- "iopub.status.busy": "2026-04-21T00:17:41.769967Z",
- "iopub.status.idle": "2026-04-21T00:17:41.857910Z",
- "shell.execute_reply": "2026-04-21T00:17:41.857310Z"
+ "iopub.execute_input": "2026-05-31T21:13:49.221592Z",
+ "iopub.status.busy": "2026-05-31T21:13:49.220966Z",
+ "iopub.status.idle": "2026-05-31T21:13:49.420259Z",
+ "shell.execute_reply": "2026-05-31T21:13:49.419883Z"
},
+ "papermill": {
+ "duration": 0.210723,
+ "end_time": "2026-05-31T21:13:49.420385",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.209662",
+ "status": "completed"
+ },
+ "tags": [],
"vscode": {
"languageId": "polyglot-notebook"
}
},
"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"
]
}
],
- "source": "// Test avec le solveur optimise\n// Note : le runtime IKVM necessite un environnement specifique (IKVM_HOME, assembly v8.0.0.5)\n// qui n'est pas disponible dans dotnet-interactive .NET 10. Le code ci-dessous est correct\n// mais ne peut pas s'executer dans cet environnement notebook.\ntry\n{\n var solver = new ChocoSolverVariableSelector();\n var stopwatch = System.Diagnostics.Stopwatch.StartNew();\n\n var solution = solver.Solve(testPuzzle);\n stopwatch.Stop();\n\n Console.WriteLine($\"\\nSolution trouvee en {stopwatch.ElapsedMilliseconds} ms:\");\n Console.WriteLine(solution);\n}\ncatch (System.TypeInitializationException ex)\n{\n Console.WriteLine($\"[IKVM Runtime] {ex.InnerException?.Message ?? ex.Message}\");\n Console.WriteLine(\"Le solveur Choco via IKVM ne peut pas s'initialiser dans dotnet-interactive.\");\n Console.WriteLine(\"Cause : IKVM necessite un runtime Java/.NET specifique non disponible ici.\");\n Console.WriteLine(\"Le code est correct et fonctionnerait avec un runtime IKVM complet.\");\n}"
+ "source": [
+ "// Test avec le solveur optimise\n",
+ "// Note : le runtime IKVM necessite un environnement specifique (IKVM_HOME, assembly v8.0.0.5)\n",
+ "// qui n'est pas disponible dans dotnet-interactive .NET 10. Le code ci-dessous est correct\n",
+ "// mais ne peut pas s'executer dans cet environnement notebook.\n",
+ "try\n",
+ "{\n",
+ " var solver = new ChocoSolverVariableSelector();\n",
+ " var stopwatch = System.Diagnostics.Stopwatch.StartNew();\n",
+ "\n",
+ " var solution = solver.Solve(testPuzzle);\n",
+ " stopwatch.Stop();\n",
+ "\n",
+ " Console.WriteLine($\"\\nSolution trouvee en {stopwatch.ElapsedMilliseconds} ms:\");\n",
+ " Console.WriteLine(solution);\n",
+ "}\n",
+ "catch (System.TypeInitializationException ex)\n",
+ "{\n",
+ " Console.WriteLine($\"[IKVM Runtime] {ex.InnerException?.Message ?? ex.Message}\");\n",
+ " Console.WriteLine(\"Le solveur Choco via IKVM ne peut pas s'initialiser dans dotnet-interactive.\");\n",
+ " Console.WriteLine(\"Cause : IKVM necessite un runtime Java/.NET specifique non disponible ici.\");\n",
+ " Console.WriteLine(\"Le code est correct et fonctionnerait avec un runtime IKVM complet.\");\n",
+ "}"
+ ]
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "97d223d8",
+ "metadata": {
+ "papermill": {
+ "duration": 0.008156,
+ "end_time": "2026-05-31T21:13:49.436049",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.427893",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## 4. Comparaison des Strategies\n",
"\n",
@@ -778,7 +1338,17 @@
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "9d0d191d",
+ "metadata": {
+ "papermill": {
+ "duration": 0.009877,
+ "end_time": "2026-05-31T21:13:49.455742",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.445865",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## Exemple guide : Resoudre le probleme des N-Reines avec Choco\n",
"\n",
@@ -800,18 +1370,27 @@
{
"cell_type": "code",
"execution_count": 9,
+ "id": "a7bbee4f",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-21T00:17:41.859680Z",
- "iopub.status.busy": "2026-04-21T00:17:41.859404Z",
- "iopub.status.idle": "2026-04-21T00:17:41.908082Z",
- "shell.execute_reply": "2026-04-21T00:17:41.907362Z"
- }
+ "iopub.execute_input": "2026-05-31T21:13:49.476999Z",
+ "iopub.status.busy": "2026-05-31T21:13:49.476409Z",
+ "iopub.status.idle": "2026-05-31T21:13:49.539369Z",
+ "shell.execute_reply": "2026-05-31T21:13:49.539048Z"
+ },
+ "papermill": {
+ "duration": 0.072328,
+ "end_time": "2026-05-31T21:13:49.539528",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.467200",
+ "status": "completed"
+ },
+ "tags": []
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
+ "output_type": "stream",
"text": [
"TODO: Implementez NQueensChocoSolver.CountSolutions() pour le probleme des 8-Reines\r\n"
]
@@ -865,12 +1444,40 @@
},
{
"cell_type": "markdown",
- "source": "## Resume et perspectives\n\nCe notebook a explore la resolution de Sudoku par **programmation par contraintes** avec Choco-solver, une librairie Java mature appelee depuis C# via le bridge IKVM. L'implementation a couvert deux niveaux de sophistication : un solveur simple (`ChocoSimpleSolver`) posant directement les 27 contraintes `allDifferent` (9 lignes, 9 colonnes, 9 blocs), puis un solveur optimise (`ChocoSolverVariableSelector`) integrant des heuristiques de recherche avancees comme **FirstFail** (equivalent MRV, choisissant la variable au plus petit domaine) et le **noGood recording** pour eviter de revisiter des branches deja ecartees. L'exercice guide sur les N-Reines a permis de transposer le modele CSP vers un autre probleme classique, en exploitant les memes primitives Choco (`allDifferent`, `arithm`, comptage de solutions).\n\nLa comparaison theorique avec OR-Tools, Z3 et python-constraint montre que Choco se situe dans une niche intermediaire : moins performant qu'OR-Tools CP-SAT sur les instances difficiles, mais offrant un acces natif a des contraintes globales optimisees et des strategies de recherche fines (DomOverWDeg, Impact-based search). La limitation technique rencontree avec IKVM dans dotnet-interactive illustre les defis d'interoperabilite Java/.NET en environnement notebook, et confirme l'interet de approaches natives comme OR-Tools pour un usage pedagogique fluide.\n\nLe prochain notebook, **Sudoku-12-Z3-Csharp**, aborde une approche complementaire avec le solveur SMT Z3, qui represente le Sudoku non pas comme un CSP mais comme un systeme de contraintes logiques, offrant des garanties de completude et des techniques de raisonnement differentes (theorie des tableaux, resolution SAT).",
- "metadata": {}
+ "id": "326ac208",
+ "metadata": {
+ "papermill": {
+ "duration": 0.011486,
+ "end_time": "2026-05-31T21:13:49.559837",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.548351",
+ "status": "completed"
+ },
+ "tags": []
+ },
+ "source": [
+ "## Resume et perspectives\n",
+ "\n",
+ "Ce notebook a explore la resolution de Sudoku par **programmation par contraintes** avec Choco-solver, une librairie Java mature appelee depuis C# via le bridge IKVM. L'implementation a couvert deux niveaux de sophistication : un solveur simple (`ChocoSimpleSolver`) posant directement les 27 contraintes `allDifferent` (9 lignes, 9 colonnes, 9 blocs), puis un solveur optimise (`ChocoSolverVariableSelector`) integrant des heuristiques de recherche avancees comme **FirstFail** (equivalent MRV, choisissant la variable au plus petit domaine) et le **noGood recording** pour eviter de revisiter des branches deja ecartees. L'exercice guide sur les N-Reines a permis de transposer le modele CSP vers un autre probleme classique, en exploitant les memes primitives Choco (`allDifferent`, `arithm`, comptage de solutions).\n",
+ "\n",
+ "La comparaison theorique avec OR-Tools, Z3 et python-constraint montre que Choco se situe dans une niche intermediaire : moins performant qu'OR-Tools CP-SAT sur les instances difficiles, mais offrant un acces natif a des contraintes globales optimisees et des strategies de recherche fines (DomOverWDeg, Impact-based search). La limitation technique rencontree avec IKVM dans dotnet-interactive illustre les defis d'interoperabilite Java/.NET en environnement notebook, et confirme l'interet de approaches natives comme OR-Tools pour un usage pedagogique fluide.\n",
+ "\n",
+ "Le prochain notebook, **Sudoku-12-Z3-Csharp**, aborde une approche complementaire avec le solveur SMT Z3, qui represente le Sudoku non pas comme un CSP mais comme un systeme de contraintes logiques, offrant des garanties de completude et des techniques de raisonnement differentes (theorie des tableaux, resolution SAT)."
+ ]
},
{
"cell_type": "markdown",
- "metadata": {},
+ "id": "bb42f3d5",
+ "metadata": {
+ "papermill": {
+ "duration": 0.011431,
+ "end_time": "2026-05-31T21:13:49.583647",
+ "exception": false,
+ "start_time": "2026-05-31T21:13:49.572216",
+ "status": "completed"
+ },
+ "tags": []
+ },
"source": [
"## 5. Resume\n",
"\n",
@@ -909,7 +1516,19 @@
"mimetype": "text/x-csharp",
"name": "C#",
"pygments_lexer": "csharp",
- "version": "13.0"
+ "version": "12.0"
+ },
+ "papermill": {
+ "default_parameters": {},
+ "duration": 13.792054,
+ "end_time": "2026-05-31T21:13:49.849938",
+ "environment_variables": {},
+ "exception": null,
+ "input_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-11-Choco-Csharp.ipynb",
+ "output_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-11-Choco-Csharp_output.ipynb",
+ "parameters": {},
+ "start_time": "2026-05-31T21:13:36.057884",
+ "version": "2.6.0"
},
"polyglot_notebook": {
"kernelInfo": {
@@ -925,5 +1544,5 @@
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 5
}
\ No newline at end of file
diff --git a/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb b/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
index be541ea3a..2e1a6a968 100644
--- a/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
+++ b/MyIA.AI.Notebooks/Sudoku/Sudoku-14-BDD-Csharp.ipynb
@@ -5,10 +5,10 @@
"id": "300cd4ca",
"metadata": {
"papermill": {
- "duration": 0.00801,
- "end_time": "2026-04-25T14:47:49.707139",
+ "duration": 0.010264,
+ "end_time": "2026-05-31T21:14:05.337785",
"exception": false,
- "start_time": "2026-04-25T14:47:49.699129",
+ "start_time": "2026-05-31T21:14:05.327521",
"status": "completed"
},
"tags": []
@@ -69,10 +69,10 @@
"id": "1e2c7db9",
"metadata": {
"papermill": {
- "duration": 0.012072,
- "end_time": "2026-04-25T14:47:49.725732",
+ "duration": 0.009483,
+ "end_time": "2026-05-31T21:14:05.353571",
"exception": false,
- "start_time": "2026-04-25T14:47:49.713660",
+ "start_time": "2026-05-31T21:14:05.344088",
"status": "completed"
},
"tags": []
@@ -123,10 +123,10 @@
"id": "6a91a2b3",
"metadata": {
"papermill": {
- "duration": 0.003784,
- "end_time": "2026-04-25T14:47:49.733899",
+ "duration": 0.01215,
+ "end_time": "2026-05-31T21:14:05.376173",
"exception": false,
- "start_time": "2026-04-25T14:47:49.730115",
+ "start_time": "2026-05-31T21:14:05.364023",
"status": "completed"
},
"tags": []
@@ -147,50 +147,177 @@
"id": "a6c520e4",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:49.761687Z",
- "iopub.status.busy": "2026-04-25T14:47:49.761074Z",
- "iopub.status.idle": "2026-04-25T14:47:52.541778Z",
- "shell.execute_reply": "2026-04-25T14:47:52.534314Z"
+ "iopub.execute_input": "2026-05-31T21:14:05.403221Z",
+ "iopub.status.busy": "2026-05-31T21:14:05.397598Z",
+ "iopub.status.idle": "2026-05-31T21:14:06.638562Z",
+ "shell.execute_reply": "2026-05-31T21:14:06.635404Z"
},
"papermill": {
- "duration": 2.804341,
- "end_time": "2026-04-25T14:47:52.541995",
+ "duration": 1.254019,
+ "end_time": "2026-05-31T21:14:06.639218",
"exception": false,
- "start_time": "2026-04-25T14:47:49.737654",
+ "start_time": "2026-05-31T21:14:05.385199",
"status": "completed"
},
"tags": []
},
"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": [
@@ -306,10 +433,10 @@
"id": "ce7ac457",
"metadata": {
"papermill": {
- "duration": 0.005338,
- "end_time": "2026-04-25T14:47:52.553193",
+ "duration": 0.008,
+ "end_time": "2026-05-31T21:14:06.659915",
"exception": false,
- "start_time": "2026-04-25T14:47:52.547855",
+ "start_time": "2026-05-31T21:14:06.651915",
"status": "completed"
},
"tags": []
@@ -326,100 +453,138 @@
"id": "2bede738",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:52.566557Z",
- "iopub.status.busy": "2026-04-25T14:47:52.566230Z",
- "iopub.status.idle": "2026-04-25T14:47:52.712980Z",
- "shell.execute_reply": "2026-04-25T14:47:52.712743Z"
+ "iopub.execute_input": "2026-05-31T21:14:06.681470Z",
+ "iopub.status.busy": "2026-05-31T21:14:06.680381Z",
+ "iopub.status.idle": "2026-05-31T21:14:07.049080Z",
+ "shell.execute_reply": "2026-05-31T21:14:07.046347Z"
},
"papermill": {
- "duration": 0.153915,
- "end_time": "2026-04-25T14:47:52.713077",
+ "duration": 0.38324,
+ "end_time": "2026-05-31T21:14:07.050183",
"exception": false,
- "start_time": "2026-04-25T14:47:52.559162",
+ "start_time": "2026-05-31T21:14:06.666943",
"status": "completed"
},
"tags": []
},
"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": [
@@ -456,10 +621,10 @@
"id": "dcc5dd43",
"metadata": {
"papermill": {
- "duration": 0.004808,
- "end_time": "2026-04-25T14:47:52.722941",
+ "duration": 0.049963,
+ "end_time": "2026-05-31T21:14:07.155385",
"exception": false,
- "start_time": "2026-04-25T14:47:52.718133",
+ "start_time": "2026-05-31T21:14:07.105422",
"status": "completed"
},
"tags": []
@@ -490,10 +655,10 @@
"id": "3112185a",
"metadata": {
"papermill": {
- "duration": 0.008546,
- "end_time": "2026-04-25T14:47:52.736627",
+ "duration": 0.026496,
+ "end_time": "2026-05-31T21:14:07.217613",
"exception": false,
- "start_time": "2026-04-25T14:47:52.728081",
+ "start_time": "2026-05-31T21:14:07.191117",
"status": "completed"
},
"tags": []
@@ -514,25 +679,27 @@
"id": "2a3c3f45",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:52.752522Z",
- "iopub.status.busy": "2026-04-25T14:47:52.752049Z",
- "iopub.status.idle": "2026-04-25T14:47:53.042298Z",
- "shell.execute_reply": "2026-04-25T14:47:53.042080Z"
+ "iopub.execute_input": "2026-05-31T21:14:07.247265Z",
+ "iopub.status.busy": "2026-05-31T21:14:07.245465Z",
+ "iopub.status.idle": "2026-05-31T21:14:08.162186Z",
+ "shell.execute_reply": "2026-05-31T21:14:08.161387Z"
},
"papermill": {
- "duration": 0.297518,
- "end_time": "2026-04-25T14:47:53.042388",
+ "duration": 0.934272,
+ "end_time": "2026-05-31T21:14:08.162424",
"exception": false,
- "start_time": "2026-04-25T14:47:52.744870",
+ "start_time": "2026-05-31T21:14:07.228152",
"status": "completed"
},
"tags": []
},
"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": [
@@ -614,10 +781,10 @@
"id": "a6b99a0f",
"metadata": {
"papermill": {
- "duration": 0.008363,
- "end_time": "2026-04-25T14:47:53.056702",
+ "duration": 0.011575,
+ "end_time": "2026-05-31T21:14:08.183159",
"exception": false,
- "start_time": "2026-04-25T14:47:53.048339",
+ "start_time": "2026-05-31T21:14:08.171584",
"status": "completed"
},
"tags": []
@@ -634,90 +801,118 @@
"id": "e4c2904c",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:53.073333Z",
- "iopub.status.busy": "2026-04-25T14:47:53.072927Z",
- "iopub.status.idle": "2026-04-25T14:47:53.207243Z",
- "shell.execute_reply": "2026-04-25T14:47:53.207040Z"
+ "iopub.execute_input": "2026-05-31T21:14:08.207391Z",
+ "iopub.status.busy": "2026-05-31T21:14:08.207001Z",
+ "iopub.status.idle": "2026-05-31T21:14:08.343913Z",
+ "shell.execute_reply": "2026-05-31T21:14:08.343657Z"
},
"papermill": {
- "duration": 0.142491,
- "end_time": "2026-04-25T14:47:53.207366",
+ "duration": 0.150631,
+ "end_time": "2026-05-31T21:14:08.344040",
"exception": false,
- "start_time": "2026-04-25T14:47:53.064875",
+ "start_time": "2026-05-31T21:14:08.193409",
"status": "completed"
},
"tags": []
},
"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": [
@@ -761,10 +956,10 @@
"id": "43598773",
"metadata": {
"papermill": {
- "duration": 0.008929,
- "end_time": "2026-04-25T14:47:53.224903",
+ "duration": 0.008026,
+ "end_time": "2026-05-31T21:14:08.360814",
"exception": false,
- "start_time": "2026-04-25T14:47:53.215974",
+ "start_time": "2026-05-31T21:14:08.352788",
"status": "completed"
},
"tags": []
@@ -792,25 +987,27 @@
"id": "49a2296c",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:53.245495Z",
- "iopub.status.busy": "2026-04-25T14:47:53.245064Z",
- "iopub.status.idle": "2026-04-25T14:47:53.537991Z",
- "shell.execute_reply": "2026-04-25T14:47:53.537626Z"
+ "iopub.execute_input": "2026-05-31T21:14:08.381880Z",
+ "iopub.status.busy": "2026-05-31T21:14:08.381490Z",
+ "iopub.status.idle": "2026-05-31T21:14:08.659478Z",
+ "shell.execute_reply": "2026-05-31T21:14:08.659234Z"
},
"papermill": {
- "duration": 0.303817,
- "end_time": "2026-04-25T14:47:53.538162",
+ "duration": 0.289186,
+ "end_time": "2026-05-31T21:14:08.659598",
"exception": false,
- "start_time": "2026-04-25T14:47:53.234345",
+ "start_time": "2026-05-31T21:14:08.370412",
"status": "completed"
},
"tags": []
},
"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": [
@@ -900,10 +1097,10 @@
"id": "45ea0520",
"metadata": {
"papermill": {
- "duration": 0.005734,
- "end_time": "2026-04-25T14:47:53.551984",
+ "duration": 0.008108,
+ "end_time": "2026-05-31T21:14:08.676301",
"exception": false,
- "start_time": "2026-04-25T14:47:53.546250",
+ "start_time": "2026-05-31T21:14:08.668193",
"status": "completed"
},
"tags": []
@@ -922,25 +1119,27 @@
"id": "78d9cfe9",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:53.568558Z",
- "iopub.status.busy": "2026-04-25T14:47:53.568117Z",
- "iopub.status.idle": "2026-04-25T14:47:53.645085Z",
- "shell.execute_reply": "2026-04-25T14:47:53.644896Z"
+ "iopub.execute_input": "2026-05-31T21:14:08.697180Z",
+ "iopub.status.busy": "2026-05-31T21:14:08.696727Z",
+ "iopub.status.idle": "2026-05-31T21:14:08.766391Z",
+ "shell.execute_reply": "2026-05-31T21:14:08.766164Z"
},
"papermill": {
- "duration": 0.085491,
- "end_time": "2026-04-25T14:47:53.645204",
+ "duration": 0.079433,
+ "end_time": "2026-05-31T21:14:08.766502",
"exception": false,
- "start_time": "2026-04-25T14:47:53.559713",
+ "start_time": "2026-05-31T21:14:08.687069",
"status": "completed"
},
"tags": []
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "RowMDDBuilder OK (memoization bitmask).\r\n"
+ "output_type": "stream",
+ "text": [
+ "RowMDDBuilder OK (memoization bitmask).\r\n"
+ ]
}
],
"source": [
@@ -999,10 +1198,10 @@
"id": "f5dcabcd",
"metadata": {
"papermill": {
- "duration": 0.00548,
- "end_time": "2026-04-25T14:47:53.656353",
+ "duration": 0.007748,
+ "end_time": "2026-05-31T21:14:08.781357",
"exception": false,
- "start_time": "2026-04-25T14:47:53.650873",
+ "start_time": "2026-05-31T21:14:08.773609",
"status": "completed"
},
"tags": []
@@ -1019,80 +1218,104 @@
"id": "81fe3df4",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:53.668998Z",
- "iopub.status.busy": "2026-04-25T14:47:53.668739Z",
- "iopub.status.idle": "2026-04-25T14:47:54.322331Z",
- "shell.execute_reply": "2026-04-25T14:47:54.322047Z"
+ "iopub.execute_input": "2026-05-31T21:14:08.796859Z",
+ "iopub.status.busy": "2026-05-31T21:14:08.796485Z",
+ "iopub.status.idle": "2026-05-31T21:14:09.329038Z",
+ "shell.execute_reply": "2026-05-31T21:14:09.328815Z"
},
"papermill": {
- "duration": 0.660528,
- "end_time": "2026-04-25T14:47:54.322427",
+ "duration": 0.540875,
+ "end_time": "2026-05-31T21:14:09.329307",
"exception": false,
- "start_time": "2026-04-25T14:47:53.661899",
+ "start_time": "2026-05-31T21:14:08.788432",
"status": "completed"
},
"tags": []
},
"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": [
@@ -1140,10 +1363,10 @@
"id": "b1ad23f7",
"metadata": {
"papermill": {
- "duration": 0.009367,
- "end_time": "2026-04-25T14:47:54.342035",
+ "duration": 0.007611,
+ "end_time": "2026-05-31T21:14:09.345588",
"exception": false,
- "start_time": "2026-04-25T14:47:54.332668",
+ "start_time": "2026-05-31T21:14:09.337977",
"status": "completed"
},
"tags": []
@@ -1172,10 +1395,10 @@
"id": "28f8c63e",
"metadata": {
"papermill": {
- "duration": 0.009222,
- "end_time": "2026-04-25T14:47:54.360235",
+ "duration": 0.008547,
+ "end_time": "2026-05-31T21:14:09.364000",
"exception": false,
- "start_time": "2026-04-25T14:47:54.351013",
+ "start_time": "2026-05-31T21:14:09.355453",
"status": "completed"
},
"tags": []
@@ -1196,25 +1419,27 @@
"id": "0c999c25",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:54.378676Z",
- "iopub.status.busy": "2026-04-25T14:47:54.378402Z",
- "iopub.status.idle": "2026-04-25T14:47:54.538382Z",
- "shell.execute_reply": "2026-04-25T14:47:54.538177Z"
+ "iopub.execute_input": "2026-05-31T21:14:09.382632Z",
+ "iopub.status.busy": "2026-05-31T21:14:09.382282Z",
+ "iopub.status.idle": "2026-05-31T21:14:09.475412Z",
+ "shell.execute_reply": "2026-05-31T21:14:09.475121Z"
},
"papermill": {
- "duration": 0.168863,
- "end_time": "2026-04-25T14:47:54.538473",
+ "duration": 0.102972,
+ "end_time": "2026-05-31T21:14:09.475510",
"exception": false,
- "start_time": "2026-04-25T14:47:54.369610",
+ "start_time": "2026-05-31T21:14:09.372538",
"status": "completed"
},
"tags": []
},
"outputs": [
{
- "output_type": "stream",
"name": "stdout",
- "text": "MDDOperations OK (Product).\r\n"
+ "output_type": "stream",
+ "text": [
+ "MDDOperations OK (Product).\r\n"
+ ]
}
],
"source": [
@@ -1293,10 +1518,10 @@
"id": "7a167a52",
"metadata": {
"papermill": {
- "duration": 0.005795,
- "end_time": "2026-04-25T14:47:54.550279",
+ "duration": 0.008442,
+ "end_time": "2026-05-31T21:14:09.494674",
"exception": false,
- "start_time": "2026-04-25T14:47:54.544484",
+ "start_time": "2026-05-31T21:14:09.486232",
"status": "completed"
},
"tags": []
@@ -1313,85 +1538,113 @@
"id": "880d00f1",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:54.564198Z",
- "iopub.status.busy": "2026-04-25T14:47:54.563938Z",
- "iopub.status.idle": "2026-04-25T14:47:54.688360Z",
- "shell.execute_reply": "2026-04-25T14:47:54.688156Z"
+ "iopub.execute_input": "2026-05-31T21:14:09.518688Z",
+ "iopub.status.busy": "2026-05-31T21:14:09.518354Z",
+ "iopub.status.idle": "2026-05-31T21:14:09.639082Z",
+ "shell.execute_reply": "2026-05-31T21:14:09.638821Z"
},
"papermill": {
- "duration": 0.132502,
- "end_time": "2026-04-25T14:47:54.688453",
+ "duration": 0.134118,
+ "end_time": "2026-05-31T21:14:09.639207",
"exception": false,
- "start_time": "2026-04-25T14:47:54.555951",
+ "start_time": "2026-05-31T21:14:09.505089",
"status": "completed"
},
"tags": []
},
"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": [
@@ -1491,10 +1744,10 @@
"id": "1d591f2f",
"metadata": {
"papermill": {
- "duration": 0.006313,
- "end_time": "2026-04-25T14:47:54.701349",
+ "duration": 0.009241,
+ "end_time": "2026-05-31T21:14:09.660898",
"exception": false,
- "start_time": "2026-04-25T14:47:54.695036",
+ "start_time": "2026-05-31T21:14:09.651657",
"status": "completed"
},
"tags": []
@@ -1526,35 +1779,41 @@
"id": "1388b811",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:54.716529Z",
- "iopub.status.busy": "2026-04-25T14:47:54.716265Z",
- "iopub.status.idle": "2026-04-25T14:47:54.866543Z",
- "shell.execute_reply": "2026-04-25T14:47:54.866355Z"
+ "iopub.execute_input": "2026-05-31T21:14:09.683632Z",
+ "iopub.status.busy": "2026-05-31T21:14:09.683013Z",
+ "iopub.status.idle": "2026-05-31T21:14:09.856251Z",
+ "shell.execute_reply": "2026-05-31T21:14:09.855848Z"
},
"papermill": {
- "duration": 0.158722,
- "end_time": "2026-04-25T14:47:54.866704",
+ "duration": 0.184239,
+ "end_time": "2026-05-31T21:14:09.856462",
"exception": false,
- "start_time": "2026-04-25T14:47:54.707982",
+ "start_time": "2026-05-31T21:14:09.672223",
"status": "completed"
},
"tags": []
},
"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": [
@@ -1684,10 +1943,10 @@
"id": "3608933f",
"metadata": {
"papermill": {
- "duration": 0.006273,
- "end_time": "2026-04-25T14:47:54.882004",
+ "duration": 0.010129,
+ "end_time": "2026-05-31T21:14:09.881372",
"exception": false,
- "start_time": "2026-04-25T14:47:54.875731",
+ "start_time": "2026-05-31T21:14:09.871243",
"status": "completed"
},
"tags": []
@@ -1704,590 +1963,819 @@
"id": "2c4c0f77",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:54.896369Z",
- "iopub.status.busy": "2026-04-25T14:47:54.896080Z",
- "iopub.status.idle": "2026-04-25T14:47:55.017835Z",
- "shell.execute_reply": "2026-04-25T14:47:54.993484Z"
+ "iopub.execute_input": "2026-05-31T21:14:09.908898Z",
+ "iopub.status.busy": "2026-05-31T21:14:09.908222Z",
+ "iopub.status.idle": "2026-05-31T21:14:10.069806Z",
+ "shell.execute_reply": "2026-05-31T21:14:10.022329Z"
},
"papermill": {
- "duration": 0.129591,
- "end_time": "2026-04-25T14:47:55.017931",
+ "duration": 0.177449,
+ "end_time": "2026-05-31T21:14:10.069917",
"exception": false,
- "start_time": "2026-04-25T14:47:54.888340",
+ "start_time": "2026-05-31T21:14:09.892468",
"status": "completed"
},
"tags": []
},
"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 1,02 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": [
@@ -2337,10 +2825,10 @@
"id": "bdbd8c6a",
"metadata": {
"papermill": {
- "duration": 0.010485,
- "end_time": "2026-04-25T14:47:55.038749",
+ "duration": 0.015602,
+ "end_time": "2026-05-31T21:14:10.100474",
"exception": false,
- "start_time": "2026-04-25T14:47:55.028264",
+ "start_time": "2026-05-31T21:14:10.084872",
"status": "completed"
},
"tags": []
@@ -2360,10 +2848,10 @@
"id": "6e343b5b",
"metadata": {
"papermill": {
- "duration": 0.009638,
- "end_time": "2026-04-25T14:47:55.058551",
+ "duration": 0.017561,
+ "end_time": "2026-05-31T21:14:10.131198",
"exception": false,
- "start_time": "2026-04-25T14:47:55.048913",
+ "start_time": "2026-05-31T21:14:10.113637",
"status": "completed"
},
"tags": []
@@ -2410,10 +2898,10 @@
"id": "de87e32a",
"metadata": {
"papermill": {
- "duration": 0.009808,
- "end_time": "2026-04-25T14:47:55.077949",
+ "duration": 0.037208,
+ "end_time": "2026-05-31T21:14:10.190558",
"exception": false,
- "start_time": "2026-04-25T14:47:55.068141",
+ "start_time": "2026-05-31T21:14:10.153350",
"status": "completed"
},
"tags": []
@@ -2463,10 +2951,10 @@
"id": "534aea95",
"metadata": {
"papermill": {
- "duration": 0.010507,
- "end_time": "2026-04-25T14:47:55.099081",
+ "duration": 0.021004,
+ "end_time": "2026-05-31T21:14:10.246037",
"exception": false,
- "start_time": "2026-04-25T14:47:55.088574",
+ "start_time": "2026-05-31T21:14:10.225033",
"status": "completed"
},
"tags": []
@@ -2502,10 +2990,10 @@
"id": "7cff0504",
"metadata": {
"papermill": {
- "duration": 0.013521,
- "end_time": "2026-04-25T14:47:55.124438",
+ "duration": 0.021022,
+ "end_time": "2026-05-31T21:14:10.298860",
"exception": false,
- "start_time": "2026-04-25T14:47:55.110917",
+ "start_time": "2026-05-31T21:14:10.277838",
"status": "completed"
},
"tags": []
@@ -2541,10 +3029,10 @@
"id": "b6d161b4",
"metadata": {
"papermill": {
- "duration": 0.010285,
- "end_time": "2026-04-25T14:47:55.144887",
+ "duration": 0.014611,
+ "end_time": "2026-05-31T21:14:10.335980",
"exception": false,
- "start_time": "2026-04-25T14:47:55.134602",
+ "start_time": "2026-05-31T21:14:10.321369",
"status": "completed"
},
"tags": []
@@ -2586,21 +3074,29 @@
"id": "0ef0f013",
"metadata": {
"execution": {
- "iopub.execute_input": "2026-04-25T14:47:55.177840Z",
- "iopub.status.busy": "2026-04-25T14:47:55.177552Z",
- "iopub.status.idle": "2026-04-25T14:47:55.283094Z",
- "shell.execute_reply": "2026-04-25T14:47:55.283248Z"
+ "iopub.execute_input": "2026-05-31T21:14:10.394785Z",
+ "iopub.status.busy": "2026-05-31T21:14:10.393968Z",
+ "iopub.status.idle": "2026-05-31T21:14:10.461911Z",
+ "shell.execute_reply": "2026-05-31T21:14:10.461640Z"
},
"papermill": {
- "duration": 0.127979,
- "end_time": "2026-04-25T14:47:55.283342",
+ "duration": 0.099137,
+ "end_time": "2026-05-31T21:14:10.462042",
"exception": false,
- "start_time": "2026-04-25T14:47:55.155363",
+ "start_time": "2026-05-31T21:14:10.362905",
"status": "completed"
},
"tags": []
},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Exercice a completer : solveur BDD avec propagation de contraintes\r\n"
+ ]
+ }
+ ],
"source": [
"// A COMPLETER : Solveur BDD avec propagation de contraintes\n",
"\n",
@@ -2650,7 +3146,9 @@
"// string puzzle = \"003020600900305001001806400008102900700000008006708200002609500800203009005010300\";\n",
"// var propagator = new BDDConstraintPropagator();\n",
"// var solution = propagator.Solve(puzzle);\n",
- "// Console.WriteLine(solution != null ? \"Solution trouvee !\" : \"Echec !\");"
+ "// Console.WriteLine(solution != null ? \"Solution trouvee !\" : \"Echec !\");\n",
+ "\n",
+ "Console.WriteLine(\"Exercice a completer : solveur BDD avec propagation de contraintes\");"
]
}
],
@@ -2665,18 +3163,18 @@
"mimetype": "text/x-csharp",
"name": "C#",
"pygments_lexer": "csharp",
- "version": "13.0"
+ "version": "12.0"
},
"papermill": {
"default_parameters": {},
- "duration": 8.981084,
- "end_time": "2026-04-25T14:47:55.533063",
+ "duration": 7.692005,
+ "end_time": "2026-05-31T21:14:10.721946",
"environment_variables": {},
"exception": null,
- "input_path": "D:\\Dev\\CoursIA\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-14-BDD-Csharp.ipynb",
- "output_path": "D:\\Dev\\CoursIA\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-14-BDD-Csharp_output.ipynb",
+ "input_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-14-BDD-Csharp.ipynb",
+ "output_path": "D:\\dev\\CoursIA-2\\MyIA.AI.Notebooks\\Sudoku\\Sudoku-14-BDD-Csharp_output.ipynb",
"parameters": {},
- "start_time": "2026-04-25T14:47:46.551979",
+ "start_time": "2026-05-31T21:14:03.029941",
"version": "2.6.0"
}
},