diff --git a/MyIA.AI.Notebooks/Search/Part4-Metaheuristics/MGS-vs-mealpy/MGS-28-BareBonesPSO-vs-Mealpy.ipynb b/MyIA.AI.Notebooks/Search/Part4-Metaheuristics/MGS-vs-mealpy/MGS-28-BareBonesPSO-vs-Mealpy.ipynb
index 80d9fe6668..a5529cb8ce 100644
--- a/MyIA.AI.Notebooks/Search/Part4-Metaheuristics/MGS-vs-mealpy/MGS-28-BareBonesPSO-vs-Mealpy.ipynb
+++ b/MyIA.AI.Notebooks/Search/Part4-Metaheuristics/MGS-vs-mealpy/MGS-28-BareBonesPSO-vs-Mealpy.ipynb
@@ -16,7 +16,7 @@
"\n",
"MGS-27 a refermé la question FBI sur la paire qui prétendait le moins à la différence : le port C# dérivé battait sa référence mealpy des deux mains. La paire 7 descend d'un cran encore dans la prétention — et change de nature : le **Bare Bones PSO** de Kennedy (2003) est le PSO dépouillé de toute sa mécanique, ni inertie *w*, ni coefficients *c1*/*c2* : chaque gène de la nouvelle particule est un simple **tirage gaussien** autour du milieu entre le meilleur personnel et le meilleur global. Deux conséquences structurelles gouvernent ce protocole :\n",
"\n",
- "1. **Aucun PSO de mealpy 3.0.2 n'est bare-bones** — les sept variantes du module (`OriginalPSO`, `P_PSO`, `C_PSO`, `CL_PSO`, `AIW_PSO`, `HPSO_TVAC`, `LDW_PSO`) portent toutes les constantes de vitesse du PSO classique ; en prendre une pour jumeau serait mesurer un **PSO classique déguisé** en bare-bones. Le jumeau mealpy est donc un *subclass* de `Optimizer` — le point d'extension natif de la bibliothèque — qui **pinne la formule de Kennedy** dans le harnais mealpy (graine, comptage d'évaluations, correction de bornes).\n",
+ "1. **Aucun PSO de mealpy 3.0.2 n'est bare-bones** — les sept variantes du module (`OriginalPSO`, `P_PSO`, `C_PSO`, `CL_PSO`, `AIW_PSO`, `HPSO_TVAC`, `LDW_PSO`) conservent toutes une **vitesse explicite** et un couple de coefficients de vitesse — constantes *w*/*c1*/*c2* (ou leurs variantes `w_min`/`w_max`/`ci`/`cf`/`c_local`) pour six d'entre elles, coefficients sin/cos dynamiques pour `P_PSO` ; en prendre une pour jumeau serait mesurer un **PSO classique déguisé** en bare-bones. Le jumeau mealpy est donc un *subclass* de `Optimizer` — le point d'extension natif de la bibliothèque — qui **pinne la formule de Kennedy** dans le harnais mealpy (graine, comptage d'évaluations, correction de bornes).\n",
"2. **Le portage MGS est ancré sur la position courante, pas sur le pbest** — le framework géométrique n'expose pas de mémoire *pbest_i* par particule, et l'écart est documenté *in-source* dans `BareBonesParticleSwarm.cs`. Pour distinguer l'écart **noyau** (moteur contre moteur) de l'écart **d'ancrage** (sémantique du portage), le bench croise donc **trois bras** : le composé MGS, la variante mealpy alignée sur sa sémantique, et le Kennedy 2003 littéral.\n",
"\n",
"La grille, la représentation R1, le budget (population 50, 160 générations) et les graines {0, 1, 7, 42} sont ceux des paires précédentes : les médianes se lisent dans la même colonne du tableau croisé de l'Epic.\n"
@@ -34,6 +34,112 @@
"execution_count": 1,
"metadata": {},
"outputs": [
+ {
+ "output_type": "display_data",
+ "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": "stream",
"name": "stdout",
@@ -45,9 +151,9 @@
"source": [
"// === MGS-28 : socle commun — DLLs MGS, grille de référence, fonction de coût ===\n",
"// Même socle que MGS-22/23 : la représentation R1 (continu + arrondi) est le substrat du bench.\n",
- "#r \"../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/GeneticSharp.Infrastructure.Framework.dll\"\n",
- "#r \"../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/MetaGeneticSharp.Infrastructure.dll\"\n",
- "#r \"../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/MetaGeneticSharp.Domain.dll\"\n",
+ "#r \"../../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/GeneticSharp.Infrastructure.Framework.dll\"\n",
+ "#r \"../../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/MetaGeneticSharp.Infrastructure.dll\"\n",
+ "#r \"../../MetaGeneticSharp/src/MetaGeneticSharp.Domain/bin/Debug/net9.0/MetaGeneticSharp.Domain.dll\"\n",
"using MetaGeneticSharp;\n",
"using GeneticSharp;\n",
"using System.Diagnostics;\n",
@@ -112,7 +218,7 @@
"source": [
"**Lecture.** Le socle est posé, identique à MGS-23 au nom près — c'est voulu : la comparabilité\n",
"des paires de l'Epic repose sur un protocole strictement apparié (même grille Easy[0], même\n",
- "représentation R1 continue à 51 gènes, même fonction de coût comptée en conflits, renvoyant 0\n",
+ "représentation R1 continue à 36 gènes, même fonction de coût comptée en conflits, renvoyant 0\n",
"ssi la grille est résolue). Le pont PythonNet qui suivra réimplémente ce comptage *à\n",
"l'identique* et le vérifie sur des vecteurs témoins déterministes : la seule différence\n",
"mesurable entre les bras sera donc le moteur, pas l'échelle de la fitness.\n"
@@ -127,7 +233,7 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS BBPSO (graine 7, témoin) : 29 conflits, 8000 évaluations, 327 ms, checkpoints 25/50/75/100 % = 29/29/29/29.\r\n"
+ "MGS BBPSO (graine 7, témoin) : 29 conflits, 8000 évaluations, 291 ms, checkpoints 25/50/75/100 % = 29/29/29/29.\r\n"
]
}
],
@@ -234,18 +340,18 @@
"outputs": [
{
"output_type": "display_data",
- "metadata": {},
"data": {
"text/html": [
""
]
- }
+ },
+ "metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "Pont PythonNet actif : mealpy 3.0.2 sur Python 3.13.3\r\n"
+ "Pont PythonNet actif : mealpy 3.0.2 sur Python 3.13.12\r\n"
]
},
{
@@ -496,8 +602,10 @@
"source": [
"**Lecture.** Le pont est actif et la sanity check porte tout le bench : la fonction de coût\n",
"Python redonne *exactement* le comptage C# sur les vecteurs témoins déterministes. Le point\n",
- "structurant est le **subclass `OriginalBBPSO`** : mealpy n'offre aucun PSO bare-bones (les\n",
- "sept variantes du module portent toutes *w*/*c1*/*c2*), et le point d'extension officiel de la\n",
+ "structurant est le **subclass `OriginalBBPSO`** : mealpy n'offre aucun PSO bare-bones (six des sept\n",
+ "variantes du module exposent explicitement *w*/*c1*/*c2* — ou leurs variantes\n",
+ "`w_min`/`w_max`/`ci`/`cf`/`c_local` — et la septième, `P_PSO`, porte des coefficients\n",
+ "sin/cos dynamiques sur la même mise à jour de vitesse), et le point d'extension officiel de la\n",
"bibliothèque est précisément la classe `Optimizer` — le jumeau hérite donc du harnais mealpy\n",
"complet (générateur seedé par `solve(prob, seed=...)`, comptage d'évaluations par `Problem`,\n",
"correction de bornes `correct_solution`, suivi `g_best`) en pinnant la formule de Kennedy.\n",
@@ -569,7 +677,9 @@
"// d'ancre et de sélection pour que l'écart mesuré s'interprète (noyau vs portage), pas le subir.\n",
"using (Py.GIL())\n",
"{\n",
- " // 1) La détection Clerc : aucun PSO mealpy 3.0.2 n'est bare-bones — tous portent w/c1/c2.\n",
+ " // 1) La détection Clerc : aucun PSO mealpy 3.0.2 n'est bare-bones — six portent w/c1/c2\n",
+ " // (ou leurs variantes w_min/w_max/ci/cf/c_local) ; P_PSO porte des coefficients\n",
+ " // sin/cos dynamiques sur la même mise à jour de vitesse.\n",
" S28.Exec(@\"__pso_catalog__ = ''\n",
"for _cls in (OriginalPSO, P_PSO, C_PSO, CL_PSO, AIW_PSO, HPSO_TVAC, LDW_PSO):\n",
" _m = _cls(epoch=10, pop_size=5)\n",
@@ -613,9 +723,12 @@
"écart MGS↔mealpy sur cette paire serait **ininterprétable** — il mêlerait le moteur (C#\n",
" GéneticSharp + composé géométrique contre NumPy + harnais mealpy) et la sémantique du\n",
"portage (ancre courante contre *pbest*, glouton pool contre per-particle contre remplacement\n",
- "inconditionnel). Le catalogue de la cellule établit la **détection Clerc** : les sept PSO\n",
- "mealpy portent tous des constantes de vitesse — aucun ne prétend au bare-bones, et le\n",
- "subclass est la seule voie honnête vers un jumeau. La propriété de gel (écart-type nul ⇒\n",
+ "inconditionnel). Le catalogue de la cellule établit la **détection Clerc** : six des sept PSO\n",
+ "mealpy exposent explicitement les constantes de vitesse (*w*/*c1*/*c2* ou leurs\n",
+ "variantes), et le septième, `P_PSO`, porte des coefficients sin/cos dynamiques sur la\n",
+ "même mise à jour de vitesse — **aucun** ne prétend au bare-bones (la sortie le montre :\n",
+ "la ligne `P_PSO` est la seule à ne lister aucun paramètre), et le subclass est la seule\n",
+ "voie honnête vers un jumeau. La propriété de gel (écart-type nul ⇒\n",
"tirage déterministe) est le comportement littéral de Kennedy : l'élite ne bouge pas tant\n",
"qu'elle est le gbest, et c'est une **propriété**, pas un bug à corriger — l'Exercice 2 en\n",
"mesurera le prix.\n"
@@ -630,14 +743,14 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy BBPSO-kennedy (graine 7, témoin) : 26 conflits, 8050 évaluations, 600 ms.\r\n"
+ "mealpy BBPSO-kennedy (graine 7, témoin) : 26 conflits, 8050 évaluations, 548 ms.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy BBPSO-mgs (graine 7, témoin) : 26 conflits, 8050 évaluations, 539 ms.\r\n"
+ "mealpy BBPSO-mgs (graine 7, témoin) : 26 conflits, 8050 évaluations, 480 ms.\r\n"
]
},
{
@@ -694,84 +807,84 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS 0 31 8000 292 0,036 33/31/31/31 \r\n"
+ "MGS 0 31 8000 200 0,025 33/31/31/31 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS 1 31 8000 289 0,036 31/31/31/31 \r\n"
+ "MGS 1 31 8000 204 0,025 31/31/31/31 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS 7 29 8000 302 0,038 29/29/29/29 \r\n"
+ "MGS 7 29 8000 191 0,024 29/29/29/29 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS 42 30 8000 283 0,035 30/30/30/30 \r\n"
+ "MGS 42 30 8000 212 0,027 30/30/30/30 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-mgs 0 19 8050 562 0,070 32/22/20/19 \r\n"
+ "mealpy-mgs 0 19 8050 532 0,066 32/22/20/19 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-mgs 1 25 8050 567 0,070 31/26/25/25 \r\n"
+ "mealpy-mgs 1 25 8050 515 0,064 31/26/25/25 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-mgs 7 26 8050 579 0,072 32/26/26/26 \r\n"
+ "mealpy-mgs 7 26 8050 529 0,066 32/26/26/26 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-mgs 42 27 8050 631 0,078 32/30/28/27 \r\n"
+ "mealpy-mgs 42 27 8050 539 0,067 32/30/28/27 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-kennedy 0 19 8050 793 0,098 32/22/20/19 \r\n"
+ "mealpy-kennedy 0 19 8050 540 0,067 32/22/20/19 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-kennedy 1 25 8050 667 0,083 31/26/25/25 \r\n"
+ "mealpy-kennedy 1 25 8050 570 0,071 31/26/25/25 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-kennedy 7 26 8050 826 0,103 32/26/26/26 \r\n"
+ "mealpy-kennedy 7 26 8050 582 0,072 32/26/26/26 \r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-kennedy 42 27 8050 724 0,090 32/30/28/27 \r\n"
+ "mealpy-kennedy 42 27 8050 577 0,072 32/30/28/27 \r\n"
]
},
{
@@ -785,21 +898,21 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "MGS : médiane conflits 30,5 (min 29, max 31), ms/éval moyen 0,036\r\n"
+ "MGS : médiane conflits 30,5 (min 29, max 31), ms/éval moyen 0,025\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-mgs : médiane conflits 25,5 (min 19, max 27), ms/éval moyen 0,073\r\n"
+ "mealpy-mgs : médiane conflits 25,5 (min 19, max 27), ms/éval moyen 0,066\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- "mealpy-kennedy : médiane conflits 25,5 (min 19, max 27), ms/éval moyen 0,093\r\n"
+ "mealpy-kennedy : médiane conflits 25,5 (min 19, max 27), ms/éval moyen 0,070\r\n"
]
},
{
@@ -813,7 +926,7 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "ECART NOYAU (bras1 - bras2, sémantique alignée) : médianes 30,5 vs 25,5, ms/éval 0,50x\r\n"
+ "ECART NOYAU (bras1 - bras2, sémantique alignée) : médianes 30,5 vs 25,5, ms/éval 0,38x\r\n"
]
},
{
@@ -827,7 +940,7 @@
"output_type": "stream",
"name": "stdout",
"text": [
- "ECART BRUT (bras1 - bras3, lecture des paires) : médianes 30,5 vs 25,5, ms/éval 0,39x\r\n"
+ "ECART BRUT (bras1 - bras3, lecture des paires) : médianes 30,5 vs 25,5, ms/éval 0,36x\r\n"
]
},
{
@@ -1027,21 +1140,21 @@
"output_type": "stream",
"name": "stdout",
"text": [
- " C# : 4,1 ms total -> 0,008 ms/éval\r\n"
+ " C# : 3,1 ms total -> 0,006 ms/éval\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- " Python : 18,8 ms total -> 0,038 ms/éval\r\n"
+ " Python : 19,3 ms total -> 0,039 ms/éval\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
- " rapport Python/C# : 4,59x\r\n"
+ " rapport Python/C# : 6,30x\r\n"
]
}
],
@@ -1086,8 +1199,8 @@
"\n",
"- **Classement** : les deux jumeaux mealpy ex æquo en tête (médiane 25,5 conflits chacun), MGS troisième (30,5). L'écart brut de 5 conflits est donc imputable au moteur, pas au portage.\n",
"- **Écart d'ancrage nul — la paire la plus propre de l'Epic** : les deux jumeaux mealpy (ancre `local_solution` = pbest contre ancre `solution` = position courante, remplacement inconditionnel contre glouton) produisent des trajectoires **identiques graine par graine** — mêmes conflits finaux et mêmes checkpoints sur les 4 graines (écarts `[0,0,0,0]` partout). La divergence tranchée dans la cellule formules ne change rien ici : sur ce problème, la mise à jour locale gloutonne confond pbest et position courante dès qu'une particule s'améliore.\n",
- "- **Écart noyau réel, 5 conflits pour mealpy** : à sémantique strictement alignée (le bras mealpy-mgs porte exactement la formule MGS dans le harnais mealpy), mealpy atteint 25,5 contre 30,5 — la différence vient du moteur (harnais mealpy : évaluation initiale de la population, `update_global_best` post-epoch), pas des équations. La forme le confirme : MGS est devant ou égal au premier quart (checkpoints 29-33 contre 31-32), puis mealpy creuse l'écart de mi-course à la fin — graine 0 persistante `[1,9,11,12]`, graines 1/7/42 en croisement. Concrètement, mealpy continue d'exploiter en fin de course (20→19 et 28→27 entre 75 % et 100 %) quand MGS est figé dès le premier quart (cp25 = cp100 sur 3 graines sur 4) — la propriété de **gel** de la cellule formules, visible dans la sortie.\n",
- "- **Vitesse** : MGS reste 2× moins cher par évaluation (0,036 contre 0,073 ms/éval, ratio 0,50×) et la fitness C# isolée est 4,59× plus rapide — mais le budget est apparié (8 000/8 050 évaluations), donc mealpy gagne à budget égal. C'est le profil inversé du FBI (MGS-27) : là-bas le portage dérivait et gagnait des deux mains ; ici le portage est fidèle, ne dérive pas — et c'est le harnais adverse qui paie la qualité.\n",
+ "- **Écart noyau réel, 5 conflits pour mealpy** : à sémantique strictement alignée (le bras mealpy-mgs porte exactement la formule MGS dans le harnais mealpy), mealpy atteint 25,5 contre 30,5 — la différence vient du moteur (harnais mealpy : évaluation initiale de la population, `update_global_best` post-epoch), pas des équations. La forme le confirme, mais **pas uniformément selon la graine** : au premier quart MGS mène sur deux graines (7 : 29 contre 32 ; 42 : 30 contre 32) et fait jeu égal sur la graine 1 (31 contre 31), mais il est **déjà derrière sur la graine 0** (33 contre 32) — le profil de cette graine est *persistant* (delta `[1,9,11,12]`, l'écart s'installe et grandit), là où les graines 1/7/42 sont classées *mixtes* (`[0,5,6,6]`, `[-3,3,3,3]`, `[-2,0,2,3]` : MGS repasse derrière mealpy au plus tard au troisième quart, après avoir été devant ou à égalité au premier). Concrètement, mealpy continue d'exploiter en fin de course (20→19 et 28→27 entre 75 % et 100 %) quand MGS est figé après le premier quart — `cp25 = cp100` sur 3 graines sur 4, la graine 0 plaçant sa seule amélioration entre 25 % et 50 % — la propriété de **gel** de la cellule formules, visible dans la sortie.\n",
+ "- **Vitesse** : MGS reste environ deux fois moins cher par évaluation — le rapport `ms/éval` de ce passage kernel (0,38×) est lu dans la cellule de bench, et la fitness C# isolée reste plus rapide d'un facteur du même ordre (rapport Python/C# : 6,30× dans la cellule de coût par évaluation). Ce sont des mesures **machine** : les valeurs absolues ne sont donc pas recopiées ici, seuls les rapports le sont — et ces rapports eux-mêmes varient d'un passage kernel à l'autre ; le verdict ne repose pas sur eux — mais le budget est apparié (8 000/8 050 évaluations), donc mealpy gagne à budget égal. C'est le profil inversé du FBI (MGS-27) : là-bas le portage dérivait et gagnait des deux mains ; ici le portage est fidèle, ne dérive pas — et c'est le harnais adverse qui paie la qualité.\n",
"- **Fil rouge PSO de l'Epic** : MGS-22 (PSO classique à coefficients) donnait mealpy devant en qualité à ex æquo en vitesse ; MGS-28 (BBPSO, zéro coefficient) resserre la démonstration — dépouiller la particule de w/c1/c2 ne change pas le verdict moteur, il l'isole : tout ce qui reste de l'écart est noyau."
]
},
@@ -1255,6 +1368,64 @@
"\n",
"Console.WriteLine(\"Exercice a completer (decommentez le bloc ci-dessus).\");\n"
]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Diagnostic dérive\n",
+ "\n",
+ "**Cause (a) — environnement / résolution de chemin (#13959).** Les trois directives `#r` de la cellule\n",
+ "socle pointaient `../MetaGeneticSharp/...`, une profondeur de répertoire calculée quand ce\n",
+ "notebook vivait à la racine de `Part4-Metaheuristics/`. L'isolation des face-à-face\n",
+ "MGS ↔ mealpy dans la sous-série `MGS-vs-mealpy/` (#13959, déplacement `R100`) a ajouté un\n",
+ "niveau d'arborescence : `../MetaGeneticSharp` ne résolvait plus rien, la cellule socle ne\n",
+ "compilait plus, et les sorties — transportées telles quelles par le déplacement, jamais\n",
+ "re-confirmées par un run — se sont figées.\n",
+ "\n",
+ "**Correctif.** Les trois directives passent à `../../MetaGeneticSharp/...` (mêmes DLLs\n",
+ "`net9.0` Debug, même gitlink `78ce550`) et le notebook est ré-exécuté de bout en bout au\n",
+ "kernel `.net-csharp` réel, pont PythonNet vers mealpy 3.0.2. Aucune sortie n'est éditée à la\n",
+ "main.\n",
+ "\n",
+ "**Contradictions prose ↔ sorties, pré-existantes, corrigées dans le même passage.** Elles ont\n",
+ "survécu au gel des sorties précisément parce qu'aucun run ne les confrontait plus :\n",
+ "\n",
+ "- la lecture du socle annonçait une représentation R1 à `51 gènes` alors que la sortie du socle\n",
+ " en compte **36** (36 cellules vides, 45 indices fixes, 36 gènes) ;\n",
+ "- la lecture du croisement annonçait les graines 1/7/42 *en croisement* alors que le classifieur\n",
+ " imprimé les donne **mixtes** (et la graine 0 *persistante*), surestimait la position de MGS au\n",
+ " premier quart — MGS y est **déjà derrière sur la graine 0** (33 conflits contre 32) — et\n",
+ " recopiait des temps muraux absolus ;\n",
+ "- l'introduction et la lecture de la cellule formules affirmaient que **les sept** PSO mealpy\n",
+ " portent les constantes *w*/*c1*/*c2*, ce que le catalogue imprimé contredit pour `P_PSO`\n",
+ " (aucun paramètre listé). Vérifié in-source : `P_PSO` porte des coefficients sin/cos dynamiques,\n",
+ " pas les constantes de Clerc. La conclusion (« aucun n'est bare-bones ») tient ; la raison\n",
+ " invoquée est corrigée.\n",
+ "\n",
+ "**Verdict C.4 : `CAUSE_FIXED`.** Protocole inchangé — graines `{0, 1, 7, 42}`, population 50,\n",
+ "160 générations/epochs, 8 000 évaluations (MGS) / 8 050 (mealpy), représentation R1, fonction\n",
+ "de coût en conflits, checkpoints 25/50/75/100 %. Sur **sept** exécutions complètes — trois par\n",
+ "le moteur d'exécution (`dotnet_executor.py`), quatre par le wrapper canonique de la famille\n",
+ "(`exec_dotnet_persist.py`), la dernière fournissant les sorties committées — les grandeurs\n",
+ "déterministes — conflits finaux par graine, checkpoints, budget d'évaluations, drapeau `12/12`\n",
+ "bras-graines stables — sont **exactes et identiques** entre elles et à celles déjà committées :\n",
+ "la non-régression est **mesurée**, pas supposée. Seuls les temps muraux varient d'un passage\n",
+ "kernel à l'autre ; ils sont conservés en **rapport**, jamais en valeur absolue.\n",
+ "\n",
+ "**Verdict de performance : `NO IMPROVEMENT`.** Sur la taxonomie fermée `IMPROVES` /\n",
+ "`NO IMPROVEMENT` / `TRADE-OFF` / `INCONCLUSIVE`, ce grain vaut `NO IMPROVEMENT` : l'axe performance\n",
+ "est une **invariance mesurée contre le moteur mis à jour** — protocole, graines, budget\n",
+ "d'évaluations et fonction de coût sont identiques d'un bout à l'autre, mais les sorties\n",
+ "committées sortent d'un moteur reconstruit (`net9.0` Debug) et non de celui qui avait produit\n",
+ "les sorties gelées : l'égalité est **constatée** run après run, jamais déduite du seul\n",
+ "protocole. Seul le chemin de résolution des directives `#r` est corrigé. Le livrable n'est donc pas\n",
+ "un gain de performance\n",
+ "mais l'**exécutabilité restaurée** — cellule socle de nouveau compilable, notebook entier\n",
+ "relançable au kernel `.net-csharp` réel — assortie d'une **non-régression mesurée**. Les deux\n",
+ "verdicts coexistent sans se contredire : `CAUSE_FIXED` qualifie la cause de la dérive (fixée),\n",
+ "`NO IMPROVEMENT` qualifie l'axe performance (inchangé)."
+ ]
}
],
"metadata": {