diff --git a/MyIA.AI.Notebooks/Search/Applications/Hybrid/App-17-VRP-Logistics.ipynb b/MyIA.AI.Notebooks/Search/Applications/Hybrid/App-17-VRP-Logistics.ipynb index 7b381ee77c..5748983c59 100644 --- a/MyIA.AI.Notebooks/Search/Applications/Hybrid/App-17-VRP-Logistics.ipynb +++ b/MyIA.AI.Notebooks/Search/Applications/Hybrid/App-17-VRP-Logistics.ipynb @@ -1244,7 +1244,7 @@ "id": "a041eea7", "metadata": {}, "source": [ - "### Lecture : décomposer l'écart — où est la distance récupérable\n", + "### Lecture : décomposer l'écart — ce que gagne le solveur SOTA\n", "\n", "Le tableau se lit aussi en differences qu'en pourcentages : `417.49` a\n", "`414.49` pour le 2-opt (`-0.7%`), puis `414.49` a `403.45` pour OR-Tools\n", @@ -1257,28 +1257,9 @@ "recherche locale piétine, la question n'est pas « comment l'accélérer » mais\n", "« quel mouvement n'est pas dans son voisinage ». C'est ce diagnostic qui\n", "justifie les métaheuristiques à mouvements inter-tournées du notebook 17b —\n", - "relocate, recuit simulé — avant même de les écrire." - ] - }, - { - "cell_type": "markdown", - "id": "cd644708", - "metadata": { - "papermill": { - "duration": 0.008617, - "end_time": "2026-06-29T03:47:04.147343+00:00", - "exception": false, - "start_time": "2026-06-29T03:47:04.138726+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation : ce que gagne le solveur SOTA\n", + "relocate, recuit simulé — avant même de les écrire.\n", "\n", - "Sur la même instance, OR-Tools trouve une tournée globale **plus courte** que le greedy et que le\n", - "greedy+2-opt, sans aucun réglage manuel. L'écart est modeste ici (instance à 15 clients, où 2-opt\n", - "n'a déjà presque rien à gratter), mais il illustre l'essentiel :\n", + "L'écart est modeste sur cette instance (15 clients, où 2-opt n'a déjà presque rien à gratter), mais OR-Tools l'obtient **sans aucun réglage manuel**, et le mécanisme est l'essentiel :\n", "\n", "- **2-opt** n'améliore *que l'ordre interne de chaque tournée déjà fixée* — il ne peut pas\n", " **déplacer un client d'un véhicule à un autre**. Son gain est donc plafonné par l'affectation\n", diff --git a/MyIA.AI.Notebooks/Search/Applications/Search/App-14-ConnectFour-Adversarial.ipynb b/MyIA.AI.Notebooks/Search/Applications/Search/App-14-ConnectFour-Adversarial.ipynb index aaedc44c44..2bacc8c3ea 100644 --- a/MyIA.AI.Notebooks/Search/Applications/Search/App-14-ConnectFour-Adversarial.ipynb +++ b/MyIA.AI.Notebooks/Search/Applications/Search/App-14-ConnectFour-Adversarial.ipynb @@ -2232,50 +2232,7 @@ "3. **MCTS en difficulté** : dernier du tournoi, perd contre Alpha-Beta (0-6), Minimax (0-6) et meme contre Random (2-4) -- 1000 iterations restent peu pour Connect Four\n", "4. **échantillon insuffisant** : 6 parties par match = résultats variables\n", "\n", - "> **Note technique** : Le tournoi est **seedé** (`random.seed(42)` dans `run_tournament`, #9434) : ces scores sont reproductibles a la re-execution. La différence entre Minimax et Alpha-Beta devrait etre nulle en theorie (même profondeur = même coups) ; le 6-0 d'Alpha-Beta sur Minimax suggere une différence d'ordonnancement des coups dans l'elagage. Avec 50+ parties (exercice 5), les win rates des duels équilibrés convergeraient vers ~50% pour Minimax vs Alpha-Beta.\n" - ] - }, - { - "cell_type": "markdown", - "id": "tournament-analysis", - "metadata": { - "papermill": { - "duration": 0.006642, - "end_time": "2026-08-17T13:04:15.339123+00:00", - "exception": false, - "start_time": "2026-08-17T13:04:15.332481+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Analyse du tournoi\n", - "\n", - "Les résultats du tournoi montrent la hiérarchie des algorithmes :\n", - "\n", - "1. **Alpha-Beta et Minimax** devraient dominer Random facilement\n", - "2. **Alpha-Beta vs Minimax** : résultats similaires (même qualite de jeu)\n", - "3. **MCTS** : Performance variable selon le nombre d'itérations\n", - "\n", - "> **Note** : Avec seulement 6 parties par match, les résultats peuvent varier.\n", - "> Pour une évaluation robuste, utiliser 50+ parties." - ] - }, - { - "cell_type": "markdown", - "id": "interpretation-section", - "metadata": { - "papermill": { - "duration": 0.01257, - "end_time": "2026-08-17T13:04:15.359102+00:00", - "exception": false, - "start_time": "2026-08-17T13:04:15.346532+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation des résultats\n", + "Points forts / faibles par algorithme :\n", "\n", "| Algorithme | Points forts | Points faibles | Usage recommande |\n", "|------------|--------------|----------------|------------------|\n", @@ -2286,9 +2243,9 @@ "**observations cles** :\n", "\n", "1. **Alpha-Beta** réduit drastiquement le nombre de noeuds (facteur 5-20x selon la profondeur)\n", - "2. **L'ordonnancement** des coups est crucial pour maximiser l'elagage\n", - "3. **MCTS** converge vers de bons coups sans fonction d'évaluation explicite\n", - "4. Pour un temps donne, Alpha-Beta profond bat souvent MCTS sur Connect Four" + "2. **MCTS** converge vers de bons coups sans fonction d'évaluation explicite\n", + "\n", + "> **Note technique** : Le tournoi est **seedé** (`random.seed(42)` dans `run_tournament`, #9434) : ces scores sont reproductibles a la re-execution. La différence entre Minimax et Alpha-Beta devrait etre nulle en theorie (même profondeur = même coups) ; le 6-0 d'Alpha-Beta sur Minimax suggere une différence d'ordonnancement des coups dans l'elagage. Avec 50+ parties (exercice 5), les win rates des duels équilibrés convergeraient vers ~50% pour Minimax vs Alpha-Beta." ] }, { diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-06-AdversarialSearch.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-06-AdversarialSearch.ipynb index e71f54ba76..37d57e27b1 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-06-AdversarialSearch.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-06-AdversarialSearch.ipynb @@ -538,34 +538,9 @@ "4. **Co^ut computationnel eleve** : Minimax explore tout l'arbre de jeu (mesure = runtime *machine-dep* sur ce Tic-Tac-Toe, cf section Alpha-Beta)\n", "5. **Optimalite garantie** : Minimax trouve toujours le meilleur coup possible\n", "\n", - "> **Note technique** : La valeur 0 indique que le jeu est \"resolu\" : avec un jeu parfait, les deux joueurs peuvent forcer le nul. Pour des jeux plus complexes (echecs, Go), la valeur initiale est inconnue et on utilise des heuristiques. La complexite O(b^m) devient rapidement impraticable : echecs = 35^100 noeuds !" - ] - }, - { - "cell_type": "markdown", - "id": "minimax-analysis", - "metadata": { - "id": "minimax-analysis", - "papermill": { - "duration": 0.00659, - "end_time": "2026-08-17T07:43:40.511188+00:00", - "exception": false, - "start_time": "2026-08-17T07:43:40.504598+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Analyse de complexite\n", - "\n", - "| Metrique | Valeur |\n", - "|----------|--------|\n", - "| **Complexite temporelle** | O(b^m) ou b = branching factor, m = profondeur max |\n", - "| **Complexite spatiale** | O(m) pour la pile de recursion |\n", - "\n", - "Pour le Tic-Tac-Toe : b = 9, m = 9, environ 9! = 362,880 noeuds.\n", + "**Complexite** : temporelle O(b^m) ou b = branching factor, m = profondeur max ; spatiale O(m) pour la pile de recursion. Pour le Tic-Tac-Toe : b = 9, m = 9, environ 9! = 362,880 noeuds. Pour les echecs : b ~ 35, m ~ 100, environ 35^100 noeuds (impossible !) -- la complexite O(b^m) devient rapidement impraticable.\n", "\n", - "Pour les echecs : b ~ 35, m ~ 100, environ 35^100 noeuds (impossible !)" + "> **Note technique** : La valeur 0 indique que le jeu est \"resolu\" : avec un jeu parfait, les deux joueurs peuvent forcer le nul. Pour des jeux plus complexes (echecs, Go), la valeur initiale est inconnue et on utilise des heuristiques." ] }, { diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond-CSharp.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond-CSharp.ipynb index 92e6a22a97..b2c581077c 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond-CSharp.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond-CSharp.ipynb @@ -277,15 +277,7 @@ "3. **Stabilite tardive** : a 5000 itérations, la valeur estimee MCTS est très proche de l'optimal (0).\n", "4. **Variabilite des actions** : les actions choisies varient selon le budget, montrant que le nombre d'itérations influence la stabilite du choix.\n", "\n", - "> **Note technique** : La valeur de Minimax (0) est exacte car l'algorithme explore tout l'arbre de jeu du Morpion. La valeur MCTS est une estimation probabiliste qui converge vers 0 avec plus d'itérations.\n" - ], - "id": "cell-961c0211" - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Analyse des résultats\n", + "La comparaison qualitative complete :\n", "\n", "| Critere | Minimax | MCTS |\n", "|---------|---------|------|\n", @@ -295,14 +287,16 @@ "| **Parallellisable** | Difficile | Très facile |\n", "| **Jeux a grand facteur de branchement** | Impraticable | Adapte |\n", "\n", - "### Quand utiliser MCTS ?\n", + "**Quand utiliser MCTS ?**\n", "\n", "- Jeux avec grand espace d'etat (Go, Hex)\n", "- Jeux sans bonne fonction d'evaluation\n", "- Situations avec contrainte de temps variable\n", - "- Jeux avec hasard (backgammon, poker)\n" + "- Jeux avec hasard (backgammon, poker)\n", + "\n", + "> **Note technique** : La valeur de Minimax (0) est exacte car l'algorithme explore tout l'arbre de jeu du Morpion. La valeur MCTS est une estimation probabiliste qui converge vers 0 avec plus d'itérations." ], - "id": "cell-6d1c1a6e" + "id": "cell-961c0211" }, { "cell_type": "markdown", diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb index b7daad159a..24905278c5 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb @@ -738,39 +738,24 @@ "3. **MCTS bruite et biaise vers le positif** : les valeurs MCTS (0.35-0.74) sont positives alors que la vraie valeur est 0. Ce biais ne s'attenuera pas avec le budget : meme a 5000 iterations, l'estimation reste autour de 0.5, parce que les rollouts aleatoires sont structurellement aveugles a l'equilibre du jeu (ils avantagent le premier joueur). MCTS echange donc l'exactitude contre la vitesse -- son estimation est bruitee, elle ne converge pas vers la valeur theorique.\n", "4. **Bons coups** : a tous les budgets, MCTS choisit un coin ou le centre -- les bons premiers coups au Morpion.\n", "\n", - "> **Note sur le hasard** : MCTS etant stochastique, les valeurs et l'action exacte varieraient d'une execution a l'autre sans graine ; `random.seed(42)` les fige pour la reproductibilite. Les conclusions qualitatives (vitesse massive, biais positif persistant, bons coups) sont stables.\n" - ] - }, - { - "cell_type": "markdown", - "id": "mcts-analysis-section", - "metadata": { - "papermill": { - "duration": 0.007192, - "end_time": "2026-09-26T15:15:46.727144+00:00", - "exception": false, - "start_time": "2026-09-26T15:15:46.719952+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Analyse des résultats\n", + "La comparaison qualitative complete :\n", "\n", "| Critere | Minimax | MCTS |\n", "|---------|---------|------|\n", "| **Garantie d'optimalite** | Oui (si arbre complet) | Non (probabiliste) |\n", "| **Fonction d'evaluation** | Necessaire | Non necessaire |\n", - "| **Complexite** | O(b^d) | O(n * d) ou n = itérations |\n", - "| **Parallellisable** | Difficile | très facile |\n", - "| **Jeux a grand facteur de branchement** | Impraticable | Adapté |\n", + "| **Complexite** | O(b^d) | O(n * d) ou n = iterations |\n", + "| **Parallellisable** | Difficile | tres facile |\n", + "| **Jeux a grand facteur de branchement** | Impraticable | Adapte |\n", "\n", - "### Quand utiliser MCTS ?\n", + "**Quand utiliser MCTS ?**\n", "\n", "- Jeux avec grand espace d'etat (Go, Hex)\n", "- Jeux sans bonne fonction d'evaluation\n", "- Situations avec contrainte de temps variable\n", - "- Jeux avec hasard (backgammon, poker)" + "- Jeux avec hasard (backgammon, poker)\n", + "\n", + "> **Note sur le hasard** : MCTS etant stochastique, les valeurs et l'action exacte varieraient d'une execution a l'autre sans graine ; `random.seed(42)` les fige pour la reproductibilite. Les conclusions qualitatives (vitesse massive, biais positif persistant, bons coups) sont stables." ] }, { diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-11b-Metaheuristiques-Deep.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-11b-Metaheuristiques-Deep.ipynb index 5f472309c5..bf01f3745d 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-11b-Metaheuristiques-Deep.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-11b-Metaheuristiques-Deep.ipynb @@ -481,24 +481,9 @@ "id": "e9c3bfb9", "metadata": {}, "source": [ - "**Lecture chiffree — la convergence Ackley se lit par paliers.** Les 9 lignes rendues (paliers 0 a 200, tous les 25) racontent la trajectoire : `best f = 10,770053` au depart, `0,292674` des le palier 25 — le meilleur est divise par environ 37 en un quart de course. Puis deux geleurs : `0,064659` tient les paliers 75, 100 et 125 (trois lignes identiques), casse a `0,038244` au palier 150 et ne bouge plus jusqu'a 200 — l'exploitation finale apres l'exploration, exactement le scenario Metropolis. Le point final `(-0,0001, -0,0121)` porte sa distance a l'origine (0,012136) presque entierement sur la seconde coordonnee : sur les valeurs affichees, 0,0121 / 0,0001 = 121. Et la sanity Sphere se verifie par carres : le meilleur f rendu `0,000043` est bien la somme 0,0050^2 + 0,0042^2 — la fonction objective est ce qu'elle dit etre.\n" - ] - }, - { - "cell_type": "markdown", - "id": "s11c12", - "metadata": { - "papermill": { - "duration": 0.002166, - "end_time": "2026-07-06T02:32:44.052141", - "exception": false, - "start_time": "2026-07-06T02:32:44.049975", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation : Ackley — SA vs descente pure\n", + "### Lecture : Ackley — la convergence par paliers, SA contre descente pure\n", + "\n", + "**Lecture chiffree.** Les paliers rendus (paliers 0 a 200, tous les 25) racontent la trajectoire : `best f = 10,770053` au depart, `0,292674` des le palier 25 — le meilleur est divise par environ 37 en un quart de course. Puis deux geleurs : `0,064659` tient les paliers 75, 100 et 125 (trois lignes identiques), casse a `0,038244` au palier 150 et ne bouge plus jusqu'a 200 — l'exploitation finale apres l'exploration, exactement le scenario Metropolis. Le point final `(-0,0001, -0,0121)` porte sa distance a l'origine (0,012136) presque entierement sur la seconde coordonnee : sur les valeurs affichees, 0,0121 / 0,0001 = 121. Et la sanity Sphere se verifie par carres : le meilleur f rendu `0,000043` est bien la somme 0,0050^2 + 0,0042^2 — la fonction objective est ce qu'elle dit etre.\n", "\n", "Ackley est le test discriminant : son paysage est parsemé d'optima locaux, et seul $\\mathbf{0}$ est le minimum global. Une **descente pure** (hill-climbing greedy) s'arrête au premier optimum local rencontré — typiquement $f \\approx 2$ à $6$, jamais $0$.\n", "\n", diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-12a-Composer-Regards.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-12a-Composer-Regards.ipynb index 8ae09a98bb..6d55672757 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-12a-Composer-Regards.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-12a-Composer-Regards.ipynb @@ -290,24 +290,9 @@ "id": "ba1f8ab5", "metadata": {}, "source": [ - "**Lecture chiffree — le corridor se ferme arithmetiquement.** `corridor f* == OPT : 19 noeuds sur 140 (14% de la grille)`. Ou viennent ces 19 exactement ? La convention de paiement — lisible dans le A* de la section 5 (`g + COST[v[0]][v[1]] + h.get(v, 0)`) et dans `route_cost` (`sum(COST[r][c] for r, c in path[1:])`) — paie une cellule quand on y ENTRE ; depart et arrivee sont forces en plaine (`COST[0][0], COST[H - 1][W - 1] = PLAIN, PLAIN`). Il suit que f*(n) = OPT + cout(n) - 1 : le compose egale OPT exactement sur les cellules de plaine des routes optimales. Et les nombres se referment : la route paie 22 cellules = 18 plaines + 4 forets (18 x 1 + 4 x 3 = 30 = OPT), et 18 + le depart non paye = 19 = le corridor compte. Chaque chiffre de la sortie se recoupe par une voie independante — c'est le test que la lecture est juste.\n" - ] - }, - { - "cell_type": "markdown", - "id": "6736e693", - "metadata": { - "papermill": { - "duration": 0.003139, - "end_time": "2026-09-16T15:11:02.932006", - "exception": false, - "start_time": "2026-09-16T15:11:02.928867", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture\n", + "### Lecture : le corridor — la fermeture arithmetique, puis le contenu informationnel\n", + "\n", + "`corridor f* == OPT : 19 noeuds sur 140 (14% de la grille)`. Ou viennent ces 19 exactement ? La convention de paiement — lisible dans le A* de la section 5 (`g + COST[v[0]][v[1]] + h.get(v, 0)`) et dans `route_cost` (`sum(COST[r][c] for r, c in path[1:])`) — paie une cellule quand on y ENTRE ; depart et arrivee sont forces en plaine (`COST[0][0], COST[H - 1][W - 1] = PLAIN, PLAIN`). Il suit que f*(n) = OPT + cout(n) - 1 : le compose egale OPT exactement sur les cellules de plaine des routes optimales. Et les nombres se referment : la route paie cellules = 18 plaines + 4 forets (18 x 1 + 4 x 3 = 30 = OPT), et 18 + le depart non paye = 19 = le corridor compte. Chaque chiffre de la sortie se recoupe par une voie independante — c'est le test que la lecture est juste.\n", "\n", "La loi tient (`f* >= OPT` partout) et l'égalité sélectionne exactement le corridor : **19 noeuds sur 140 (14 % de la grille)**. C'est le contenu informationnel de la composition : ni `g` seule (qui ne sait rien de l'arrivée) ni `d` seule (qui ne sait rien du départ) ne peut isoler ces 19 noeuds — leur somme le fait, parce qu'un noeud est sur une route optimale **ssi les deux lectures le confirment ensemble**. Le Dijkstra uni-directionnel, lui, doit sortir les 140 noeuds pour garantir son optimum : la composition achève la focalisation que chaque lecture ne faisait qu'ébaucher." ] @@ -401,7 +386,7 @@ "source": [ "### Lecture\n", "\n", - "Deux lois distinctes, mesurées. **Associativité : vraie dans les deux groupements** (`assoc. True`) — propriété de l'opérateur (addition de tronçons), indépendante du terrain. **Exactitude : conditionnelle.** Pour `n = (2, 1)`, relais et noeud sur la route optimale : chaîné 27 == direct 27, écart 0. Pour `n = (3, 4)`, hors route : chaîné 33 contre direct 31 — **surestimation stricte de +2**, l'inégalité triangulaire qui mord. Composer des lectures cohérentes ne sous-estime jamais ; mais l'estimé chaîné ne dit la vérité **que** quand les relais sont posés là où les lectures se croisent — sur une route optimale." + "Deux lois distinctes, mesurées. **Associativité : vraie dans les deux groupements** (`assoc. True` sur les deux lignes) — propriété de l'opérateur (addition de tronçons), indépendante du terrain. **Exactitude : conditionnelle.** Pour `n = (2, 1)`, relais et noeud sur la route optimale : chaîné 27 == direct 27, écart 0. Pour `n = (3, 4)`, hors route : chaîné 33 contre direct 31 — **surestimation stricte de +2**, l'inégalité triangulaire qui mord. Composer des lectures cohérentes ne sous-estime jamais ; mais l'estimé chaîné ne dit la vérité **que** quand les relais sont posés là où les lectures se croisent — sur une route optimale." ] }, { @@ -499,26 +484,11 @@ "id": "75cff95d", "metadata": {}, "source": [ - "**Lecture chiffree — trois regimes d'expansion, deux gloutons de meme longueur.** `A* lecture exacte : 24 expansions | A* lecture pas : 75 expansions` et, au-dessus, `glouton guide par la lecture COUT : 22 pas, cout 30` contre `glouton guide par la lecture PAS` — 22 pas, cout 62. Les deux gloutons font 22 pas — l'optimum en PAS tous les deux — mais le cout par pas passe de 30/22 ~ 1,4 a 62/22 ~ 2,8 : optimal en pas ne dit rien du cout, facteur ~2,1 sur la facture. Cote recherche informee, la meme grille se paie 140 expansions (Dijkstra sans guide, section 2), 75 (A* guide en pas) ou 24 (A* guide exact) : l'information du guide vaut un facteur ~5,8 contre le guide aveugle et ~3,1 contre le guide mal informe — et ces trois nombres ne mesurent qu'une chose, la QUALITE de la lecture arriere branchee dans f.\n" - ] - }, - { - "cell_type": "markdown", - "id": "d56e6444", - "metadata": { - "papermill": { - "duration": 0.002547, - "end_time": "2026-09-16T15:11:02.996351", - "exception": false, - "start_time": "2026-09-16T15:11:02.993804", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture\n", + "### Lecture : trois regimes d'expansion, deux gloutons de meme longueur\n", + "\n", + "`A* lecture exacte : 24 expansions | A* lecture pas : 75 expansions` et, au-dessus, `glouton guide par la lecture COUT : 22 pas, cout 30` contre `glouton guide par la lecture PAS` — 22 pas, cout 62. Les deux gloutons font 22 pas — l'optimum en PAS tous les deux — mais le cout par pas passe de 30/22 ~ 1,4 a 62/22 ~ 2,8 : optimal en pas ne dit rien du cout, facteur ~2,1 sur la facture. Cote recherche informee, la meme grille se paie 140 expansions (Dijkstra sans guide, section 2), 75 (A* guide en pas) ou 24 (A* guide exact) : l'information du guide vaut un facteur ~5,8 contre le guide aveugle et ~3,1 contre le guide mal informe — et ces trois nombres ne mesurent qu'une chose, la QUALITE de la lecture arriere branchee dans f.\n", "\n", - "La paire incompatible a un témoin chirurgical : **dès le premier pas**, la lecture coût envoie en `(0, 1)` — l'entrée du corridor bon marché — et la lecture pas en `(1, 0)` — la diagonale courte. Les deux gloutons font 22 pas ; celui guidé par le coût paie OPT = 30, celui guidé par les pas paie **62 (+32, plus du double)**. Le point fin : `h_pas` reste *admissible* (un pas coûte au moins 1, donc compter les pas ne surestime jamais un coût) — l'A* pondéré par les pas trouve encore l'optimum, mais en **75 expansions contre 24** pour la lecture exacte : admissible, mal informée. Ce que la paire incompatible perd n'est pas la correction de l'algorithme, c'est la **sémantique du composé** : `g + h_pas` n'est plus le coût d'aucune route réelle — l'unité du guide a changé sous lui, et le glouton, qui n'a pas de file ouverte pour se corriger, paie l'écart en plein." + "La paire incompatible a un témoin chirurgical : **dès le premier pas**, la lecture coût envoie en `(0, 1)` — l'entrée du corridor bon marché — et la lecture pas envoie en `(1, 0)` — la diagonale courte. Les deux gloutons font 22 pas ; celui guidé par le coût paie OPT = 30, celui guidé par les pas paie **62 (+32, plus du double)**. Le point fin : `h_pas` reste *admissible* (un pas coûte au moins 1, donc compter les pas ne surestime jamais un coût) — l'A* pondéré par les pas trouve encore l'optimum, mais en **75 expansions contre 24** pour la lecture exacte : admissible, mal informée. Ce que la paire incompatible perd n'est pas la correction de l'algorithme, c'est la **sémantique du composé** : `g + h_pas` n'est plus le coût d'aucune route réelle — l'unité du guide a changé sous lui, et le glouton, qui n'a pas de file ouverte pour se corriger, paie l'écart en plein." ] }, { @@ -767,7 +737,7 @@ "id": "7c829ee8", "metadata": {}, "source": [ - "**Lecture chiffree — les trois exercices relus comme des reprises de regimes mesures.** Les stubs C.1 s'executent sans erreur, le notebook est livrable completable. Mais le programme cache est dans les indices : `inflate` demande le balayage epsilon de A* pondere — exactement le regime 24-contre-75 expansions de la section 5, ou l'on cherchera le seuil ou l'optimalite casse ; `regard_projete` construit une lecture arriere par relaxation (projection 1D) — le cas limite du guide admissible-mal-informe, lui aussi deja chiffrable ; `metrique_unifiee` force toutes les cellules a cout 1 et rejoue les deux gloutons — la paire incompatible de la section 5 rendue compatible par changement de METRIQUE, ou l'egalite 22 pas = 22 pas devra cette fois couter le meme prix. Trois exercices, trois phenomenes du corps du notebook : les completer, c'est reproduire, pas decouvrir autre chose.\n" + "**Lecture chiffree — les trois exercices relus comme des reprises de regimes mesures.** `Exercice a completer` trois fois, `execution_count` 7-9 contigus : les stubs C.1 s'executent sans erreur, le notebook est livrable completable. Mais le programme cache est dans les indices : `inflate` demande le balayage epsilon de A* pondere — exactement le regime 24-contre-75 expansions de la section 5, ou l'on cherchera le seuil ou l'optimalite casse ; `regard_projete` construit une lecture arriere par relaxation (projection 1D) — le cas limite du guide admissible-mal-informe, lui aussi deja chiffrable ; `metrique_unifiee` force toutes les cellules a cout 1 et rejoue les deux gloutons — la paire incompatible de la section 5 rendue compatible par changement de METRIQUE, ou l'egalite 22 pas = 22 pas devra cette fois couter le meme prix. Trois exercices, trois phenomenes du corps du notebook : les completer, c'est reproduire, pas decouvrir autre chose.\n" ] }, { diff --git a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals.ipynb b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals.ipynb index 50e4b6d6be..7edc121f78 100644 --- a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals.ipynb +++ b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-1-Fundamentals.ipynb @@ -970,34 +970,6 @@ "print(f\"Assignations tentees : {small_csp.n_assigns}\")" ] }, - { - "cell_type": "markdown", - "id": "bdb687f0", - "metadata": { - "papermill": { - "duration": 0.010157, - "end_time": "2026-07-11T14:28:39.762489+00:00", - "exception": false, - "start_time": "2026-07-11T14:28:39.752332+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation : trace du backtracking\n", - "\n", - "La trace montre le processus de décision pas à pas :\n", - "\n", - "1. L'algorithme assigne une valeur à la première variable\n", - "2. Il détecte les conflits immédiatement grâce à la vérification de consistance\n", - "3. Quand un conflit survient sur toutes les valeurs, il revient en arrière (backtrack)\n", - "\n", - "**Observations** :\n", - "- Les conflits sont détectés **dès l'assignation**, pas à la fin\n", - "- Le \"backtrack\" est visible dans la trace par les retours en arrière\n", - "- L'indentation montre la profondeur de recursion" - ] - }, { "cell_type": "markdown", "id": "c121csp1-trace-zero-backtrack", @@ -1289,39 +1261,11 @@ "\n", "La sortie chiffre l'arbre : `Nombre de noeuds explores : 11` et `Nombre de valeurs rejetees : 4`. La différence 11 - 4 = 7 redonne exactement les sept variables du problème : chaque noeud est soit une assignation retenue (7), soit une valeur rejetée à la volée (4). Chaque rejet correspond à un conflit détecté par `consistent()` avant toute récursion — ce sont des branches coupées à la naissance, jamais explorées.\n", "\n", - "Le rapprochement le plus instructif est cross-cellule : le backtracking simple de la section 4 affichait lui aussi 11 assignations, et sa solution était `{'WA': 'Rouge', 'NT': 'Vert', 'SA': 'Bleu', ...}`. En renommant R en Rouge, G en Vert et B en Bleu, la solution imprimée ici (`{'WA': 'R', 'NT': 'G', 'SA': 'B', ...}`) est la coloration identique. Deux implémentations indépendantes — avec et sans instrumentation visuelle — parcourent la même trajectoire parce qu'elles partagent le même ordre naïf des variables et des valeurs : l'instrumentation n'a pas perturbé la recherche, ce qui valide la visualisation comme fidèle au calcul.\n", - "\n", - "Remarque d'échelle : le dessin est limité à `max_depth=4` pour la lisibilité, mais les compteurs (11 noeuds, 4 rejets) couvrent la recherche complète, pas seulement la portion dessinée.\n" - ] - }, - { - "cell_type": "markdown", - "id": "tgyto74w32o", - "metadata": { - "papermill": { - "duration": 0.010322, - "end_time": "2026-07-11T14:28:40.102435+00:00", - "exception": false, - "start_time": "2026-07-11T14:28:40.092113+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation de la visualisation\n", - "\n", - "L'arbre de recherche montre :\n", - "\n", - "- **Noeuds verts** : Assignations réussies (la valeur est cohérente avec l'assignation partielle)\n", - "- **Noeuds rouges** : Assignations échouées (conflit détecté immédiatement)\n", - "- **Profondeur** : Correspond au nombre de variables assignées\n", - "- **Largeur** : Correspond aux différentes valeurs essayees pour chaque variable\n", + "Clé de lecture de l'arbre : **noeuds verts** = assignations réussies (la valeur est cohérente avec l'assignation partielle), **noeuds rouges** = assignations échouées (conflit détecté immédiatement), **profondeur** = nombre de variables assignées, **largeur** = valeurs essayées pour chaque variable. L'élagage est visible : les branches rouges sont coupées dès qu'un conflit est détecté.\n", "\n", - "**Observations clés** :\n", + "Le rapprochement le plus instructif est cross-cellule : le backtracking simple de la section 4 affichait lui aussi 11 assignations, et sa solution était `{'WA': 'Rouge', 'NT': 'Vert', 'SA': 'Bleu', ...}`. En renommant R en Rouge, G en Vert et B en Bleu, la solution imprimée ici (`{'WA': 'R', 'NT': 'G', 'SA': 'B', ...}`) est la coloration identique. Deux implémentations indépendantes — avec et sans instrumentation visuelle — parcourent la même trajectoire parce qu'elles partagent le même ordre naïf des variables et des valeurs : l'instrumentation n'a pas perturbé la recherche, ce qui valide la visualisation comme fidèle au calcul.\n", "\n", - "1. L'élagage est visible : les branches rouges sont coupées dès qu'un conflit est détecté\n", - "2. Le backtrack se produit quand toutes les valeurs d'une variable echouent\n", - "3. L'ordre des variables influence la forme de l'arbre (variables a petit domaine en premier = arbre plus etroit)\n" + "Remarque d'échelle : le dessin est limité à `max_depth=4` pour la lisibilité, mais les compteurs (11 noeuds, 4 rejets) couvrent la recherche complète, pas seulement la portion dessinée." ] }, { @@ -1981,26 +1925,7 @@ "\n", "Deux vérifications arithmétiques sur les valeurs : les huit lignes {0, 4, 7, 5, 1, 2, 6, 3} sont exactement les entiers de 0 à 7, tous distincts — une reine par ligne, par construction du modèle (une variable par colonne) — et la ligne de vérification conclut `VALIDE`, diagonales incluses.\n", "\n", - "Mise en perspective : 677 assignations face à l'espace brut 8^8 = 16 777 216, soit environ 4 dix-millièmes de l'espace visité (un facteur de réduction d'environ 24 800). Le temps `3.37 ms` est une mesure machine-dépendante sur un seul passage, non moyennée : c'est le compte d'assignations, structurel, qui fait foi.\n" - ] - }, - { - "cell_type": "markdown", - "id": "39daf9c3", - "metadata": { - "papermill": { - "duration": 0.009566, - "end_time": "2026-07-11T14:28:40.876442+00:00", - "exception": false, - "start_time": "2026-07-11T14:28:40.866876+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation : 8-Reines\n", - "\n", - "**Sortie obtenue** : le backtracking avec MRV + LCV résout les 8-Reines en 677 assignations.\n", + "La comparaison des variantes se lit sur le même compte d'assignations :\n", "\n", "| Mesure | Valeur |\n", "|--------|--------|\n", @@ -2009,10 +1934,7 @@ "| + MRV | 572 assignations |\n", "| + MRV + LCV | 677 assignations |\n", "\n", - "**Points clés** :\n", - "1. L'echiquier montre qu'aucune reine n'est sur la même ligne, colonne ou diagonale\n", - "2. La modélisation CSP (une variable par colonne) résout le problème en ~$10^3$ assignations au lieu des $16{,}8$ millions de l'espace brut\n", - "3. MRV (876 -> 572) réduit nettement le compte ; en revanche, ajouter LCV le remonte à 677 : l'ordonnancement des valeurs par LCV est ici moins favorable que l'ordre naïf combiné à MRV -- c'est un effet connu, l'ordonnancement des valeurs étant moins robuste que celui des variables" + "MRV (876 -> 572) réduit nettement le compte ; en revanche, ajouter LCV le remonte à 677 : l'ordonnancement des valeurs par LCV est ici moins favorable que l'ordre naïf combiné à MRV -- c'est un effet connu, l'ordonnancement des valeurs étant moins robuste que celui des variables. Mise en perspective : 677 assignations face à l'espace brut, soit environ 4 dix-millièmes de l'espace visité (un facteur de réduction d'environ 24 800). Le temps `3.37 ms` est une mesure machine-dépendante sur un seul passage, non moyennée : c'est le compte d'assignations, structurel, qui fait foi." ] }, { @@ -2373,9 +2295,13 @@ "tags": [] }, "source": [ - "### Interprétation : python-constraint vs implémentation manuelle\n", + "### Lecture croisée : premières solutions différentes, compte identique\n", + "\n", + "La solution renvoyée ici commence par `{'SA': 'Bleu', 'NSW': 'Vert', 'Q': 'Rouge', ...}` — un ordre de clés et une coloration qui diffèrent du backtracking manuel (WA en premier, T = Rouge) : la bibliothèque attribue ici T = Bleu. Aucune incohérence : chaque solveur visite l'espace dans son propre ordre, et la première solution rencontrée dépend de cet ordre. Sur un problème à solutions multiples, comparer des premiers résultats n'a de sens qu'à parcours fixe ; seuls les comptes exhaustifs sont comparables.\n", + "\n", + "La grandeur qui doit coïncider coïncide : `Nombre total de solutions : 18`, exactement les 18 solutions comptées par la brute force en section 4. Deux moteurs indépendants, un même espace de solutions — la vérification croisée la plus forte disponible sur ce problème.\n", "\n", - "**Sortie obtenue** : la bibliothèque trouve rapidement une solution et peut énumérer toutes les solutions.\n", + "Le reste de la comparaison est d'ordre d'API, pas de résultat :\n", "\n", "| Aspect | Implémentation manuelle | python-constraint |\n", "|--------|------------------------|-------------------|\n", @@ -2384,24 +2310,7 @@ "| Contraintes prédéfinies | À coder soi-même | `AllDifferentConstraint`, etc. |\n", "| Pedagogie | Comprendre les mécanismes | Utiliser en production |\n", "\n", - "**Points clés** :\n", - "1. La bibliothèque abstrait les détails d'implémentation (backtracking, heuristiques)\n", - "2. `getSolutions()` énumère exhaustivement toutes les solutions valides\n", - "3. L'API déclarative est plus lisible et moins sujette aux erreurs" - ] - }, - { - "cell_type": "markdown", - "id": "c152csp1-parite-18", - "metadata": {}, - "source": [ - "### Lecture croisée : premières solutions différentes, compte identique\n", - "\n", - "La solution renvoyée ici commence par `{'SA': 'Bleu', 'NSW': 'Vert', 'Q': 'Rouge', ...}` — un ordre de clés et une coloration qui diffèrent du backtracking manuel (WA en premier, T = Rouge) : la bibliothèque attribue ici T = Bleu. Aucune incohérence : chaque solveur visite l'espace dans son propre ordre, et la première solution rencontrée dépend de cet ordre. Sur un problème à solutions multiples, comparer des premiers résultats n'a de sens qu'à parcours fixe ; seuls les comptes exhaustifs sont comparables.\n", - "\n", - "La grandeur qui doit coïncider coïncide : `Nombre total de solutions : 18`, exactement les 18 solutions comptées par la brute force en section 4. Deux moteurs indépendants, un même espace de solutions — la vérification croisée la plus forte disponible sur ce problème.\n", - "\n", - "Côté coûts, honnêtement : les temps imprimés (`0.11 ms` pour la première solution, `0.26 ms` pour les 18) sont machine-dépendants et non moyennés. Surtout, le solveur interne de la bibliothèque n'est pas instrumenté ici : contrairement à notre classe CSP, aucun compteur d'assignations n'est exposé. On ne sait donc pas combien d'essais internes coûtent ces 0,26 ms — la comparaison avec le backtracking manuel (11 assignations chiffrées) reste asymétrique.\n" + "Côté coûts, honnêtement : les temps imprimés (`0.11 ms` pour la première solution, `0.26 ms` pour les 18) sont machine-dépendants et non moyennés. Surtout, le solveur interne de la bibliothèque n'est pas instrumenté ici : contrairement à notre classe CSP, aucun compteur d'assignations n'est exposé. On ne sait donc pas combien d'essais internes coûtent ces 0,26 ms — la comparaison avec le backtracking manuel (11 assignations chiffrées) reste asymétrique." ] }, { @@ -2626,37 +2535,7 @@ "\n", "Pourquoi seulement deux ? L'espace brut est 4^4 = 256 placements ; les contraintes de ligne et de diagonale, imposées paire à paire dans le modèle, ne laissent que ces deux placements valides. Les damiers imprimés le confirment visuellement : aucune paire de reines ne partage une ligne, une colonne ou une diagonale.\n", "\n", - "Généralisation sûre : le miroir d'une solution est toujours une solution (les contraintes sont invariantes par réflexion), donc les solutions vont par paires miroirs — un comptage impair serait suspect a posteriori. Le temps `0.16 ms` est machine-dépendant, un seul passage ; la grandeur structurelle est le compte : 2.\n" - ] - }, - { - "cell_type": "markdown", - "id": "feb7518b", - "metadata": { - "papermill": { - "duration": 0.010835, - "end_time": "2026-07-11T14:28:45.391775+00:00", - "exception": false, - "start_time": "2026-07-11T14:28:45.380940+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Interprétation : 4-Reines avec la bibliothèque\n", - "\n", - "**Sortie obtenue** : le problème des 4-Reines a exactement 2 solutions (symetriques l'une de l'autre).\n", - "\n", - "| Aspect | Valeur |\n", - "|--------|--------|\n", - "| Solutions | 2 (symetrie miroir) |\n", - "| Espace brut | $4^4 = 256$ |\n", - "| Code | plus court qu'en manuel |\n", - "\n", - "**Points clés** :\n", - "1. La bibliothèque gère automatiquement le backtracking et les heuristiques\n", - "2. `getSolutions()` retourne la liste exhaustive des solutions\n", - "3. En production, on préfère utiliser une bibliothèque pour gagner en fiabilité et en temps de développement\n", + "Généralisation sûre : le miroir d'une solution est toujours une solution (les contraintes sont invariantes par réflexion), donc les solutions vont par paires miroirs — un comptage impair serait suspect a posteriori. Le temps `0.16 ms` est machine-dépendant, un seul passage ; la grandeur structurelle est le compte : 2.\n", "\n", "> **Quand utiliser quoi ?** Implémentation manuelle pour **apprendre** les mécanismes. Bibliothèque pour **résoudre** des problèmes réels." ] @@ -2786,24 +2665,14 @@ "cell_type": "markdown", "id": "a735ed14", "metadata": {}, - "source": [ - "### Lecture du resultat : Choco sur l'Australie\n", - "\n", - "**Sortie obtenue** : Choco trouve une coloration valide par propagation de contraintes (pas d'enumeration aveugle). Le temps en ms affiche est une mesure *machine-dep* en sortie live de la cellule ci-dessus -- regle #9434, non fige en prose. On peut le comparer au temps d'enumeration de la cellule brute-force de la section 4 : la propagation evite d'explorer les 2187 combinaisons.\n" - ] - }, - { - "cell_type": "markdown", - "id": "c162csp1-meme-coloriage", - "metadata": {}, "source": [ "### Lecture : le même coloriage que le backtracking naïf, par un chemin différent\n", "\n", "La sortie imprime chaque région avec sa valeur interne et son nom : `WA = Rouge (0)`, `NT = Vert (1)`, `SA = Bleu (2)`, etc. Ces annotations révèlent l'encodage du modèle Choco — des IntVar sur {0, 1, 2} — le mapping vers les noms de couleurs n'étant qu'une couche d'affichage ajoutée pour la lisibilité.\n", "\n", - "Le fait saillant est cross-cellule : cette coloration est exactement celle du backtracking manuel de la section 4 (WA Rouge, NT Vert, SA Bleu, Q Rouge, NSW Vert, V Rouge, T Rouge). Or les deux moteurs n'ont rien de commun ici : notre backtracking explore dans l'ordre naïf des variables avec vérification d'assignation au coup par coup, Choco résout par propagation de contraintes sur les domaines. Deux mécanismes différents qui convergent sur la même première solution. Sur une instance petite et fortement contrainte cette convergence est plausible mais n'est pas une garantie : le solveur python-constraint, lui, avait renvoyé une première solution différente (T = Bleu). L'ordre de parcours reste spécifique à chaque moteur.\n", + "Le fait saillant est cross-cellule : cette coloration est exactement celle du backtracking manuel de la section 4 (WA Rouge, NT Vert, SA Bleu, Q Rouge, NSW Vert, V Rouge, T Rouge). Or les deux moteurs n'ont rien de commun ici : notre backtracking explore dans l'ordre naïf des variables avec vérification d'assignation au coup par coup, Choco résout par propagation de contraintes sur les domaines — la propagation évite d'explorer les 2187 combinaisons que parcourait la brute force de la section 4. Deux mécanismes différents qui convergent sur la même première solution. Sur une instance petite et fortement contrainte cette convergence est plausible mais n'est pas une garantie : le solveur python-constraint, lui, avait renvoyé une première solution différente (T = Bleu). L'ordre de parcours reste spécifique à chaque moteur.\n", "\n", - "Vérifications locales sur le résultat imprimé : WA (Rouge) et NT (Vert), adjacents, diffèrent ; SA (Bleu) diffère de ses cinq voisins affichés (WA Rouge, NT Vert, Q Rouge, NSW Vert, V Rouge). Le temps `0.23 ms` est machine-dépendant, un seul passage.\n" + "Vérifications locales sur le résultat imprimé : WA (Rouge) et NT (Vert), adjacents, diffèrent ; SA (Bleu) diffère de ses cinq voisins affichés (WA Rouge, NT Vert, Q Rouge, NSW Vert, V Rouge). Le temps `0.23 ms` est machine-dépendant, un seul passage." ] }, { @@ -2877,16 +2746,6 @@ "cell_type": "markdown", "id": "693c77ef", "metadata": {}, - "source": [ - "### Lecture du resultat : enumeration exhaustive\n", - "\n", - "**Sortie obtenue** : **18 solutions** au total -- exactement le compte de la brute force de la section 4 **et** celui du jumeau C# avec Choco via IKVM. Les trois moteurs (enumeration manuelle, Choco/IKVM cote .NET, Choco/pychoco cote Python) enumerent le meme espace de solutions : la parite lib-vs-lib est verifiee sur une grandeur observable, pas seulement sur l'API.\n" - ] - }, - { - "cell_type": "markdown", - "id": "c165csp1-decomposition-18", - "metadata": {}, "source": [ "### Lecture : décomposer les 18 solutions en 6 coloriages continentaux x 3\n", "\n", @@ -2896,7 +2755,7 @@ "\n", "Honnêtement, ce qui n'est pas démontré ici : l'existence d'exactement 6 coloriages continentaux. Les cinq solutions échantillonnées n'en couvrent que 2 ; les quatre autres sont inférées du total (18 / 3), pas affichées. L'égalité 18 = 6 x 3 est une cohérence arithmétique, pas une énumération complète du continent — la vérifier pleinement exigerait d'énumérer les 18 et de dédupliquer selon T, ce que la sortie ne fait pas.\n", "\n", - "Troisième moteur, même total : ce 18 égale celui de la brute force (section 4) et celui de python-constraint (section 6) — la parité tient sur le compte exact.\n" + "Trois moteurs, même total : ce 18 égale celui de la brute force (section 4), celui de python-constraint (section 6) **et** celui du jumeau C# avec Choco via IKVM. Les trois moteurs énumèrent le même espace de solutions : la parité lib-vs-lib est vérifiée sur une grandeur observable, pas seulement sur l'API." ] }, { @@ -2984,23 +2843,13 @@ "source": [ "### Lecture : vérifier l'échiquier ASCII à partir du mapping imprimé\n", "\n", - "La sortie donne d'abord le mapping colonne -> ligne : `0->4, 1->6, 2->1, 3->5, 4->2, 5->0, 6->7, 7->3`. Les huit valeurs {4, 6, 1, 5, 2, 0, 7, 3} sont exactement les entiers de 0 à 7 sans doublon : une reine par colonne et une par ligne, condition portée par la contrainte globale `all_different` du modèle.\n", + "La sortie donne d'abord le mapping colonne -> ligne : `0->4, 1->6, 2->1, 3->5, 4->2, 5->0, 6->7, 7->3`. Les huit valeurs {4, 6, 1, 5, 2, 0, 7, 3} sont exactement les entiers de 0 à 7 sans doublon : une reine par colonne et une par ligne, condition portée par la contrainte globale `all_different` du modèle — elle remplace la paire de boucles `!=` du modèle manuel, la propagation native du solveur prune l'espace.\n", "\n", "L'échiquier ASCII se relit avec ce mapping : la ligne `Ligne 7` porte son Q en colonne 6 (conforme à 6->7), la ligne 6 en colonne 1 (1->6), la ligne 5 en colonne 3 (3->5), et ainsi de suite jusqu'à la ligne 0 en colonne 5 (5->0). Grille et mapping sont cohérents ligne à ligne — huit Q au total, un par ligne affichée.\n", "\n", - "Pour les diagonales, trois couples vérifiés à la main sur le mapping : colonnes 0 et 4 (écart de colonnes 4, écart de lignes |4 - 2| = 2), colonnes 1 et 5 (4 contre |6 - 0| = 6), colonnes 3 et 7 (4 contre |5 - 3| = 2) — aucune paire en prise. Point d'honnêteté : cette cellule n'imprime pas de ligne `VALIDE`, contrairement aux cellules du backtracking manuel qui appelaient `is_solution()`. La validité complète exigerait les 28 paires de colonnes ; les trois sondages ci-dessus ne constituent pas une preuve — celle-ci repose sur la correction de la construction du modèle (all_different + contraintes diagonales scalaires). Le temps `1.41 ms` reste machine-dépendant, un seul passage.\n" - ] - }, - { - "cell_type": "markdown", - "id": "ca6c8261", - "metadata": {}, - "source": [ - "### Lecture du resultat : 8-Reines avec Choco\n", - "\n", - "**Sortie obtenue** : une solution valide des 8-Reines, quasi instantanee (temps en ms en sortie live de la cellule ci-dessus). La contrainte globale `all_different` remplace la paire de boucles `!=` du modele manuel -- c'est la propagation native du solveur qui prune l'espace.\n", + "Pour les diagonales, trois couples vérifiés à la main sur le mapping : colonnes 0 et 4 (écart de colonnes 4, écart de lignes |4 - 2| = 2), colonnes 1 et 5 (4 contre |6 - 0| = 6), colonnes 3 et 7 (4 contre |5 - 3| = 2) — aucune paire en prise. Point d'honnêteté : cette cellule n'imprime pas de ligne `VALIDE`, contrairement aux cellules du backtracking manuel qui appelaient `is_solution()`. La validité complète exigerait les 28 paires de colonnes ; les trois sondages ci-dessus ne constituent pas une preuve — celle-ci repose sur la correction de la construction du modèle (all_different + contraintes diagonales scalaires). Le temps `1.41 ms` reste machine-dépendant, un seul passage.\n", "\n", - "**Note de parite** : la *premiere* solution affichee peut differer de celle du jumeau C# -- l'ordre de creation des variables auxiliaires diagonales influence l'heuristique de recherche par defaut, et les deux notebooks ne les construisent pas dans le meme ordre. Les deux sont des solutions valides du **meme** modele, resolu par le **meme** moteur (Choco) : l'espace des solutions est identique par construction.\n" + "**Note de parité** : la *première* solution affichée peut différer de celle du jumeau C# -- l'ordre de création des variables auxiliaires diagonales influence l'heuristique de recherche par défaut, et les deux notebooks ne les construisent pas dans le même ordre. Les deux sont des solutions valides du **même** modèle, résolu par le **même** moteur (Choco) : l'espace des solutions est identique par construction." ] }, { diff --git a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-8-Temporal-CSharp.ipynb b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-8-Temporal-CSharp.ipynb index df3806fd78..b6760b68a3 100644 --- a/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-8-Temporal-CSharp.ipynb +++ b/MyIA.AI.Notebooks/Search/Part2-CSP/CSP-8-Temporal-CSharp.ipynb @@ -323,7 +323,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Lecture de la declaration Allen** (code[1]) :\n", + "### Lecture : la déclaration Allen et ses trois propriétés structurales\n", "\n", "La cellule declare :\n", "\n", @@ -347,21 +347,7 @@ "sens de lecture est de gauche a droite. C'est la convention d'Allen (1983), heritee de la\n", "theorie des relations.\n", "\n", - "**Sortie attendue** : declaration compilee, pas de sortie console directe (les 169 entrees\n", - "seront utilisees par les exemples ulterieurs).\n", - "\n", - "**Coût** : ~0.5 seconde (compilation de 1 enum + 1 classe static avec 32 entrees : 13 converse + 19 composition)." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "59b19ae7", - "metadata": {}, - "source": [ - "### Interpretation : Relations d'Allen\n", - "\n", - "Les **13 relations** couvrent l'exhaustivite de tous les positionnements possibles entre 2\n", + "**Ce que la declaration porte** : les **13 relations** couvrent l'exhaustivite de tous les positionnements possibles entre 2\n", "intervalles. La **transitivite** de la relation `equals` reflete le fait qu'un intervalle est\n", "transparent (egal a lui-meme). Les compositions non triviales (`Overlaps o Overlaps`,\n", "`During o Contains`, etc.) produisent des unions d'intervalles -- d'ou l'interet du TCSP pour\n", @@ -385,10 +371,8 @@ "est plus complexe (13x13 vs ~7 pour les points), et certaines compositions sont **non-uniques**.\n", "Mais c'est le prix a payer pour la richesse expressive.\n", "\n", - "**Sortie de la cellule** : tableau 13x13 imprime en console (169 entrees), chacune etant\n", - "l'ensemble des relations possibles apres composition.\n", - "\n", - "**Coût** : ~0.3 seconde (1 Console.WriteLine)." + "**Sortie attendue** : declaration compilee, pas de sortie console directe (les 169 entrees\n", + "seront utilisees par les exemples ulterieurs). **Coût** : ~0.5 seconde (compilation de 1 enum + 1 classe static avec 32 entrees : 13 converse + 19 composition)." ] }, { diff --git a/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0017-2026-10-01-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0017-2026-10-01-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..ab587f029b --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0017-2026-10-01-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,11 @@ +date: '2026-10-01' +by: myia-po-2027:CoursIA-2 +python_sha: 2bacc8c3ea6a78c987de126344d122a8762bc495 +csharp_sha: 281b6cf09a5bf1a6ad82ec52fd0fedaa106966aa +content_python_sha: dd7f54aadd8a7f3a6f26ebfb0989cbec57d1a75b2e6e17b0e707b3ed9014c26a +content_csharp_sha: 9e24922c7ca37fc8e615ef4168176c674988f034381f690fe15b9aec01a396a2 +reason: >- + Re-attestation post-merge #18536 -> main (#18543 + #18429 modifies + certain blobs Search). Collision des numeros d'attestation resolue par + ai-01 (numeros reserves par DM HIGH 2026-10-01). Le re-attestation + capture l'etat des jumeaux a la tete post-fusion. diff --git a/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0018-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0018-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..d642017801 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0018-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: f1a647ab8308ea2cb10604cee33dd19000bf7e13 +csharp_sha: fec2aff63d9bb3832f6a6e5712628eac3c00fb27 +content_python_sha: 4bf8f1b8576090f1eb2a2d5a0b8d77dbdb4406c851b58b495c06c175669726b6 +content_csharp_sha: c5653475b98ba109427ced840e7527df179a1be318d00c5082457b1d4d5518eb diff --git a/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0019-2026-10-04-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0019-2026-10-04-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..72d97357bc --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/app-14-connectfour-adversarial/0019-2026-10-04-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-10-04' +by: myia-po-2027:CoursIA-2 +python_sha: 2bacc8c3ea6a78c987de126344d122a8762bc495 +csharp_sha: 281b6cf09a5bf1a6ad82ec52fd0fedaa106966aa +content_python_sha: dd7f54aadd8a7f3a6f26ebfb0989cbec57d1a75b2e6e17b0e707b3ed9014c26a +content_csharp_sha: 9e24922c7ca37fc8e615ef4168176c674988f034381f690fe15b9aec01a396a2 diff --git a/scripts/notebook_tools/twin_pairs.d/app-17-vrp-logistics/0007-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/app-17-vrp-logistics/0007-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..750b2e1f06 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/app-17-vrp-logistics/0007-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: 5748983c59960861316e3f4cad4019f112dd87dd +csharp_sha: 18cb9498aa7237ce986f47957f11633605ca20ec +content_python_sha: 0c25de1e3e2e42b8eca0a9528ac44828990631759223d11c4d4303d7a9d42fea +content_csharp_sha: 5fd4a561985dbf8a8491c2dbffb91920e3438016899e185a35ba903411eb0494 diff --git a/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0023-2026-10-01-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0023-2026-10-01-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..560f9f0e1e --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0023-2026-10-01-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,11 @@ +date: '2026-10-01' +by: myia-po-2027:CoursIA-2 +python_sha: 7edc121f78a9a487a202a2e5f49eaec43a245445 +csharp_sha: 31793b24be471dc98da6c5809fde3dbbaba60b07 +content_python_sha: a76e4ad934031a4b7f24883b9c889c782f14bb0d17e7e031283e5e438c8ae826 +content_csharp_sha: bdd606f07e29ed10a78ec0e7ac9874e08e9089e3f580c6aab5f0cbd459ac161f +reason: >- + Re-attestation post-merge #18536 -> main (#18543 + #18429 modifies + certain blobs Search). Collision des numeros d'attestation resolue par + ai-01 (numeros reserves par DM HIGH 2026-10-01). Le re-attestation + capture l'etat des jumeaux a la tete post-fusion. diff --git a/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0024-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0024-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..4a6ce6caa8 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0024-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: 7edc121f78a9a487a202a2e5f49eaec43a245445 +csharp_sha: f66f573ce93976a2771b9cb1c95a87a97a398c5b +content_python_sha: a76e4ad934031a4b7f24883b9c889c782f14bb0d17e7e031283e5e438c8ae826 +content_csharp_sha: 6d74508f919b178c559a8223d6323c755ece625cd401b940ce586c67824ee682 diff --git a/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0025-2026-10-04-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0025-2026-10-04-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..9bced954da --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/csp-1-fundamentals/0025-2026-10-04-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-10-04' +by: myia-po-2027:CoursIA-2 +python_sha: 7edc121f78a9a487a202a2e5f49eaec43a245445 +csharp_sha: 31793b24be471dc98da6c5809fde3dbbaba60b07 +content_python_sha: a76e4ad934031a4b7f24883b9c889c782f14bb0d17e7e031283e5e438c8ae826 +content_csharp_sha: bdd606f07e29ed10a78ec0e7ac9874e08e9089e3f580c6aab5f0cbd459ac161f diff --git a/scripts/notebook_tools/twin_pairs.d/csp-8-temporal/0011-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/csp-8-temporal/0011-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..945ed4a7ac --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/csp-8-temporal/0011-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: 44e714cad7d520bb4c5dc0473ad8d7c23723ae28 +csharp_sha: b6760b68a39655fd378970e278cb535488ade50a +content_python_sha: 2f214c97191fae50c3469b81e3b5d830d1ce9d0b31c9925158c4f2f97c7964a8 +content_csharp_sha: 78e7ac510f11f2a3e0ae557e6dbd75a03314301deeddf37228ed678f2a98c304 diff --git a/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0010-2026-10-01-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0010-2026-10-01-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..5a31fddcd8 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0010-2026-10-01-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,11 @@ +date: '2026-10-01' +by: myia-po-2027:CoursIA-2 +python_sha: 37d57e27b1a2eb42f3368ffb35758a2e99e1c2c8 +csharp_sha: d0b3e4051c6b9f964110ecb2c52adbf74802ce36 +content_python_sha: 38d80548508c77b6729c733896193fd3847953e02b34e32aa77a92f94f274365 +content_csharp_sha: 58e69ce7082a72bb11a1dcdbb184461a6b66c31ac4568944a9f2924529b71a22 +reason: >- + Re-attestation post-merge #18536 -> main (#18543 + #18429 modifies + certain blobs Search). Collision des numeros d'attestation resolue par + ai-01 (numeros reserves par DM HIGH 2026-10-01). Le re-attestation + capture l'etat des jumeaux a la tete post-fusion. diff --git a/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0011-2026-10-04-myia-po-2027-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0011-2026-10-04-myia-po-2027-CoursIA.yaml new file mode 100644 index 0000000000..bb9cd8580c --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0011-2026-10-04-myia-po-2027-CoursIA.yaml @@ -0,0 +1,11 @@ +date: '2026-10-04' +by: myia-po-2027:CoursIA +python_sha: 37d57e27b1a2eb42f3368ffb35758a2e99e1c2c8 +csharp_sha: 4be90894fde497efe55915f29cc273c0b1b76e2c +content_python_sha: 38d80548508c77b6729c733896193fd3847953e02b34e32aa77a92f94f274365 +content_csharp_sha: 8fe5cc4aba880f6b5edab7cd9c89618ca93e09af268abf8dee262bde3fb1e33c +reason: >- + Corrige 0010 : son content_csharp_sha (58e69ce7) citait le blob pre-#17636 + (commit 15c605c5, 2026-09-24), calcule depuis un worktree sans le main du 01/10. + Re-attestation de l etat reel du head : python consolide (38d80548), csharp + = version main courante (8fe5cc4a, blob 4be90894 via 17528ec3). diff --git a/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0012-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0012-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..06be90f73a --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0012-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: 37d57e27b1a2eb42f3368ffb35758a2e99e1c2c8 +csharp_sha: d0b3e4051c6b9f964110ecb2c52adbf74802ce36 +content_python_sha: 38d80548508c77b6729c733896193fd3847953e02b34e32aa77a92f94f274365 +content_csharp_sha: 58e69ce7082a72bb11a1dcdbb184461a6b66c31ac4568944a9f2924529b71a22 diff --git a/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0013-2026-10-04-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0013-2026-10-04-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..7a6e694a44 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-06-adversarialsearch/0013-2026-10-04-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-10-04' +by: myia-po-2027:CoursIA-2 +python_sha: 37d57e27b1a2eb42f3368ffb35758a2e99e1c2c8 +csharp_sha: 4be90894fde497efe55915f29cc273c0b1b76e2c +content_python_sha: 38d80548508c77b6729c733896193fd3847953e02b34e32aa77a92f94f274365 +content_csharp_sha: 8fe5cc4aba880f6b5edab7cd9c89618ca93e09af268abf8dee262bde3fb1e33c diff --git a/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0015-2026-10-01-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0015-2026-10-01-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..3d53201edb --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0015-2026-10-01-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,11 @@ +date: '2026-10-01' +by: myia-po-2027:CoursIA-2 +python_sha: 24905278c5a789bda74b73ef4ec45f4091f7fa3d +csharp_sha: b2c581077c9b247baba97014950bd692094370f3 +content_python_sha: 03242af762003fb9f877865350737c93e460ef199808fe9253524a44e21c0980 +content_csharp_sha: c340c49a3f4b6d26efd8dd35c09c687b7de9b95e44caf804a64ace9e41251671 +reason: >- + Re-attestation post-merge #18536 -> main (#18543 + #18429 modifies + certain blobs Search). Collision des numeros d'attestation resolue par + ai-01 (numeros reserves par DM HIGH 2026-10-01). Le re-attestation + capture l'etat des jumeaux a la tete post-fusion. diff --git a/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0016-2026-09-30-myia-po-2027-CoursIA-2.yaml b/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0016-2026-09-30-myia-po-2027-CoursIA-2.yaml new file mode 100644 index 0000000000..3fe59a7e8f --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-07-mcts-and-beyond/0016-2026-09-30-myia-po-2027-CoursIA-2.yaml @@ -0,0 +1,6 @@ +date: '2026-09-30' +by: myia-po-2027:CoursIA-2 +python_sha: 24905278c5a789bda74b73ef4ec45f4091f7fa3d +csharp_sha: b2c581077c9b247baba97014950bd692094370f3 +content_python_sha: 03242af762003fb9f877865350737c93e460ef199808fe9253524a44e21c0980 +content_csharp_sha: c340c49a3f4b6d26efd8dd35c09c687b7de9b95e44caf804a64ace9e41251671