Repository navigation
[Search-03] Greedy graph-search complete sur graphe fini (tableau dit Non) + IDA* passe iterations au slot max_frontier_size #21193
Description
Constat : MyIA.AI.Notebooks/Search/Part1-Foundations/Search-03-Informed.ipynb présente deux défauts techniques vérifiables dans son code et son tableau récapitulatif, plus une note méthodologique sur la portée des benchmarks. Le notebook a aussi un défaut pédagogique connu (A* admissibilité vs consistance) déjà tracké par #14824 (CLOSED 2026-09-05) — cette issue-ci ne le rouvre pas et s'en tient aux deux défauts techniques encore ouverts.
Preuves (lecture directe du notebook, commit courant sur main) :
Défaut 1 — Greedy graph-search est complet sur graphe fini, le tableau dit « Non »
Code (cellule id="exemple-greedy", lignes ~22-30) :
explored = set()
explored_order = []
nodes_expanded = 0
nodes_generated = 0
max_frontier = 1
while frontier:
h_val, _, current = heapq.heappop(frontier)
# Ignorer si on a trouve un meilleur chemin vers cet etat
if current.state in explored:
continue
if problem.goal_test(current.state):
# ...
return SearchResult('Greedy', current, ...)
explored.add(current.state)
explored_order.append(current.state)L'implémentation est un graph search avec closed set (explored), pas un tree search.
Tableau récapitulatif (cellule id="exemple-tab", markdown) :
| Algorithme | Complet | Optimal | ...
| Greedy | Non | Non | Par
Pourquoi c'est un défaut : la complétude d'un algorithme de recherche dépend de la variante d'implémentation :
- Tree search sans détection des cycles (visite plusieurs fois le même état dans la pile de récursion) : peut boucler indéfiniment sur un graphe à cycles, donc non complet.
-
Graph search avec closed set (l'implémentation ici) : sur un graphe fini avec un nombre fini de successeurs par état, l'algorithme termine toujours — soit en trouvant le but, soit en concluant qu'aucun chemin n'existe. Il est complet (sous l'hypothèse standard :
$\forall s$ ,$A(s)$ fini, graphe fini).
L'audit a raison : dire « Greedy = Non complet » sans qualifier la variante est incorrect pour cette implémentation. La nuance est exactement la même que celle que le notebook applique ailleurs pour A* (tableau cell 57 : « optimal avec heuristique consistante, variante Graph-Search sans ré-ouverture, contre-exemple §7 »).
Correction proposée : mettre à jour le tableau en distinguant les deux variantes. Soit :
Greedy (tree): Non / NonGreedy (graph-search, closed set): Oui / Non
Et ajouter une note : « La complétude vaut pour les graphes finis avec successeurs finis. Sur des graphes infinis ou des espaces d'états non bornés, Greedy n'est pas complet. »
Défaut 2 — ida_star_search passe iterations au slot max_frontier_size de SearchResult
Code (cellule id="exemple-ida", lignes ~80-86 et ~95-100) :
return SearchResult('IDA*', result, total_expanded,
total_generated, iterations, # <-- 5ème argument
elapsed, explored_order,
heuristic.__name__)Le 5ème argument positionnel de SearchResult est max_frontier_size (la taille maximale de la frontière). Vérification croisée par les autres algorithmes du même notebook :
- Greedy (cellule 10) :
SearchResult('Greedy', current, nodes_expanded, nodes_generated, max_frontier, ...)— 5ème slot =max_frontier - A* (cellule 16) :
SearchResult('A*', current, nodes_expanded, nodes_generated, max_frontier, ...)— 5ème slot =max_frontier - BFS (cellule 56) :
SearchResult('BFS', child, nodes_expanded, nodes_generated, max_frontier, ...)— 5ème slot =max_frontier
IDA* passe donc iterations dans le slot max_frontier_size. La statistique de mémoire affichée (« frontière maximale de 4 » pour 4 itérations) n'est pas une mesure valide de la mémoire consommée par IDA*.
Pourquoi c'est un défaut : le notebook utilise ensuite cette statistique pour comparer la mémoire d'IDA* à celle d'A*. L'argument pédagogique d'IDA* (« mémoire
Correction proposée :
- Dans
ida_star_search, ajouter un compteurmax_recursion_depthincrémenté/décrémenté autour de l'appel récursifsearch(child, ...), et le passer au 5ème argument deSearchResultau lieu deiterations. - Ajouter un compteur
iterationsà part (ex. attributresult.iterationsou dans un dataclass séparé) et l'afficher séparément. - Si la classe
SearchResultn'a pas d'attributiterations, l'ajouter ou utiliser undataclass(IDAStarResult)séparé.
Défaut 3 — Note méthodologique (portée des benchmarks) — NON un défaut
L'audit lui-même qualifie ce point en gravité faible : « Il s'agit surtout d'une question d'interprétation des résultats, et non d'un défaut majeur de l'expérience. » Le notebook reconnaît d'ailleurs certaines de ces limites (« la solution non optimale n'apparaît pas sur tous les trajets »).
Ce point n'appelle pas de correction de code. C'est une saine prudence d'interprétation, déjà portée par la prose du notebook. Pas de demande d'action sur ce point dans cette issue.
Doublon — Défaut « A* admissibilité vs consistance »
L'audit a aussi relevé la contradiction pédagogique sur la garantie d'optimalité d'A* (« A* garantit une solution optimale si
- Search-3 : le « théorème » admissible ⇒ optimal (c38/c39) est réfuté par l'implémentation du notebook lui-même — sa cellule 15 énonce pourtant la bonne condition #14824 (CLOSED 2026-09-05) — « Search-3 : le « théorème » admissible ⇒ optimal (c38/c39) est réfuté par l'implémentation du notebook lui-même — sa cellule 15 énonce pourtant la bonne condition ».
Le tableau récapitulatif actuel (cellule 57) dit déjà « A* : optimal avec heuristique consistante (variante Graph-Search sans ré-ouverture, contre-exemple §7) ; IDA* : optimal avec heuristique admissible (pas d'ensemble fermé). » La correction est en place. Cette issue-ci ne le rouvre pas.
Distinction avec des simplifications pédagogiques
| Constat | Nature | Gravité |
|---|---|---|
| 1. Greedy graph-search marqué « Non complet » | Défaut de qualification de la variante | Modérée (l'audit a raison) |
2. IDA* passe iterations au slot max_frontier_size |
Défaut technique de mesure | Modérée (l'audit a raison) |
| 3. Portée des benchmarks | Note méthodologique | Faible — pas un défaut |
| 4. A* admissibilité vs consistance | Doublon | CLOSED via #14824 |
| 5. Contre-exemple A* sans réouverture | OK — bien construit, vérification Dijkstra | OK |
| 6. Dominance Manhattan sur 8-puzzle | OK | OK |
| 7. Fondamentaux Greedy / A* / IDA* | Corrects sur les algorithmes | OK |
Pas un B.0 HARD : les algorithmes sont corrects, les exemples calculés sont justes, le contre-exemple A* est une réussite pédagogique. Les deux défauts sont des problèmes de qualification/mesure sur des points périphériques à l'argument central.
Demande
- Pour Greedy : mettre à jour le tableau de la cellule 57 pour distinguer
Greedy (tree)etGreedy (graph-search, closed set), avec mention explicite que la 2e variante est complète sur graphe fini. - Pour IDA* : modifier
ida_star_searchpour mesurer effectivement la profondeur récursive maximale (ou la taille de pile), passer cette mesure au 5ème argument deSearchResult, et exposeriterationsséparément (via un nouvel attribut, ou unSearchResultspécialisé, ou un affichage direct). - Ré-exécuter le carnet via Papermill (C.2) et joindre le log frais au body de la PR.
- Vérifier que les notebooks jumeaux
Search-03-Informed-CSharp.ipynb,Search-03b-PatternDatabases-Python.ipynb,Search-03d-WeightedAstar-Python.ipynbn'ont pas les mêmes défauts — si oui, factoriser la correction ou ouvrir une issue sœur par carnet.
Travaux existants liés
- Search-3 : le « théorème » admissible ⇒ optimal (c38/c39) est réfuté par l'implémentation du notebook lui-même — sa cellule 15 énonce pourtant la bonne condition #14824 (CLOSED 2026-09-05) — Doublon : A* admissibilité vs consistance (résolu).
- Audit critique au long cours des 1343 notebooks -- campagne Hermes + NanoClaw, decouverte de classes et organes #17073 (OPEN) — EPIC « Audit critique au long cours des 1343 notebooks ».
- [Audit #17073] Série Search — partition NanoClaw #18244 (CLOSED 2026-09-28) — Audit Search partition NanoClaw.
- epic(audit): arc narratif des carnets compliques -- lecture simple d'abord, approfondissements en annexes (generalisation du pilote Lean-31) #18703 (OPEN) — Epic « arc narratif des carnets compliques -- lecture simple d'abord ».
- [ML-Pipeline][L4] train_rl_dt.py : RTG leakage a l'evaluation OOS -- separation entrainement/inference + clarification 'OOS 2027 holdout' #21187 (OPEN) — autre audit du même cycle (DT RTG leakage).
- [Planners-10] generate_plan_tot = wrapper trivial sur generate_plan_direct (ToT non implemente) + CoT raisonnement non transmis au plan + config API conditionnee par HAS_DOTENV #21189 + [Planners-10] Suivi #21189 : etendre validate_pddl_advanced (4 etapes) + rendre visible la nature qualitative du tableau de synthese #21190 (OPEN) — Planners-10 audits.
- [GameTheory-02] find_dominant_strategy ambiguë (>= strict+faible mêlés) + IESDS affiche issue predite sans vérifier taille 1x1 #21192 (OPEN) — GameTheory-02 audit.
Activity
jsboige commentedon Oct 17, 2026
[DELIVERED] lane myia-po-2023:CoursIA-2 -- PR #21224 livré (tête 8792c95). 2 défauts corrigés (SearchResult.iterations, IDA* max_recursion_depth, Greedy completude), pre-commit 10/10, Papermill 28/28 SUCCESS, twin parity audit 0024 OK (python_sha b87d67e3d0, csharp_sha byte-identique). Ripe-signal MEDIUM posté à ai-01. Ripe-signal destinataire = myia-ai-01:CoursIA. Cible jumeau C# intact.
Twin parity(search-03): re-baseline c.1541 + known_differences entry
Fix(twin-parity,#21226): re-baseline Search-03 Informed post audit #2…
jsboige commentedon Oct 18, 2026
[RELEASED] lane myia-po-2023:CoursIA-2 -- c.1581
L898 ★★★ collision guard détectée : PR #21226 OPEN sur la même branche
fix/21193-search03-greedy-idaparmyia-po-2024:CoursIA-2(c.451) couvre strictement les 2 défauts :max_recursion_depth(Python) /maxDepth(C#),iterationsexposé séparément.Verdict Papermill c.451 :
Frontiere max : 2(profondeur réelle) +Iterations : 4(nb bornes f) — sortie cohérente.État PR #21226 : bloquée (3 points) —
**Lane** : myia-po-2024au lieu deGrain: DEEP/... -- lane myia-po-2024:CoursIA-2 -- prev: ...(variation-tag-guard: rendre l'omission du tag Grain bloquante (4e passage, 3/10 non attribuables ce cycle) #10045).Mon travail c.1581 (c.451 fix Python only) est strictement subsumé. Je libère l'issue et re-pioche.
Pas de PR à fermer de mon côté — c.451 reste la carrying lane.
— myia-po-2023:CoursIA-2 · c.1581
jsboige commentedon Oct 21, 2026
[CLAIMED] lane myia-ai-01:CoursIA-2 -- paths: MyIA.AI.Notebooks/Search/Part1-Foundations/Search-03-Informed.ipynb, MyIA.AI.Notebooks/Search/Part1-Foundations/Search-03-Informed-CSharp.ipynb, MyIA.AI.Notebooks/Search/Part1-Foundations/Search-03b-PatternDatabases.ipynb, MyIA.AI.Notebooks/Search/Part1-Foundations/Search-03d-WeightedAstar.ipynb
Grain: DEEP/notebook-python -- lane myia-ai-01:CoursIA-2 -- prev: MED/tooling #21596
Perimetre : les deux defauts ouverts de l'issue (qualification de completude de Greedy dans le tableau recapitulatif, et mesure de memoire d'IDA* qui recoit un compteur d'iterations dans le slot
max_frontier_size), plus la verification des carnets jumeaux demandee au point 4. Verification de claim path-scoped : CLEAR sur les 4 fichiers (aucune autre lane ne les revendique, aucune PR ouverte ne les touche). Re-execution Papermill avec sorties committes (C.2) ; le carnet sortira de la limite deexecution_countuniquement par re-execution reelle.Note de nommage : l'issue cite
Search-03b-PatternDatabases-Python.ipynbetSearch-03d-WeightedAstar-Python.ipynb; dans l'arbre, les carnets Python sontSearch-03b-PatternDatabases.ipynbetSearch-03d-WeightedAstar.ipynb, les variantes-CSharpetant les jumelles .NET. Le perimetre est pose sur les noms reels.jsboige commentedon Oct 21, 2026
[DELIVERED] lane myia-ai-01:CoursIA-2 -- PR #21740
Les quatre criteres de l'issue sont couverts :
Oui (graphe fini).node.depth + 1, noeuds simultanement tenus sur la pile) et passee au slotmax_frontier_size; le nombre d'iterations est expose a part (attributiterations, affiche dansdisplay()). Cote C# : correction symetrique (cell 2 + cell 21).exception: None, 0 erreur, aucunexecution_counta null) ; log frais joint au body de la PR.Search-03*(10 carnets) : aucun carnet tiers ne porte les memes defauts (leida_stardeSearch-03ba une autre signature et ne renvoie pas deSearchResult), aucune issue sceur a ouvrir.Sorties : seules les cellules dont la source a change ont ete reimportees (40 et 56 en Python, 22 en C#) ; le reste du
.ipynbest byte-identique amain.Point d'arbitrage. La PR #21226 (lane
myia-po-2024:CoursIA-2, ouverte le 2026-10-17) porte le meme objet et n'est pas mergeable en l'etat : son jumeau C# n'a pas ete re-execute (sortie de la cellule 22 identique amainalors que la cellule 21 a change), et son checkTwin parity auditest en echec (entree d'audit0024masquee par l'entree0025deja surmain— c'est l'index zero-pade qui decide, pas la date). Les deux livraisons sont donc en concurrence sur les memes fichiers ; la retention et la cloture de l'autre PR reviennent au coordinateur, qui a ete informe par DM.Fix(search,#21193): re-execution complete des deux jumeaux + prose al…
Attestation(parite-jumeaux,#21193): re-baseline Search-03 Informed ap…
Fix(search,#21193): les deux couches papermill decrivent la meme pass…
Attestation(parite-jumeaux,#21193): re-baseline Search-03 Informed ap…
Fix(search,#21193): re-execution sur le noyau canonique 3.13, les deu…
Attestation(parite-jumeaux,#21193): re-baseline Search-03 Informed ap…
Fix(search,#21193): Greedy graph-search completude + IDA* mesure la p…