From 35e22297e095fbb88160756f851c958987d5423d Mon Sep 17 00:00:00 2001 From: jsboige Date: Sat, 26 Sep 2026 22:44:53 +0200 Subject: [PATCH 1/5] enrich(ict,#17977): banc appris Huang sur hypercube vrai -- verdict pre-enregistre FAIL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ICT-15g ajoute le banc #17977 : reseaux booleens appris (MLP 16, numpy pur, CPU borne) mesures sur l'hypercube 3-4 bits avec VRAI degre de Fourier-Walsh (reserve #9771 : plus de proxy de masse) et s_max exact definition Huang (distinct de la sensibilite sur graphe observe du banc herite, reserve #9764 : saturation testee, 46 % au plafond < 75 %). - Pre-enregistrement complet scelle avant mesure : encodage, seuils, graines {0,1,7,42}, cibles OR/AND/MAJ/PAR/TRI_bal, garde anti-degenerescence (21,2 % comptes honnetement), 3 amendements pre-execution documentes (gradient BCE signe faux, BCE equilibree, lambda=0.5) calibres sur graines disjointes {11,22} - Entrainement normal vs adversarial (pire voisin Hamming-1) : 28 paires appariees -- 27 delta=0, la prediction P1 est REFUTEE, verdict FAIL livre sans re-seuillage - Controles : untrained (meme init) + bande aleatoire appariee en degre (n=3 exhaustive 256/256, n=4 3000 tirages) -- 100 % des ratios appris dans la bande aléatoire : le ratio ne discrimine pas une fonction apprise - Huang verifie mecaniquement : 0/118 tables realisees, 256/256 exhaustif n=3 - Matrice dissociations : rangee ICT-15g (strate 5) ; formulation "transposition conjecturale" conservee pour le banc herite - Execution Papermill reelle 13/13 cellules, 0 erreur, outputs committes ; exercices et cellules originaux preserves (seul le statut epistemique, cellule 1, est mis a jour) ; ict/sensitivity.py intact See #17977, #4588, #7288, #9771, #9764 Co-Authored-By: Claude Sonnet 5 --- .../ICT-15g-EmpiricalHuangExploitation.ipynb | 1023 +++++++++++++++-- docs/ict/dissociations-matrix.md | 1 + 2 files changed, 912 insertions(+), 112 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb index d91ece0c8d..f05e67a167 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb @@ -5,10 +5,10 @@ "id": "ict-15b-empirical-cadrage", "metadata": { "papermill": { - "duration": 0.001791, - "end_time": "2026-09-01T06:42:01.493086+00:00", + "duration": 0.007972, + "end_time": "2026-09-26T20:41:46.959427+00:00", "exception": false, - "start_time": "2026-09-01T06:42:01.491295+00:00", + "start_time": "2026-09-26T20:41:46.951455+00:00", "status": "completed" }, "tags": [] @@ -65,9 +65,18 @@ { "cell_type": "markdown", "id": "statut-epistemique", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.005548, + "end_time": "2026-09-26T20:41:46.970393+00:00", + "exception": false, + "start_time": "2026-09-26T20:41:46.964845+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ - "> **Statut épistémique** — **Sans verdict à ce jour** : aucune ligne de la [matrice de dissociations](../../../docs/ict/dissociations-matrix.md) ne concerne ce notebook ; son statut épistémique sera porté par la matrice le cas échéant." + "> **Statut épistémique** — Deux strates. (1) Le banc hérité (cellules 2 à 9 : conjecture `s_max ≥ √deg_proxy` sur graphes de transition markoviens) reste une **transposition conjecturale, sans verdict** : ses verdicts par substrat sont des repères d'instrument, pas des théorèmes. (2) Le **banc appris [#17977](https://github.com/jsboige/CoursIA/issues/17977)** (fin de notebook) livre un verdict pré-enregistré **FAIL** — réfutation honnête de la prédiction « l'adversarial réduit s_max » (27/28 paires Δ = 0) sur l'hypercube vrai, où la borne de Huang est un théorème vérifié mécaniquement (0/118 violations). Reporté dans la [matrice de dissociations](../../../docs/ict/dissociations-matrix.md), ligne **ICT-15g**." ] }, { @@ -76,16 +85,16 @@ "id": "ict-15b-empirical-imports", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:01.496073Z", - "iopub.status.busy": "2026-09-01T06:42:01.496073Z", - "iopub.status.idle": "2026-09-01T06:42:01.942336Z", - "shell.execute_reply": "2026-09-01T06:42:01.940711Z" + "iopub.execute_input": "2026-09-26T20:41:46.978615Z", + "iopub.status.busy": "2026-09-26T20:41:46.978225Z", + "iopub.status.idle": "2026-09-26T20:41:50.231696Z", + "shell.execute_reply": "2026-09-26T20:41:50.230677Z" }, "papermill": { - "duration": 0.448746, - "end_time": "2026-09-01T06:42:01.943285+00:00", + "duration": 3.258325, + "end_time": "2026-09-26T20:41:50.232957+00:00", "exception": false, - "start_time": "2026-09-01T06:42:01.494539+00:00", + "start_time": "2026-09-26T20:41:46.974632+00:00", "status": "completed" }, "tags": [] @@ -127,16 +136,16 @@ "id": "ict-15b-empirical-sanity", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:01.950896Z", - "iopub.status.busy": "2026-09-01T06:42:01.949889Z", - "iopub.status.idle": "2026-09-01T06:42:01.956710Z", - "shell.execute_reply": "2026-09-01T06:42:01.955565Z" + "iopub.execute_input": "2026-09-26T20:41:50.242761Z", + "iopub.status.busy": "2026-09-26T20:41:50.242357Z", + "iopub.status.idle": "2026-09-26T20:41:50.252599Z", + "shell.execute_reply": "2026-09-26T20:41:50.250809Z" }, "papermill": { - "duration": 0.011361, - "end_time": "2026-09-01T06:42:01.957602+00:00", + "duration": 0.017114, + "end_time": "2026-09-26T20:41:50.253693+00:00", "exception": false, - "start_time": "2026-09-01T06:42:01.946241+00:00", + "start_time": "2026-09-26T20:41:50.236579+00:00", "status": "completed" }, "tags": [] @@ -192,10 +201,10 @@ "id": "ict-15b-empirical-methode", "metadata": { "papermill": { - "duration": 0.002473, - "end_time": "2026-09-01T06:42:01.963056+00:00", + "duration": 0.004353, + "end_time": "2026-09-26T20:41:50.261260+00:00", "exception": false, - "start_time": "2026-09-01T06:42:01.960583+00:00", + "start_time": "2026-09-26T20:41:50.256907+00:00", "status": "completed" }, "tags": [] @@ -228,16 +237,16 @@ "id": "ict-15b-empirical-gray-scott", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:01.969661Z", - "iopub.status.busy": "2026-09-01T06:42:01.969156Z", - "iopub.status.idle": "2026-09-01T06:42:02.051825Z", - "shell.execute_reply": "2026-09-01T06:42:02.050244Z" + "iopub.execute_input": "2026-09-26T20:41:50.269795Z", + "iopub.status.busy": "2026-09-26T20:41:50.269255Z", + "iopub.status.idle": "2026-09-26T20:41:50.407876Z", + "shell.execute_reply": "2026-09-26T20:41:50.407066Z" }, "papermill": { - "duration": 0.087294, - "end_time": "2026-09-01T06:42:02.052646+00:00", + "duration": 0.144242, + "end_time": "2026-09-26T20:41:50.408600+00:00", "exception": false, - "start_time": "2026-09-01T06:42:01.965352+00:00", + "start_time": "2026-09-26T20:41:50.264358+00:00", "status": "completed" }, "tags": [] @@ -285,16 +294,16 @@ "id": "ict-15b-empirical-axelrod", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.058337Z", - "iopub.status.busy": "2026-09-01T06:42:02.058337Z", - "iopub.status.idle": "2026-09-01T06:42:02.236338Z", - "shell.execute_reply": "2026-09-01T06:42:02.235748Z" + "iopub.execute_input": "2026-09-26T20:41:50.415091Z", + "iopub.status.busy": "2026-09-26T20:41:50.414903Z", + "iopub.status.idle": "2026-09-26T20:41:50.666528Z", + "shell.execute_reply": "2026-09-26T20:41:50.665644Z" }, "papermill": { - "duration": 0.182635, - "end_time": "2026-09-01T06:42:02.238250+00:00", + "duration": 0.25593, + "end_time": "2026-09-26T20:41:50.667335+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.055615+00:00", + "start_time": "2026-09-26T20:41:50.411405+00:00", "status": "completed" }, "tags": [] @@ -345,16 +354,16 @@ "id": "ict-15b-empirical-grokking", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.243368Z", - "iopub.status.busy": "2026-09-01T06:42:02.243368Z", - "iopub.status.idle": "2026-09-01T06:42:02.252040Z", - "shell.execute_reply": "2026-09-01T06:42:02.251448Z" + "iopub.execute_input": "2026-09-26T20:41:50.673909Z", + "iopub.status.busy": "2026-09-26T20:41:50.673557Z", + "iopub.status.idle": "2026-09-26T20:41:50.681048Z", + "shell.execute_reply": "2026-09-26T20:41:50.679965Z" }, "papermill": { - "duration": 0.012387, - "end_time": "2026-09-01T06:42:02.253476+00:00", + "duration": 0.01191, + "end_time": "2026-09-26T20:41:50.681855+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.241089+00:00", + "start_time": "2026-09-26T20:41:50.669945+00:00", "status": "completed" }, "tags": [] @@ -408,16 +417,16 @@ "id": "ict-15b-empirical-may", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.261063Z", - "iopub.status.busy": "2026-09-01T06:42:02.260057Z", - "iopub.status.idle": "2026-09-01T06:42:02.283278Z", - "shell.execute_reply": "2026-09-01T06:42:02.282274Z" + "iopub.execute_input": "2026-09-26T20:41:50.691347Z", + "iopub.status.busy": "2026-09-26T20:41:50.691038Z", + "iopub.status.idle": "2026-09-26T20:41:50.711636Z", + "shell.execute_reply": "2026-09-26T20:41:50.710819Z" }, "papermill": { - "duration": 0.027555, - "end_time": "2026-09-01T06:42:02.284315+00:00", + "duration": 0.026944, + "end_time": "2026-09-26T20:41:50.712666+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.256760+00:00", + "start_time": "2026-09-26T20:41:50.685722+00:00", "status": "completed" }, "tags": [] @@ -466,16 +475,16 @@ "id": "ict-15b-empirical-cross-substrat", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.291824Z", - "iopub.status.busy": "2026-09-01T06:42:02.290304Z", - "iopub.status.idle": "2026-09-01T06:42:02.314155Z", - "shell.execute_reply": "2026-09-01T06:42:02.313571Z" + "iopub.execute_input": "2026-09-26T20:41:50.720051Z", + "iopub.status.busy": "2026-09-26T20:41:50.719688Z", + "iopub.status.idle": "2026-09-26T20:41:50.731977Z", + "shell.execute_reply": "2026-09-26T20:41:50.730942Z" }, "papermill": { - "duration": 0.02795, - "end_time": "2026-09-01T06:42:02.315459+00:00", + "duration": 0.016612, + "end_time": "2026-09-26T20:41:50.732850+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.287509+00:00", + "start_time": "2026-09-26T20:41:50.716238+00:00", "status": "completed" }, "tags": [] @@ -548,10 +557,10 @@ "id": "ict-15b-empirical-interp-cross", "metadata": { "papermill": { - "duration": 0.002744, - "end_time": "2026-09-01T06:42:02.321334+00:00", + "duration": 0.003393, + "end_time": "2026-09-26T20:41:50.739845+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.318590+00:00", + "start_time": "2026-09-26T20:41:50.736452+00:00", "status": "completed" }, "tags": [] @@ -581,10 +590,10 @@ "id": "ict-15b-empirical-exo1-md", "metadata": { "papermill": { - "duration": 0.002496, - "end_time": "2026-09-01T06:42:02.326574+00:00", + "duration": 0.002301, + "end_time": "2026-09-26T20:41:50.744763+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.324078+00:00", + "start_time": "2026-09-26T20:41:50.742462+00:00", "status": "completed" }, "tags": [] @@ -605,16 +614,16 @@ "id": "ict-15b-empirical-exo1-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.332983Z", - "iopub.status.busy": "2026-09-01T06:42:02.331984Z", - "iopub.status.idle": "2026-09-01T06:42:02.345595Z", - "shell.execute_reply": "2026-09-01T06:42:02.345092Z" + "iopub.execute_input": "2026-09-26T20:41:50.755742Z", + "iopub.status.busy": "2026-09-26T20:41:50.755180Z", + "iopub.status.idle": "2026-09-26T20:41:50.760976Z", + "shell.execute_reply": "2026-09-26T20:41:50.760014Z" }, "papermill": { - "duration": 0.018198, - "end_time": "2026-09-01T06:42:02.347367+00:00", + "duration": 0.012947, + "end_time": "2026-09-26T20:41:50.761744+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.329169+00:00", + "start_time": "2026-09-26T20:41:50.748797+00:00", "status": "completed" }, "tags": [] @@ -665,10 +674,10 @@ "id": "ict-15b-empirical-exo2-md", "metadata": { "papermill": { - "duration": 0.002735, - "end_time": "2026-09-01T06:42:02.353282+00:00", + "duration": 0.002979, + "end_time": "2026-09-26T20:41:50.769158+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.350547+00:00", + "start_time": "2026-09-26T20:41:50.766179+00:00", "status": "completed" }, "tags": [] @@ -695,16 +704,16 @@ "id": "ict-15b-empirical-exo2-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.359646Z", - "iopub.status.busy": "2026-09-01T06:42:02.359646Z", - "iopub.status.idle": "2026-09-01T06:42:02.377207Z", - "shell.execute_reply": "2026-09-01T06:42:02.376698Z" + "iopub.execute_input": "2026-09-26T20:41:50.776444Z", + "iopub.status.busy": "2026-09-26T20:41:50.776182Z", + "iopub.status.idle": "2026-09-26T20:41:50.788323Z", + "shell.execute_reply": "2026-09-26T20:41:50.786931Z" }, "papermill": { - "duration": 0.022647, - "end_time": "2026-09-01T06:42:02.378618+00:00", + "duration": 0.016446, + "end_time": "2026-09-26T20:41:50.789270+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.355971+00:00", + "start_time": "2026-09-26T20:41:50.772824+00:00", "status": "completed" }, "tags": [] @@ -755,10 +764,10 @@ "id": "ict-15b-empirical-exo3-md", "metadata": { "papermill": { - "duration": 0.002742, - "end_time": "2026-09-01T06:42:02.384918+00:00", + "duration": 0.003088, + "end_time": "2026-09-26T20:41:50.795087+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.382176+00:00", + "start_time": "2026-09-26T20:41:50.791999+00:00", "status": "completed" }, "tags": [] @@ -825,16 +834,16 @@ "id": "ict-15b-empirical-exo3-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-01T06:42:02.392020Z", - "iopub.status.busy": "2026-09-01T06:42:02.392020Z", - "iopub.status.idle": "2026-09-01T06:42:02.438661Z", - "shell.execute_reply": "2026-09-01T06:42:02.438070Z" + "iopub.execute_input": "2026-09-26T20:41:50.802331Z", + "iopub.status.busy": "2026-09-26T20:41:50.801962Z", + "iopub.status.idle": "2026-09-26T20:41:50.853258Z", + "shell.execute_reply": "2026-09-26T20:41:50.852480Z" }, "papermill": { - "duration": 0.051933, - "end_time": "2026-09-01T06:42:02.439958+00:00", + "duration": 0.055885, + "end_time": "2026-09-26T20:41:50.853798+00:00", "exception": false, - "start_time": "2026-09-01T06:42:02.388025+00:00", + "start_time": "2026-09-26T20:41:50.797913+00:00", "status": "completed" }, "tags": [] @@ -846,22 +855,9 @@ "text": [ "=== Verdict de Cech recalcule sur les trajectoires de CE notebook ===\n", " gray_scott : TRIVIAL | s2/s1=1.0000 | rank=3 | cob=0.0000 | n_windows=30\n", - " axelrod : TRIVIAL | s2/s1=0.0572 | rank=1 | cob=0.0806 | n_windows=30\n", - " grokking : NON_TRIVIAL | s2/s1=0.6627 | rank=3 | cob=0.7767 | n_windows=30\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " may : NON_TRIVIAL | s2/s1=0.4081 | rank=3 | cob=0.5992 | n_windows=30" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", + " axelrod : TRIVIAL | s2/s1=0.0000 | rank=1 | cob=0.0000 | n_windows=30\n", + " grokking : NON_TRIVIAL | s2/s1=0.6627 | rank=3 | cob=0.7767 | n_windows=30\n", + " may : NON_TRIVIAL | s2/s1=0.4081 | rank=3 | cob=0.5992 | n_windows=30\n", "\n", "Exercice a completer : table de comparaison + conclusion.\n" ] @@ -914,6 +910,809 @@ "print(\"\")\n", "print(\"Exercice a completer : table de comparaison + conclusion.\")\n" ] + }, + { + "cell_type": "markdown", + "id": "5d784bf7", + "metadata": { + "id": "ict-15g-learned-prereg", + "papermill": { + "duration": 0.002474, + "end_time": "2026-09-26T20:41:50.858890+00:00", + "exception": false, + "start_time": "2026-09-26T20:41:50.856416+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Banc appris (#17977) — où le ratio s_max / √deg sature-t-il sur de petits réseaux appris ?\n", + "\n", + "*See [#17977](https://github.com/jsboige/CoursIA/issues/17977) — Part of [#4588](https://github.com/jsboige/CoursIA/issues/4588), suite de [#7288](https://github.com/jsboige/CoursIA/issues/7288) (ICT-15b) et des réserves mesurées [#9771](https://github.com/jsboige/CoursIA/issues/9771) / [#9764](https://github.com/jsboige/CoursIA/issues/9764).*\n", + "\n", + "Le banc précédent (cellules 2 à 9) transpose Huang sur des **graphes de transition markoviens** — une **transposition conjecturale** : l'hypercube, la régularité du graphe et le degré polynomial y sont remplacés par des proxys. Ce statut est **conservé** pour ce banc legacy et pour la lecture ICT qui en découle. Le présent banc ajoute le chaînon demandé par #17977 : des **réseaux booléens réellement appris**, mesurés sur l'**hypercube vrai** — là où l'inégalité de Huang est un **théorème** (l'instrument est calibré par le théorème ; la question empirique porte ailleurs : la saturation du ratio et le déplacement par entraînement adversarial).\n", + "\n", + "**Question (#17977)** : pour des fonctions booléennes apprises par de petits réseaux, où le ratio s_max / √deg sature-t-il ? L'entraînement adversarial déplace-t-il ce ratio, et dans quel sens ?\n", + "\n", + "### Pré-enregistrement (scellé AVANT toute mesure)\n", + "\n", + "Les définitions, seuils, graines, cibles et prédictions ci-dessous sont figées avant l'inspection de toute sortie. Toute déviation sera signalée dans l'interprétation.\n", + "\n", + "**Encodage pré-défini** (réserve #9771 : le VRAI degré de Fourier, pas un proxy de masse) :\n", + "\n", + "- entrées `b ∈ {0,1}^n`, encodage `x = 1 − 2b ∈ {−1,+1}^n` ;\n", + "- réseau `g : R^n → R` (MLP `n → 16 (tanh) → 1 (linéaire)`), fonction réalisée `f̂(x) = +1 si g(x) ≥ 0, −1 sinon` (table de vérité complète, déterministe) ;\n", + "- coefficients de Fourier-Walsh `f̂(S) = 2^{−n} Σ_x f(x) χ_S(x)` avec `χ_S(x) = Π_{i∈S} x_i` ;\n", + "- **degré réel** : `deg(f) = max{|S| : |f̂(S)| > TOL}` avec `TOL = 1e-9` — les tables sont exactes, les coefficients sont des multiples de `2^{1−n}` : la tolérance stricte est légitime ;\n", + "- **s_max exact sur l'hypercube** `Q_n` : `s_max(f) = max_x |{i : f(x ⊕ e_i) ≠ f(x)}|` — c'est la **définition de Huang**, **distincte** de la sensibilité sur graphe de transition observé (`ict.sensitivity.local_sensitivity`, banc legacy ci-dessus). Les deux grandeurs sont nommées séparément et jamais mélangées.\n", + "\n", + "**Design gelé** :\n", + "\n", + "| Élément | Valeur |\n", + "|---|---|\n", + "| tailles | `n ∈ {3, 4}` (tables de 8 / 16 entrées, CPU borné) |\n", + "| cibles (labels contrôlés) | `OR_n`, `AND_n`, `MAJ_n` (n=3 : ≥2 ; n=4 : ≥3), `PAR_n`, `TRI_bal_n` (table aléatoire équilibrée, graine `20260720 + n`, imprimée dans la sortie) |\n", + "| graines de test | `{0, 1, 7, 42}` (≥ 2 exigé) ; par graine : init du réseau et split 75 % train / 25 % holdout déterministes (rng séparés), **identiques entre les deux régimes** (paires appariées) |\n", + "| régimes | `normal` = BCE **équilibrée par classe** sur les points train ; `adversarial` = BCE(train) + **0,5 ×** BCE du **pire voisin Hamming-1** de chaque point train (adversaire discret exact à rayon 1, label du point propre ; λ = 0,5, cf. amendements) |\n", + "| budget | 400 étapes Adam lr 0.05, full batch — budget FIXE, convergence non forcée (c'est l'écart de généralisation qui porte le signal) |\n", + "| garde anti-dégénérescence (régimes entraînés) | entrée marquée `degenerate` si table réalisée constante OU train_acc < 0.9 ; exclue des verdicts, comptée honnêtement (réserve : éviter les réseaux constants vacuous) ; pour le contrôle `untrained`, seule la constance exclut (aucune exigence d'accuracy à 0 étape) |\n", + "\n", + "**Contrôles** :\n", + "\n", + "1. réseau non entraîné (même init que la paire, 0 étape) ;\n", + "2. bande aléatoire appariée en degré : n=3 **exhaustive** (les 256 fonctions booléennes), n=4 échantillon de 3000 fonctions uniformes — distribution de référence du ratio par degré.\n", + "\n", + "**Prédictions falsifiables** :\n", + "\n", + "- **P1 (la question de l'issue)** : l'entraînement adversarial **réduit** s_max de la fonction réalisée. CONFIRMÉE ssi (i) `n_paires ≥ 8` (paires non-dégénérées des deux côtés), (ii) `médiane(Δs_max = s_max_adv − s_max_norm) < 0`, (iii) `#{Δ < 0} > #{Δ > 0}` (les égalités à 0 ne comptent pour aucun camp).\n", + "- **P2 (gate instrument — théorème, pas prédiction)** : toute table réalisée non constante satisfait `s_max ≥ √deg` (Huang sur Q_n). Violation = bug instrument → verdict `INVALID`.\n", + "- **P3 (contrôle untrained)** : `médiane(s_max_norm) ≤ médiane(s_max_untrained)` — l'entraînement sur labels contrôlés n'augmente pas la sensibilité médiane.\n", + "- **P4 (résolution / saturation, réserves #9771-#9764)** : au moins **2 degrés distincts** parmi les tables réalisées non-dégénérées des régimes entraînés, ET fraction des entrées entraînées (non-dégénérées) au plafond structurel `s_max = n` **strictement inférieure à 3/4** (la mesure ne sature pas).\n", + "\n", + "**Verdict global pré-enregistré** :\n", + "\n", + "| Condition | Verdict |\n", + "|---|---|\n", + "| P2 violée ou gates instrument en échec | `INVALID` |\n", + "| P4 non tenue, ou n_paires < 8, ou fraction de dégénérés > 1/3 (régimes entraînés) | `INCONCLUSIVE` |\n", + "| P1 confirmée (hors régime INCONCLUSIVE) | `PASS` |\n", + "| P1 réfutée (`médiane(Δ) ≥ 0` ou direction inversée) hors régime INCONCLUSIVE | `FAIL` |\n", + "\n", + "Le verdict porte sur P1 (déplacement du ratio par l'adversarial, sens prédit : vers le bas) ; P3 et P4 sont des contrôles rapportés, pas des conditions du verdict.\n", + "\n", + "### Amendements pré-exécution (scellés AVANT l'exécution de test ; graines 0/1/7/42 vierges)\n", + "\n", + "Trois corrections d'**instrument**, calibrées sur des **graines de calibration disjointes {11, 22}** (jamais relues sur les graines de test), avec pour seul critère la **santé de l'instrument** — taux de dégénérés et train_acc du régime normal —, jamais le signal Δs_max. **Aucun seuil de verdict n'a bougé** (P1-P4, bornes, graines de test, garde anti-dégénérescence : inchangés).\n", + "\n", + "1. **Gradient BCE (v1 → v2)** : la première version codait `dL/dz = −y·σ(y·z)` au lieu de `−y·σ(−y·z)` — un gradient de signe faut qui plafonnait train_acc vers 0,5-0,85 en rendant la confiance répulsive. Corrigé + gate optimiseur ajoutée (fit parfait de MAJ_3 sur table complète, graine 11).\n", + "2. **BCE équilibrée par classe (v2)** : poids `1/(2·fréquence de classe)` normalisés — sans elle, les cibles déséquilibrées (OR/AND : `2^n − 1` contre 1) convergent vers la constante vacuous, précisément ce que la garde anti-dégénérescence doit éviter de produire en masse.\n", + "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre et l'apprentissage échoue (mesuré en calibration : 57,5 % de dégénérés). λ = 0,5 (poids à la TRADES) restaure l'apprentissage (train_acc 1,0 en calibration sur 18/20 bras adversariaux) en conservant la pression de lissage local — c'est l'objet même de la question P1." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ae365629", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T20:41:50.865487Z", + "iopub.status.busy": "2026-09-26T20:41:50.865072Z", + "iopub.status.idle": "2026-09-26T20:41:51.020500Z", + "shell.execute_reply": "2026-09-26T20:41:51.020103Z" + }, + "id": "ict-15g-learned-instrument", + "papermill": { + "duration": 0.159752, + "end_time": "2026-09-26T20:41:51.021199+00:00", + "exception": false, + "start_time": "2026-09-26T20:41:50.861447+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Gates instrument (valeurs de reference) ===\n", + " dictateur_4 : deg=1 (attendu 1), s_max=1 (attendu 1) -> OK\n", + " OR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", + " MAJ_3 : deg=3 (attendu 3), s_max=2 (attendu 2) -> OK\n", + " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : 0 violation(s)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " gate optimiseur (MAJ_3 complet, graine 11 disjointe) : train_acc normal = 1.000, adversarial (lam=0.5) = 1.000 (attendus 1.0 / >= 0.9)\n", + "Gates instrument PASS : l instrument discrimine (deg et s_max exacts), respecte Huang sur n=3, et l optimiseur converge (normal ET adversarial lam=0.5).\n" + ] + } + ], + "source": [ + "# --- Banc #17977 : instrument -- degre de Fourier REEL + sensibilite hypercube exacte ---\n", + "# Reserve #9771 : le degre mesure ici est le VRAI degre de Fourier-Walsh de la table de\n", + "# verite complete, pas un proxy de masse de probabilite.\n", + "# Reserve #9764 : la saturation de la mesure est testee explicitement (gate P4) avant\n", + "# tout verdict. numpy pur, CPU borne, deterministe (rng explicites, aucun alea cache).\n", + "import itertools\n", + "\n", + "TOL_FOURIER = 1e-9 # pre-enregistre : coefficients multiples de 2^{1-n}, tolerance stricte legitime\n", + "\n", + "\n", + "def hypercube_inputs(n):\n", + " \"\"\"Encodage pre-defini : b in {0,1}^n -> x = 1 - 2*b in {-1,+1}^n (ordre lexicographique).\"\"\"\n", + " B = np.array(list(itertools.product([0, 1], repeat=n)), dtype=float)\n", + " return 1.0 - 2.0 * B\n", + "\n", + "\n", + "def fourier_degree(table_pm1, n):\n", + " \"\"\"Degre de Fourier-Walsh REEL de f : {-1,+1}^n -> {-1,+1} (table sur l'hypercube ordonne).\n", + "\n", + " f_hat(S) = 2^{-n} * sum_x f(x) * chi_S(x), chi_S(x) = prod_{i in S} x_i.\n", + " deg(f) = max{ |S| : |f_hat(S)| > TOL_FOURIER }. Constante -> deg = 0.\n", + " \"\"\"\n", + " X = hypercube_inputs(n)\n", + " deg = 0\n", + " for k in range(n + 1):\n", + " for S in itertools.combinations(range(n), k):\n", + " chi = np.prod(X[:, list(S)], axis=1) if S else np.ones(len(X))\n", + " if abs(float(np.mean(table_pm1 * chi))) > TOL_FOURIER:\n", + " deg = max(deg, k)\n", + " return deg\n", + "\n", + "\n", + "def hypercube_sensitivity(table_pm1, n):\n", + " \"\"\"Sensibilite EXACTE s_x(f) sur l'hypercube Q_n (definition de Huang).\n", + "\n", + " Distincte de la sensibilite sur graphe de transition observe (banc legacy,\n", + " ict.sensitivity.local_sensitivity) : ici le voisinage est TOUJOURS l'ensemble\n", + " des n voisins Hamming-1 de l'hypercube, sans observation ni lissage.\n", + " \"\"\"\n", + " X = hypercube_inputs(n)\n", + " index = {tuple(x): i for i, x in enumerate(X)}\n", + " s = np.zeros(len(X), dtype=int)\n", + " for i, x in enumerate(X):\n", + " flips = 0\n", + " for j in range(n):\n", + " x_nb = x.copy()\n", + " x_nb[j] = -x_nb[j]\n", + " flips += int(table_pm1[index[tuple(x_nb)]] != table_pm1[i])\n", + " s[i] = flips\n", + " return s\n", + "\n", + "\n", + "# --- Petit MLP numpy (CPU borne, deterministe) ---\n", + "class TinyMLP:\n", + " \"\"\"MLP n -> hidden(tanh) -> 1 (lineaire), gradient manuel, Adam externe.\"\"\"\n", + "\n", + " def __init__(self, n, hidden=16, seed=None):\n", + " r = np.random.default_rng(seed)\n", + " self.W1 = r.uniform(-1.0, 1.0, size=(n, hidden)) / np.sqrt(n)\n", + " self.b1 = np.zeros(hidden)\n", + " self.W2 = r.uniform(-1.0, 1.0, size=hidden) / np.sqrt(hidden)\n", + " self.b2 = np.zeros(1)\n", + " self._X = None\n", + " self._h = None\n", + "\n", + " def forward(self, X):\n", + " self._X = X\n", + " self._h = np.tanh(X @ self.W1 + self.b1)\n", + " return self._h @ self.W2 + self.b2[0]\n", + "\n", + " def params(self):\n", + " return [self.W1, self.b1, self.W2, self.b2]\n", + "\n", + " def backward(self, dlogit):\n", + " gW2 = self._h.T @ dlogit\n", + " gb2 = np.array([dlogit.sum()])\n", + " dh = np.outer(dlogit, self.W2) * (1.0 - self._h ** 2)\n", + " gW1 = self._X.T @ dh\n", + " gb1 = dh.sum(axis=0)\n", + " return [gW1, gb1, gW2, gb2]\n", + "\n", + "\n", + "def _sigmoid(v):\n", + " return 0.5 * (1.0 + np.tanh(0.5 * v)) # stable\n", + "\n", + "\n", + "def bce_with_logits(z, y, w=None):\n", + " \"\"\"BCE moyenne avec logits, y in {-1,+1} : L = mean softplus(-y*z).\n", + "\n", + " w : poids optionnels par point (normalises, moyenne 1) -- ponderation equilibree\n", + " par classe pour eviter que les cibles desequilibrees (OR/AND : 2^n - 1 contre 1)\n", + " ne convergent vers la constante vacuous (amendement pre-execution v2).\n", + " dL/dz_i = -y_i * sigma(-y_i*z_i) * w_i / m (sigma(-u) = 1 - sigma(u)).\n", + " \"\"\"\n", + " u = -y * z\n", + " if w is None:\n", + " w = np.ones_like(z)\n", + " loss = float(np.mean(w * np.logaddexp(0.0, u)))\n", + " dz = -(w * y * _sigmoid(u)) / len(z)\n", + " return loss, dz\n", + "\n", + "\n", + "def _class_balance_weights(ytr):\n", + " \"\"\"Poids 1/(2*freq_classe), normalises a la moyenne 1 (ponderation equilibree).\"\"\"\n", + " frac_pos = float(np.mean(ytr > 0))\n", + " w = np.where(ytr > 0, 0.5 / max(frac_pos, 1e-9), 0.5 / max(1.0 - frac_pos, 1e-9))\n", + " return w / w.mean()\n", + "\n", + "\n", + "def train_mlp(n, Xtr, ytr, *, regime, seed, steps=400, lr=0.05, lam=0.5):\n", + " \"\"\"Entraine un TinyMLP ; regime in {'normal', 'adversarial', 'untrained'}.\n", + "\n", + " normal : L = BCE equilibree(g(Xtr), y).\n", + " adversarial : L = BCE equilibree(g(Xtr), y) + lam * BCE equilibree(g(x_adv), y)\n", + " ou x_adv est le pire voisin Hamming-1 de chaque point train\n", + " (adversaire discret exact a rayon 1, label du point propre).\n", + " lam = 0.5 (amendement pre-execution v3) : a rayon 1 sur l'hypercube,\n", + " le pire voisin porte souvent le label oppose (toujours pour PAR) ;\n", + " lam = 1 rend l'apprentissage impossible (57,5 % de degeneres en\n", + " calibration sur graines disjointes 11/22) ; lam = 0.5 restaure\n", + " l'apprentissage en conservant la pression de lissage local.\n", + " untrained : reseau a l'initialisation (controle, 0 etape).\n", + " \"\"\"\n", + " net = TinyMLP(n, seed=seed)\n", + " if regime == 'untrained':\n", + " return net\n", + " w = _class_balance_weights(ytr)\n", + " params = net.params()\n", + " m_a = [np.zeros_like(p) for p in params]\n", + " v_a = [np.zeros_like(p) for p in params]\n", + " beta1, beta2, eps = 0.9, 0.999, 1e-8\n", + " for t in range(1, steps + 1):\n", + " z = net.forward(Xtr)\n", + " _, dl = bce_with_logits(z, ytr, w)\n", + " grads = net.backward(dl)\n", + " if regime == 'adversarial':\n", + " Xnb = np.repeat(Xtr[:, None, :], n, axis=1).copy()\n", + " jj = np.arange(n)\n", + " Xnb[:, jj, jj] *= -1.0 # Xnb[i, j] = Xtr[i] avec coord j basculee\n", + " znb = net.forward(Xnb.reshape(-1, n)).reshape(len(Xtr), n)\n", + " losses_nb = np.logaddexp(0.0, -ytr[:, None] * znb)\n", + " worst = np.argmax(losses_nb, axis=1)\n", + " X_adv = Xnb[np.arange(len(Xtr)), worst]\n", + " z_adv = net.forward(X_adv)\n", + " _, dl_adv = bce_with_logits(z_adv, ytr, w)\n", + " g_adv = net.backward(dl_adv * lam)\n", + " grads = [g + ga for g, ga in zip(grads, g_adv)]\n", + " for k, (p, g) in enumerate(zip(params, grads)):\n", + " m_a[k] = beta1 * m_a[k] + (1.0 - beta1) * g\n", + " v_a[k] = beta2 * v_a[k] + (1.0 - beta2) * (g * g)\n", + " mh = m_a[k] / (1.0 - beta1 ** t)\n", + " vh = v_a[k] / (1.0 - beta2 ** t)\n", + " p -= lr * mh / (np.sqrt(vh) + eps)\n", + " return net\n", + "\n", + "\n", + "# --- Gates instrument : retrouver les valeurs de reference AVANT toute mesure (pattern L934) ---\n", + "def _ref_tables(n):\n", + " B = np.array(list(itertools.product([0, 1], repeat=n)))\n", + " s1 = B.sum(axis=1)\n", + " return {\n", + " f'dictateur_{n}': (B[:, 0] == 1).astype(int),\n", + " f'OR_{n}': (s1 >= 1).astype(int),\n", + " f'AND_{n}': (s1 == n).astype(int),\n", + " f'MAJ_{n}': (s1 >= n // 2 + 1).astype(int),\n", + " f'PAR_{n}': (s1 % 2).astype(int),\n", + " }\n", + "\n", + "\n", + "# valeurs classiques, verifiees a la main. MAJ_3 : s_max = 2 (les points de poids 1 et 2\n", + "# ont exactement 2 voisins qui basculent la majorite ; 2 >= sqrt(3), Huang tient). Une\n", + "# premiere version de ce gate attendait s_max = 3 par erreur de calcul manuel -- c'est le\n", + "# gate qui a raison, correction apportee AVANT toute mesure du banc.\n", + "gates_attendus = {\n", + " 'dictateur_4': (1, 1),\n", + " 'OR_4': (4, 4),\n", + " 'MAJ_3': (3, 2),\n", + " 'PAR_4': (4, 4),\n", + "}\n", + "print('=== Gates instrument (valeurs de reference) ===')\n", + "all_gates_ok = True\n", + "for name, (deg_att, smax_att) in gates_attendus.items():\n", + " n_g = int(name[-1])\n", + " tab = 1.0 - 2.0 * _ref_tables(n_g)[name].astype(float)\n", + " d_g = fourier_degree(tab, n_g)\n", + " s_g = int(hypercube_sensitivity(tab, n_g).max())\n", + " ok = (d_g == deg_att) and (s_g == smax_att)\n", + " all_gates_ok &= ok\n", + " print(f' {name:>12} : deg={d_g} (attendu {deg_att}), s_max={s_g} (attendu {smax_att}) -> {\"OK\" if ok else \"ECHEC\"}')\n", + "\n", + "# Verification EXHAUSTIVE du theoreme de Huang sur n=3 : les 256 fonctions booleennes\n", + "n_viol_huang = 0\n", + "for v in range(2 ** (2 ** 3)):\n", + " tab = 1.0 - 2.0 * np.array([(v >> i) & 1 for i in range(8)], dtype=float)\n", + " if np.all(tab == tab[0]):\n", + " continue # constante : deg = 0, inegalite triviale\n", + " d_h = fourier_degree(tab, 3)\n", + " s_h = int(hypercube_sensitivity(tab, 3).max())\n", + " if s_h < np.sqrt(d_h) - 1e-12:\n", + " n_viol_huang += 1\n", + "print(f' theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : {n_viol_huang} violation(s)')\n", + "all_gates_ok &= (n_viol_huang == 0)\n", + "\n", + "# Gate optimiseur (amendements v2/v3) : le gradient corrige + ponderation equilibree\n", + "# doivent laisser le regime NORMAL fitter PARFAITEMENT une cible complete (graine de\n", + "# calibration 11, disjointe des graines de test), et le regime ADVERSARIAL lam=0.5\n", + "# doit rester apprenable sur une cible equilibree (train_acc >= 0.9).\n", + "_tab_maj3 = 1.0 - 2.0 * _ref_tables(3)['MAJ_3'].astype(float)\n", + "_X3 = hypercube_inputs(3)\n", + "_net_g = train_mlp(3, _X3, _tab_maj3, regime='normal', seed=2011, steps=600, lr=0.1)\n", + "_acc_norm = float(np.mean(np.where(_net_g.forward(_X3) >= 0, 1.0, -1.0) == _tab_maj3))\n", + "_net_a = train_mlp(3, _X3, _tab_maj3, regime='adversarial', seed=2011, steps=600, lr=0.1)\n", + "_acc_adv = float(np.mean(np.where(_net_a.forward(_X3) >= 0, 1.0, -1.0) == _tab_maj3))\n", + "print(f' gate optimiseur (MAJ_3 complet, graine 11 disjointe) : train_acc normal = {_acc_norm:.3f}, '\n", + " f'adversarial (lam=0.5) = {_acc_adv:.3f} (attendus 1.0 / >= 0.9)')\n", + "all_gates_ok &= (_acc_norm == 1.0) and (_acc_adv >= 0.9)\n", + "\n", + "if not all_gates_ok:\n", + " raise RuntimeError('Gates instrument en echec : ne pas mesurer avant correction.')\n", + "print('Gates instrument PASS : l instrument discrimine (deg et s_max exacts), respecte Huang '\n", + " 'sur n=3, et l optimiseur converge (normal ET adversarial lam=0.5).')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "0a857aa1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T20:41:51.027170Z", + "iopub.status.busy": "2026-09-26T20:41:51.026967Z", + "iopub.status.idle": "2026-09-26T20:41:55.081703Z", + "shell.execute_reply": "2026-09-26T20:41:55.080927Z" + }, + "id": "ict-15g-learned-bench", + "papermill": { + "duration": 4.058593, + "end_time": "2026-09-26T20:41:55.082418+00:00", + "exception": false, + "start_time": "2026-09-26T20:41:51.023825+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--- n=3 : cible TRI_bal_3 (labels controles) = [1, 0, 1, 0, 0, 1, 0, 1]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--- n=4 : cible TRI_bal_4 (labels controles) = [0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "=== Banc #17977 : mesure complete (cible = reference ; plafond = s_max == n) ===\n", + " n cible graine regime train_acc deg s_max ratio degenerate plafond\n", + " 3 OR_3 -1 cible 1.000000 3 3 1.732051 False True\n", + " 3 OR_3 0 untrained 0.500000 3 2 1.154701 False False\n", + " 3 OR_3 0 normal 1.000000 3 3 1.732051 False True\n", + " 3 OR_3 0 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 OR_3 1 untrained 0.500000 1 1 1.000000 False False\n", + " 3 OR_3 1 normal 1.000000 0 0 NaN True False\n", + " 3 OR_3 1 adversarial 1.000000 0 0 NaN True False\n", + " 3 OR_3 7 untrained 0.500000 3 2 1.154701 False False\n", + " 3 OR_3 7 normal 1.000000 2 2 1.414214 False False\n", + " 3 OR_3 7 adversarial 1.000000 0 0 NaN True False\n", + " 3 OR_3 42 untrained 0.500000 3 2 1.154701 False False\n", + " 3 OR_3 42 normal 1.000000 3 2 1.154701 False False\n", + " 3 OR_3 42 adversarial 0.833333 3 2 1.154701 True False\n", + " 3 AND_3 -1 cible 1.000000 3 3 1.732051 False True\n", + " 3 AND_3 0 untrained 0.666667 3 2 1.154701 False False\n", + " 3 AND_3 0 normal 1.000000 2 2 1.414214 False False\n", + " 3 AND_3 0 adversarial 1.000000 0 0 NaN True False\n", + " 3 AND_3 1 untrained 0.666667 1 1 1.000000 False False\n", + " 3 AND_3 1 normal 1.000000 2 2 1.414214 False False\n", + " 3 AND_3 1 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 AND_3 7 untrained 0.666667 3 2 1.154701 False False\n", + " 3 AND_3 7 normal 1.000000 3 3 1.732051 False True\n", + " 3 AND_3 7 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 AND_3 42 untrained 0.166667 3 2 1.154701 False False\n", + " 3 AND_3 42 normal 1.000000 3 3 1.732051 False True\n", + " 3 AND_3 42 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 MAJ_3 -1 cible 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 0 untrained 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 0 normal 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 0 adversarial 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 1 untrained 0.666667 1 1 1.000000 False False\n", + " 3 MAJ_3 1 normal 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 1 adversarial 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 7 untrained 0.500000 3 2 1.154701 False False\n", + " 3 MAJ_3 7 normal 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 7 adversarial 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 42 untrained 0.333333 3 2 1.154701 False False\n", + " 3 MAJ_3 42 normal 1.000000 3 2 1.154701 False False\n", + " 3 MAJ_3 42 adversarial 1.000000 3 2 1.154701 False False\n", + " 3 PAR_3 -1 cible 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 0 untrained 0.166667 3 2 1.154701 False False\n", + " 3 PAR_3 0 normal 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 0 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 1 untrained 0.500000 1 1 1.000000 False False\n", + " 3 PAR_3 1 normal 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 1 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 7 untrained 0.666667 3 2 1.154701 False False\n", + " 3 PAR_3 7 normal 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 7 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 42 untrained 0.333333 3 2 1.154701 False False\n", + " 3 PAR_3 42 normal 1.000000 3 3 1.732051 False True\n", + " 3 PAR_3 42 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 TRI_bal_3 -1 cible 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 0 untrained 0.333333 3 2 1.154701 False False\n", + " 3 TRI_bal_3 0 normal 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 0 adversarial 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 1 untrained 0.500000 1 1 1.000000 False False\n", + " 3 TRI_bal_3 1 normal 1.000000 3 3 1.732051 False True\n", + " 3 TRI_bal_3 1 adversarial 1.000000 3 3 1.732051 False True\n", + " 3 TRI_bal_3 7 untrained 0.666667 3 2 1.154701 False False\n", + " 3 TRI_bal_3 7 normal 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 7 adversarial 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 42 untrained 0.500000 3 2 1.154701 False False\n", + " 3 TRI_bal_3 42 normal 1.000000 2 2 1.414214 False False\n", + " 3 TRI_bal_3 42 adversarial 0.833333 3 3 1.732051 True True\n", + " 4 OR_4 -1 cible 1.000000 4 4 2.000000 False True\n", + " 4 OR_4 0 untrained 0.500000 3 3 1.732051 False False\n", + " 4 OR_4 0 normal 1.000000 3 3 1.732051 False False\n", + " 4 OR_4 0 adversarial 1.000000 3 3 1.732051 False False\n", + " 4 OR_4 1 untrained 0.500000 1 1 1.000000 False False\n", + " 4 OR_4 1 normal 1.000000 0 0 NaN True False\n", + " 4 OR_4 1 adversarial 1.000000 0 0 NaN True False\n", + " 4 OR_4 7 untrained 0.583333 1 1 1.000000 False False\n", + " 4 OR_4 7 normal 1.000000 0 0 NaN True False\n", + " 4 OR_4 7 adversarial 1.000000 0 0 NaN True False\n", + " 4 OR_4 42 untrained 0.666667 3 2 1.154701 False False\n", + " 4 OR_4 42 normal 1.000000 3 3 1.732051 False False\n", + " 4 OR_4 42 adversarial 0.750000 4 3 1.500000 True False\n", + " 4 AND_4 -1 cible 1.000000 4 4 2.000000 False True\n", + " 4 AND_4 0 untrained 0.583333 3 3 1.732051 False False\n", + " 4 AND_4 0 normal 1.000000 0 0 NaN True False\n", + " 4 AND_4 0 adversarial 1.000000 0 0 NaN True False\n", + " 4 AND_4 1 untrained 0.416667 1 1 1.000000 False False\n", + " 4 AND_4 1 normal 1.000000 3 3 1.732051 False False\n", + " 4 AND_4 1 adversarial 0.833333 4 3 1.500000 True False\n", + " 4 AND_4 7 untrained 0.416667 1 1 1.000000 False False\n", + " 4 AND_4 7 normal 1.000000 0 0 NaN True False\n", + " 4 AND_4 7 adversarial 1.000000 0 0 NaN True False\n", + " 4 AND_4 42 untrained 0.500000 3 2 1.154701 False False\n", + " 4 AND_4 42 normal 1.000000 3 3 1.732051 False False\n", + " 4 AND_4 42 adversarial 0.833333 4 3 1.500000 True False\n", + " 4 MAJ_4 -1 cible 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 0 untrained 0.833333 3 3 1.732051 False False\n", + " 4 MAJ_4 0 normal 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 0 adversarial 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 1 untrained 0.333333 1 1 1.000000 False False\n", + " 4 MAJ_4 1 normal 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 1 adversarial 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 7 untrained 0.250000 1 1 1.000000 False False\n", + " 4 MAJ_4 7 normal 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 7 adversarial 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 42 untrained 0.416667 3 2 1.154701 False False\n", + " 4 MAJ_4 42 normal 1.000000 4 3 1.500000 False False\n", + " 4 MAJ_4 42 adversarial 1.000000 4 3 1.500000 False False\n", + " 4 PAR_4 -1 cible 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 0 untrained 0.583333 3 3 1.732051 False False\n", + " 4 PAR_4 0 normal 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 0 adversarial 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 1 untrained 0.666667 1 1 1.000000 False False\n", + " 4 PAR_4 1 normal 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 1 adversarial 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 7 untrained 0.500000 1 1 1.000000 False False\n", + " 4 PAR_4 7 normal 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 7 adversarial 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 42 untrained 0.416667 3 2 1.154701 False False\n", + " 4 PAR_4 42 normal 1.000000 4 4 2.000000 False True\n", + " 4 PAR_4 42 adversarial 1.000000 4 4 2.000000 False True\n", + " 4 TRI_bal_4 -1 cible 1.000000 4 4 2.000000 False True\n", + " 4 TRI_bal_4 0 untrained 0.500000 3 3 1.732051 False False\n", + " 4 TRI_bal_4 0 normal 1.000000 4 4 2.000000 False True\n", + " 4 TRI_bal_4 0 adversarial 1.000000 4 4 2.000000 False True\n", + " 4 TRI_bal_4 1 untrained 0.583333 1 1 1.000000 False False\n", + " 4 TRI_bal_4 1 normal 1.000000 4 3 1.500000 False False\n", + " 4 TRI_bal_4 1 adversarial 1.000000 4 3 1.500000 False False\n", + " 4 TRI_bal_4 7 untrained 0.583333 1 1 1.000000 False False\n", + " 4 TRI_bal_4 7 normal 1.000000 4 4 2.000000 False True\n", + " 4 TRI_bal_4 7 adversarial 1.000000 3 4 2.309401 False True\n", + " 4 TRI_bal_4 42 untrained 0.583333 3 2 1.154701 False False\n", + " 4 TRI_bal_4 42 normal 1.000000 4 3 1.500000 False False\n", + " 4 TRI_bal_4 42 adversarial 1.000000 4 3 1.500000 False False\n", + "\n", + "Entrees entrainees : 80 ; degeneres (garde pre-enregistree) : 17 (21.2%)\n" + ] + } + ], + "source": [ + "# --- Banc #17977 : execution (design gele, cf pre-enregistrement ci-dessus) ---\n", + "SEEDS_BENCH = [0, 1, 7, 42]\n", + "STEPS_BENCH, LR_BENCH, HIDDEN_BENCH = 400, 0.05, 16 # budget FIXE pre-enregistre\n", + "\n", + "rows_17977 = []\n", + "for n_b in (3, 4):\n", + " B = np.array(list(itertools.product([0, 1], repeat=n_b)))\n", + " X_full = 1.0 - 2.0 * B.astype(float) # (2^n, n)\n", + " # Cibles : labels CONTROLES en encodage b (0/1), convertis en +-1 pour l entrainement\n", + " targets_b = {\n", + " f'OR_{n_b}': (B.sum(axis=1) >= 1).astype(int),\n", + " f'AND_{n_b}': (B.sum(axis=1) == n_b).astype(int),\n", + " f'MAJ_{n_b}': (B.sum(axis=1) >= n_b // 2 + 1).astype(int),\n", + " f'PAR_{n_b}': (B.sum(axis=1) % 2).astype(int),\n", + " }\n", + " r_tgt = np.random.default_rng(20260720 + n_b) # TRI_bal : table aleatoire equilibree, graine publiee\n", + " tab_bal = np.array([1] * (2 ** (n_b - 1)) + [0] * (2 ** (n_b - 1)))\n", + " r_tgt.shuffle(tab_bal)\n", + " targets_b[f'TRI_bal_{n_b}'] = tab_bal\n", + " print(f'--- n={n_b} : cible TRI_bal_{n_b} (labels controles) = {tab_bal.tolist()}')\n", + "\n", + " for tname, t01 in targets_b.items():\n", + " y_full = 1.0 - 2.0 * t01.astype(float) # +-1\n", + " deg_t = fourier_degree(y_full, n_b)\n", + " s_t = int(hypercube_sensitivity(y_full, n_b).max())\n", + " rows_17977.append(dict(n=n_b, cible=tname, graine=-1, regime='cible',\n", + " train_acc=1.0, deg=deg_t, s_max=s_t,\n", + " ratio=(s_t / np.sqrt(deg_t)) if deg_t > 0 else float('nan'),\n", + " degenerate=False, plafond=(s_t == n_b)))\n", + " for seed in SEEDS_BENCH:\n", + " # Split deterministe par graine, IDENTIQUE entre regimes (paires appariees)\n", + " r_split = np.random.default_rng(1000 + seed)\n", + " perm = r_split.permutation(len(X_full))\n", + " n_train = 3 * len(X_full) // 4 # 75 % train / 25 % holdout\n", + " itr = perm[:n_train]\n", + " Xtr, ytr = X_full[itr], y_full[itr]\n", + " for regime in ('untrained', 'normal', 'adversarial'):\n", + " net = train_mlp(n_b, Xtr, ytr, regime=regime, seed=2000 + seed,\n", + " steps=STEPS_BENCH, lr=LR_BENCH)\n", + " table = np.where(net.forward(X_full) >= 0, 1.0, -1.0)\n", + " constant = bool(np.all(table == table[0]))\n", + " train_acc = float(np.mean(np.where(net.forward(Xtr) >= 0, 1.0, -1.0) == ytr))\n", + " deg_r = fourier_degree(table, n_b)\n", + " s_r = int(hypercube_sensitivity(table, n_b).max())\n", + " # Garde pre-enregistree : regimes entraines -> constance OU train_acc < 0.9 ;\n", + " # controle untrained -> seule la constance exclut.\n", + " if regime == 'untrained':\n", + " degen = constant\n", + " else:\n", + " degen = constant or (train_acc < 0.9)\n", + " rows_17977.append(dict(n=n_b, cible=tname, graine=seed, regime=regime,\n", + " train_acc=train_acc, deg=deg_r, s_max=s_r,\n", + " ratio=(s_r / np.sqrt(deg_r)) if (deg_r > 0 and not constant) else float('nan'),\n", + " degenerate=degen, plafond=(s_r == n_b)))\n", + "\n", + "bench_17977 = pd.DataFrame(rows_17977)\n", + "print('\\n=== Banc #17977 : mesure complete (cible = reference ; plafond = s_max == n) ===')\n", + "print(bench_17977.to_string(index=False))\n", + "\n", + "n_trained = len(bench_17977[bench_17977['regime'].isin(['normal', 'adversarial'])])\n", + "n_degen = int(bench_17977.loc[bench_17977['regime'].isin(['normal', 'adversarial']), 'degenerate'].sum())\n", + "print(f'\\nEntrees entrainees : {n_trained} ; degeneres (garde pre-enregistree) : {n_degen} '\n", + " f'({n_degen / n_trained:.1%})')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6fbaf32e", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T20:41:55.090432Z", + "iopub.status.busy": "2026-09-26T20:41:55.090100Z", + "iopub.status.idle": "2026-09-26T20:41:55.887879Z", + "shell.execute_reply": "2026-09-26T20:41:55.887109Z" + }, + "id": "ict-15g-learned-verdicts", + "papermill": { + "duration": 0.802652, + "end_time": "2026-09-26T20:41:55.888477+00:00", + "exception": false, + "start_time": "2026-09-26T20:41:55.085825+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Bande aleatoire appariee en degre (controle 2) : ratio par degre ===\n", + " n med p5 p95 vmin vmax\n", + "n deg \n", + "3 1 6 1.000000 1.000000 1.000000 1.000000 1.000000\n", + " 2 62 1.414214 1.414214 2.121320 1.414214 2.121320\n", + " 3 186 1.732051 1.154701 1.732051 1.154701 1.732051\n", + "4 2 9 1.414214 1.414214 1.414214 1.414214 1.414214\n", + " 3 564 1.732051 1.732051 2.309401 1.154701 2.309401\n", + " 4 2427 2.000000 1.500000 2.000000 1.000000 2.000000\n", + "\n", + "=== Carte de saturation du ratio s_max / sqrt(deg) (tables realisees non-degeneres) ===\n", + " n_entrees ratio_med ratio_min ratio_max frac_plafond\n", + "n regime deg \n", + "3 adversarial 2 2 1.414214 1.414214 1.414214 0.000000\n", + " 3 13 1.732051 1.154701 1.732051 0.692308\n", + " normal 2 6 1.414214 1.414214 1.414214 0.000000\n", + " 3 13 1.732051 1.154701 1.732051 0.615385\n", + " untrained 1 5 1.000000 1.000000 1.000000 0.000000\n", + " 3 15 1.154701 1.154701 1.154701 0.000000\n", + "4 adversarial 3 2 2.020726 1.732051 2.309401 0.500000\n", + " 4 11 1.500000 1.500000 2.000000 0.454545\n", + " normal 3 4 1.732051 1.732051 1.732051 0.000000\n", + " 4 12 1.750000 1.500000 2.000000 0.500000\n", + " untrained 1 10 1.000000 1.000000 1.000000 0.000000\n", + " 3 10 1.443376 1.154701 1.732051 0.000000\n", + "\n", + "Fraction des tables entrainees dont le ratio tombe dans la bande aleatoire appariee en degre [p5, p95] :\n", + "regime\n", + "adversarial 1.0\n", + "normal 1.0\n", + "\n", + "--- P1 (pre-enregistre) : l adversarial reduit s_max ---\n", + " paires non-degeneres : 28 ; Delta = s_max_adv - s_max_norm : 0 negatives / 27 nulles / 1 positives ; mediane = 0.0\n", + " P1 : NON CONFIRMEE\n", + "--- P2 (theoreme, gate instrument) : 118 tables non constantes, 0 violation(s) de s_max >= sqrt(deg) -> OK\n", + "--- P3 (controle untrained) : mediane s_max normal = 3.0, untrained = 2.0 -> NON CONFIRMEE (l entrainement n augmente pas la sensibilite)\n", + "--- P4 (resolution/saturation) : degres distincts = 3 (>= 2 requis), fraction au plafond s_max = n : 46.0% (< 75 % requis) -> CONFIRMEE\n", + "\n", + "=== VERDICT #17977 (pre-enregistre) : FAIL ===\n", + " fraction degeneree (entraines) : 21.2% (seuil INCONCLUSIVE : > 33,3 %)\n", + " Rappel des conditions : INVALID si P2 violee ; INCONCLUSIVE si P4 non tenue, n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).\n" + ] + } + ], + "source": [ + "# --- Banc #17977 : carte de saturation + verdicts PRE-ENREGISTRES ---\n", + "# (analyse executee selon les seuils scelles ci-dessus ; aucune re-seuillage post-hoc)\n", + "\n", + "# Bande aleatoire appariee en degre : n=3 exhaustive (256 fonctions), n=4 echantillon 3000\n", + "rand_rows = []\n", + "for n_r in (3, 4):\n", + " if n_r == 3:\n", + " tables_rand = [1.0 - 2.0 * np.array([(v >> i) & 1 for i in range(8)], dtype=float)\n", + " for v in range(2 ** 8)]\n", + " else:\n", + " r_rand = np.random.default_rng(20260721)\n", + " tables_rand = [1.0 - 2.0 * r_rand.integers(0, 2, 16).astype(float) for _ in range(3000)]\n", + " for tab_r in tables_rand:\n", + " if np.all(tab_r == tab_r[0]):\n", + " continue\n", + " d_r = fourier_degree(tab_r, n_r)\n", + " s_r = int(hypercube_sensitivity(tab_r, n_r).max())\n", + " rand_rows.append(dict(n=n_r, deg=d_r, ratio=s_r / np.sqrt(d_r)))\n", + "rand_band = pd.DataFrame(rand_rows)\n", + "print('=== Bande aleatoire appariee en degre (controle 2) : ratio par degre ===')\n", + "band_summary = rand_band.groupby(['n', 'deg'])['ratio'].agg(\n", + " n='size', med='median', p5=lambda s: float(np.percentile(s, 5)),\n", + " p95=lambda s: float(np.percentile(s, 95)), vmin='min', vmax='max')\n", + "print(band_summary.to_string())\n", + "\n", + "# Entrees conclusives : non-degeneres, ratio defini, hors lignes 'cible' (reference)\n", + "conc_17977 = bench_17977[(~bench_17977['degenerate'])\n", + " & bench_17977['ratio'].notna()\n", + " & (bench_17977['regime'] != 'cible')]\n", + "\n", + "# Carte de saturation : stats du ratio par (n, regime, deg) pour les tables realisees\n", + "print('\\n=== Carte de saturation du ratio s_max / sqrt(deg) (tables realisees non-degeneres) ===')\n", + "map_17977 = conc_17977.groupby(['n', 'regime', 'deg']).agg(\n", + " n_entrees=('ratio', 'size'),\n", + " ratio_med=('ratio', 'median'),\n", + " ratio_min=('ratio', 'min'),\n", + " ratio_max=('ratio', 'max'),\n", + " frac_plafond=('plafond', 'mean'))\n", + "print(map_17977.to_string())\n", + "\n", + "# Position vs bande aleatoire appariee en degre (descriptif) : ratio dans [p5, p95] de sa bande ?\n", + "def _dans_bande(row):\n", + " grp = rand_band[(rand_band['n'] == row['n']) & (rand_band['deg'] == row['deg'])]\n", + " if grp.empty:\n", + " return np.nan\n", + " lo, hi = np.percentile(grp['ratio'], [5, 95])\n", + " return bool(lo - 1e-12 <= row['ratio'] <= hi + 1e-12)\n", + "\n", + "trained_mask = conc_17977['regime'].isin(['normal', 'adversarial'])\n", + "conc_trained = conc_17977[trained_mask].copy()\n", + "conc_trained['dans_bande'] = conc_trained.apply(_dans_bande, axis=1)\n", + "in_band = conc_trained.groupby('regime')['dans_bande'].mean()\n", + "print('\\nFraction des tables entrainees dont le ratio tombe dans la bande aleatoire '\n", + " 'appariee en degre [p5, p95] :')\n", + "print(in_band.to_string())\n", + "\n", + "# --- P1 : deplacement adversarial (paires appariees n x cible x graine) ---\n", + "pn = conc_17977[conc_17977['regime'] == 'normal'].set_index(['n', 'cible', 'graine'])['s_max']\n", + "pa = conc_17977[conc_17977['regime'] == 'adversarial'].set_index(['n', 'cible', 'graine'])['s_max']\n", + "common = pn.index.intersection(pa.index)\n", + "delta_smax = (pa.loc[common] - pn.loc[common]).sort_values()\n", + "n_pairs = len(delta_smax)\n", + "med_delta = float(delta_smax.median()) if n_pairs else float('nan')\n", + "n_neg, n_pos = int((delta_smax < 0).sum()), int((delta_smax > 0).sum())\n", + "p1_confirmee = bool(n_pairs >= 8 and med_delta < 0 and n_neg > n_pos)\n", + "print(f'\\n--- P1 (pre-enregistre) : l adversarial reduit s_max ---')\n", + "print(f' paires non-degeneres : {n_pairs} ; Delta = s_max_adv - s_max_norm : '\n", + " f'{n_neg} negatives / {n_pairs - n_neg - n_pos} nulles / {n_pos} positives ; mediane = {med_delta}')\n", + "print(f' P1 : {\"CONFIRMEE\" if p1_confirmee else \"NON CONFIRMEE\"}')\n", + "\n", + "# --- P2 : gate theoreme sur TOUTES les tables realisees non constantes ---\n", + "non_const = bench_17977[(bench_17977['deg'] > 0) & (bench_17977['s_max'] >= 0)]\n", + "p2_ok = bool((non_const['s_max'] >= np.sqrt(non_const['deg']) - 1e-12).all())\n", + "n_p2_viol = int((non_const['s_max'] < np.sqrt(non_const['deg']) - 1e-12).sum())\n", + "print(f'--- P2 (theoreme, gate instrument) : {len(non_const)} tables non constantes, '\n", + " f'{n_p2_viol} violation(s) de s_max >= sqrt(deg) -> {\"OK\" if p2_ok else \"INVALID\"}')\n", + "\n", + "# --- P3 : controle untrained ---\n", + "med_norm = float(conc_17977[conc_17977['regime'] == 'normal']['s_max'].median())\n", + "med_untr = float(conc_17977[conc_17977['regime'] == 'untrained']['s_max'].median())\n", + "p3_confirmee = bool(med_norm <= med_untr)\n", + "print(f'--- P3 (controle untrained) : mediane s_max normal = {med_norm}, untrained = {med_untr} '\n", + " f'-> {\"CONFIRMEE\" if p3_confirmee else \"NON CONFIRMEE\"} (l entrainement n augmente pas la sensibilite)')\n", + "\n", + "# --- P4 : resolution + non-saturation (reserves #9771/#9764) ---\n", + "deg_distincts = conc_trained['deg'].nunique()\n", + "frac_plafond_glob = float(conc_trained['plafond'].mean())\n", + "p4_ok = bool(deg_distincts >= 2 and frac_plafond_glob < 0.75)\n", + "print(f'--- P4 (resolution/saturation) : degres distincts = {deg_distincts} (>= 2 requis), '\n", + " f'fraction au plafond s_max = n : {frac_plafond_glob:.1%} (< 75 % requis) '\n", + " f'-> {\"CONFIRMEE\" if p4_ok else \"NON CONFIRMEE\"}')\n", + "\n", + "# --- Verdict global pre-enregistre ---\n", + "frac_degen = n_degen / n_trained\n", + "if not p2_ok:\n", + " verdict_17977 = 'INVALID'\n", + "elif (not p4_ok) or n_pairs < 8 or frac_degen > 1 / 3:\n", + " verdict_17977 = 'INCONCLUSIVE'\n", + "elif p1_confirmee:\n", + " verdict_17977 = 'PASS'\n", + "else:\n", + " verdict_17977 = 'FAIL'\n", + "print(f'\\n=== VERDICT #17977 (pre-enregistre) : {verdict_17977} ===')\n", + "print(f' fraction degeneree (entraines) : {frac_degen:.1%} (seuil INCONCLUSIVE : > 33,3 %)')\n", + "print(' Rappel des conditions : INVALID si P2 violee ; INCONCLUSIVE si P4 non tenue, '\n", + " 'n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).')" + ] + }, + { + "cell_type": "markdown", + "id": "acea4183", + "metadata": { + "id": "ict-15g-learned-interp" + }, + "source": [ + "### Interprétation du banc #17977 — verdict pré-enregistré : FAIL (délivré tel quel, sans re-seuillage)\n", + "\n", + "**Ce qui est réfuté, et ce qui ne l'est pas.** Le verdict `FAIL` porte **uniquement** sur P1 — la prédiction pré-enregistrée « l'entraînement adversarial réduit s_max de la fonction réalisée ». Mesure : **28 paires appariées non-dégénérées, 27 Δs_max = 0, 1 Δ > 0, 0 Δ < 0, médiane 0,0** — les deux régimes réalisent la **même table de vérité** dans 27 cas sur 28. La borne de Huang, elle, est **intouchée** : P2 constate **0 violation sur 118 tables réalisées non constantes** (et 256/256 à l'exhaustif n=3) — le théorème tient sur l'hypercube vrai, c'est la prédiction de déplacement qui tombe.\n", + "\n", + "**Pourquoi la fenêtre d'effet est vide à cette échelle.** À rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point d'entraînement porte souvent le label opposé (toujours, pour la parité) : l'adversaire contredit directement les labels observés. La calibration sur graines disjointes {11, 22} l'a mesuré : à poids λ = 1, l'apprentissage échoue (57,5 % de dégénérés) ; à λ = 0,5, l'apprentissage réussit mais la table réalisée devient **identique** au régime normal. Entre les deux, pas de régime intermédiaire : à 3-4 bits, **le lissage adversarial ne traverse pas le seuil** — il déplace la géométrie du logit, pas la fonction seuillée. La réponse à la question de l'issue (« l'adversarial déplace-t-il le ratio, et dans quel sens ? ») est donc, dans CE régime : **pas de déplacement détectable — la fenêtre d'effet observable est vide à cette échelle**.\n", + "\n", + "**Carte de saturation (le livrable de #17977).** Les ratios réalisés vivent dans **[1,0 ; 2,31]**, Huang garantissant le plancher 1. Le plafond structurel `s_max = n` est touché par **46,0 %** des entrées entraînées non-dégénérées — la mesure ne sature pas (P4 confirmée : 3 degrés distincts, < 75 % au plafond). Lectures fines :\n", + "\n", + "| Observation | Valeur mesurée | Lecture |\n", + "|---|---|---|\n", + "| ratio médian (n=4, deg=4, normal) | 1,75 | sous la médiane aléatoire appariée (2,0) |\n", + "| ratio médian (n=4, deg=4, adversarial) | 1,50 | idem — les deux régimes dans la bande |\n", + "| fraction des ratios entraînés dans la bande aléatoire [p5, p95] de leur degré | 100 % (normal et adversarial) | le ratio des fonctions apprises est **indiscernable** de celui de fonctions aléatoires de même degré de Fourier |\n", + "| médiane s_max : entraîné normal vs untrained | 3,0 vs 2,0 | **P3 réfutée** : apprendre des cibles de haut degré AUGMENTE la sensibilité médiane par rapport à l'init (les tables untrained réalisent surtout des fonctions de degré 1-3 à faible ratio) |\n", + "\n", + "Le contrôle « fonction aléatoire de même degré » fait son travail : il montre que le ratio s_max/√deg **ne discrimine pas** une fonction apprise d'une fonction aléatoire de même degré — l'information de l'apprentissage ne vit pas dans ce ratio, elle vit dans la table (train_acc 1,0 partout où non-dégénéré).\n", + "\n", + "**Dégénérés : 17/80 = 21,2 %** (garde pré-enregistrée, sous le seuil INCONCLUSIVE de 33,3 %). Dominés par OR_4/AND_4 lorsque le point minoritaire tombe en holdout : le train est alors uniforme, la constante est exacte sur le train (train_acc 1,0) mais vacuous — exclue et comptée honnêtement.\n", + "\n", + "**Portée (bornée, pas généralisable)** : hypercubes 3-4 bits, MLP 16 cachées, 75 % de couverture, budget fixe 400 étapes, 4 graines, 5 cibles, λ = 0,5. La littérature adversariale continue (perturbations ℓ∞ ε ≪ 1) opère dans un régime sans équivalent discret — à n croissant, la densité de contraintes contradictoires par point diminue et la fenêtre pourrait s'ouvrir ; ce banc ne dit rien des grands n. La formulation **« transposition conjecturale »** reste portée par le banc hérité (graphes de transition, cellules 2-9) ; sur l'hypercube vrai, l'inégalité de Huang est un théorème et l'instrument la vérifie mécaniquement." + ] } ], "metadata": { @@ -932,18 +1731,18 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.11" + "version": "3.13.14" }, "papermill": { "default_parameters": {}, - "duration": 2.89415, - "end_time": "2026-09-01T06:42:02.685174+00:00", + "duration": 17.300553, + "end_time": "2026-09-26T20:41:56.236547+00:00", "environment_variables": {}, "exception": null, - "input_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", - "output_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", + "input_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", + "output_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", "parameters": {}, - "start_time": "2026-09-01T06:41:59.791024+00:00", + "start_time": "2026-09-26T20:41:38.935994+00:00", "version": "2.7.0" } }, diff --git a/docs/ict/dissociations-matrix.md b/docs/ict/dissociations-matrix.md index 020d66b3c8..b719ac68c3 100644 --- a/docs/ict/dissociations-matrix.md +++ b/docs/ict/dissociations-matrix.md @@ -95,6 +95,7 @@ Conventions : | **ICT-15c** | Le **motif de désaccord** entre proxys est stable cross-substrat = obstruction informative (≠ dispersion d'échelle) | `s` ✓ | Vecteur d'obstruction `(a−b)/(\|a\|+\|b\|+ε)`, `mean_norm_L2`, verdict `STABLE`/`NOISE` | `f(x)=x%2` saturait (artefact plafonné) → `f(x)=x` (identité) restaure un panel non-plafonné | 4 substrats (Gray-Scott, Axelrod, Grokking, May) | proxy_interpretation | **Spéculatif** | **Candidat obstruction** (régime 2, *pas* érigé en obstruction cohomologique régime 3 — cf garde-fou A2). Verdict falsifiable `STABLE` si `mean_norm_L2 ≤ 0.05`. See [#7395](https://github.com/jsboige/CoursIA/issues/7395) | | **ICT-15d** | La cochaîne de Čech pondérée discriminate les substrats (`NON_TRIVIAL` = les proxys ne se recollent pas en 1D) | `s` ✓ | `mean_coboundary`, `s2_over_s1`, `effective_rank`, verdict `TRIVIAL`/`NON_TRIVIAL` | Sanity check + 4 substrats ICT-15c | 4 substrats × 3 proxys × fenêtrage | reproduced_in_toy_model | **Spéculatif** *(réserve de non-discrimination — voir [§ ICT-15d-corr](#note-ict-15d-corr--requalification-2026-08-21))* | 4/4 substrats `NON_TRIVIAL` sur la mesure courante ; l'« honnête négatif 0/4 » de la version précédente mesurait un `sensitivity.py` défectueux (réparé par [#9792](https://github.com/jsboige/CoursIA/pull/9792)). **Réserve** : la sortie reste dominée par la SVD (`s2_over_s1`, `effective_rank`) ; le contre-exemple `axelrod` (`mean_cocycle=0`, `obstruction_ratio=0`, `sign_consistency=0`) ne consulte ni le nerf ni H¹. Le verdict **ne porte pas** l'énoncé « Čech discrimine les substrats ». Issue [#7744](https://github.com/jsboige/CoursIA/issues/7744) closed-archived. | | **ICT-15e** | La trajectoire de réparation **est** un signal distinct d'un random walk calibré (recouvrabilité = agentivité, ≠ simple gain) | `s` ✓, `q` ○, `π` ○ | Distance de Mahalanobis sur signature 5-D, seuil p95 par permutation null | Random walk calibré sur mêmes extrema + 1 contrôle structural ; conjecture pré-enregistrée | 3 configs Gray-Scott (pearl/spots/seed=7) | reproduced_in_toy_model | **Fortement soutenu** | `CONFIRMED` sur substrats à dynamique réaction-diffusion informative (signature `slope_ratio` élevé) ; `FALSIFIED` sinon (random walk reproduit la structure) — verdict nuancé honnête, *pas* universel. See [#8077](https://github.com/jsboige/CoursIA/issues/8077) | +| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux vit dans la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne déplace **pas** le ratio à 3-4 bits — la prédiction pré-enregistrée « l'adversarial réduit s_max » est **réfutée** (28 paires appariées : 27 Δ=0, 1 Δ>0, 0 Δ<0, médiane 0) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — calibration sur graines disjointes {11, 22} | reproduced_in_toy_model + pre_enregistrement | **TESTÉ (FAIL — prédiction réfutée, livrée sans re-seuillage)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est réfuté, pas la borne. À λ=1 l'adversaire rayon-1 rend l'apprentissage impossible (57,5 % dégénérés en calibration) : la fenêtre d'effet est **vide à cette échelle**, lecture bornée ne généralisant pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | | **ICT-16** | `F` = partie résiduelle de `K` + bosse complexité-entropie | `s` ✓ | MDL two-part code | Modèles témoins sans bosse | RNG multi-source | established_external | **Établi** | Bosse Crutchfield-Feldman 1998 mesurée à H* ≈ 1.99 bits/symbole ; cave emptor : **un seul couple (modèle, famille de sources)** dans la figure rendue | | **ICT-17** | L'ε-machine (Crutchfield) ≠ Hoel : deux lectures de l'émergence causale | `s` ✓, `W` ○ | États causaux + complexité statistique + entropie d'excès | Hoel info effective, CE 2.0 | multi-substrat | conceptual_analogy | **Fortement soutenu** | Dissociation reconnue mais pas hiérarchisée | | **ICT-17b** | 2/5 proxys dissocient du progrès de généralisation pendant le grokking | `s` ✓, `q` ○ | ‖w‖², Fisher-MDL, 1-test_acc, trace de Fisher, pred-zlib | Baseline avant-grokking | 5 proxys | reproduced_in_toy_model | **Établi** | 3 co-localisent (‖w‖², Fisher-MDL, 1-test_acc) ; 2 dissocient (trace Fisher, pred-zlib). Verdict honnête dissociatif (#7268) | From 4bf32119f88e77f0efd88845cc32b0b5559d0576 Mon Sep 17 00:00:00 2001 From: jsboige Date: Sat, 26 Sep 2026 22:54:05 +0200 Subject: [PATCH 2/5] =?UTF-8?q?fix(ict,#17977):=20fidelite=20des=20claims?= =?UTF-8?q?=20post-revue=20=E2=80=94=20Delta=20ratio=20mesure,=20plan=20de?= =?UTF-8?q?clare?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrections demandees en revue du commit 249f6b06e0 : - Code (cellule verdicts) : bloc complement post-revue mesurant explicitement le Delta RATIO apparie sur les 28 paires qualifiees (la quantite de l'issue), P1 restant le critere declare sur Delta s_max (proxy, etiquete comme tel). Re-execution Papermill complete : 13/13 cellules, 0 erreur, sorties reelles. Resultat execute : 0 negatif / 26 nul / 2 positif, mediane 0 ; paire (4, TRI_bal_4, 7) s_max 4->4 mais deg 4->3 (Delta ratio +0.309401) ; paire (3, AND_3, 1) s_max 2->3, deg 2->3 (+0.317837). - Narrative + statut + matrice : "27/28 meme table" corrige en "27/28 meme s_max" avec contre-exemple degre ; "indiscernable" corrige en chevauchement (n'etablit pas une indistinguabilite statistique) ; grille lambda qualifiee ({0, 0.5, 1} seulement, intermediaires non testes) ; claim grands n retire. - Honnetete temporelle : "scelle avant toute mesure" remplace par plan d'analyse declare avec amendements de calibration documentes (graines de calibration {11,22} disjointes des graines de verdict), sans affirmation d'horodatage independant ; criteres d'echec P1-P4 inchanges et explicites. Verdict #17977 inchange : FAIL (criteres declares, sans re-seuillage). Co-Authored-By: Claude Sonnet 5 --- .../ICT-15g-EmpiricalHuangExploitation.ipynb | 339 ++++++++++-------- docs/ict/dissociations-matrix.md | 2 +- 2 files changed, 186 insertions(+), 155 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb index f05e67a167..4b53e3b00b 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb @@ -5,10 +5,10 @@ "id": "ict-15b-empirical-cadrage", "metadata": { "papermill": { - "duration": 0.007972, - "end_time": "2026-09-26T20:41:46.959427+00:00", + "duration": 0.002864, + "end_time": "2026-09-26T20:52:00.310360+00:00", "exception": false, - "start_time": "2026-09-26T20:41:46.951455+00:00", + "start_time": "2026-09-26T20:52:00.307496+00:00", "status": "completed" }, "tags": [] @@ -67,16 +67,16 @@ "id": "statut-epistemique", "metadata": { "papermill": { - "duration": 0.005548, - "end_time": "2026-09-26T20:41:46.970393+00:00", + "duration": 0.00204, + "end_time": "2026-09-26T20:52:00.315085+00:00", "exception": false, - "start_time": "2026-09-26T20:41:46.964845+00:00", + "start_time": "2026-09-26T20:52:00.313045+00:00", "status": "completed" }, "tags": [] }, "source": [ - "> **Statut épistémique** — Deux strates. (1) Le banc hérité (cellules 2 à 9 : conjecture `s_max ≥ √deg_proxy` sur graphes de transition markoviens) reste une **transposition conjecturale, sans verdict** : ses verdicts par substrat sont des repères d'instrument, pas des théorèmes. (2) Le **banc appris [#17977](https://github.com/jsboige/CoursIA/issues/17977)** (fin de notebook) livre un verdict pré-enregistré **FAIL** — réfutation honnête de la prédiction « l'adversarial réduit s_max » (27/28 paires Δ = 0) sur l'hypercube vrai, où la borne de Huang est un théorème vérifié mécaniquement (0/118 violations). Reporté dans la [matrice de dissociations](../../../docs/ict/dissociations-matrix.md), ligne **ICT-15g**." + "> **Statut épistémique** — Deux strates. (1) Le banc hérité (cellules 2 à 9 : conjecture `s_max ≥ √deg_proxy` sur graphes de transition markoviens) reste une **transposition conjecturale, sans verdict** : ses verdicts par substrat sont des repères d'instrument, pas des théorèmes. (2) Le **banc appris [#17977](https://github.com/jsboige/CoursIA/issues/17977)** (fin de notebook) livre un verdict **FAIL** aux critères **déclarés** (Δs_max, proxy de la quantité de l'issue) : 27/28 paires Δs_max = 0, 1 Δ > 0, 0 Δ < 0 ; le complément post-revue sur le ratio ne détecte pas non plus de déplacement (26 Δratio = 0, 2 > 0, 0 < 0, médiane 0,0). L'analyse suit un **plan déclaré avec amendements de calibration documentés** (graines de calibration disjointes), sans re-seuillage. Sur l'hypercube vrai, la borne de Huang est un théorème vérifié mécaniquement (0/118 violations). Reporté dans la [matrice de dissociations](../../../docs/ict/dissociations-matrix.md), ligne **ICT-15g**." ] }, { @@ -85,16 +85,16 @@ "id": "ict-15b-empirical-imports", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:46.978615Z", - "iopub.status.busy": "2026-09-26T20:41:46.978225Z", - "iopub.status.idle": "2026-09-26T20:41:50.231696Z", - "shell.execute_reply": "2026-09-26T20:41:50.230677Z" + "iopub.execute_input": "2026-09-26T20:52:00.324393Z", + "iopub.status.busy": "2026-09-26T20:52:00.324055Z", + "iopub.status.idle": "2026-09-26T20:52:03.000279Z", + "shell.execute_reply": "2026-09-26T20:52:02.999567Z" }, "papermill": { - "duration": 3.258325, - "end_time": "2026-09-26T20:41:50.232957+00:00", + "duration": 2.680069, + "end_time": "2026-09-26T20:52:03.000878+00:00", "exception": false, - "start_time": "2026-09-26T20:41:46.974632+00:00", + "start_time": "2026-09-26T20:52:00.320809+00:00", "status": "completed" }, "tags": [] @@ -136,16 +136,16 @@ "id": "ict-15b-empirical-sanity", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.242761Z", - "iopub.status.busy": "2026-09-26T20:41:50.242357Z", - "iopub.status.idle": "2026-09-26T20:41:50.252599Z", - "shell.execute_reply": "2026-09-26T20:41:50.250809Z" + "iopub.execute_input": "2026-09-26T20:52:03.007208Z", + "iopub.status.busy": "2026-09-26T20:52:03.006970Z", + "iopub.status.idle": "2026-09-26T20:52:03.012418Z", + "shell.execute_reply": "2026-09-26T20:52:03.011767Z" }, "papermill": { - "duration": 0.017114, - "end_time": "2026-09-26T20:41:50.253693+00:00", + "duration": 0.009325, + "end_time": "2026-09-26T20:52:03.012933+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.236579+00:00", + "start_time": "2026-09-26T20:52:03.003608+00:00", "status": "completed" }, "tags": [] @@ -201,10 +201,10 @@ "id": "ict-15b-empirical-methode", "metadata": { "papermill": { - "duration": 0.004353, - "end_time": "2026-09-26T20:41:50.261260+00:00", + "duration": 0.002294, + "end_time": "2026-09-26T20:52:03.017788+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.256907+00:00", + "start_time": "2026-09-26T20:52:03.015494+00:00", "status": "completed" }, "tags": [] @@ -237,16 +237,16 @@ "id": "ict-15b-empirical-gray-scott", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.269795Z", - "iopub.status.busy": "2026-09-26T20:41:50.269255Z", - "iopub.status.idle": "2026-09-26T20:41:50.407876Z", - "shell.execute_reply": "2026-09-26T20:41:50.407066Z" + "iopub.execute_input": "2026-09-26T20:52:03.023617Z", + "iopub.status.busy": "2026-09-26T20:52:03.023433Z", + "iopub.status.idle": "2026-09-26T20:52:03.101626Z", + "shell.execute_reply": "2026-09-26T20:52:03.101064Z" }, "papermill": { - "duration": 0.144242, - "end_time": "2026-09-26T20:41:50.408600+00:00", + "duration": 0.082207, + "end_time": "2026-09-26T20:52:03.102389+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.264358+00:00", + "start_time": "2026-09-26T20:52:03.020182+00:00", "status": "completed" }, "tags": [] @@ -294,16 +294,16 @@ "id": "ict-15b-empirical-axelrod", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.415091Z", - "iopub.status.busy": "2026-09-26T20:41:50.414903Z", - "iopub.status.idle": "2026-09-26T20:41:50.666528Z", - "shell.execute_reply": "2026-09-26T20:41:50.665644Z" + "iopub.execute_input": "2026-09-26T20:52:03.111584Z", + "iopub.status.busy": "2026-09-26T20:52:03.111320Z", + "iopub.status.idle": "2026-09-26T20:52:03.329206Z", + "shell.execute_reply": "2026-09-26T20:52:03.328420Z" }, "papermill": { - "duration": 0.25593, - "end_time": "2026-09-26T20:41:50.667335+00:00", + "duration": 0.223855, + "end_time": "2026-09-26T20:52:03.329921+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.411405+00:00", + "start_time": "2026-09-26T20:52:03.106066+00:00", "status": "completed" }, "tags": [] @@ -354,16 +354,16 @@ "id": "ict-15b-empirical-grokking", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.673909Z", - "iopub.status.busy": "2026-09-26T20:41:50.673557Z", - "iopub.status.idle": "2026-09-26T20:41:50.681048Z", - "shell.execute_reply": "2026-09-26T20:41:50.679965Z" + "iopub.execute_input": "2026-09-26T20:52:03.336422Z", + "iopub.status.busy": "2026-09-26T20:52:03.336179Z", + "iopub.status.idle": "2026-09-26T20:52:03.341273Z", + "shell.execute_reply": "2026-09-26T20:52:03.340766Z" }, "papermill": { - "duration": 0.01191, - "end_time": "2026-09-26T20:41:50.681855+00:00", + "duration": 0.008973, + "end_time": "2026-09-26T20:52:03.341848+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.669945+00:00", + "start_time": "2026-09-26T20:52:03.332875+00:00", "status": "completed" }, "tags": [] @@ -417,16 +417,16 @@ "id": "ict-15b-empirical-may", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.691347Z", - "iopub.status.busy": "2026-09-26T20:41:50.691038Z", - "iopub.status.idle": "2026-09-26T20:41:50.711636Z", - "shell.execute_reply": "2026-09-26T20:41:50.710819Z" + "iopub.execute_input": "2026-09-26T20:52:03.348108Z", + "iopub.status.busy": "2026-09-26T20:52:03.347842Z", + "iopub.status.idle": "2026-09-26T20:52:03.361786Z", + "shell.execute_reply": "2026-09-26T20:52:03.361000Z" }, "papermill": { - "duration": 0.026944, - "end_time": "2026-09-26T20:41:50.712666+00:00", + "duration": 0.018037, + "end_time": "2026-09-26T20:52:03.362605+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.685722+00:00", + "start_time": "2026-09-26T20:52:03.344568+00:00", "status": "completed" }, "tags": [] @@ -475,16 +475,16 @@ "id": "ict-15b-empirical-cross-substrat", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.720051Z", - "iopub.status.busy": "2026-09-26T20:41:50.719688Z", - "iopub.status.idle": "2026-09-26T20:41:50.731977Z", - "shell.execute_reply": "2026-09-26T20:41:50.730942Z" + "iopub.execute_input": "2026-09-26T20:52:03.369374Z", + "iopub.status.busy": "2026-09-26T20:52:03.369191Z", + "iopub.status.idle": "2026-09-26T20:52:03.380065Z", + "shell.execute_reply": "2026-09-26T20:52:03.379486Z" }, "papermill": { - "duration": 0.016612, - "end_time": "2026-09-26T20:41:50.732850+00:00", + "duration": 0.015021, + "end_time": "2026-09-26T20:52:03.380733+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.716238+00:00", + "start_time": "2026-09-26T20:52:03.365712+00:00", "status": "completed" }, "tags": [] @@ -557,10 +557,10 @@ "id": "ict-15b-empirical-interp-cross", "metadata": { "papermill": { - "duration": 0.003393, - "end_time": "2026-09-26T20:41:50.739845+00:00", + "duration": 0.002683, + "end_time": "2026-09-26T20:52:03.386390+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.736452+00:00", + "start_time": "2026-09-26T20:52:03.383707+00:00", "status": "completed" }, "tags": [] @@ -590,10 +590,10 @@ "id": "ict-15b-empirical-exo1-md", "metadata": { "papermill": { - "duration": 0.002301, - "end_time": "2026-09-26T20:41:50.744763+00:00", + "duration": 0.004097, + "end_time": "2026-09-26T20:52:03.393097+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.742462+00:00", + "start_time": "2026-09-26T20:52:03.389000+00:00", "status": "completed" }, "tags": [] @@ -614,16 +614,16 @@ "id": "ict-15b-empirical-exo1-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.755742Z", - "iopub.status.busy": "2026-09-26T20:41:50.755180Z", - "iopub.status.idle": "2026-09-26T20:41:50.760976Z", - "shell.execute_reply": "2026-09-26T20:41:50.760014Z" + "iopub.execute_input": "2026-09-26T20:52:03.399863Z", + "iopub.status.busy": "2026-09-26T20:52:03.399674Z", + "iopub.status.idle": "2026-09-26T20:52:03.404744Z", + "shell.execute_reply": "2026-09-26T20:52:03.403787Z" }, "papermill": { - "duration": 0.012947, - "end_time": "2026-09-26T20:41:50.761744+00:00", + "duration": 0.009135, + "end_time": "2026-09-26T20:52:03.405247+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.748797+00:00", + "start_time": "2026-09-26T20:52:03.396112+00:00", "status": "completed" }, "tags": [] @@ -674,10 +674,10 @@ "id": "ict-15b-empirical-exo2-md", "metadata": { "papermill": { - "duration": 0.002979, - "end_time": "2026-09-26T20:41:50.769158+00:00", + "duration": 0.003364, + "end_time": "2026-09-26T20:52:03.411367+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.766179+00:00", + "start_time": "2026-09-26T20:52:03.408003+00:00", "status": "completed" }, "tags": [] @@ -704,16 +704,16 @@ "id": "ict-15b-empirical-exo2-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.776444Z", - "iopub.status.busy": "2026-09-26T20:41:50.776182Z", - "iopub.status.idle": "2026-09-26T20:41:50.788323Z", - "shell.execute_reply": "2026-09-26T20:41:50.786931Z" + "iopub.execute_input": "2026-09-26T20:52:03.418729Z", + "iopub.status.busy": "2026-09-26T20:52:03.418551Z", + "iopub.status.idle": "2026-09-26T20:52:03.427212Z", + "shell.execute_reply": "2026-09-26T20:52:03.426583Z" }, "papermill": { - "duration": 0.016446, - "end_time": "2026-09-26T20:41:50.789270+00:00", + "duration": 0.012799, + "end_time": "2026-09-26T20:52:03.427805+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.772824+00:00", + "start_time": "2026-09-26T20:52:03.415006+00:00", "status": "completed" }, "tags": [] @@ -764,10 +764,10 @@ "id": "ict-15b-empirical-exo3-md", "metadata": { "papermill": { - "duration": 0.003088, - "end_time": "2026-09-26T20:41:50.795087+00:00", + "duration": 0.002685, + "end_time": "2026-09-26T20:52:03.433260+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.791999+00:00", + "start_time": "2026-09-26T20:52:03.430575+00:00", "status": "completed" }, "tags": [] @@ -834,16 +834,16 @@ "id": "ict-15b-empirical-exo3-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.802331Z", - "iopub.status.busy": "2026-09-26T20:41:50.801962Z", - "iopub.status.idle": "2026-09-26T20:41:50.853258Z", - "shell.execute_reply": "2026-09-26T20:41:50.852480Z" + "iopub.execute_input": "2026-09-26T20:52:03.440110Z", + "iopub.status.busy": "2026-09-26T20:52:03.439908Z", + "iopub.status.idle": "2026-09-26T20:52:03.482583Z", + "shell.execute_reply": "2026-09-26T20:52:03.481880Z" }, "papermill": { - "duration": 0.055885, - "end_time": "2026-09-26T20:41:50.853798+00:00", + "duration": 0.047127, + "end_time": "2026-09-26T20:52:03.483198+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.797913+00:00", + "start_time": "2026-09-26T20:52:03.436071+00:00", "status": "completed" }, "tags": [] @@ -917,10 +917,10 @@ "metadata": { "id": "ict-15g-learned-prereg", "papermill": { - "duration": 0.002474, - "end_time": "2026-09-26T20:41:50.858890+00:00", + "duration": 0.002354, + "end_time": "2026-09-26T20:52:03.488133+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.856416+00:00", + "start_time": "2026-09-26T20:52:03.485779+00:00", "status": "completed" }, "tags": [] @@ -934,9 +934,9 @@ "\n", "**Question (#17977)** : pour des fonctions booléennes apprises par de petits réseaux, où le ratio s_max / √deg sature-t-il ? L'entraînement adversarial déplace-t-il ce ratio, et dans quel sens ?\n", "\n", - "### Pré-enregistrement (scellé AVANT toute mesure)\n", + "### Plan d'analyse déclaré (critères d'échec explicites)\n", "\n", - "Les définitions, seuils, graines, cibles et prédictions ci-dessous sont figées avant l'inspection de toute sortie. Toute déviation sera signalée dans l'interprétation.\n", + "Les définitions, seuils, graines, cibles et prédiction ci-dessous constituent le **plan d'analyse déclaré** du banc : les critères d'échec (P1 réfutée → verdict `FAIL`) sont explicites et n'ont pas été re-seuillés après lecture des résultats. Les corrections d'instrument nécessaires à la mise au point sont **documentées** dans la section « Amendements de calibration » (graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42}) ; l'assemblage du notebook ne fournit pas d'horodatage indépendant externe de ces étapes — la traçabilité repose sur cette documentation, pas sur une affirmation temporelle invérifiable.\n", "\n", "**Encodage pré-défini** (réserve #9771 : le VRAI degré de Fourier, pas un proxy de masse) :\n", "\n", @@ -946,13 +946,13 @@ "- **degré réel** : `deg(f) = max{|S| : |f̂(S)| > TOL}` avec `TOL = 1e-9` — les tables sont exactes, les coefficients sont des multiples de `2^{1−n}` : la tolérance stricte est légitime ;\n", "- **s_max exact sur l'hypercube** `Q_n` : `s_max(f) = max_x |{i : f(x ⊕ e_i) ≠ f(x)}|` — c'est la **définition de Huang**, **distincte** de la sensibilité sur graphe de transition observé (`ict.sensitivity.local_sensitivity`, banc legacy ci-dessus). Les deux grandeurs sont nommées séparément et jamais mélangées.\n", "\n", - "**Design gelé** :\n", + "**Design** :\n", "\n", "| Élément | Valeur |\n", "|---|---|\n", "| tailles | `n ∈ {3, 4}` (tables de 8 / 16 entrées, CPU borné) |\n", "| cibles (labels contrôlés) | `OR_n`, `AND_n`, `MAJ_n` (n=3 : ≥2 ; n=4 : ≥3), `PAR_n`, `TRI_bal_n` (table aléatoire équilibrée, graine `20260720 + n`, imprimée dans la sortie) |\n", - "| graines de test | `{0, 1, 7, 42}` (≥ 2 exigé) ; par graine : init du réseau et split 75 % train / 25 % holdout déterministes (rng séparés), **identiques entre les deux régimes** (paires appariées) |\n", + "| graines de verdict | `{0, 1, 7, 42}` (≥ 2 exigé) ; par graine : init du réseau et split 75 % train / 25 % holdout déterministes (rng séparés), **identiques entre les deux régimes** (paires appariées) |\n", "| régimes | `normal` = BCE **équilibrée par classe** sur les points train ; `adversarial` = BCE(train) + **0,5 ×** BCE du **pire voisin Hamming-1** de chaque point train (adversaire discret exact à rayon 1, label du point propre ; λ = 0,5, cf. amendements) |\n", "| budget | 400 étapes Adam lr 0.05, full batch — budget FIXE, convergence non forcée (c'est l'écart de généralisation qui porte le signal) |\n", "| garde anti-dégénérescence (régimes entraînés) | entrée marquée `degenerate` si table réalisée constante OU train_acc < 0.9 ; exclue des verdicts, comptée honnêtement (réserve : éviter les réseaux constants vacuous) ; pour le contrôle `untrained`, seule la constance exclut (aucune exigence d'accuracy à 0 étape) |\n", @@ -962,14 +962,14 @@ "1. réseau non entraîné (même init que la paire, 0 étape) ;\n", "2. bande aléatoire appariée en degré : n=3 **exhaustive** (les 256 fonctions booléennes), n=4 échantillon de 3000 fonctions uniformes — distribution de référence du ratio par degré.\n", "\n", - "**Prédictions falsifiables** :\n", + "**Prédiction falsifiable P1 et sa mesure** :\n", "\n", - "- **P1 (la question de l'issue)** : l'entraînement adversarial **réduit** s_max de la fonction réalisée. CONFIRMÉE ssi (i) `n_paires ≥ 8` (paires non-dégénérées des deux côtés), (ii) `médiane(Δs_max = s_max_adv − s_max_norm) < 0`, (iii) `#{Δ < 0} > #{Δ > 0}` (les égalités à 0 ne comptent pour aucun camp).\n", + "- **P1** : l'entraînement adversarial **réduit** s_max de la fonction réalisée — critère déclaré sur **Δs_max**, **proxy** de la quantité de l'issue (le ratio s_max/√deg ; le complément Δratio est mesuré en fin de banc, section post-revue). CONFIRMÉE ssi (i) `n_paires ≥ 8` (paires non-dégénérées des deux côtés), (ii) `médiane(Δs_max) < 0`, (iii) `#{Δ < 0} > #{Δ > 0}` (les égalités à 0 ne comptent pour aucun camp).\n", "- **P2 (gate instrument — théorème, pas prédiction)** : toute table réalisée non constante satisfait `s_max ≥ √deg` (Huang sur Q_n). Violation = bug instrument → verdict `INVALID`.\n", "- **P3 (contrôle untrained)** : `médiane(s_max_norm) ≤ médiane(s_max_untrained)` — l'entraînement sur labels contrôlés n'augmente pas la sensibilité médiane.\n", "- **P4 (résolution / saturation, réserves #9771-#9764)** : au moins **2 degrés distincts** parmi les tables réalisées non-dégénérées des régimes entraînés, ET fraction des entrées entraînées (non-dégénérées) au plafond structurel `s_max = n` **strictement inférieure à 3/4** (la mesure ne sature pas).\n", "\n", - "**Verdict global pré-enregistré** :\n", + "**Verdict global (critères déclarés)** :\n", "\n", "| Condition | Verdict |\n", "|---|---|\n", @@ -978,15 +978,15 @@ "| P1 confirmée (hors régime INCONCLUSIVE) | `PASS` |\n", "| P1 réfutée (`médiane(Δ) ≥ 0` ou direction inversée) hors régime INCONCLUSIVE | `FAIL` |\n", "\n", - "Le verdict porte sur P1 (déplacement du ratio par l'adversarial, sens prédit : vers le bas) ; P3 et P4 sont des contrôles rapportés, pas des conditions du verdict.\n", + "Le verdict porte sur P1 (déplacement par l'adversarial, sens prédit : vers le bas) ; P3 et P4 sont des contrôles rapportés, pas des conditions du verdict.\n", "\n", - "### Amendements pré-exécution (scellés AVANT l'exécution de test ; graines 0/1/7/42 vierges)\n", + "### Amendements de calibration (documentés ; graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42})\n", "\n", - "Trois corrections d'**instrument**, calibrées sur des **graines de calibration disjointes {11, 22}** (jamais relues sur les graines de test), avec pour seul critère la **santé de l'instrument** — taux de dégénérés et train_acc du régime normal —, jamais le signal Δs_max. **Aucun seuil de verdict n'a bougé** (P1-P4, bornes, graines de test, garde anti-dégénérescence : inchangés).\n", + "Trois corrections d'**instrument**, appliquées en utilisant **uniquement** les graines {11, 22} — disjointes des graines de verdict — avec pour seul critère la **santé de l'instrument** (taux de dégénérés, train_acc du régime normal), pas le signal Δs_max ou Δratio. Les seuils de verdict (P1-P4, bornes, graines de verdict, garde anti-dégénérescence) sont restés inchangés du plan initial à l'analyse.\n", "\n", "1. **Gradient BCE (v1 → v2)** : la première version codait `dL/dz = −y·σ(y·z)` au lieu de `−y·σ(−y·z)` — un gradient de signe faut qui plafonnait train_acc vers 0,5-0,85 en rendant la confiance répulsive. Corrigé + gate optimiseur ajoutée (fit parfait de MAJ_3 sur table complète, graine 11).\n", "2. **BCE équilibrée par classe (v2)** : poids `1/(2·fréquence de classe)` normalisés — sans elle, les cibles déséquilibrées (OR/AND : `2^n − 1` contre 1) convergent vers la constante vacuous, précisément ce que la garde anti-dégénérescence doit éviter de produire en masse.\n", - "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre et l'apprentissage échoue (mesuré en calibration : 57,5 % de dégénérés). λ = 0,5 (poids à la TRADES) restaure l'apprentissage (train_acc 1,0 en calibration sur 18/20 bras adversariaux) en conservant la pression de lissage local — c'est l'objet même de la question P1." + "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre et l'apprentissage échoue (mesuré en calibration : 57,5 % de dégénérés). λ = 0,5 (poids à la TRADES) restaure l'apprentissage (train_acc 1,0 en calibration sur 18/20 bras adversariaux) en conservant la pression de lissage local. **Grille λ testée : {0 (= normal), 0,5, 1}** — aucune valeur intermédiaire entre 0,5 et 1 n'a été essayée." ] }, { @@ -995,17 +995,17 @@ "id": "ae365629", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:50.865487Z", - "iopub.status.busy": "2026-09-26T20:41:50.865072Z", - "iopub.status.idle": "2026-09-26T20:41:51.020500Z", - "shell.execute_reply": "2026-09-26T20:41:51.020103Z" + "iopub.execute_input": "2026-09-26T20:52:03.494229Z", + "iopub.status.busy": "2026-09-26T20:52:03.494052Z", + "iopub.status.idle": "2026-09-26T20:52:03.675299Z", + "shell.execute_reply": "2026-09-26T20:52:03.674055Z" }, "id": "ict-15g-learned-instrument", "papermill": { - "duration": 0.159752, - "end_time": "2026-09-26T20:41:51.021199+00:00", + "duration": 0.185463, + "end_time": "2026-09-26T20:52:03.675999+00:00", "exception": false, - "start_time": "2026-09-26T20:41:50.861447+00:00", + "start_time": "2026-09-26T20:52:03.490536+00:00", "status": "completed" }, "tags": [] @@ -1019,13 +1019,7 @@ " dictateur_4 : deg=1 (attendu 1), s_max=1 (attendu 1) -> OK\n", " OR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", " MAJ_3 : deg=3 (attendu 3), s_max=2 (attendu 2) -> OK\n", - " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", " theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : 0 violation(s)\n" ] }, @@ -1268,17 +1262,17 @@ "id": "0a857aa1", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:51.027170Z", - "iopub.status.busy": "2026-09-26T20:41:51.026967Z", - "iopub.status.idle": "2026-09-26T20:41:55.081703Z", - "shell.execute_reply": "2026-09-26T20:41:55.080927Z" + "iopub.execute_input": "2026-09-26T20:52:03.683490Z", + "iopub.status.busy": "2026-09-26T20:52:03.683177Z", + "iopub.status.idle": "2026-09-26T20:52:07.174949Z", + "shell.execute_reply": "2026-09-26T20:52:07.173822Z" }, "id": "ict-15g-learned-bench", "papermill": { - "duration": 4.058593, - "end_time": "2026-09-26T20:41:55.082418+00:00", + "duration": 3.496793, + "end_time": "2026-09-26T20:52:07.175965+00:00", "exception": false, - "start_time": "2026-09-26T20:41:51.023825+00:00", + "start_time": "2026-09-26T20:52:03.679172+00:00", "status": "completed" }, "tags": [] @@ -1512,17 +1506,17 @@ "id": "6fbaf32e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:41:55.090432Z", - "iopub.status.busy": "2026-09-26T20:41:55.090100Z", - "iopub.status.idle": "2026-09-26T20:41:55.887879Z", - "shell.execute_reply": "2026-09-26T20:41:55.887109Z" + "iopub.execute_input": "2026-09-26T20:52:07.185531Z", + "iopub.status.busy": "2026-09-26T20:52:07.185151Z", + "iopub.status.idle": "2026-09-26T20:52:08.270652Z", + "shell.execute_reply": "2026-09-26T20:52:08.269613Z" }, "id": "ict-15g-learned-verdicts", "papermill": { - "duration": 0.802652, - "end_time": "2026-09-26T20:41:55.888477+00:00", + "duration": 1.092434, + "end_time": "2026-09-26T20:52:08.271791+00:00", "exception": false, - "start_time": "2026-09-26T20:41:55.085825+00:00", + "start_time": "2026-09-26T20:52:07.179357+00:00", "status": "completed" }, "tags": [] @@ -1563,22 +1557,29 @@ "adversarial 1.0\n", "normal 1.0\n", "\n", - "--- P1 (pre-enregistre) : l adversarial reduit s_max ---\n", + "--- P1 (declaree) : l adversarial reduit s_max ---\n", " paires non-degeneres : 28 ; Delta = s_max_adv - s_max_norm : 0 negatives / 27 nulles / 1 positives ; mediane = 0.0\n", " P1 : NON CONFIRMEE\n", "--- P2 (theoreme, gate instrument) : 118 tables non constantes, 0 violation(s) de s_max >= sqrt(deg) -> OK\n", "--- P3 (controle untrained) : mediane s_max normal = 3.0, untrained = 2.0 -> NON CONFIRMEE (l entrainement n augmente pas la sensibilite)\n", "--- P4 (resolution/saturation) : degres distincts = 3 (>= 2 requis), fraction au plafond s_max = n : 46.0% (< 75 % requis) -> CONFIRMEE\n", "\n", - "=== VERDICT #17977 (pre-enregistre) : FAIL ===\n", + "=== VERDICT #17977 (criteres declares) : FAIL ===\n", " fraction degeneree (entraines) : 21.2% (seuil INCONCLUSIVE : > 33,3 %)\n", - " Rappel des conditions : INVALID si P2 violee ; INCONCLUSIVE si P4 non tenue, n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).\n" + " Rappel des conditions : INVALID si P2 violee ; INCONCLUSIVE si P4 non tenue, n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).\n", + "\n", + "--- Complement post-revue : Delta ratio = ratio_adv - ratio_norm (memes paires qualifiees que P1) ---\n", + " paires : 28 ; negatives = 0, nulles = 26, positives = 2 ; mediane = 0.000000\n", + " paire (4, 'TRI_bal_4', 7) : Delta ratio = +0.309401 (s_max 4->4, deg 4->3)\n", + " paire (3, 'AND_3', 1) : Delta ratio = +0.317837 (s_max 2->3, deg 2->3)\n", + " Lecture descriptive (hors verdict declare) : aucun deplacement negatif du ratio ;\n", + " les paires a s_max constant montrent que degre realise et ratio peuvent bouger seuls.\n" ] } ], "source": [ - "# --- Banc #17977 : carte de saturation + verdicts PRE-ENREGISTRES ---\n", - "# (analyse executee selon les seuils scelles ci-dessus ; aucune re-seuillage post-hoc)\n", + "# --- Banc #17977 : carte de saturation + verdicts du plan DECLARE ---\n", + "# (analyse executee selon les seuils declares ci-dessus ; aucun re-seuillage post-hoc)\n", "\n", "# Bande aleatoire appariee en degre : n=3 exhaustive (256 fonctions), n=4 echantillon 3000\n", "rand_rows = []\n", @@ -1642,7 +1643,7 @@ "med_delta = float(delta_smax.median()) if n_pairs else float('nan')\n", "n_neg, n_pos = int((delta_smax < 0).sum()), int((delta_smax > 0).sum())\n", "p1_confirmee = bool(n_pairs >= 8 and med_delta < 0 and n_neg > n_pos)\n", - "print(f'\\n--- P1 (pre-enregistre) : l adversarial reduit s_max ---')\n", + "print(f'\\n--- P1 (declaree) : l adversarial reduit s_max ---')\n", "print(f' paires non-degeneres : {n_pairs} ; Delta = s_max_adv - s_max_norm : '\n", " f'{n_neg} negatives / {n_pairs - n_neg - n_pos} nulles / {n_pos} positives ; mediane = {med_delta}')\n", "print(f' P1 : {\"CONFIRMEE\" if p1_confirmee else \"NON CONFIRMEE\"}')\n", @@ -1669,7 +1670,7 @@ " f'fraction au plafond s_max = n : {frac_plafond_glob:.1%} (< 75 % requis) '\n", " f'-> {\"CONFIRMEE\" if p4_ok else \"NON CONFIRMEE\"}')\n", "\n", - "# --- Verdict global pre-enregistre ---\n", + "# --- Verdict global (criteres declares) ---\n", "frac_degen = n_degen / n_trained\n", "if not p2_ok:\n", " verdict_17977 = 'INVALID'\n", @@ -1679,24 +1680,54 @@ " verdict_17977 = 'PASS'\n", "else:\n", " verdict_17977 = 'FAIL'\n", - "print(f'\\n=== VERDICT #17977 (pre-enregistre) : {verdict_17977} ===')\n", + "print(f'\\n=== VERDICT #17977 (criteres declares) : {verdict_17977} ===')\n", "print(f' fraction degeneree (entraines) : {frac_degen:.1%} (seuil INCONCLUSIVE : > 33,3 %)')\n", "print(' Rappel des conditions : INVALID si P2 violee ; INCONCLUSIVE si P4 non tenue, '\n", - " 'n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).')" + " 'n_paires < 8 ou degen > 1/3 ; PASS si P1 confirmee ; FAIL sinon (mediane >= 0).')\n", + "\n", + "# --- Complement post-revue : Delta RATIO apparie (la quantite de l'issue #17977) ---\n", + "# P1 declaree porte sur Delta s_max, PROXY de la quantite de l'issue (le ratio).\n", + "# Ce bloc, ajoute apres revue, mesure la quantite elle-meme : lecture DESCRIPTIVE,\n", + "# sans critere declare -- aucun seuil du plan ne porte sur Delta ratio. Rappel :\n", + "# Delta s_max = 0 n'entraine PAS Delta ratio = 0 (le degre de la table realisee\n", + "# peut differer entre les deux regimes d'une meme paire).\n", + "rn_q = conc_17977[conc_17977['regime'] == 'normal'].set_index(['n', 'cible', 'graine'])\n", + "ra_q = conc_17977[conc_17977['regime'] == 'adversarial'].set_index(['n', 'cible', 'graine'])\n", + "common_q = rn_q.index.intersection(ra_q.index)\n", + "delta_ratio = (ra_q.loc[common_q, 'ratio'] - rn_q.loc[common_q, 'ratio']).sort_values()\n", + "n_neg_r, n_nul_r, n_pos_r = int((delta_ratio < 0).sum()), int((delta_ratio == 0).sum()), int((delta_ratio > 0).sum())\n", + "print('\\n--- Complement post-revue : Delta ratio = ratio_adv - ratio_norm (memes paires qualifiees que P1) ---')\n", + "print(' paires : %d ; negatives = %d, nulles = %d, positives = %d ; mediane = %.6f'\n", + " % (len(delta_ratio), n_neg_r, n_nul_r, n_pos_r, float(delta_ratio.median())))\n", + "for k_q, v_q in delta_ratio[delta_ratio != 0].items():\n", + " s_n = int(rn_q.loc[k_q, 's_max']); s_a = int(ra_q.loc[k_q, 's_max'])\n", + " d_n = int(rn_q.loc[k_q, 'deg']); d_a = int(ra_q.loc[k_q, 'deg'])\n", + " print(' paire %s : Delta ratio = %+.6f (s_max %d->%d, deg %d->%d)'\n", + " % (k_q, float(v_q), s_n, s_a, d_n, d_a))\n", + "print(' Lecture descriptive (hors verdict declare) : aucun deplacement negatif du ratio ;')\n", + "print(' les paires a s_max constant montrent que degre realise et ratio peuvent bouger seuls.')" ] }, { "cell_type": "markdown", "id": "acea4183", "metadata": { - "id": "ict-15g-learned-interp" + "id": "ict-15g-learned-interp", + "papermill": { + "duration": 0.002679, + "end_time": "2026-09-26T20:52:08.278199+00:00", + "exception": false, + "start_time": "2026-09-26T20:52:08.275520+00:00", + "status": "completed" + }, + "tags": [] }, "source": [ - "### Interprétation du banc #17977 — verdict pré-enregistré : FAIL (délivré tel quel, sans re-seuillage)\n", + "### Interprétation du banc #17977 — verdict FAIL aux critères déclarés (délivré tel quel, sans re-seuillage)\n", "\n", - "**Ce qui est réfuté, et ce qui ne l'est pas.** Le verdict `FAIL` porte **uniquement** sur P1 — la prédiction pré-enregistrée « l'entraînement adversarial réduit s_max de la fonction réalisée ». Mesure : **28 paires appariées non-dégénérées, 27 Δs_max = 0, 1 Δ > 0, 0 Δ < 0, médiane 0,0** — les deux régimes réalisent la **même table de vérité** dans 27 cas sur 28. La borne de Huang, elle, est **intouchée** : P2 constate **0 violation sur 118 tables réalisées non constantes** (et 256/256 à l'exhaustif n=3) — le théorème tient sur l'hypercube vrai, c'est la prédiction de déplacement qui tombe.\n", + "**Ce qui est réfuté, et ce qui ne l'est pas.** Le verdict `FAIL` porte **uniquement** sur P1 — la prédiction déclarée « l'entraînement adversarial réduit s_max de la fonction réalisée ». P1 est un critère sur **Δs_max**, **proxy** de la quantité de l'issue (le ratio s_max/√deg). Mesure : **28 paires appariées non-dégénérées, 27 Δs_max = 0, 1 Δ > 0, 0 Δ < 0, médiane 0,0** — s_max est **inchangé** dans 27 paires sur 28. Inchangé en s_max **n'implique pas** même table de vérité ni ratio inchangé : le complément post-revue mesure explicitement la quantité de l'issue — **Δratio : 0 négatif / 26 nul / 2 positif, médiane 0,0** (analyse descriptive, sans critère déclaré) ; les deux paires non nulles : (n=4, TRI_bal_4, graine 7) conserve s_max = 4 mais passe de deg 4 à deg 3, soit Δratio = +0,309, et (n=3, AND_3, graine 1) monte de s_max 2 à 3 avec deg 2→3, soit Δratio = +0,318. Conclusion double : **aucun déplacement négatif du ratio détecté** (aucune paire négative), et la réfutation de P1 est bien celle du critère déclaré (Δs_max), le ratio étant mesuré en complément. La borne de Huang, elle, est **intouchée** : P2 constate **0 violation sur 118 tables réalisées non constantes** (et 256/256 à l'exhaustif n=3) — le théorème tient sur l'hypercube vrai, c'est la prédiction de déplacement qui tombe.\n", "\n", - "**Pourquoi la fenêtre d'effet est vide à cette échelle.** À rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point d'entraînement porte souvent le label opposé (toujours, pour la parité) : l'adversaire contredit directement les labels observés. La calibration sur graines disjointes {11, 22} l'a mesuré : à poids λ = 1, l'apprentissage échoue (57,5 % de dégénérés) ; à λ = 0,5, l'apprentissage réussit mais la table réalisée devient **identique** au régime normal. Entre les deux, pas de régime intermédiaire : à 3-4 bits, **le lissage adversarial ne traverse pas le seuil** — il déplace la géométrie du logit, pas la fonction seuillée. La réponse à la question de l'issue (« l'adversarial déplace-t-il le ratio, et dans quel sens ? ») est donc, dans CE régime : **pas de déplacement détectable — la fenêtre d'effet observable est vide à cette échelle**.\n", + "**Pourquoi aucun effet détecté à cette échelle.** À rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point d'entraînement porte souvent le label opposé (toujours, pour la parité) : l'adversaire contredit directement les labels observés. La calibration sur graines disjointes {11, 22} l'a mesuré : à poids λ = 1, l'apprentissage échoue (57,5 % de dégénérés) ; à λ = 0,5, l'apprentissage réussit mais s_max reste inchangé (27/28 paires Δs_max = 0, et aucun Δratio négatif). **Grille λ testée : {0 (= normal), 0,5, 1} seulement** — un régime intermédiaire (0,5 < λ < 1) n'a **pas** été testé et n'est pas exclu par ce banc. Dans les régimes testés, à 3-4 bits, le lissage adversarial ne traverse pas le seuil : il déplace la géométrie du logit, pas la fonction seuillée. La réponse à la question de l'issue (« l'adversarial déplace-t-il le ratio, et dans quel sens ? ») est donc : **dans les régimes λ ∈ {0,5} testés avec apprentissage réussi, aucun déplacement détecté** (descriptif pour le ratio ; réfutation déclarée pour s_max).\n", "\n", "**Carte de saturation (le livrable de #17977).** Les ratios réalisés vivent dans **[1,0 ; 2,31]**, Huang garantissant le plancher 1. Le plafond structurel `s_max = n` est touché par **46,0 %** des entrées entraînées non-dégénérées — la mesure ne sature pas (P4 confirmée : 3 degrés distincts, < 75 % au plafond). Lectures fines :\n", "\n", @@ -1704,14 +1735,14 @@ "|---|---|---|\n", "| ratio médian (n=4, deg=4, normal) | 1,75 | sous la médiane aléatoire appariée (2,0) |\n", "| ratio médian (n=4, deg=4, adversarial) | 1,50 | idem — les deux régimes dans la bande |\n", - "| fraction des ratios entraînés dans la bande aléatoire [p5, p95] de leur degré | 100 % (normal et adversarial) | le ratio des fonctions apprises est **indiscernable** de celui de fonctions aléatoires de même degré de Fourier |\n", + "| fraction des ratios entraînés dans la bande aléatoire [p5, p95] de leur degré | 100 % (normal et adversarial) | **chevauchement complet** avec la bande appariée en degré — un chevauchement, qui **n'établit pas** une indistinguabilité statistique (aucun test formel n'est posé) |\n", "| médiane s_max : entraîné normal vs untrained | 3,0 vs 2,0 | **P3 réfutée** : apprendre des cibles de haut degré AUGMENTE la sensibilité médiane par rapport à l'init (les tables untrained réalisent surtout des fonctions de degré 1-3 à faible ratio) |\n", "\n", - "Le contrôle « fonction aléatoire de même degré » fait son travail : il montre que le ratio s_max/√deg **ne discrimine pas** une fonction apprise d'une fonction aléatoire de même degré — l'information de l'apprentissage ne vit pas dans ce ratio, elle vit dans la table (train_acc 1,0 partout où non-dégénéré).\n", + "Le contrôle « fonction aléatoire de même degré » fait son travail : les ratios appris **chevauchent** ceux de fonctions aléatoires de même degré de Fourier — à cette échelle, le ratio s_max/√deg ne sépare pas une fonction apprise d'une aléatoire de même degré ; l'information de l'apprentissage ne vit pas dans ce ratio, elle vit dans la table (train_acc 1,0 partout où non-dégénéré).\n", "\n", - "**Dégénérés : 17/80 = 21,2 %** (garde pré-enregistrée, sous le seuil INCONCLUSIVE de 33,3 %). Dominés par OR_4/AND_4 lorsque le point minoritaire tombe en holdout : le train est alors uniforme, la constante est exacte sur le train (train_acc 1,0) mais vacuous — exclue et comptée honnêtement.\n", + "**Dégénérés : 17/80 = 21,2 %** (garde déclarée, sous le seuil INCONCLUSIVE de 33,3 %). Dominés par OR_4/AND_4 lorsque le point minoritaire tombe en holdout : le train est alors uniforme, la constante est exacte sur le train (train_acc 1,0) mais vacuous — exclue et comptée honnêtement.\n", "\n", - "**Portée (bornée, pas généralisable)** : hypercubes 3-4 bits, MLP 16 cachées, 75 % de couverture, budget fixe 400 étapes, 4 graines, 5 cibles, λ = 0,5. La littérature adversariale continue (perturbations ℓ∞ ε ≪ 1) opère dans un régime sans équivalent discret — à n croissant, la densité de contraintes contradictoires par point diminue et la fenêtre pourrait s'ouvrir ; ce banc ne dit rien des grands n. La formulation **« transposition conjecturale »** reste portée par le banc hérité (graphes de transition, cellules 2-9) ; sur l'hypercube vrai, l'inégalité de Huang est un théorème et l'instrument la vérifie mécaniquement." + "**Portée (bornée, pas généralisable)** : hypercubes 3-4 bits, MLP 16 cachées, 75 % de couverture, budget fixe 400 étapes, 4 graines de verdict, 5 cibles, poids adversarial λ = 0,5 (grille testée {0, 0,5, 1}). La littérature adversariale continue (perturbations ℓ∞ ε ≪ 1) opère dans un régime sans équivalent discret ; **ce banc ne dit rien des grands n**. La formulation **« transposition conjecturale »** reste portée par le banc hérité (graphes de transition, cellules 2-9) ; sur l'hypercube vrai, l'inégalité de Huang est un théorème et l'instrument la vérifie mécaniquement." ] } ], @@ -1735,14 +1766,14 @@ }, "papermill": { "default_parameters": {}, - "duration": 17.300553, - "end_time": "2026-09-26T20:41:56.236547+00:00", + "duration": 9.726582, + "end_time": "2026-09-26T20:52:08.626777+00:00", "environment_variables": {}, "exception": null, "input_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", "output_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", "parameters": {}, - "start_time": "2026-09-26T20:41:38.935994+00:00", + "start_time": "2026-09-26T20:51:58.900195+00:00", "version": "2.7.0" } }, diff --git a/docs/ict/dissociations-matrix.md b/docs/ict/dissociations-matrix.md index b719ac68c3..10af3b2a39 100644 --- a/docs/ict/dissociations-matrix.md +++ b/docs/ict/dissociations-matrix.md @@ -95,7 +95,7 @@ Conventions : | **ICT-15c** | Le **motif de désaccord** entre proxys est stable cross-substrat = obstruction informative (≠ dispersion d'échelle) | `s` ✓ | Vecteur d'obstruction `(a−b)/(\|a\|+\|b\|+ε)`, `mean_norm_L2`, verdict `STABLE`/`NOISE` | `f(x)=x%2` saturait (artefact plafonné) → `f(x)=x` (identité) restaure un panel non-plafonné | 4 substrats (Gray-Scott, Axelrod, Grokking, May) | proxy_interpretation | **Spéculatif** | **Candidat obstruction** (régime 2, *pas* érigé en obstruction cohomologique régime 3 — cf garde-fou A2). Verdict falsifiable `STABLE` si `mean_norm_L2 ≤ 0.05`. See [#7395](https://github.com/jsboige/CoursIA/issues/7395) | | **ICT-15d** | La cochaîne de Čech pondérée discriminate les substrats (`NON_TRIVIAL` = les proxys ne se recollent pas en 1D) | `s` ✓ | `mean_coboundary`, `s2_over_s1`, `effective_rank`, verdict `TRIVIAL`/`NON_TRIVIAL` | Sanity check + 4 substrats ICT-15c | 4 substrats × 3 proxys × fenêtrage | reproduced_in_toy_model | **Spéculatif** *(réserve de non-discrimination — voir [§ ICT-15d-corr](#note-ict-15d-corr--requalification-2026-08-21))* | 4/4 substrats `NON_TRIVIAL` sur la mesure courante ; l'« honnête négatif 0/4 » de la version précédente mesurait un `sensitivity.py` défectueux (réparé par [#9792](https://github.com/jsboige/CoursIA/pull/9792)). **Réserve** : la sortie reste dominée par la SVD (`s2_over_s1`, `effective_rank`) ; le contre-exemple `axelrod` (`mean_cocycle=0`, `obstruction_ratio=0`, `sign_consistency=0`) ne consulte ni le nerf ni H¹. Le verdict **ne porte pas** l'énoncé « Čech discrimine les substrats ». Issue [#7744](https://github.com/jsboige/CoursIA/issues/7744) closed-archived. | | **ICT-15e** | La trajectoire de réparation **est** un signal distinct d'un random walk calibré (recouvrabilité = agentivité, ≠ simple gain) | `s` ✓, `q` ○, `π` ○ | Distance de Mahalanobis sur signature 5-D, seuil p95 par permutation null | Random walk calibré sur mêmes extrema + 1 contrôle structural ; conjecture pré-enregistrée | 3 configs Gray-Scott (pearl/spots/seed=7) | reproduced_in_toy_model | **Fortement soutenu** | `CONFIRMED` sur substrats à dynamique réaction-diffusion informative (signature `slope_ratio` élevé) ; `FALSIFIED` sinon (random walk reproduit la structure) — verdict nuancé honnête, *pas* universel. See [#8077](https://github.com/jsboige/CoursIA/issues/8077) | -| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux vit dans la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne déplace **pas** le ratio à 3-4 bits — la prédiction pré-enregistrée « l'adversarial réduit s_max » est **réfutée** (28 paires appariées : 27 Δ=0, 1 Δ>0, 0 Δ<0, médiane 0) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — calibration sur graines disjointes {11, 22} | reproduced_in_toy_model + pre_enregistrement | **TESTÉ (FAIL — prédiction réfutée, livrée sans re-seuillage)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est réfuté, pas la borne. À λ=1 l'adversaire rayon-1 rend l'apprentissage impossible (57,5 % dégénérés en calibration) : la fenêtre d'effet est **vide à cette échelle**, lecture bornée ne généralisant pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | +| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux **chevauche** la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne déplace **ni s_max ni le ratio** à 3-4 bits — critère **déclaré** (Δs_max, **proxy** de la quantité de l'issue) : 28 paires appariées, 27 Δs_max=0, 1 Δ>0, 0 Δ<0, médiane 0 → **FAIL** ; complément post-revue sur le ratio : 26 Δratio=0, 2 >0, 0 <0, médiane 0 (descriptif, sans critère déclaré) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) ; Δratio apparié mesuré explicitement (post-revue) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — plan d'analyse **déclaré** avec amendements de calibration documentés sur graines disjointes {11, 22} (pas d'horodatage indépendant externe) | reproduced_in_toy_model | **TESTÉ (FAIL du critère déclaré Δs_max, sans re-seuillage ; pas de déplacement du ratio détecté non plus)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est non détecté, pas la borne qui tombe. **Grille λ testée : {0 (= normal), 0,5, 1}** : à λ=1 l'apprentissage échoue (57,5 % dégénérés en calibration), à λ=0,5 aucun déplacement détecté ; les valeurs intermédiaires (0,5 < λ < 1) **non testées**. Chevauchement de bande **≠** indistinguabilité statistique (aucun test formel). Δs_max = 0 n'implique pas même table : une paire (n=4, TRI_bal_4, graine 7) garde s_max = 4 mais passe de deg 4 à deg 3 (Δratio = +0,309). Lecture bornée aux régimes testés, ne généralise pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | | **ICT-16** | `F` = partie résiduelle de `K` + bosse complexité-entropie | `s` ✓ | MDL two-part code | Modèles témoins sans bosse | RNG multi-source | established_external | **Établi** | Bosse Crutchfield-Feldman 1998 mesurée à H* ≈ 1.99 bits/symbole ; cave emptor : **un seul couple (modèle, famille de sources)** dans la figure rendue | | **ICT-17** | L'ε-machine (Crutchfield) ≠ Hoel : deux lectures de l'émergence causale | `s` ✓, `W` ○ | États causaux + complexité statistique + entropie d'excès | Hoel info effective, CE 2.0 | multi-substrat | conceptual_analogy | **Fortement soutenu** | Dissociation reconnue mais pas hiérarchisée | | **ICT-17b** | 2/5 proxys dissocient du progrès de généralisation pendant le grokking | `s` ✓, `q` ○ | ‖w‖², Fisher-MDL, 1-test_acc, trace de Fisher, pred-zlib | Baseline avant-grokking | 5 proxys | reproduced_in_toy_model | **Établi** | 3 co-localisent (‖w‖², Fisher-MDL, 1-test_acc) ; 2 dissocient (trace Fisher, pred-zlib). Verdict honnête dissociatif (#7268) | From 700e5ef95dbb162dea58bc1cbceec116416d62e2 Mon Sep 17 00:00:00 2001 From: jsboige Date: Sat, 26 Sep 2026 22:56:52 +0200 Subject: [PATCH 3/5] docs(ict): qualifier les limites du banc adversarial Distingue le critere declare sur s_max du ratio mesure en complement, retire les explications causales non testees et corrige la portee du chevauchement temoin. Co-Authored-By: Claude Code --- .../ICT-15g-EmpiricalHuangExploitation.ipynb | 20 ++++++++----------- docs/ict/dissociations-matrix.md | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb index 4b53e3b00b..96fdab53af 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb @@ -1723,26 +1723,22 @@ "tags": [] }, "source": [ - "### Interprétation du banc #17977 — verdict FAIL aux critères déclarés (délivré tel quel, sans re-seuillage)\n", + "### Interprétation du banc #17977 — FAIL du critère déclaré sur Δs_max\n", "\n", - "**Ce qui est réfuté, et ce qui ne l'est pas.** Le verdict `FAIL` porte **uniquement** sur P1 — la prédiction déclarée « l'entraînement adversarial réduit s_max de la fonction réalisée ». P1 est un critère sur **Δs_max**, **proxy** de la quantité de l'issue (le ratio s_max/√deg). Mesure : **28 paires appariées non-dégénérées, 27 Δs_max = 0, 1 Δ > 0, 0 Δ < 0, médiane 0,0** — s_max est **inchangé** dans 27 paires sur 28. Inchangé en s_max **n'implique pas** même table de vérité ni ratio inchangé : le complément post-revue mesure explicitement la quantité de l'issue — **Δratio : 0 négatif / 26 nul / 2 positif, médiane 0,0** (analyse descriptive, sans critère déclaré) ; les deux paires non nulles : (n=4, TRI_bal_4, graine 7) conserve s_max = 4 mais passe de deg 4 à deg 3, soit Δratio = +0,309, et (n=3, AND_3, graine 1) monte de s_max 2 à 3 avec deg 2→3, soit Δratio = +0,318. Conclusion double : **aucun déplacement négatif du ratio détecté** (aucune paire négative), et la réfutation de P1 est bien celle du critère déclaré (Δs_max), le ratio étant mesuré en complément. La borne de Huang, elle, est **intouchée** : P2 constate **0 violation sur 118 tables réalisées non constantes** (et 256/256 à l'exhaustif n=3) — le théorème tient sur l'hypercube vrai, c'est la prédiction de déplacement qui tombe.\n", + "**Deux quantités à distinguer.** Le verdict `FAIL` porte sur P1, le critère d'analyse déclaré dans ce notebook : « l'entraînement adversarial réduit s_max ». Sur **28 paires appariées non dégénérées**, 27 ont Δs_max = 0, une a Δs_max > 0, aucune n'a Δs_max < 0 ; la médiane est 0. Le commentaire de claim sur l'issue formulait toutefois l'hypothèse en termes de **ratio** s_max/√deg : P1 (sur Δs_max) n'en est qu'un proxy et ne suffit pas, seul, à répondre à cette formulation. Le complément calculé après revue mesure donc directement Δratio : **26 valeurs nulles, 2 positives, aucune négative**, médiane 0. Sur (n=4, TRI_bal_4, graine 7), s_max reste 4 mais deg passe de 4 à 3 (Δratio = +0,309) ; sur (n=3, AND_3, graine 1), s_max passe de 2 à 3 et deg de 2 à 3 (Δratio = +0,318). Ces résultats ne montrent **aucune baisse dans les paires qualifiées**, mais ne constituent pas un test pré-enregistré du ratio. Δs_max nul n'implique ni même table ni même ratio.\n", "\n", - "**Pourquoi aucun effet détecté à cette échelle.** À rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point d'entraînement porte souvent le label opposé (toujours, pour la parité) : l'adversaire contredit directement les labels observés. La calibration sur graines disjointes {11, 22} l'a mesuré : à poids λ = 1, l'apprentissage échoue (57,5 % de dégénérés) ; à λ = 0,5, l'apprentissage réussit mais s_max reste inchangé (27/28 paires Δs_max = 0, et aucun Δratio négatif). **Grille λ testée : {0 (= normal), 0,5, 1} seulement** — un régime intermédiaire (0,5 < λ < 1) n'a **pas** été testé et n'est pas exclu par ce banc. Dans les régimes testés, à 3-4 bits, le lissage adversarial ne traverse pas le seuil : il déplace la géométrie du logit, pas la fonction seuillée. La réponse à la question de l'issue (« l'adversarial déplace-t-il le ratio, et dans quel sens ? ») est donc : **dans les régimes λ ∈ {0,5} testés avec apprentissage réussi, aucun déplacement détecté** (descriptif pour le ratio ; réfutation déclarée pour s_max).\n", + "**Borne et portée de l'effet.** P2 donne 0 violation sur les 118 tables réalisées non constantes ; le contrôle exhaustif n=3 donne également 0 violation sur 256 fonctions. La borne de Huang sur l'hypercube vrai n'est pas réfutée. À λ = 1, la calibration sur graines disjointes {11, 22} a produit 57,5 % de cas dégénérés ; à λ = 0,5, les paires qualifiées ne montrent aucune baisse de s_max ou du ratio. Seuls λ ∈ {0 ; 0,5 ; 1} ont été examinés ; les valeurs intermédiaires ne sont pas exclues. Le banc ne mesure ni la géométrie des logits ni les grands n : il ne peut expliquer mécaniquement l'absence de baisse ni la généraliser.\n", "\n", - "**Carte de saturation (le livrable de #17977).** Les ratios réalisés vivent dans **[1,0 ; 2,31]**, Huang garantissant le plancher 1. Le plafond structurel `s_max = n` est touché par **46,0 %** des entrées entraînées non-dégénérées — la mesure ne sature pas (P4 confirmée : 3 degrés distincts, < 75 % au plafond). Lectures fines :\n", + "**Carte de saturation.** Les ratios mesurés des tables non constantes sont dans [1,0 ; 2,31]. Parmi les entrées entraînées non dégénérées, 46,0 % atteignent le plafond s_max = n ; trois degrés distincts sont représentés, ce qui satisfait le contrôle P4 déclaré. La bande de fonctions aléatoires appariées en degré recouvre 100 % des ratios appris aux quantiles [p5, p95] de l'échantillon retenu. C'est un **chevauchement descriptif**, pas une preuve d'indistinguabilité statistique.\n", "\n", "| Observation | Valeur mesurée | Lecture |\n", "|---|---|---|\n", "| ratio médian (n=4, deg=4, normal) | 1,75 | sous la médiane aléatoire appariée (2,0) |\n", - "| ratio médian (n=4, deg=4, adversarial) | 1,50 | idem — les deux régimes dans la bande |\n", - "| fraction des ratios entraînés dans la bande aléatoire [p5, p95] de leur degré | 100 % (normal et adversarial) | **chevauchement complet** avec la bande appariée en degré — un chevauchement, qui **n'établit pas** une indistinguabilité statistique (aucun test formel n'est posé) |\n", - "| médiane s_max : entraîné normal vs untrained | 3,0 vs 2,0 | **P3 réfutée** : apprendre des cibles de haut degré AUGMENTE la sensibilité médiane par rapport à l'init (les tables untrained réalisent surtout des fonctions de degré 1-3 à faible ratio) |\n", + "| ratio médian (n=4, deg=4, adversarial) | 1,50 | également dans la bande témoin |\n", + "| médiane s_max : normal vs non entraîné | 3,0 vs 2,0 | P3 non confirmée ; la comparaison brute ne contrôle pas la distribution des degrés réalisés |\n", + "| dégénérés parmi les régimes entraînés | 17/80 = 21,2 % | exclus des paires qualifiées, mais comptés dans le garde |\n", "\n", - "Le contrôle « fonction aléatoire de même degré » fait son travail : les ratios appris **chevauchent** ceux de fonctions aléatoires de même degré de Fourier — à cette échelle, le ratio s_max/√deg ne sépare pas une fonction apprise d'une aléatoire de même degré ; l'information de l'apprentissage ne vit pas dans ce ratio, elle vit dans la table (train_acc 1,0 partout où non-dégénéré).\n", - "\n", - "**Dégénérés : 17/80 = 21,2 %** (garde déclarée, sous le seuil INCONCLUSIVE de 33,3 %). Dominés par OR_4/AND_4 lorsque le point minoritaire tombe en holdout : le train est alors uniforme, la constante est exacte sur le train (train_acc 1,0) mais vacuous — exclue et comptée honnêtement.\n", - "\n", - "**Portée (bornée, pas généralisable)** : hypercubes 3-4 bits, MLP 16 cachées, 75 % de couverture, budget fixe 400 étapes, 4 graines de verdict, 5 cibles, poids adversarial λ = 0,5 (grille testée {0, 0,5, 1}). La littérature adversariale continue (perturbations ℓ∞ ε ≪ 1) opère dans un régime sans équivalent discret ; **ce banc ne dit rien des grands n**. La formulation **« transposition conjecturale »** reste portée par le banc hérité (graphes de transition, cellules 2-9) ; sur l'hypercube vrai, l'inégalité de Huang est un théorème et l'instrument la vérifie mécaniquement." + "Les cas dégénérés sont surtout des cibles OR_4/AND_4 dont le point minoritaire tombe dans le holdout : le train ne contient alors qu'une classe, et une prédiction constante peut atteindre train_acc = 1 sans résoudre la cible complète. Le résultat reste limité aux hypercubes de 3 et 4 bits, au MLP de 16 neurones cachés, au split 75/25, à 400 étapes, aux quatre graines et aux cinq cibles étudiées. La **transposition conjecturale** du banc hérité, qui emploie un graphe de transitions observées plutôt que l'hypercube, conserve son statut distinct." ] } ], diff --git a/docs/ict/dissociations-matrix.md b/docs/ict/dissociations-matrix.md index 10af3b2a39..bfea5eb442 100644 --- a/docs/ict/dissociations-matrix.md +++ b/docs/ict/dissociations-matrix.md @@ -95,7 +95,7 @@ Conventions : | **ICT-15c** | Le **motif de désaccord** entre proxys est stable cross-substrat = obstruction informative (≠ dispersion d'échelle) | `s` ✓ | Vecteur d'obstruction `(a−b)/(\|a\|+\|b\|+ε)`, `mean_norm_L2`, verdict `STABLE`/`NOISE` | `f(x)=x%2` saturait (artefact plafonné) → `f(x)=x` (identité) restaure un panel non-plafonné | 4 substrats (Gray-Scott, Axelrod, Grokking, May) | proxy_interpretation | **Spéculatif** | **Candidat obstruction** (régime 2, *pas* érigé en obstruction cohomologique régime 3 — cf garde-fou A2). Verdict falsifiable `STABLE` si `mean_norm_L2 ≤ 0.05`. See [#7395](https://github.com/jsboige/CoursIA/issues/7395) | | **ICT-15d** | La cochaîne de Čech pondérée discriminate les substrats (`NON_TRIVIAL` = les proxys ne se recollent pas en 1D) | `s` ✓ | `mean_coboundary`, `s2_over_s1`, `effective_rank`, verdict `TRIVIAL`/`NON_TRIVIAL` | Sanity check + 4 substrats ICT-15c | 4 substrats × 3 proxys × fenêtrage | reproduced_in_toy_model | **Spéculatif** *(réserve de non-discrimination — voir [§ ICT-15d-corr](#note-ict-15d-corr--requalification-2026-08-21))* | 4/4 substrats `NON_TRIVIAL` sur la mesure courante ; l'« honnête négatif 0/4 » de la version précédente mesurait un `sensitivity.py` défectueux (réparé par [#9792](https://github.com/jsboige/CoursIA/pull/9792)). **Réserve** : la sortie reste dominée par la SVD (`s2_over_s1`, `effective_rank`) ; le contre-exemple `axelrod` (`mean_cocycle=0`, `obstruction_ratio=0`, `sign_consistency=0`) ne consulte ni le nerf ni H¹. Le verdict **ne porte pas** l'énoncé « Čech discrimine les substrats ». Issue [#7744](https://github.com/jsboige/CoursIA/issues/7744) closed-archived. | | **ICT-15e** | La trajectoire de réparation **est** un signal distinct d'un random walk calibré (recouvrabilité = agentivité, ≠ simple gain) | `s` ✓, `q` ○, `π` ○ | Distance de Mahalanobis sur signature 5-D, seuil p95 par permutation null | Random walk calibré sur mêmes extrema + 1 contrôle structural ; conjecture pré-enregistrée | 3 configs Gray-Scott (pearl/spots/seed=7) | reproduced_in_toy_model | **Fortement soutenu** | `CONFIRMED` sur substrats à dynamique réaction-diffusion informative (signature `slope_ratio` élevé) ; `FALSIFIED` sinon (random walk reproduit la structure) — verdict nuancé honnête, *pas* universel. See [#8077](https://github.com/jsboige/CoursIA/issues/8077) | -| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux **chevauche** la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne déplace **ni s_max ni le ratio** à 3-4 bits — critère **déclaré** (Δs_max, **proxy** de la quantité de l'issue) : 28 paires appariées, 27 Δs_max=0, 1 Δ>0, 0 Δ<0, médiane 0 → **FAIL** ; complément post-revue sur le ratio : 26 Δratio=0, 2 >0, 0 <0, médiane 0 (descriptif, sans critère déclaré) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) ; Δratio apparié mesuré explicitement (post-revue) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — plan d'analyse **déclaré** avec amendements de calibration documentés sur graines disjointes {11, 22} (pas d'horodatage indépendant externe) | reproduced_in_toy_model | **TESTÉ (FAIL du critère déclaré Δs_max, sans re-seuillage ; pas de déplacement du ratio détecté non plus)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est non détecté, pas la borne qui tombe. **Grille λ testée : {0 (= normal), 0,5, 1}** : à λ=1 l'apprentissage échoue (57,5 % dégénérés en calibration), à λ=0,5 aucun déplacement détecté ; les valeurs intermédiaires (0,5 < λ < 1) **non testées**. Chevauchement de bande **≠** indistinguabilité statistique (aucun test formel). Δs_max = 0 n'implique pas même table : une paire (n=4, TRI_bal_4, graine 7) garde s_max = 4 mais passe de deg 4 à deg 3 (Δratio = +0,309). Lecture bornée aux régimes testés, ne généralise pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | +| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux **chevauche** la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne produit **aucune baisse de s_max ni du ratio** dans les paires qualifiées de ce banc à 3-4 bits — critère **déclaré** (Δs_max, **proxy** de la quantité de l'issue) : 28 paires appariées, 27 Δs_max=0, 1 Δ>0, 0 Δ<0, médiane 0 → **FAIL** ; complément post-revue sur le ratio : 26 Δratio=0, 2 >0, 0 <0, médiane 0 (descriptif, sans critère déclaré) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) ; Δratio apparié mesuré explicitement (post-revue) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — plan d'analyse **déclaré** avec amendements de calibration documentés sur graines disjointes {11, 22} (pas d'horodatage indépendant externe) | reproduced_in_toy_model | **TESTÉ (FAIL du critère déclaré Δs_max, sans re-seuillage ; pas de déplacement du ratio détecté non plus)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est non détecté, pas la borne qui tombe. **Grille λ testée : {0 (= normal), 0,5, 1}** : à λ=1 l'apprentissage échoue (57,5 % dégénérés en calibration), à λ=0,5 aucun déplacement détecté ; les valeurs intermédiaires (0,5 < λ < 1) **non testées**. Chevauchement de bande **≠** indistinguabilité statistique (aucun test formel). Δs_max = 0 n'implique pas même table : une paire (n=4, TRI_bal_4, graine 7) garde s_max = 4 mais passe de deg 4 à deg 3 (Δratio = +0,309). Lecture bornée aux régimes testés, ne généralise pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | | **ICT-16** | `F` = partie résiduelle de `K` + bosse complexité-entropie | `s` ✓ | MDL two-part code | Modèles témoins sans bosse | RNG multi-source | established_external | **Établi** | Bosse Crutchfield-Feldman 1998 mesurée à H* ≈ 1.99 bits/symbole ; cave emptor : **un seul couple (modèle, famille de sources)** dans la figure rendue | | **ICT-17** | L'ε-machine (Crutchfield) ≠ Hoel : deux lectures de l'émergence causale | `s` ✓, `W` ○ | États causaux + complexité statistique + entropie d'excès | Hoel info effective, CE 2.0 | multi-substrat | conceptual_analogy | **Fortement soutenu** | Dissociation reconnue mais pas hiérarchisée | | **ICT-17b** | 2/5 proxys dissocient du progrès de généralisation pendant le grokking | `s` ✓, `q` ○ | ‖w‖², Fisher-MDL, 1-test_acc, trace de Fisher, pred-zlib | Baseline avant-grokking | 5 proxys | reproduced_in_toy_model | **Établi** | 3 co-localisent (‖w‖², Fisher-MDL, 1-test_acc) ; 2 dissocient (trace Fisher, pred-zlib). Verdict honnête dissociatif (#7268) | From 61cbcde99c72cf4f5b61817f29732fb38ed14892 Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 27 Sep 2026 00:15:58 +0200 Subject: [PATCH 4/5] fix(ict): remove unrecorded calibration statistics Preserve the declared FAIL verdict and actual notebook outputs while qualifying off-record calibration measurements. Co-Authored-By: Claude Code --- .../ICT-15g-EmpiricalHuangExploitation.ipynb | 268 +++++++++--------- docs/ict/dissociations-matrix.md | 2 +- 2 files changed, 139 insertions(+), 131 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb index 96fdab53af..e83a8fd544 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb @@ -5,10 +5,10 @@ "id": "ict-15b-empirical-cadrage", "metadata": { "papermill": { - "duration": 0.002864, - "end_time": "2026-09-26T20:52:00.310360+00:00", + "duration": 0.013018, + "end_time": "2026-09-26T22:10:44.036038+00:00", "exception": false, - "start_time": "2026-09-26T20:52:00.307496+00:00", + "start_time": "2026-09-26T22:10:44.023020+00:00", "status": "completed" }, "tags": [] @@ -67,10 +67,10 @@ "id": "statut-epistemique", "metadata": { "papermill": { - "duration": 0.00204, - "end_time": "2026-09-26T20:52:00.315085+00:00", + "duration": 0.003831, + "end_time": "2026-09-26T22:10:44.047532+00:00", "exception": false, - "start_time": "2026-09-26T20:52:00.313045+00:00", + "start_time": "2026-09-26T22:10:44.043701+00:00", "status": "completed" }, "tags": [] @@ -85,16 +85,16 @@ "id": "ict-15b-empirical-imports", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:00.324393Z", - "iopub.status.busy": "2026-09-26T20:52:00.324055Z", - "iopub.status.idle": "2026-09-26T20:52:03.000279Z", - "shell.execute_reply": "2026-09-26T20:52:02.999567Z" + "iopub.execute_input": "2026-09-26T22:10:44.054215Z", + "iopub.status.busy": "2026-09-26T22:10:44.054050Z", + "iopub.status.idle": "2026-09-26T22:10:46.528239Z", + "shell.execute_reply": "2026-09-26T22:10:46.527504Z" }, "papermill": { - "duration": 2.680069, - "end_time": "2026-09-26T20:52:03.000878+00:00", + "duration": 2.478486, + "end_time": "2026-09-26T22:10:46.529377+00:00", "exception": false, - "start_time": "2026-09-26T20:52:00.320809+00:00", + "start_time": "2026-09-26T22:10:44.050891+00:00", "status": "completed" }, "tags": [] @@ -136,16 +136,16 @@ "id": "ict-15b-empirical-sanity", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.007208Z", - "iopub.status.busy": "2026-09-26T20:52:03.006970Z", - "iopub.status.idle": "2026-09-26T20:52:03.012418Z", - "shell.execute_reply": "2026-09-26T20:52:03.011767Z" + "iopub.execute_input": "2026-09-26T22:10:46.535917Z", + "iopub.status.busy": "2026-09-26T22:10:46.535578Z", + "iopub.status.idle": "2026-09-26T22:10:46.544232Z", + "shell.execute_reply": "2026-09-26T22:10:46.543293Z" }, "papermill": { - "duration": 0.009325, - "end_time": "2026-09-26T20:52:03.012933+00:00", + "duration": 0.01311, + "end_time": "2026-09-26T22:10:46.545204+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.003608+00:00", + "start_time": "2026-09-26T22:10:46.532094+00:00", "status": "completed" }, "tags": [] @@ -201,10 +201,10 @@ "id": "ict-15b-empirical-methode", "metadata": { "papermill": { - "duration": 0.002294, - "end_time": "2026-09-26T20:52:03.017788+00:00", + "duration": 0.003936, + "end_time": "2026-09-26T22:10:46.553409+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.015494+00:00", + "start_time": "2026-09-26T22:10:46.549473+00:00", "status": "completed" }, "tags": [] @@ -237,16 +237,16 @@ "id": "ict-15b-empirical-gray-scott", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.023617Z", - "iopub.status.busy": "2026-09-26T20:52:03.023433Z", - "iopub.status.idle": "2026-09-26T20:52:03.101626Z", - "shell.execute_reply": "2026-09-26T20:52:03.101064Z" + "iopub.execute_input": "2026-09-26T22:10:46.560530Z", + "iopub.status.busy": "2026-09-26T22:10:46.560073Z", + "iopub.status.idle": "2026-09-26T22:10:46.647856Z", + "shell.execute_reply": "2026-09-26T22:10:46.647002Z" }, "papermill": { - "duration": 0.082207, - "end_time": "2026-09-26T20:52:03.102389+00:00", + "duration": 0.092324, + "end_time": "2026-09-26T22:10:46.648381+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.020182+00:00", + "start_time": "2026-09-26T22:10:46.556057+00:00", "status": "completed" }, "tags": [] @@ -294,16 +294,16 @@ "id": "ict-15b-empirical-axelrod", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.111584Z", - "iopub.status.busy": "2026-09-26T20:52:03.111320Z", - "iopub.status.idle": "2026-09-26T20:52:03.329206Z", - "shell.execute_reply": "2026-09-26T20:52:03.328420Z" + "iopub.execute_input": "2026-09-26T22:10:46.654177Z", + "iopub.status.busy": "2026-09-26T22:10:46.653946Z", + "iopub.status.idle": "2026-09-26T22:10:46.838287Z", + "shell.execute_reply": "2026-09-26T22:10:46.837300Z" }, "papermill": { - "duration": 0.223855, - "end_time": "2026-09-26T20:52:03.329921+00:00", + "duration": 0.188033, + "end_time": "2026-09-26T22:10:46.838855+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.106066+00:00", + "start_time": "2026-09-26T22:10:46.650822+00:00", "status": "completed" }, "tags": [] @@ -354,16 +354,16 @@ "id": "ict-15b-empirical-grokking", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.336422Z", - "iopub.status.busy": "2026-09-26T20:52:03.336179Z", - "iopub.status.idle": "2026-09-26T20:52:03.341273Z", - "shell.execute_reply": "2026-09-26T20:52:03.340766Z" + "iopub.execute_input": "2026-09-26T22:10:46.844987Z", + "iopub.status.busy": "2026-09-26T22:10:46.844736Z", + "iopub.status.idle": "2026-09-26T22:10:46.849958Z", + "shell.execute_reply": "2026-09-26T22:10:46.849247Z" }, "papermill": { - "duration": 0.008973, - "end_time": "2026-09-26T20:52:03.341848+00:00", + "duration": 0.009123, + "end_time": "2026-09-26T22:10:46.850759+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.332875+00:00", + "start_time": "2026-09-26T22:10:46.841636+00:00", "status": "completed" }, "tags": [] @@ -417,16 +417,16 @@ "id": "ict-15b-empirical-may", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.348108Z", - "iopub.status.busy": "2026-09-26T20:52:03.347842Z", - "iopub.status.idle": "2026-09-26T20:52:03.361786Z", - "shell.execute_reply": "2026-09-26T20:52:03.361000Z" + "iopub.execute_input": "2026-09-26T22:10:46.857596Z", + "iopub.status.busy": "2026-09-26T22:10:46.857416Z", + "iopub.status.idle": "2026-09-26T22:10:46.872623Z", + "shell.execute_reply": "2026-09-26T22:10:46.872032Z" }, "papermill": { - "duration": 0.018037, - "end_time": "2026-09-26T20:52:03.362605+00:00", + "duration": 0.019344, + "end_time": "2026-09-26T22:10:46.873264+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.344568+00:00", + "start_time": "2026-09-26T22:10:46.853920+00:00", "status": "completed" }, "tags": [] @@ -475,16 +475,16 @@ "id": "ict-15b-empirical-cross-substrat", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.369374Z", - "iopub.status.busy": "2026-09-26T20:52:03.369191Z", - "iopub.status.idle": "2026-09-26T20:52:03.380065Z", - "shell.execute_reply": "2026-09-26T20:52:03.379486Z" + "iopub.execute_input": "2026-09-26T22:10:46.880619Z", + "iopub.status.busy": "2026-09-26T22:10:46.880373Z", + "iopub.status.idle": "2026-09-26T22:10:46.902219Z", + "shell.execute_reply": "2026-09-26T22:10:46.901397Z" }, "papermill": { - "duration": 0.015021, - "end_time": "2026-09-26T20:52:03.380733+00:00", + "duration": 0.026894, + "end_time": "2026-09-26T22:10:46.903143+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.365712+00:00", + "start_time": "2026-09-26T22:10:46.876249+00:00", "status": "completed" }, "tags": [] @@ -557,10 +557,10 @@ "id": "ict-15b-empirical-interp-cross", "metadata": { "papermill": { - "duration": 0.002683, - "end_time": "2026-09-26T20:52:03.386390+00:00", + "duration": 0.003724, + "end_time": "2026-09-26T22:10:46.911105+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.383707+00:00", + "start_time": "2026-09-26T22:10:46.907381+00:00", "status": "completed" }, "tags": [] @@ -590,10 +590,10 @@ "id": "ict-15b-empirical-exo1-md", "metadata": { "papermill": { - "duration": 0.004097, - "end_time": "2026-09-26T20:52:03.393097+00:00", + "duration": 0.003468, + "end_time": "2026-09-26T22:10:46.918504+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.389000+00:00", + "start_time": "2026-09-26T22:10:46.915036+00:00", "status": "completed" }, "tags": [] @@ -614,16 +614,16 @@ "id": "ict-15b-empirical-exo1-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.399863Z", - "iopub.status.busy": "2026-09-26T20:52:03.399674Z", - "iopub.status.idle": "2026-09-26T20:52:03.404744Z", - "shell.execute_reply": "2026-09-26T20:52:03.403787Z" + "iopub.execute_input": "2026-09-26T22:10:46.926442Z", + "iopub.status.busy": "2026-09-26T22:10:46.926111Z", + "iopub.status.idle": "2026-09-26T22:10:46.931385Z", + "shell.execute_reply": "2026-09-26T22:10:46.930637Z" }, "papermill": { - "duration": 0.009135, - "end_time": "2026-09-26T20:52:03.405247+00:00", + "duration": 0.010202, + "end_time": "2026-09-26T22:10:46.932117+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.396112+00:00", + "start_time": "2026-09-26T22:10:46.921915+00:00", "status": "completed" }, "tags": [] @@ -674,10 +674,10 @@ "id": "ict-15b-empirical-exo2-md", "metadata": { "papermill": { - "duration": 0.003364, - "end_time": "2026-09-26T20:52:03.411367+00:00", + "duration": 0.002612, + "end_time": "2026-09-26T22:10:46.937511+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.408003+00:00", + "start_time": "2026-09-26T22:10:46.934899+00:00", "status": "completed" }, "tags": [] @@ -704,16 +704,16 @@ "id": "ict-15b-empirical-exo2-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.418729Z", - "iopub.status.busy": "2026-09-26T20:52:03.418551Z", - "iopub.status.idle": "2026-09-26T20:52:03.427212Z", - "shell.execute_reply": "2026-09-26T20:52:03.426583Z" + "iopub.execute_input": "2026-09-26T22:10:46.944229Z", + "iopub.status.busy": "2026-09-26T22:10:46.943949Z", + "iopub.status.idle": "2026-09-26T22:10:46.953427Z", + "shell.execute_reply": "2026-09-26T22:10:46.952628Z" }, "papermill": { - "duration": 0.012799, - "end_time": "2026-09-26T20:52:03.427805+00:00", + "duration": 0.013942, + "end_time": "2026-09-26T22:10:46.954177+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.415006+00:00", + "start_time": "2026-09-26T22:10:46.940235+00:00", "status": "completed" }, "tags": [] @@ -764,10 +764,10 @@ "id": "ict-15b-empirical-exo3-md", "metadata": { "papermill": { - "duration": 0.002685, - "end_time": "2026-09-26T20:52:03.433260+00:00", + "duration": 0.002784, + "end_time": "2026-09-26T22:10:46.959928+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.430575+00:00", + "start_time": "2026-09-26T22:10:46.957144+00:00", "status": "completed" }, "tags": [] @@ -834,16 +834,16 @@ "id": "ict-15b-empirical-exo3-stub", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.440110Z", - "iopub.status.busy": "2026-09-26T20:52:03.439908Z", - "iopub.status.idle": "2026-09-26T20:52:03.482583Z", - "shell.execute_reply": "2026-09-26T20:52:03.481880Z" + "iopub.execute_input": "2026-09-26T22:10:46.966451Z", + "iopub.status.busy": "2026-09-26T22:10:46.966247Z", + "iopub.status.idle": "2026-09-26T22:10:47.020837Z", + "shell.execute_reply": "2026-09-26T22:10:47.020130Z" }, "papermill": { - "duration": 0.047127, - "end_time": "2026-09-26T20:52:03.483198+00:00", + "duration": 0.058984, + "end_time": "2026-09-26T22:10:47.021633+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.436071+00:00", + "start_time": "2026-09-26T22:10:46.962649+00:00", "status": "completed" }, "tags": [] @@ -917,10 +917,10 @@ "metadata": { "id": "ict-15g-learned-prereg", "papermill": { - "duration": 0.002354, - "end_time": "2026-09-26T20:52:03.488133+00:00", + "duration": 0.003566, + "end_time": "2026-09-26T22:10:47.028098+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.485779+00:00", + "start_time": "2026-09-26T22:10:47.024532+00:00", "status": "completed" }, "tags": [] @@ -986,7 +986,7 @@ "\n", "1. **Gradient BCE (v1 → v2)** : la première version codait `dL/dz = −y·σ(y·z)` au lieu de `−y·σ(−y·z)` — un gradient de signe faut qui plafonnait train_acc vers 0,5-0,85 en rendant la confiance répulsive. Corrigé + gate optimiseur ajoutée (fit parfait de MAJ_3 sur table complète, graine 11).\n", "2. **BCE équilibrée par classe (v2)** : poids `1/(2·fréquence de classe)` normalisés — sans elle, les cibles déséquilibrées (OR/AND : `2^n − 1` contre 1) convergent vers la constante vacuous, précisément ce que la garde anti-dégénérescence doit éviter de produire en masse.\n", - "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre et l'apprentissage échoue (mesuré en calibration : 57,5 % de dégénérés). λ = 0,5 (poids à la TRADES) restaure l'apprentissage (train_acc 1,0 en calibration sur 18/20 bras adversariaux) en conservant la pression de lissage local. **Grille λ testée : {0 (= normal), 0,5, 1}** — aucune valeur intermédiaire entre 0,5 et 1 n'a été essayée." + "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre au point de bloquer l'apprentissage — λ = 1 a été écarté à ce stade de calibration (graines disjointes {11, 22}), sans que le taux de dégénérés mesuré alors soit conservé dans une sortie committée. λ = 0,5 (poids à la TRADES) a été retenu : il conserve la pression de lissage local tout en laissant l'apprentissage converger (le gate optimiseur de la cellule instrument, exécuté dans le notebook, exige train_acc ≥ 0,9 en régime adversarial λ = 0,5). **Grille λ testée : {0 (= normal), 0,5, 1}** — aucune valeur intermédiaire entre 0,5 et 1 n'a été essayée." ] }, { @@ -995,17 +995,17 @@ "id": "ae365629", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.494229Z", - "iopub.status.busy": "2026-09-26T20:52:03.494052Z", - "iopub.status.idle": "2026-09-26T20:52:03.675299Z", - "shell.execute_reply": "2026-09-26T20:52:03.674055Z" + "iopub.execute_input": "2026-09-26T22:10:47.038767Z", + "iopub.status.busy": "2026-09-26T22:10:47.038327Z", + "iopub.status.idle": "2026-09-26T22:10:47.301319Z", + "shell.execute_reply": "2026-09-26T22:10:47.300480Z" }, "id": "ict-15g-learned-instrument", "papermill": { - "duration": 0.185463, - "end_time": "2026-09-26T20:52:03.675999+00:00", + "duration": 0.268792, + "end_time": "2026-09-26T22:10:47.301970+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.490536+00:00", + "start_time": "2026-09-26T22:10:47.033178+00:00", "status": "completed" }, "tags": [] @@ -1019,7 +1019,13 @@ " dictateur_4 : deg=1 (attendu 1), s_max=1 (attendu 1) -> OK\n", " OR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", " MAJ_3 : deg=3 (attendu 3), s_max=2 (attendu 2) -> OK\n", - " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", + " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ " theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : 0 violation(s)\n" ] }, @@ -1151,9 +1157,11 @@ " (adversaire discret exact a rayon 1, label du point propre).\n", " lam = 0.5 (amendement pre-execution v3) : a rayon 1 sur l'hypercube,\n", " le pire voisin porte souvent le label oppose (toujours pour PAR) ;\n", - " lam = 1 rend l'apprentissage impossible (57,5 % de degeneres en\n", - " calibration sur graines disjointes 11/22) ; lam = 0.5 restaure\n", - " l'apprentissage en conservant la pression de lissage local.\n", + " lam = 1 a ete ecarte en calibration (graines disjointes 11/22) :\n", + " a ce poids le terme adversarial bloque l'apprentissage (taux de\n", + " degeneres non conserve dans une sortie committee) ; lam = 0.5\n", + " (poids a la TRADES) restaure l'apprentissage en conservant la\n", + " pression de lissage local.\n", " untrained : reseau a l'initialisation (controle, 0 etape).\n", " \"\"\"\n", " net = TinyMLP(n, seed=seed)\n", @@ -1262,17 +1270,17 @@ "id": "0a857aa1", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:03.683490Z", - "iopub.status.busy": "2026-09-26T20:52:03.683177Z", - "iopub.status.idle": "2026-09-26T20:52:07.174949Z", - "shell.execute_reply": "2026-09-26T20:52:07.173822Z" + "iopub.execute_input": "2026-09-26T22:10:47.309064Z", + "iopub.status.busy": "2026-09-26T22:10:47.308762Z", + "iopub.status.idle": "2026-09-26T22:10:50.138596Z", + "shell.execute_reply": "2026-09-26T22:10:50.137793Z" }, "id": "ict-15g-learned-bench", "papermill": { - "duration": 3.496793, - "end_time": "2026-09-26T20:52:07.175965+00:00", + "duration": 2.833873, + "end_time": "2026-09-26T22:10:50.139182+00:00", "exception": false, - "start_time": "2026-09-26T20:52:03.679172+00:00", + "start_time": "2026-09-26T22:10:47.305309+00:00", "status": "completed" }, "tags": [] @@ -1506,17 +1514,17 @@ "id": "6fbaf32e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T20:52:07.185531Z", - "iopub.status.busy": "2026-09-26T20:52:07.185151Z", - "iopub.status.idle": "2026-09-26T20:52:08.270652Z", - "shell.execute_reply": "2026-09-26T20:52:08.269613Z" + "iopub.execute_input": "2026-09-26T22:10:50.146273Z", + "iopub.status.busy": "2026-09-26T22:10:50.146105Z", + "iopub.status.idle": "2026-09-26T22:10:50.903213Z", + "shell.execute_reply": "2026-09-26T22:10:50.902722Z" }, "id": "ict-15g-learned-verdicts", "papermill": { - "duration": 1.092434, - "end_time": "2026-09-26T20:52:08.271791+00:00", + "duration": 0.761561, + "end_time": "2026-09-26T22:10:50.903918+00:00", "exception": false, - "start_time": "2026-09-26T20:52:07.179357+00:00", + "start_time": "2026-09-26T22:10:50.142357+00:00", "status": "completed" }, "tags": [] @@ -1714,10 +1722,10 @@ "metadata": { "id": "ict-15g-learned-interp", "papermill": { - "duration": 0.002679, - "end_time": "2026-09-26T20:52:08.278199+00:00", + "duration": 0.002404, + "end_time": "2026-09-26T22:10:50.909202+00:00", "exception": false, - "start_time": "2026-09-26T20:52:08.275520+00:00", + "start_time": "2026-09-26T22:10:50.906798+00:00", "status": "completed" }, "tags": [] @@ -1727,7 +1735,7 @@ "\n", "**Deux quantités à distinguer.** Le verdict `FAIL` porte sur P1, le critère d'analyse déclaré dans ce notebook : « l'entraînement adversarial réduit s_max ». Sur **28 paires appariées non dégénérées**, 27 ont Δs_max = 0, une a Δs_max > 0, aucune n'a Δs_max < 0 ; la médiane est 0. Le commentaire de claim sur l'issue formulait toutefois l'hypothèse en termes de **ratio** s_max/√deg : P1 (sur Δs_max) n'en est qu'un proxy et ne suffit pas, seul, à répondre à cette formulation. Le complément calculé après revue mesure donc directement Δratio : **26 valeurs nulles, 2 positives, aucune négative**, médiane 0. Sur (n=4, TRI_bal_4, graine 7), s_max reste 4 mais deg passe de 4 à 3 (Δratio = +0,309) ; sur (n=3, AND_3, graine 1), s_max passe de 2 à 3 et deg de 2 à 3 (Δratio = +0,318). Ces résultats ne montrent **aucune baisse dans les paires qualifiées**, mais ne constituent pas un test pré-enregistré du ratio. Δs_max nul n'implique ni même table ni même ratio.\n", "\n", - "**Borne et portée de l'effet.** P2 donne 0 violation sur les 118 tables réalisées non constantes ; le contrôle exhaustif n=3 donne également 0 violation sur 256 fonctions. La borne de Huang sur l'hypercube vrai n'est pas réfutée. À λ = 1, la calibration sur graines disjointes {11, 22} a produit 57,5 % de cas dégénérés ; à λ = 0,5, les paires qualifiées ne montrent aucune baisse de s_max ou du ratio. Seuls λ ∈ {0 ; 0,5 ; 1} ont été examinés ; les valeurs intermédiaires ne sont pas exclues. Le banc ne mesure ni la géométrie des logits ni les grands n : il ne peut expliquer mécaniquement l'absence de baisse ni la généraliser.\n", + "**Borne et portée de l'effet.** P2 donne 0 violation sur les 118 tables réalisées non constantes ; le contrôle exhaustif n=3 donne également 0 violation sur 256 fonctions. La borne de Huang sur l'hypercube vrai n'est pas réfutée. λ = 1 a été écarté à la calibration (graines disjointes {11, 22}) : à ce poids le terme adversarial bloque l'apprentissage, et le taux de dégénérés mesuré alors n'est pas conservé dans une sortie committée ; à λ = 0,5, les paires qualifiées ne montrent aucune baisse de s_max ou du ratio. Seuls λ ∈ {0 ; 0,5 ; 1} ont été examinés ; les valeurs intermédiaires ne sont pas exclues. Le banc ne mesure ni la géométrie des logits ni les grands n : il ne peut expliquer mécaniquement l'absence de baisse ni la généraliser.\n", "\n", "**Carte de saturation.** Les ratios mesurés des tables non constantes sont dans [1,0 ; 2,31]. Parmi les entrées entraînées non dégénérées, 46,0 % atteignent le plafond s_max = n ; trois degrés distincts sont représentés, ce qui satisfait le contrôle P4 déclaré. La bande de fonctions aléatoires appariées en degré recouvre 100 % des ratios appris aux quantiles [p5, p95] de l'échantillon retenu. C'est un **chevauchement descriptif**, pas une preuve d'indistinguabilité statistique.\n", "\n", @@ -1762,17 +1770,17 @@ }, "papermill": { "default_parameters": {}, - "duration": 9.726582, - "end_time": "2026-09-26T20:52:08.626777+00:00", + "duration": 9.107525, + "end_time": "2026-09-26T22:10:51.258221+00:00", "environment_variables": {}, "exception": null, - "input_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", - "output_path": "D:\\dev\\CoursIA\\.claude\\worktrees\\agent-a3f23f45770e9e8d0\\MyIA.AI.Notebooks\\IIT\\ICT-Series\\ICT-15g-EmpiricalHuangExploitation.ipynb", + "input_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", + "output_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", "parameters": {}, - "start_time": "2026-09-26T20:51:58.900195+00:00", + "start_time": "2026-09-26T22:10:42.150696+00:00", "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/docs/ict/dissociations-matrix.md b/docs/ict/dissociations-matrix.md index bfea5eb442..bd8755d1cd 100644 --- a/docs/ict/dissociations-matrix.md +++ b/docs/ict/dissociations-matrix.md @@ -95,7 +95,7 @@ Conventions : | **ICT-15c** | Le **motif de désaccord** entre proxys est stable cross-substrat = obstruction informative (≠ dispersion d'échelle) | `s` ✓ | Vecteur d'obstruction `(a−b)/(\|a\|+\|b\|+ε)`, `mean_norm_L2`, verdict `STABLE`/`NOISE` | `f(x)=x%2` saturait (artefact plafonné) → `f(x)=x` (identité) restaure un panel non-plafonné | 4 substrats (Gray-Scott, Axelrod, Grokking, May) | proxy_interpretation | **Spéculatif** | **Candidat obstruction** (régime 2, *pas* érigé en obstruction cohomologique régime 3 — cf garde-fou A2). Verdict falsifiable `STABLE` si `mean_norm_L2 ≤ 0.05`. See [#7395](https://github.com/jsboige/CoursIA/issues/7395) | | **ICT-15d** | La cochaîne de Čech pondérée discriminate les substrats (`NON_TRIVIAL` = les proxys ne se recollent pas en 1D) | `s` ✓ | `mean_coboundary`, `s2_over_s1`, `effective_rank`, verdict `TRIVIAL`/`NON_TRIVIAL` | Sanity check + 4 substrats ICT-15c | 4 substrats × 3 proxys × fenêtrage | reproduced_in_toy_model | **Spéculatif** *(réserve de non-discrimination — voir [§ ICT-15d-corr](#note-ict-15d-corr--requalification-2026-08-21))* | 4/4 substrats `NON_TRIVIAL` sur la mesure courante ; l'« honnête négatif 0/4 » de la version précédente mesurait un `sensitivity.py` défectueux (réparé par [#9792](https://github.com/jsboige/CoursIA/pull/9792)). **Réserve** : la sortie reste dominée par la SVD (`s2_over_s1`, `effective_rank`) ; le contre-exemple `axelrod` (`mean_cocycle=0`, `obstruction_ratio=0`, `sign_consistency=0`) ne consulte ni le nerf ni H¹. Le verdict **ne porte pas** l'énoncé « Čech discrimine les substrats ». Issue [#7744](https://github.com/jsboige/CoursIA/issues/7744) closed-archived. | | **ICT-15e** | La trajectoire de réparation **est** un signal distinct d'un random walk calibré (recouvrabilité = agentivité, ≠ simple gain) | `s` ✓, `q` ○, `π` ○ | Distance de Mahalanobis sur signature 5-D, seuil p95 par permutation null | Random walk calibré sur mêmes extrema + 1 contrôle structural ; conjecture pré-enregistrée | 3 configs Gray-Scott (pearl/spots/seed=7) | reproduced_in_toy_model | **Fortement soutenu** | `CONFIRMED` sur substrats à dynamique réaction-diffusion informative (signature `slope_ratio` élevé) ; `FALSIFIED` sinon (random walk reproduit la structure) — verdict nuancé honnête, *pas* universel. See [#8077](https://github.com/jsboige/CoursIA/issues/8077) | -| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux **chevauche** la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne produit **aucune baisse de s_max ni du ratio** dans les paires qualifiées de ce banc à 3-4 bits — critère **déclaré** (Δs_max, **proxy** de la quantité de l'issue) : 28 paires appariées, 27 Δs_max=0, 1 Δ>0, 0 Δ<0, médiane 0 → **FAIL** ; complément post-revue sur le ratio : 26 Δratio=0, 2 >0, 0 <0, médiane 0 (descriptif, sans critère déclaré) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) ; Δratio apparié mesuré explicitement (post-revue) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — plan d'analyse **déclaré** avec amendements de calibration documentés sur graines disjointes {11, 22} (pas d'horodatage indépendant externe) | reproduced_in_toy_model | **TESTÉ (FAIL du critère déclaré Δs_max, sans re-seuillage ; pas de déplacement du ratio détecté non plus)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est non détecté, pas la borne qui tombe. **Grille λ testée : {0 (= normal), 0,5, 1}** : à λ=1 l'apprentissage échoue (57,5 % dégénérés en calibration), à λ=0,5 aucun déplacement détecté ; les valeurs intermédiaires (0,5 < λ < 1) **non testées**. Chevauchement de bande **≠** indistinguabilité statistique (aucun test formel). Δs_max = 0 n'implique pas même table : une paire (n=4, TRI_bal_4, graine 7) garde s_max = 4 mais passe de deg 4 à deg 3 (Δratio = +0,309). Lecture bornée aux régimes testés, ne généralise pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | +| **ICT-15g** (banc appris) | Sur l'hypercube **vrai** (degré de Fourier-Walsh RÉEL des tables réalisées, ≠ proxy de masse #9771), le ratio s_max/√deg des fonctions apprises par petits réseaux **chevauche** la bande des fonctions aléatoires de même degré ; l'entraînement adversarial discret (pire voisin Hamming-1, λ=0,5) ne produit **aucune baisse de s_max ni du ratio** dans les paires qualifiées de ce banc à 3-4 bits — critère **déclaré** (Δs_max, **proxy** de la quantité de l'issue) : 28 paires appariées, 27 Δs_max=0, 1 Δ>0, 0 Δ<0, médiane 0 → **FAIL** ; complément post-revue sur le ratio : 26 Δratio=0, 2 >0, 0 <0, médiane 0 (descriptif, sans critère déclaré) | `s` ✓ | ratio s_max/√deg avec s_max exact sur Q_n (définition de Huang, **distinct** de la sensibilité sur graphe de transition observé du banc hérité) ; Δratio apparié mesuré explicitement (post-revue) | Réseau non entraîné (même init) + bande aléatoire appariée en degré (n=3 exhaustive : 256/256 ; n=4 : 3000 tirages) ; garde anti-constance comptée honnêtement (17/80 = 21,2 % dégénérés, sous le seuil 1/3) | 4 RNG-seeds (0/1/7/42) × 5 cibles (OR/AND/MAJ/PAR/TRI_bal) × 2 régimes × n ∈ {3, 4} — plan d'analyse **déclaré** avec amendements de calibration documentés sur graines disjointes {11, 22} (pas d'horodatage indépendant externe) | reproduced_in_toy_model | **TESTÉ (FAIL du critère déclaré Δs_max, sans re-seuillage ; pas de déplacement du ratio détecté non plus)** | CPU 3-4 bits, MLP 16 cachées, 75 % couverture, budget fixe 400 étapes. La borne Huang **vérifiée mécaniquement** (0/118 tables réalisées, 256/256 à l'exhaustif n=3) — c'est le déplacement adversarial qui est non détecté, pas la borne qui tombe. **Grille λ testée : {0 (= normal), 0,5, 1}** : à λ=1 le terme adversarial bloque l'apprentissage (λ écarté à la calibration sur graines disjointes {11, 22} ; taux de dégénérés non conservé dans une sortie committée), à λ=0,5 aucun déplacement détecté ; les valeurs intermédiaires (0,5 < λ < 1) **non testées**. Chevauchement de bande **≠** indistinguabilité statistique (aucun test formel). Δs_max = 0 n'implique pas même table : une paire (n=4, TRI_bal_4, graine 7) garde s_max = 4 mais passe de deg 4 à deg 3 (Δratio = +0,309). Lecture bornée aux régimes testés, ne généralise pas aux grands n. Le statut « transposition conjecturale » du banc hérité (graphes de transition) est conservé. See [#17977](https://github.com/jsboige/CoursIA/issues/17977) | | **ICT-16** | `F` = partie résiduelle de `K` + bosse complexité-entropie | `s` ✓ | MDL two-part code | Modèles témoins sans bosse | RNG multi-source | established_external | **Établi** | Bosse Crutchfield-Feldman 1998 mesurée à H* ≈ 1.99 bits/symbole ; cave emptor : **un seul couple (modèle, famille de sources)** dans la figure rendue | | **ICT-17** | L'ε-machine (Crutchfield) ≠ Hoel : deux lectures de l'émergence causale | `s` ✓, `W` ○ | États causaux + complexité statistique + entropie d'excès | Hoel info effective, CE 2.0 | multi-substrat | conceptual_analogy | **Fortement soutenu** | Dissociation reconnue mais pas hiérarchisée | | **ICT-17b** | 2/5 proxys dissocient du progrès de généralisation pendant le grokking | `s` ✓, `q` ○ | ‖w‖², Fisher-MDL, 1-test_acc, trace de Fisher, pred-zlib | Baseline avant-grokking | 5 proxys | reproduced_in_toy_model | **Établi** | 3 co-localisent (‖w‖², Fisher-MDL, 1-test_acc) ; 2 dissocient (trace Fisher, pred-zlib). Verdict honnête dissociatif (#7268) | From e4adf733f38f6700958eaa96dcc61b8eddbcd4fc Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 27 Sep 2026 01:46:24 +0200 Subject: [PATCH 5/5] fix(ict): place learned Huang benchmark before exercises Co-Authored-By: Claude Code --- .../ICT-15g-EmpiricalHuangExploitation.ipynb | 1038 ++++++++--------- 1 file changed, 505 insertions(+), 533 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb index e83a8fd544..3c397e3a77 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15g-EmpiricalHuangExploitation.ipynb @@ -5,10 +5,10 @@ "id": "ict-15b-empirical-cadrage", "metadata": { "papermill": { - "duration": 0.013018, - "end_time": "2026-09-26T22:10:44.036038+00:00", + "duration": 0.003228, + "end_time": "2026-09-26T23:44:37.877901+00:00", "exception": false, - "start_time": "2026-09-26T22:10:44.023020+00:00", + "start_time": "2026-09-26T23:44:37.874673+00:00", "status": "completed" }, "tags": [] @@ -67,10 +67,10 @@ "id": "statut-epistemique", "metadata": { "papermill": { - "duration": 0.003831, - "end_time": "2026-09-26T22:10:44.047532+00:00", + "duration": 0.004606, + "end_time": "2026-09-26T23:44:37.887692+00:00", "exception": false, - "start_time": "2026-09-26T22:10:44.043701+00:00", + "start_time": "2026-09-26T23:44:37.883086+00:00", "status": "completed" }, "tags": [] @@ -85,16 +85,16 @@ "id": "ict-15b-empirical-imports", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:44.054215Z", - "iopub.status.busy": "2026-09-26T22:10:44.054050Z", - "iopub.status.idle": "2026-09-26T22:10:46.528239Z", - "shell.execute_reply": "2026-09-26T22:10:46.527504Z" + "iopub.execute_input": "2026-09-26T23:44:37.895168Z", + "iopub.status.busy": "2026-09-26T23:44:37.894975Z", + "iopub.status.idle": "2026-09-26T23:44:39.199849Z", + "shell.execute_reply": "2026-09-26T23:44:39.199257Z" }, "papermill": { - "duration": 2.478486, - "end_time": "2026-09-26T22:10:46.529377+00:00", + "duration": 1.308897, + "end_time": "2026-09-26T23:44:39.200390+00:00", "exception": false, - "start_time": "2026-09-26T22:10:44.050891+00:00", + "start_time": "2026-09-26T23:44:37.891493+00:00", "status": "completed" }, "tags": [] @@ -136,16 +136,16 @@ "id": "ict-15b-empirical-sanity", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.535917Z", - "iopub.status.busy": "2026-09-26T22:10:46.535578Z", - "iopub.status.idle": "2026-09-26T22:10:46.544232Z", - "shell.execute_reply": "2026-09-26T22:10:46.543293Z" + "iopub.execute_input": "2026-09-26T23:44:39.206682Z", + "iopub.status.busy": "2026-09-26T23:44:39.206455Z", + "iopub.status.idle": "2026-09-26T23:44:39.212510Z", + "shell.execute_reply": "2026-09-26T23:44:39.211742Z" }, "papermill": { - "duration": 0.01311, - "end_time": "2026-09-26T22:10:46.545204+00:00", + "duration": 0.010248, + "end_time": "2026-09-26T23:44:39.213286+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.532094+00:00", + "start_time": "2026-09-26T23:44:39.203038+00:00", "status": "completed" }, "tags": [] @@ -201,10 +201,10 @@ "id": "ict-15b-empirical-methode", "metadata": { "papermill": { - "duration": 0.003936, - "end_time": "2026-09-26T22:10:46.553409+00:00", + "duration": 0.002361, + "end_time": "2026-09-26T23:44:39.218516+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.549473+00:00", + "start_time": "2026-09-26T23:44:39.216155+00:00", "status": "completed" }, "tags": [] @@ -237,16 +237,16 @@ "id": "ict-15b-empirical-gray-scott", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.560530Z", - "iopub.status.busy": "2026-09-26T22:10:46.560073Z", - "iopub.status.idle": "2026-09-26T22:10:46.647856Z", - "shell.execute_reply": "2026-09-26T22:10:46.647002Z" + "iopub.execute_input": "2026-09-26T23:44:39.224192Z", + "iopub.status.busy": "2026-09-26T23:44:39.223937Z", + "iopub.status.idle": "2026-09-26T23:44:39.298741Z", + "shell.execute_reply": "2026-09-26T23:44:39.298239Z" }, "papermill": { - "duration": 0.092324, - "end_time": "2026-09-26T22:10:46.648381+00:00", + "duration": 0.078406, + "end_time": "2026-09-26T23:44:39.299315+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.556057+00:00", + "start_time": "2026-09-26T23:44:39.220909+00:00", "status": "completed" }, "tags": [] @@ -294,16 +294,16 @@ "id": "ict-15b-empirical-axelrod", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.654177Z", - "iopub.status.busy": "2026-09-26T22:10:46.653946Z", - "iopub.status.idle": "2026-09-26T22:10:46.838287Z", - "shell.execute_reply": "2026-09-26T22:10:46.837300Z" + "iopub.execute_input": "2026-09-26T23:44:39.304916Z", + "iopub.status.busy": "2026-09-26T23:44:39.304760Z", + "iopub.status.idle": "2026-09-26T23:44:39.470030Z", + "shell.execute_reply": "2026-09-26T23:44:39.469628Z" }, "papermill": { - "duration": 0.188033, - "end_time": "2026-09-26T22:10:46.838855+00:00", + "duration": 0.168986, + "end_time": "2026-09-26T23:44:39.470767+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.650822+00:00", + "start_time": "2026-09-26T23:44:39.301781+00:00", "status": "completed" }, "tags": [] @@ -354,16 +354,16 @@ "id": "ict-15b-empirical-grokking", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.844987Z", - "iopub.status.busy": "2026-09-26T22:10:46.844736Z", - "iopub.status.idle": "2026-09-26T22:10:46.849958Z", - "shell.execute_reply": "2026-09-26T22:10:46.849247Z" + "iopub.execute_input": "2026-09-26T23:44:39.476172Z", + "iopub.status.busy": "2026-09-26T23:44:39.476026Z", + "iopub.status.idle": "2026-09-26T23:44:39.480130Z", + "shell.execute_reply": "2026-09-26T23:44:39.479711Z" }, "papermill": { - "duration": 0.009123, - "end_time": "2026-09-26T22:10:46.850759+00:00", + "duration": 0.007646, + "end_time": "2026-09-26T23:44:39.480723+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.841636+00:00", + "start_time": "2026-09-26T23:44:39.473077+00:00", "status": "completed" }, "tags": [] @@ -417,16 +417,16 @@ "id": "ict-15b-empirical-may", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.857596Z", - "iopub.status.busy": "2026-09-26T22:10:46.857416Z", - "iopub.status.idle": "2026-09-26T22:10:46.872623Z", - "shell.execute_reply": "2026-09-26T22:10:46.872032Z" + "iopub.execute_input": "2026-09-26T23:44:39.486422Z", + "iopub.status.busy": "2026-09-26T23:44:39.486199Z", + "iopub.status.idle": "2026-09-26T23:44:39.499977Z", + "shell.execute_reply": "2026-09-26T23:44:39.499464Z" }, "papermill": { - "duration": 0.019344, - "end_time": "2026-09-26T22:10:46.873264+00:00", + "duration": 0.017501, + "end_time": "2026-09-26T23:44:39.500672+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.853920+00:00", + "start_time": "2026-09-26T23:44:39.483171+00:00", "status": "completed" }, "tags": [] @@ -475,16 +475,16 @@ "id": "ict-15b-empirical-cross-substrat", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.880619Z", - "iopub.status.busy": "2026-09-26T22:10:46.880373Z", - "iopub.status.idle": "2026-09-26T22:10:46.902219Z", - "shell.execute_reply": "2026-09-26T22:10:46.901397Z" + "iopub.execute_input": "2026-09-26T23:44:39.506401Z", + "iopub.status.busy": "2026-09-26T23:44:39.506192Z", + "iopub.status.idle": "2026-09-26T23:44:39.527726Z", + "shell.execute_reply": "2026-09-26T23:44:39.527193Z" }, "papermill": { - "duration": 0.026894, - "end_time": "2026-09-26T22:10:46.903143+00:00", + "duration": 0.024972, + "end_time": "2026-09-26T23:44:39.528229+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.876249+00:00", + "start_time": "2026-09-26T23:44:39.503257+00:00", "status": "completed" }, "tags": [] @@ -557,10 +557,10 @@ "id": "ict-15b-empirical-interp-cross", "metadata": { "papermill": { - "duration": 0.003724, - "end_time": "2026-09-26T22:10:46.911105+00:00", + "duration": 0.002699, + "end_time": "2026-09-26T23:44:39.533807+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.907381+00:00", + "start_time": "2026-09-26T23:44:39.531108+00:00", "status": "completed" }, "tags": [] @@ -582,138 +582,88 @@ "- ICT-15d (PR #9334) : verdict `NOISE` cross-substrat pour le **proxy Cech** (sections colineaires par construction, instrument plafonne).\n", "- ICT-15b (ce notebook) : conjecture **binaire** `s_max >= sqrt(deg_proxy)` -- plus discriminante que les deux precedentes car elle donne un verdict **par substrat** et non un verdict agrege.\n", "\n", - "Si ICT-15b donne une majorite `consistent`, c'est un **signal positif** : la sensibilite locale **borne** le proxy polynomial meme hors de l'hypercube. Si majorite `inconsistent`, ICT-15b **refute** la transposition directe -- mais cela ne refute **pas** l'intuition Huang en general, juste sa transposition litterale aux graphes de transition.\n" - ] - }, - { - "cell_type": "markdown", - "id": "ict-15b-empirical-exo1-md", - "metadata": { - "papermill": { - "duration": 0.003468, - "end_time": "2026-09-26T22:10:46.918504+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:46.915036+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Exercice 1 -- `proxy_degree_fn` custom : degre pondere par les courants nets\n", + "Si ICT-15b donne une majorite `consistent`, c'est un **signal positif** : la sensibilite locale **borne** le proxy polynomial meme hors de l'hypercube. Si majorite `inconsistent`, ICT-15b **refute** la transposition directe -- mais cela ne refute **pas** l'intuition Huang en general, juste sa transposition litterale aux graphes de transition.\n", "\n", - "Le proxy par defaut `deg_proxy` (degre structurel moyen, non pondere) traite **toutes les aretes** egalement. Mais la matrice de courants nets `J` (Schnakenberg 1976) discrimine les aretes **directionnelles** : un fort courant net indique une transition irreversible (hors equilibre). On peut definir un **degre pondere par les courants nets absolus** :\n", + "## Banc appris (#17977) — où le ratio s_max / √deg sature-t-il sur de petits réseaux appris ?\n", "\n", - " deg_proxy_J(f) = mean_x ( sum_y W[x, y] * |J[x, y]| ) / mean_x ( sum_y W[x, y] )\n", + "*See [#17977](https://github.com/jsboige/CoursIA/issues/17977) — Part of [#4588](https://github.com/jsboige/CoursIA/issues/4588), suite de [#7288](https://github.com/jsboige/CoursIA/issues/7288) (ICT-15b) et des réserves mesurées [#9771](https://github.com/jsboige/CoursIA/issues/9771) / [#9764](https://github.com/jsboige/CoursIA/issues/9764).*\n", "\n", - "Cela penalise les aretes a fort courant (irreversibles) et valorise les aretes reversibles. C'est un proxy **plus restrictif** : il borne le degre polynomial **modulo l'irreversibilite**. Si la conjecture ICT-15b tient avec ce proxy plus strict, c'est un signal **plus fort** que le proxy par defaut.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "ict-15b-empirical-exo1-stub", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.926442Z", - "iopub.status.busy": "2026-09-26T22:10:46.926111Z", - "iopub.status.idle": "2026-09-26T22:10:46.931385Z", - "shell.execute_reply": "2026-09-26T22:10:46.930637Z" - }, - "papermill": { - "duration": 0.010202, - "end_time": "2026-09-26T22:10:46.932117+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:46.921915+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Exercice 1 a completer -- stub C.1\n", - "=== Exercice 1 : Grokking avec proxy_degree_fn pondere J ===\n", - " verdict = consistent (attendu : consistent)\n", - " deg_proxy_J = 1.0\n", - " threshold = 1.000\n", - " ratio = 3.000\n" - ] - } - ], - "source": [ - "# Exercice 1 -- proxy_degree_fn pondere par les courants nets.\n", - "# TODO etudiant : implementer deg_proxy_J_fn(states, n_symbols) qui calcule\n", - "# la moyenne ponderee par |J[x, y]| sur les aretes du graphe de transition.\n", - "# Indice : utiliser SP.transition_graph pour W et SP.current_matrix pour J.\n", - "# Il faut d'abord obtenir P et pi (stationary) : SP.transition_graph\n", - "# utilise transition_matrix de ict.time_arrow ; pour pi, faire eig(P.T).\n", + "Le banc précédent (cellules 2 à 9) transpose Huang sur des **graphes de transition markoviens** — une **transposition conjecturale** : l'hypercube, la régularité du graphe et le degré polynomial y sont remplacés par des proxys. Ce statut est **conservé** pour ce banc legacy et pour la lecture ICT qui en découle. Le présent banc ajoute le chaînon demandé par #17977 : des **réseaux booléens réellement appris**, mesurés sur l'**hypercube vrai** — là où l'inégalité de Huang est un **théorème** (l'instrument est calibré par le théorème ; la question empirique porte ailleurs : la saturation du ratio et le déplacement par entraînement adversarial).\n", "\n", - "def deg_proxy_J_fn(states, n_symbols):\n", - " # TODO etudiant : retourner un float = degre pondere par |J|.\n", - " print(\"Exercice 1 a completer -- stub C.1\") # stub C.1\n", - " return 1.0 # stub : retourne un degre par defaut pour permettre au test de continuer\n", + "**Question (#17977)** : pour des fonctions booléennes apprises par de petits réseaux, où le ratio s_max / √deg sature-t-il ? L'entraînement adversarial déplace-t-il ce ratio, et dans quel sens ?\n", "\n", - "# Test rapide : si l'etudiant implemente correctement, sur le substrat\n", - "# `grokking` (compression crossover), la conjecture devrait etre\n", - "# `consistent` avec ce proxy plus restrictif aussi (le crossover cree\n", - "# de forts courants nets sur la transition phase1->phase2).\n", - "verdict_gk_J = huang_conjecture_test(\n", - " grokking_states, n_symbols_gk, f_gk, proxy_degree_fn=deg_proxy_J_fn\n", - ")\n", - "print(\"=== Exercice 1 : Grokking avec proxy_degree_fn pondere J ===\")\n", - "print(f\" verdict = {verdict_gk_J['verdict']} (attendu : consistent)\")\n", - "print(f\" deg_proxy_J = {verdict_gk_J['deg_proxy']}\")\n", - "print(f\" threshold = {verdict_gk_J['threshold']:.3f}\")\n", - "print(f\" ratio = {verdict_gk_J['ratio']:.3f}\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "ict-15b-empirical-exo2-md", - "metadata": { - "papermill": { - "duration": 0.002612, - "end_time": "2026-09-26T22:10:46.937511+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:46.934899+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Exercice 2 -- `f_multi` : tester la conjecture pour plusieurs state functions par substrat\n", + "### Plan d'analyse déclaré (critères d'échec explicites)\n", "\n", - "La conjecture ICT-15b depend **crucialement** du choix de `f`. Un verdict `inconsistent` sur un seul `f` ne signifie pas que la transposition **echoue** -- cela peut signifier que **cet `f` particulier** n'est pas le bon representant. On peut tester la conjecture sur un **panel de state functions** par substrat et regarder la distribution des verdicts.\n", + "Les définitions, seuils, graines, cibles et prédiction ci-dessous constituent le **plan d'analyse déclaré** du banc : les critères d'échec (P1 réfutée → verdict `FAIL`) sont explicites et n'ont pas été re-seuillés après lecture des résultats. Les corrections d'instrument nécessaires à la mise au point sont **documentées** dans la section « Amendements de calibration » (graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42}) ; l'assemblage du notebook ne fournit pas d'horodatage indépendant externe de ces étapes — la traçabilité repose sur cette documentation, pas sur une affirmation temporelle invérifiable.\n", "\n", - "Par exemple, sur May (16 symboles), on peut tester :\n", + "**Encodage pré-défini** (réserve #9771 : le VRAI degré de Fourier, pas un proxy de masse) :\n", "\n", - "- `f_0(x) = int(x >= 8)` : bimodal haut/bas (deja teste)\n", - "- `f_1(x) = int(x >= 12)` : quartile superieur vs reste\n", - "- `f_2(x) = int(x < 4)` : quartile inferieur vs reste\n", - "- `f_3(x) = x % 2` : parite\n", - "- `f_4(x) = int(x % 4 == 0)` : congruence mod 4\n", + "- entrées `b ∈ {0,1}^n`, encodage `x = 1 − 2b ∈ {−1,+1}^n` ;\n", + "- réseau `g : R^n → R` (MLP `n → 16 (tanh) → 1 (linéaire)`), fonction réalisée `f̂(x) = +1 si g(x) ≥ 0, −1 sinon` (table de vérité complète, déterministe) ;\n", + "- coefficients de Fourier-Walsh `f̂(S) = 2^{−n} Σ_x f(x) χ_S(x)` avec `χ_S(x) = Π_{i∈S} x_i` ;\n", + "- **degré réel** : `deg(f) = max{|S| : |f̂(S)| > TOL}` avec `TOL = 1e-9` — les tables sont exactes, les coefficients sont des multiples de `2^{1−n}` : la tolérance stricte est légitime ;\n", + "- **s_max exact sur l'hypercube** `Q_n` : `s_max(f) = max_x |{i : f(x ⊕ e_i) ≠ f(x)}|` — c'est la **définition de Huang**, **distincte** de la sensibilité sur graphe de transition observé (`ict.sensitivity.local_sensitivity`, banc legacy ci-dessus). Les deux grandeurs sont nommées séparément et jamais mélangées.\n", "\n", - "Si **toutes** donnent `consistent`, la transposition est **robuste** au choix de `f`. Si **aucune** ne donne `consistent`, elle est **structurellement en echec** sur ce substrat. Si le verdict **depend de `f`**, c'est le **regime le plus interessant** : le proxy polynomial n'est pas uniformement borne, ce qui suggere une **dissociation** entre localite de `f` et structure de `W`.\n" + "**Design** :\n", + "\n", + "| Élément | Valeur |\n", + "|---|---|\n", + "| tailles | `n ∈ {3, 4}` (tables de 8 / 16 entrées, CPU borné) |\n", + "| cibles (labels contrôlés) | `OR_n`, `AND_n`, `MAJ_n` (n=3 : ≥2 ; n=4 : ≥3), `PAR_n`, `TRI_bal_n` (table aléatoire équilibrée, graine `20260720 + n`, imprimée dans la sortie) |\n", + "| graines de verdict | `{0, 1, 7, 42}` (≥ 2 exigé) ; par graine : init du réseau et split 75 % train / 25 % holdout déterministes (rng séparés), **identiques entre les deux régimes** (paires appariées) |\n", + "| régimes | `normal` = BCE **équilibrée par classe** sur les points train ; `adversarial` = BCE(train) + **0,5 ×** BCE du **pire voisin Hamming-1** de chaque point train (adversaire discret exact à rayon 1, label du point propre ; λ = 0,5, cf. amendements) |\n", + "| budget | 400 étapes Adam lr 0.05, full batch — budget FIXE, convergence non forcée (c'est l'écart de généralisation qui porte le signal) |\n", + "| garde anti-dégénérescence (régimes entraînés) | entrée marquée `degenerate` si table réalisée constante OU train_acc < 0.9 ; exclue des verdicts, comptée honnêtement (réserve : éviter les réseaux constants vacuous) ; pour le contrôle `untrained`, seule la constance exclut (aucune exigence d'accuracy à 0 étape) |\n", + "\n", + "**Contrôles** :\n", + "\n", + "1. réseau non entraîné (même init que la paire, 0 étape) ;\n", + "2. bande aléatoire appariée en degré : n=3 **exhaustive** (les 256 fonctions booléennes), n=4 échantillon de 3000 fonctions uniformes — distribution de référence du ratio par degré.\n", + "\n", + "**Prédiction falsifiable P1 et sa mesure** :\n", + "\n", + "- **P1** : l'entraînement adversarial **réduit** s_max de la fonction réalisée — critère déclaré sur **Δs_max**, **proxy** de la quantité de l'issue (le ratio s_max/√deg ; le complément Δratio est mesuré en fin de banc, section post-revue). CONFIRMÉE ssi (i) `n_paires ≥ 8` (paires non-dégénérées des deux côtés), (ii) `médiane(Δs_max) < 0`, (iii) `#{Δ < 0} > #{Δ > 0}` (les égalités à 0 ne comptent pour aucun camp).\n", + "- **P2 (gate instrument — théorème, pas prédiction)** : toute table réalisée non constante satisfait `s_max ≥ √deg` (Huang sur Q_n). Violation = bug instrument → verdict `INVALID`.\n", + "- **P3 (contrôle untrained)** : `médiane(s_max_norm) ≤ médiane(s_max_untrained)` — l'entraînement sur labels contrôlés n'augmente pas la sensibilité médiane.\n", + "- **P4 (résolution / saturation, réserves #9771-#9764)** : au moins **2 degrés distincts** parmi les tables réalisées non-dégénérées des régimes entraînés, ET fraction des entrées entraînées (non-dégénérées) au plafond structurel `s_max = n` **strictement inférieure à 3/4** (la mesure ne sature pas).\n", + "\n", + "**Verdict global (critères déclarés)** :\n", + "\n", + "| Condition | Verdict |\n", + "|---|---|\n", + "| P2 violée ou gates instrument en échec | `INVALID` |\n", + "| P4 non tenue, ou n_paires < 8, ou fraction de dégénérés > 1/3 (régimes entraînés) | `INCONCLUSIVE` |\n", + "| P1 confirmée (hors régime INCONCLUSIVE) | `PASS` |\n", + "| P1 réfutée (`médiane(Δ) ≥ 0` ou direction inversée) hors régime INCONCLUSIVE | `FAIL` |\n", + "\n", + "Le verdict porte sur P1 (déplacement par l'adversarial, sens prédit : vers le bas) ; P3 et P4 sont des contrôles rapportés, pas des conditions du verdict.\n", + "\n", + "### Amendements de calibration (documentés ; graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42})\n", + "\n", + "Trois corrections d'**instrument**, appliquées en utilisant **uniquement** les graines {11, 22} — disjointes des graines de verdict — avec pour seul critère la **santé de l'instrument** (taux de dégénérés, train_acc du régime normal), pas le signal Δs_max ou Δratio. Les seuils de verdict (P1-P4, bornes, graines de verdict, garde anti-dégénérescence) sont restés inchangés du plan initial à l'analyse.\n", + "\n", + "1. **Gradient BCE (v1 → v2)** : la première version codait `dL/dz = −y·σ(y·z)` au lieu de `−y·σ(−y·z)` — un gradient de signe faut qui plafonnait train_acc vers 0,5-0,85 en rendant la confiance répulsive. Corrigé + gate optimiseur ajoutée (fit parfait de MAJ_3 sur table complète, graine 11).\n", + "2. **BCE équilibrée par classe (v2)** : poids `1/(2·fréquence de classe)` normalisés — sans elle, les cibles déséquilibrées (OR/AND : `2^n − 1` contre 1) convergent vers la constante vacuous, précisément ce que la garde anti-dégénérescence doit éviter de produire en masse.\n", + "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre au point de bloquer l'apprentissage — λ = 1 a été écarté à ce stade de calibration (graines disjointes {11, 22}), sans que le taux de dégénérés mesuré alors soit conservé dans une sortie committée. λ = 0,5 (poids à la TRADES) a été retenu : il conserve la pression de lissage local tout en laissant l'apprentissage converger (le gate optimiseur de la cellule instrument, exécuté dans le notebook, exige train_acc ≥ 0,9 en régime adversarial λ = 0,5). **Grille λ testée : {0 (= normal), 0,5, 1}** — aucune valeur intermédiaire entre 0,5 et 1 n'a été essayée." ] }, { "cell_type": "code", - "execution_count": 9, - "id": "ict-15b-empirical-exo2-stub", + "execution_count": 8, + "id": "ae365629", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.944229Z", - "iopub.status.busy": "2026-09-26T22:10:46.943949Z", - "iopub.status.idle": "2026-09-26T22:10:46.953427Z", - "shell.execute_reply": "2026-09-26T22:10:46.952628Z" + "iopub.execute_input": "2026-09-26T23:44:39.540420Z", + "iopub.status.busy": "2026-09-26T23:44:39.540213Z", + "iopub.status.idle": "2026-09-26T23:44:39.674832Z", + "shell.execute_reply": "2026-09-26T23:44:39.674234Z" }, + "id": "ict-15g-learned-instrument", "papermill": { - "duration": 0.013942, - "end_time": "2026-09-26T22:10:46.954177+00:00", + "duration": 0.138641, + "end_time": "2026-09-26T23:44:39.675375+00:00", "exception": false, - "start_time": "2026-09-26T22:10:46.940235+00:00", + "start_time": "2026-09-26T23:44:39.536734+00:00", "status": "completed" }, "tags": [] @@ -723,352 +673,48 @@ "name": "stdout", "output_type": "stream", "text": [ - " f_0 : verdict = consistent, ratio = 1.234\n", - " f_1 : verdict = inconsistent, ratio = 0.617\n", - " f_2 : verdict = inconsistent, ratio = 0.617\n", - " f_3 : verdict = consistent, ratio = 1.234\n", - " f_4 : verdict = consistent, ratio = 2.469\n", - "\n", - "=== Distribution des verdicts sur le panel May ===\n", - " consistent : 3/5\n", - " inconsistent : 2/5\n" + "=== Gates instrument (valeurs de reference) ===\n", + " dictateur_4 : deg=1 (attendu 1), s_max=1 (attendu 1) -> OK\n", + " OR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", + " MAJ_3 : deg=3 (attendu 3), s_max=2 (attendu 2) -> OK\n", + " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", + " theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : 0 violation(s)\n", + " gate optimiseur (MAJ_3 complet, graine 11 disjointe) : train_acc normal = 1.000, adversarial (lam=0.5) = 1.000 (attendus 1.0 / >= 0.9)\n", + "Gates instrument PASS : l instrument discrimine (deg et s_max exacts), respecte Huang sur n=3, et l optimiseur converge (normal ET adversarial lam=0.5).\n" ] } ], "source": [ - "# Exercice 2 -- f_multi : tester la conjecture sur un panel de state functions\n", - "# pour le substrat May (16 symboles), et compter les verdicts.\n", - "# TODO etudiant : definir 5 state functions (f_0 a f_4) et les tester.\n", - "# Indice : f_0 est deja dans la cellule 7. Utiliser une boucle.\n", - "\n", - "f_panel_may = [\n", - " lambda x: int(x >= 8), # bimodal haut/bas\n", - " lambda x: int(x >= 12), # quartile superieur\n", - " lambda x: int(x < 4), # quartile inferieur\n", - " lambda x: x % 2, # parite\n", - " lambda x: int(x % 4 == 0), # congruence mod 4\n", - "]\n", - "verdicts_may_panel = {}\n", - "for i, f in enumerate(f_panel_may):\n", - " v = huang_conjecture_test(may_states, n_symbols_may, f)\n", - " verdicts_may_panel[f\"f_{i}\"] = v['verdict']\n", - " print(f\" f_{i} : verdict = {v['verdict']}, ratio = {v['ratio']:.3f}\")\n", + "# --- Banc #17977 : instrument -- degre de Fourier REEL + sensibilite hypercube exacte ---\n", + "# Reserve #9771 : le degre mesure ici est le VRAI degre de Fourier-Walsh de la table de\n", + "# verite complete, pas un proxy de masse de probabilite.\n", + "# Reserve #9764 : la saturation de la mesure est testee explicitement (gate P4) avant\n", + "# tout verdict. numpy pur, CPU borne, deterministe (rng explicites, aucun alea cache).\n", + "import itertools\n", "\n", - "print(\"\\n=== Distribution des verdicts sur le panel May ===\")\n", - "for verdict, count in pd.Series(list(verdicts_may_panel.values())).value_counts().items():\n", - " print(f\" {verdict:>13} : {count}/5\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "ict-15b-empirical-exo3-md", - "metadata": { - "papermill": { - "duration": 0.002784, - "end_time": "2026-09-26T22:10:46.959928+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:46.957144+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Exercice 3 -- Comparaison ICT-15b vs ICT-15d (verdict de Cech)\n", + "TOL_FOURIER = 1e-9 # pre-enregistre : coefficients multiples de 2^{1-n}, tolerance stricte legitime\n", "\n", - "ICT-15d (#7744, PR #9334) applique la **cochaine de Cech ponderee** aux memes quatre\n", - "substrats : chaque proxy devient une section locale sur des fenetres contigues, et\n", - "`cech_obstruction_verdict` rend `NON_TRIVIAL`, `TRIVIAL` ou `INCONCLUSIVE` selon que les\n", - "sections se recollent ou non en une mesure globale unique.\n", "\n", - "> **Correction d'attribution.** Une version anterieure de cet enonce pretait a ICT-15d un\n", - "> verdict `NOISE` et un « collapse SVD rang 1 » qui aurait touche les quatre substrats.\n", - "> Les deux affirmations sont a rejeter, mais pas pour la meme raison.\n", - ">\n", - "> `NOISE` n'appartient pas au vocabulaire de `cech_obstruction_verdict` : c'est un verdict\n", - "> d'ICT-15**c** (`ict.meta_proxy`). L'attribution etait donc simplement fausse.\n", - ">\n", - "> Le « rang 1 », lui, n'est pas une invention : il est **faux la ou il etait attribue, et\n", - "> vrai ailleurs**. Les rangs effectifs publies par ICT-15d valent 2 ou 3 -- jamais 1. Mais\n", - "> la cellule ci-dessous, sur les trajectoires *de ce notebook*, mesure bel et bien un\n", - "> effondrement en rang 1 sur `axelrod`. L'ancien enonce generalisait donc a quatre substrats\n", - "> et au mauvais notebook un phenomene reel mais **local**. C'est la forme d'erreur la plus\n", - "> couteuse a detecter, parce qu'un lecteur qui verifie un seul cas peut tomber sur celui qui\n", - "> confirme.\n", + "def hypercube_inputs(n):\n", + " \"\"\"Encodage pre-defini : b in {0,1}^n -> x = 1 - 2*b in {-1,+1}^n (ordre lexicographique).\"\"\"\n", + " B = np.array(list(itertools.product([0, 1], repeat=n)), dtype=float)\n", + " return 1.0 - 2.0 * B\n", "\n", - "**Pourquoi la cellule recalcule au lieu de citer.** Les substrats d'ICT-15d sont regeneres\n", - "dans *son* notebook ; recopier ses verdicts ici comparerait deux instruments sur deux jeux\n", - "de trajectoires differents, et la colonne MATCH/DIVERGE ne voudrait rien dire. La cellule\n", - "ci-dessous applique donc le meme module (`ict.cech_obstruction`) aux trajectoires **de ce\n", - "notebook** -- celles-la memes sur lesquelles ICT-15b vient de se prononcer. Les deux\n", - "instruments voient alors strictement la meme chose, ce qui est la seule condition sous\n", - "laquelle un desaccord est informatif.\n", "\n", - "**Question** : les deux instruments s'accordent-ils substrat par substrat, et lorsqu'ils\n", - "divergent, lequel des deux est le plus credible sur ce substrat-la ?\n", + "def fourier_degree(table_pm1, n):\n", + " \"\"\"Degre de Fourier-Walsh REEL de f : {-1,+1}^n -> {-1,+1} (table sur l'hypercube ordonne).\n", "\n", - "Deux lectures a departager par la mesure, pas par preference :\n", - "\n", - "- **ICT-15b discrimine ou Cech renonce** -- le scalaire local simple (`s_max`) survit la ou\n", - " la decomposition multi-dimensionnelle manque de matiere. Argument pour la canonicite de la\n", - " sensibilite.\n", - "- **Les deux renoncent ensemble** -- la structure Markovienne sous-jacente est trop pauvre\n", - " pour porter l'un ou l'autre. C'est alors un verdict sur le **substrat**, pas sur les\n", - " instruments.\n", - "\n", - "Un substrat degenere (peu d'etats visites, trajectoire quasi-constante) doit etre traite a\n", - "part : un accord entre deux instruments qui n'ont rien a mesurer n'atteste rien.\n", - "\n", - "**Piege a ne pas manquer dans la sortie ci-dessous.** Le ratio `s2/s1` n'est pas un\n", - "indicateur monotone du verdict : `TRIVIAL` y est atteint par **deux routes opposees**. Un\n", - "ratio proche de 1 signale des valeurs singulieres equilibrees (aucune direction ne domine) ;\n", - "un ratio proche de 0 signale au contraire un effondrement sur une seule direction. Les deux\n", - "donnent `TRIVIAL`, parce que le verdict est porte par l'obstruction `cob`, pas par le ratio.\n", - "Lire `s2/s1` comme un score de « qualite » conduit donc a ranger ensemble deux situations\n", - "qui n'ont rien de commun -- et c'est exactement l'erreur que la correction d'attribution\n", - "ci-dessus documente.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "ict-15b-empirical-exo3-stub", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-26T22:10:46.966451Z", - "iopub.status.busy": "2026-09-26T22:10:46.966247Z", - "iopub.status.idle": "2026-09-26T22:10:47.020837Z", - "shell.execute_reply": "2026-09-26T22:10:47.020130Z" - }, - "papermill": { - "duration": 0.058984, - "end_time": "2026-09-26T22:10:47.021633+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:46.962649+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== Verdict de Cech recalcule sur les trajectoires de CE notebook ===\n", - " gray_scott : TRIVIAL | s2/s1=1.0000 | rank=3 | cob=0.0000 | n_windows=30\n", - " axelrod : TRIVIAL | s2/s1=0.0000 | rank=1 | cob=0.0000 | n_windows=30\n", - " grokking : NON_TRIVIAL | s2/s1=0.6627 | rank=3 | cob=0.7767 | n_windows=30\n", - " may : NON_TRIVIAL | s2/s1=0.4081 | rank=3 | cob=0.5992 | n_windows=30\n", - "\n", - "Exercice a completer : table de comparaison + conclusion.\n" - ] - } - ], - "source": [ - "# Exercice 3 -- Comparaison ICT-15b (Huang) vs ICT-15d (Cech) sur LES MEMES trajectoires.\n", - "#\n", - "# Echafaudage fourni : on calcule le verdict de Cech avec le module reel\n", - "# `ict.cech_obstruction` (meme recette qu'ICT-15d : sections -> classe -> verdict).\n", - "# TODO etudiant : construire la table de comparaison et conclure (cf enonce ci-dessus).\n", - "\n", - "from ict import cech_obstruction as CO\n", - "\n", - "# Les trois proxys d'ICT-15d, reconstruits ici sur les modules deja importes (SP, SE).\n", - "def _spec_gap(states, n_symbols):\n", - " return float(SP.spectral_summary(states, n_symbols)['spectral_gap'])\n", - "\n", - "def _sens_mean(states, n_symbols):\n", - " return float(SE.sensitivity_distribution(states, n_symbols, lambda x: x)['mean'])\n", - "\n", - "def _sens_max(states, n_symbols):\n", - " return float(SE.sensitivity_distribution(states, n_symbols, lambda x: x)['max'])\n", - "\n", - "PROXIES_CECH = {\"spectral_gap\": _spec_gap, \"sens_mean\": _sens_mean, \"sens_max\": _sens_max}\n", - "N_SYMBOLS = {\"gray_scott\": n_symbols_gs, \"axelrod\": n_symbols_ax,\n", - " \"grokking\": n_symbols_gk, \"may\": n_symbols_may}\n", - "\n", - "cech_par_substrat = {}\n", - "print(\"=== Verdict de Cech recalcule sur les trajectoires de CE notebook ===\")\n", - "for nom, states in all_states.items():\n", - " n_total = len(states)\n", - " window_size = max(2, n_total // 30) # ~30 fenetres, comme ICT-15d\n", - " sections = CO.proxy_sections(states, N_SYMBOLS[nom], window_size, PROXIES_CECH)\n", - " rep = CO.cech_obstruction_class(sections)\n", - " verdict = CO.cech_obstruction_verdict(rep)\n", - " cech_par_substrat[nom] = {\"verdict\": verdict, \"report\": rep}\n", - " print(f\" {nom:>10} : {verdict:>13} | s2/s1={rep['s2_over_s1']:.4f} \"\n", - " f\"| rank={rep['effective_rank']} | cob={rep['mean_coboundary']:.4f} \"\n", - " f\"| n_windows={rep['n_windows']}\")\n", - "\n", - "# TODO etudiant : table de comparaison ICT-15b vs ICT-15d.\n", - "# Pour chaque substrat, mettre en regard verdicts[nom]['verdict'] (Huang, vocabulaire\n", - "# consistent/inconsistent/inconclusive) et cech_par_substrat[nom]['verdict'] (Cech,\n", - "# vocabulaire NON_TRIVIAL/TRIVIAL/INCONCLUSIVE). Les deux vocabulaires ne sont PAS\n", - "# comparables terme a terme : c'est a vous de definir ce que « s'accorder » veut dire\n", - "# ici, et de le justifier -- une comparaison de chaines brutes n'aurait aucun sens.\n", - "# TODO etudiant : conclure selon les deux lectures de l'enonce, en isolant les substrats\n", - "# degeneres (regarder n_visited dans `verdicts[nom]` avant de conclure quoi que ce soit).\n", - "print(\"\")\n", - "print(\"Exercice a completer : table de comparaison + conclusion.\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "5d784bf7", - "metadata": { - "id": "ict-15g-learned-prereg", - "papermill": { - "duration": 0.003566, - "end_time": "2026-09-26T22:10:47.028098+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:47.024532+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Banc appris (#17977) — où le ratio s_max / √deg sature-t-il sur de petits réseaux appris ?\n", - "\n", - "*See [#17977](https://github.com/jsboige/CoursIA/issues/17977) — Part of [#4588](https://github.com/jsboige/CoursIA/issues/4588), suite de [#7288](https://github.com/jsboige/CoursIA/issues/7288) (ICT-15b) et des réserves mesurées [#9771](https://github.com/jsboige/CoursIA/issues/9771) / [#9764](https://github.com/jsboige/CoursIA/issues/9764).*\n", - "\n", - "Le banc précédent (cellules 2 à 9) transpose Huang sur des **graphes de transition markoviens** — une **transposition conjecturale** : l'hypercube, la régularité du graphe et le degré polynomial y sont remplacés par des proxys. Ce statut est **conservé** pour ce banc legacy et pour la lecture ICT qui en découle. Le présent banc ajoute le chaînon demandé par #17977 : des **réseaux booléens réellement appris**, mesurés sur l'**hypercube vrai** — là où l'inégalité de Huang est un **théorème** (l'instrument est calibré par le théorème ; la question empirique porte ailleurs : la saturation du ratio et le déplacement par entraînement adversarial).\n", - "\n", - "**Question (#17977)** : pour des fonctions booléennes apprises par de petits réseaux, où le ratio s_max / √deg sature-t-il ? L'entraînement adversarial déplace-t-il ce ratio, et dans quel sens ?\n", - "\n", - "### Plan d'analyse déclaré (critères d'échec explicites)\n", - "\n", - "Les définitions, seuils, graines, cibles et prédiction ci-dessous constituent le **plan d'analyse déclaré** du banc : les critères d'échec (P1 réfutée → verdict `FAIL`) sont explicites et n'ont pas été re-seuillés après lecture des résultats. Les corrections d'instrument nécessaires à la mise au point sont **documentées** dans la section « Amendements de calibration » (graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42}) ; l'assemblage du notebook ne fournit pas d'horodatage indépendant externe de ces étapes — la traçabilité repose sur cette documentation, pas sur une affirmation temporelle invérifiable.\n", - "\n", - "**Encodage pré-défini** (réserve #9771 : le VRAI degré de Fourier, pas un proxy de masse) :\n", - "\n", - "- entrées `b ∈ {0,1}^n`, encodage `x = 1 − 2b ∈ {−1,+1}^n` ;\n", - "- réseau `g : R^n → R` (MLP `n → 16 (tanh) → 1 (linéaire)`), fonction réalisée `f̂(x) = +1 si g(x) ≥ 0, −1 sinon` (table de vérité complète, déterministe) ;\n", - "- coefficients de Fourier-Walsh `f̂(S) = 2^{−n} Σ_x f(x) χ_S(x)` avec `χ_S(x) = Π_{i∈S} x_i` ;\n", - "- **degré réel** : `deg(f) = max{|S| : |f̂(S)| > TOL}` avec `TOL = 1e-9` — les tables sont exactes, les coefficients sont des multiples de `2^{1−n}` : la tolérance stricte est légitime ;\n", - "- **s_max exact sur l'hypercube** `Q_n` : `s_max(f) = max_x |{i : f(x ⊕ e_i) ≠ f(x)}|` — c'est la **définition de Huang**, **distincte** de la sensibilité sur graphe de transition observé (`ict.sensitivity.local_sensitivity`, banc legacy ci-dessus). Les deux grandeurs sont nommées séparément et jamais mélangées.\n", - "\n", - "**Design** :\n", - "\n", - "| Élément | Valeur |\n", - "|---|---|\n", - "| tailles | `n ∈ {3, 4}` (tables de 8 / 16 entrées, CPU borné) |\n", - "| cibles (labels contrôlés) | `OR_n`, `AND_n`, `MAJ_n` (n=3 : ≥2 ; n=4 : ≥3), `PAR_n`, `TRI_bal_n` (table aléatoire équilibrée, graine `20260720 + n`, imprimée dans la sortie) |\n", - "| graines de verdict | `{0, 1, 7, 42}` (≥ 2 exigé) ; par graine : init du réseau et split 75 % train / 25 % holdout déterministes (rng séparés), **identiques entre les deux régimes** (paires appariées) |\n", - "| régimes | `normal` = BCE **équilibrée par classe** sur les points train ; `adversarial` = BCE(train) + **0,5 ×** BCE du **pire voisin Hamming-1** de chaque point train (adversaire discret exact à rayon 1, label du point propre ; λ = 0,5, cf. amendements) |\n", - "| budget | 400 étapes Adam lr 0.05, full batch — budget FIXE, convergence non forcée (c'est l'écart de généralisation qui porte le signal) |\n", - "| garde anti-dégénérescence (régimes entraînés) | entrée marquée `degenerate` si table réalisée constante OU train_acc < 0.9 ; exclue des verdicts, comptée honnêtement (réserve : éviter les réseaux constants vacuous) ; pour le contrôle `untrained`, seule la constance exclut (aucune exigence d'accuracy à 0 étape) |\n", - "\n", - "**Contrôles** :\n", - "\n", - "1. réseau non entraîné (même init que la paire, 0 étape) ;\n", - "2. bande aléatoire appariée en degré : n=3 **exhaustive** (les 256 fonctions booléennes), n=4 échantillon de 3000 fonctions uniformes — distribution de référence du ratio par degré.\n", - "\n", - "**Prédiction falsifiable P1 et sa mesure** :\n", - "\n", - "- **P1** : l'entraînement adversarial **réduit** s_max de la fonction réalisée — critère déclaré sur **Δs_max**, **proxy** de la quantité de l'issue (le ratio s_max/√deg ; le complément Δratio est mesuré en fin de banc, section post-revue). CONFIRMÉE ssi (i) `n_paires ≥ 8` (paires non-dégénérées des deux côtés), (ii) `médiane(Δs_max) < 0`, (iii) `#{Δ < 0} > #{Δ > 0}` (les égalités à 0 ne comptent pour aucun camp).\n", - "- **P2 (gate instrument — théorème, pas prédiction)** : toute table réalisée non constante satisfait `s_max ≥ √deg` (Huang sur Q_n). Violation = bug instrument → verdict `INVALID`.\n", - "- **P3 (contrôle untrained)** : `médiane(s_max_norm) ≤ médiane(s_max_untrained)` — l'entraînement sur labels contrôlés n'augmente pas la sensibilité médiane.\n", - "- **P4 (résolution / saturation, réserves #9771-#9764)** : au moins **2 degrés distincts** parmi les tables réalisées non-dégénérées des régimes entraînés, ET fraction des entrées entraînées (non-dégénérées) au plafond structurel `s_max = n` **strictement inférieure à 3/4** (la mesure ne sature pas).\n", - "\n", - "**Verdict global (critères déclarés)** :\n", - "\n", - "| Condition | Verdict |\n", - "|---|---|\n", - "| P2 violée ou gates instrument en échec | `INVALID` |\n", - "| P4 non tenue, ou n_paires < 8, ou fraction de dégénérés > 1/3 (régimes entraînés) | `INCONCLUSIVE` |\n", - "| P1 confirmée (hors régime INCONCLUSIVE) | `PASS` |\n", - "| P1 réfutée (`médiane(Δ) ≥ 0` ou direction inversée) hors régime INCONCLUSIVE | `FAIL` |\n", - "\n", - "Le verdict porte sur P1 (déplacement par l'adversarial, sens prédit : vers le bas) ; P3 et P4 sont des contrôles rapportés, pas des conditions du verdict.\n", - "\n", - "### Amendements de calibration (documentés ; graines de calibration {11, 22} disjointes des graines de verdict {0, 1, 7, 42})\n", - "\n", - "Trois corrections d'**instrument**, appliquées en utilisant **uniquement** les graines {11, 22} — disjointes des graines de verdict — avec pour seul critère la **santé de l'instrument** (taux de dégénérés, train_acc du régime normal), pas le signal Δs_max ou Δratio. Les seuils de verdict (P1-P4, bornes, graines de verdict, garde anti-dégénérescence) sont restés inchangés du plan initial à l'analyse.\n", - "\n", - "1. **Gradient BCE (v1 → v2)** : la première version codait `dL/dz = −y·σ(y·z)` au lieu de `−y·σ(−y·z)` — un gradient de signe faut qui plafonnait train_acc vers 0,5-0,85 en rendant la confiance répulsive. Corrigé + gate optimiseur ajoutée (fit parfait de MAJ_3 sur table complète, graine 11).\n", - "2. **BCE équilibrée par classe (v2)** : poids `1/(2·fréquence de classe)` normalisés — sans elle, les cibles déséquilibrées (OR/AND : `2^n − 1` contre 1) convergent vers la constante vacuous, précisément ce que la garde anti-dégénérescence doit éviter de produire en masse.\n", - "3. **Poids adversarial λ = 0,5 (v3)** : à rayon 1 sur l'hypercube, le pire voisin Hamming-1 d'un point porte souvent le label **opposé** (toujours, pour PAR) ; avec un poids 1/1, le terme adversarial contredit le terme propre au point de bloquer l'apprentissage — λ = 1 a été écarté à ce stade de calibration (graines disjointes {11, 22}), sans que le taux de dégénérés mesuré alors soit conservé dans une sortie committée. λ = 0,5 (poids à la TRADES) a été retenu : il conserve la pression de lissage local tout en laissant l'apprentissage converger (le gate optimiseur de la cellule instrument, exécuté dans le notebook, exige train_acc ≥ 0,9 en régime adversarial λ = 0,5). **Grille λ testée : {0 (= normal), 0,5, 1}** — aucune valeur intermédiaire entre 0,5 et 1 n'a été essayée." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ae365629", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-26T22:10:47.038767Z", - "iopub.status.busy": "2026-09-26T22:10:47.038327Z", - "iopub.status.idle": "2026-09-26T22:10:47.301319Z", - "shell.execute_reply": "2026-09-26T22:10:47.300480Z" - }, - "id": "ict-15g-learned-instrument", - "papermill": { - "duration": 0.268792, - "end_time": "2026-09-26T22:10:47.301970+00:00", - "exception": false, - "start_time": "2026-09-26T22:10:47.033178+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== Gates instrument (valeurs de reference) ===\n", - " dictateur_4 : deg=1 (attendu 1), s_max=1 (attendu 1) -> OK\n", - " OR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n", - " MAJ_3 : deg=3 (attendu 3), s_max=2 (attendu 2) -> OK\n", - " PAR_4 : deg=4 (attendu 4), s_max=4 (attendu 4) -> OK\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " theoreme Huang verifie exhaustivement sur les 256 fonctions de n=3 : 0 violation(s)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " gate optimiseur (MAJ_3 complet, graine 11 disjointe) : train_acc normal = 1.000, adversarial (lam=0.5) = 1.000 (attendus 1.0 / >= 0.9)\n", - "Gates instrument PASS : l instrument discrimine (deg et s_max exacts), respecte Huang sur n=3, et l optimiseur converge (normal ET adversarial lam=0.5).\n" - ] - } - ], - "source": [ - "# --- Banc #17977 : instrument -- degre de Fourier REEL + sensibilite hypercube exacte ---\n", - "# Reserve #9771 : le degre mesure ici est le VRAI degre de Fourier-Walsh de la table de\n", - "# verite complete, pas un proxy de masse de probabilite.\n", - "# Reserve #9764 : la saturation de la mesure est testee explicitement (gate P4) avant\n", - "# tout verdict. numpy pur, CPU borne, deterministe (rng explicites, aucun alea cache).\n", - "import itertools\n", - "\n", - "TOL_FOURIER = 1e-9 # pre-enregistre : coefficients multiples de 2^{1-n}, tolerance stricte legitime\n", - "\n", - "\n", - "def hypercube_inputs(n):\n", - " \"\"\"Encodage pre-defini : b in {0,1}^n -> x = 1 - 2*b in {-1,+1}^n (ordre lexicographique).\"\"\"\n", - " B = np.array(list(itertools.product([0, 1], repeat=n)), dtype=float)\n", - " return 1.0 - 2.0 * B\n", - "\n", - "\n", - "def fourier_degree(table_pm1, n):\n", - " \"\"\"Degre de Fourier-Walsh REEL de f : {-1,+1}^n -> {-1,+1} (table sur l'hypercube ordonne).\n", - "\n", - " f_hat(S) = 2^{-n} * sum_x f(x) * chi_S(x), chi_S(x) = prod_{i in S} x_i.\n", - " deg(f) = max{ |S| : |f_hat(S)| > TOL_FOURIER }. Constante -> deg = 0.\n", - " \"\"\"\n", - " X = hypercube_inputs(n)\n", - " deg = 0\n", - " for k in range(n + 1):\n", - " for S in itertools.combinations(range(n), k):\n", - " chi = np.prod(X[:, list(S)], axis=1) if S else np.ones(len(X))\n", - " if abs(float(np.mean(table_pm1 * chi))) > TOL_FOURIER:\n", - " deg = max(deg, k)\n", - " return deg\n", + " f_hat(S) = 2^{-n} * sum_x f(x) * chi_S(x), chi_S(x) = prod_{i in S} x_i.\n", + " deg(f) = max{ |S| : |f_hat(S)| > TOL_FOURIER }. Constante -> deg = 0.\n", + " \"\"\"\n", + " X = hypercube_inputs(n)\n", + " deg = 0\n", + " for k in range(n + 1):\n", + " for S in itertools.combinations(range(n), k):\n", + " chi = np.prod(X[:, list(S)], axis=1) if S else np.ones(len(X))\n", + " if abs(float(np.mean(table_pm1 * chi))) > TOL_FOURIER:\n", + " deg = max(deg, k)\n", + " return deg\n", "\n", "\n", "def hypercube_sensitivity(table_pm1, n):\n", @@ -1266,21 +912,21 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 9, "id": "0a857aa1", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:47.309064Z", - "iopub.status.busy": "2026-09-26T22:10:47.308762Z", - "iopub.status.idle": "2026-09-26T22:10:50.138596Z", - "shell.execute_reply": "2026-09-26T22:10:50.137793Z" + "iopub.execute_input": "2026-09-26T23:44:39.682319Z", + "iopub.status.busy": "2026-09-26T23:44:39.682065Z", + "iopub.status.idle": "2026-09-26T23:44:42.508027Z", + "shell.execute_reply": "2026-09-26T23:44:42.506924Z" }, "id": "ict-15g-learned-bench", "papermill": { - "duration": 2.833873, - "end_time": "2026-09-26T22:10:50.139182+00:00", + "duration": 2.831117, + "end_time": "2026-09-26T23:44:42.509250+00:00", "exception": false, - "start_time": "2026-09-26T22:10:47.305309+00:00", + "start_time": "2026-09-26T23:44:39.678133+00:00", "status": "completed" }, "tags": [] @@ -1510,21 +1156,21 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 10, "id": "6fbaf32e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-26T22:10:50.146273Z", - "iopub.status.busy": "2026-09-26T22:10:50.146105Z", - "iopub.status.idle": "2026-09-26T22:10:50.903213Z", - "shell.execute_reply": "2026-09-26T22:10:50.902722Z" + "iopub.execute_input": "2026-09-26T23:44:42.517640Z", + "iopub.status.busy": "2026-09-26T23:44:42.517353Z", + "iopub.status.idle": "2026-09-26T23:44:43.370440Z", + "shell.execute_reply": "2026-09-26T23:44:43.369328Z" }, "id": "ict-15g-learned-verdicts", "papermill": { - "duration": 0.761561, - "end_time": "2026-09-26T22:10:50.903918+00:00", + "duration": 0.857725, + "end_time": "2026-09-26T23:44:43.371349+00:00", "exception": false, - "start_time": "2026-09-26T22:10:50.142357+00:00", + "start_time": "2026-09-26T23:44:42.513624+00:00", "status": "completed" }, "tags": [] @@ -1722,10 +1368,10 @@ "metadata": { "id": "ict-15g-learned-interp", "papermill": { - "duration": 0.002404, - "end_time": "2026-09-26T22:10:50.909202+00:00", + "duration": 0.002588, + "end_time": "2026-09-26T23:44:43.377273+00:00", "exception": false, - "start_time": "2026-09-26T22:10:50.906798+00:00", + "start_time": "2026-09-26T23:44:43.374685+00:00", "status": "completed" }, "tags": [] @@ -1748,6 +1394,332 @@ "\n", "Les cas dégénérés sont surtout des cibles OR_4/AND_4 dont le point minoritaire tombe dans le holdout : le train ne contient alors qu'une classe, et une prédiction constante peut atteindre train_acc = 1 sans résoudre la cible complète. Le résultat reste limité aux hypercubes de 3 et 4 bits, au MLP de 16 neurones cachés, au split 75/25, à 400 étapes, aux quatre graines et aux cinq cibles étudiées. La **transposition conjecturale** du banc hérité, qui emploie un graphe de transitions observées plutôt que l'hypercube, conserve son statut distinct." ] + }, + { + "cell_type": "markdown", + "id": "ict-15b-empirical-exo1-md", + "metadata": { + "papermill": { + "duration": 0.003, + "end_time": "2026-09-26T23:44:43.383003+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.380003+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Exercice 1 -- `proxy_degree_fn` custom : degre pondere par les courants nets\n", + "\n", + "Le proxy par defaut `deg_proxy` (degre structurel moyen, non pondere) traite **toutes les aretes** egalement. Mais la matrice de courants nets `J` (Schnakenberg 1976) discrimine les aretes **directionnelles** : un fort courant net indique une transition irreversible (hors equilibre). On peut definir un **degre pondere par les courants nets absolus** :\n", + "\n", + " deg_proxy_J(f) = mean_x ( sum_y W[x, y] * |J[x, y]| ) / mean_x ( sum_y W[x, y] )\n", + "\n", + "Cela penalise les aretes a fort courant (irreversibles) et valorise les aretes reversibles. C'est un proxy **plus restrictif** : il borne le degre polynomial **modulo l'irreversibilite**. Si la conjecture ICT-15b tient avec ce proxy plus strict, c'est un signal **plus fort** que le proxy par defaut.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ict-15b-empirical-exo1-stub", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T23:44:43.391338Z", + "iopub.status.busy": "2026-09-26T23:44:43.391015Z", + "iopub.status.idle": "2026-09-26T23:44:43.397484Z", + "shell.execute_reply": "2026-09-26T23:44:43.396656Z" + }, + "papermill": { + "duration": 0.011991, + "end_time": "2026-09-26T23:44:43.398148+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.386157+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Exercice 1 a completer -- stub C.1\n", + "=== Exercice 1 : Grokking avec proxy_degree_fn pondere J ===\n", + " verdict = consistent (attendu : consistent)\n", + " deg_proxy_J = 1.0\n", + " threshold = 1.000\n", + " ratio = 3.000\n" + ] + } + ], + "source": [ + "# Exercice 1 -- proxy_degree_fn pondere par les courants nets.\n", + "# TODO etudiant : implementer deg_proxy_J_fn(states, n_symbols) qui calcule\n", + "# la moyenne ponderee par |J[x, y]| sur les aretes du graphe de transition.\n", + "# Indice : utiliser SP.transition_graph pour W et SP.current_matrix pour J.\n", + "# Il faut d'abord obtenir P et pi (stationary) : SP.transition_graph\n", + "# utilise transition_matrix de ict.time_arrow ; pour pi, faire eig(P.T).\n", + "\n", + "def deg_proxy_J_fn(states, n_symbols):\n", + " # TODO etudiant : retourner un float = degre pondere par |J|.\n", + " print(\"Exercice 1 a completer -- stub C.1\") # stub C.1\n", + " return 1.0 # stub : retourne un degre par defaut pour permettre au test de continuer\n", + "\n", + "# Test rapide : si l'etudiant implemente correctement, sur le substrat\n", + "# `grokking` (compression crossover), la conjecture devrait etre\n", + "# `consistent` avec ce proxy plus restrictif aussi (le crossover cree\n", + "# de forts courants nets sur la transition phase1->phase2).\n", + "verdict_gk_J = huang_conjecture_test(\n", + " grokking_states, n_symbols_gk, f_gk, proxy_degree_fn=deg_proxy_J_fn\n", + ")\n", + "print(\"=== Exercice 1 : Grokking avec proxy_degree_fn pondere J ===\")\n", + "print(f\" verdict = {verdict_gk_J['verdict']} (attendu : consistent)\")\n", + "print(f\" deg_proxy_J = {verdict_gk_J['deg_proxy']}\")\n", + "print(f\" threshold = {verdict_gk_J['threshold']:.3f}\")\n", + "print(f\" ratio = {verdict_gk_J['ratio']:.3f}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "ict-15b-empirical-exo2-md", + "metadata": { + "papermill": { + "duration": 0.003261, + "end_time": "2026-09-26T23:44:43.404314+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.401053+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Exercice 2 -- `f_multi` : tester la conjecture pour plusieurs state functions par substrat\n", + "\n", + "La conjecture ICT-15b depend **crucialement** du choix de `f`. Un verdict `inconsistent` sur un seul `f` ne signifie pas que la transposition **echoue** -- cela peut signifier que **cet `f` particulier** n'est pas le bon representant. On peut tester la conjecture sur un **panel de state functions** par substrat et regarder la distribution des verdicts.\n", + "\n", + "Par exemple, sur May (16 symboles), on peut tester :\n", + "\n", + "- `f_0(x) = int(x >= 8)` : bimodal haut/bas (deja teste)\n", + "- `f_1(x) = int(x >= 12)` : quartile superieur vs reste\n", + "- `f_2(x) = int(x < 4)` : quartile inferieur vs reste\n", + "- `f_3(x) = x % 2` : parite\n", + "- `f_4(x) = int(x % 4 == 0)` : congruence mod 4\n", + "\n", + "Si **toutes** donnent `consistent`, la transposition est **robuste** au choix de `f`. Si **aucune** ne donne `consistent`, elle est **structurellement en echec** sur ce substrat. Si le verdict **depend de `f`**, c'est le **regime le plus interessant** : le proxy polynomial n'est pas uniformement borne, ce qui suggere une **dissociation** entre localite de `f` et structure de `W`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "ict-15b-empirical-exo2-stub", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T23:44:43.411597Z", + "iopub.status.busy": "2026-09-26T23:44:43.411385Z", + "iopub.status.idle": "2026-09-26T23:44:43.421171Z", + "shell.execute_reply": "2026-09-26T23:44:43.420306Z" + }, + "papermill": { + "duration": 0.014544, + "end_time": "2026-09-26T23:44:43.421960+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.407416+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " f_0 : verdict = consistent, ratio = 1.234\n", + " f_1 : verdict = inconsistent, ratio = 0.617\n", + " f_2 : verdict = inconsistent, ratio = 0.617\n", + " f_3 : verdict = consistent, ratio = 1.234\n", + " f_4 : verdict = consistent, ratio = 2.469\n", + "\n", + "=== Distribution des verdicts sur le panel May ===\n", + " consistent : 3/5\n", + " inconsistent : 2/5\n" + ] + } + ], + "source": [ + "# Exercice 2 -- f_multi : tester la conjecture sur un panel de state functions\n", + "# pour le substrat May (16 symboles), et compter les verdicts.\n", + "# TODO etudiant : definir 5 state functions (f_0 a f_4) et les tester.\n", + "# Indice : f_0 est deja dans la cellule 7. Utiliser une boucle.\n", + "\n", + "f_panel_may = [\n", + " lambda x: int(x >= 8), # bimodal haut/bas\n", + " lambda x: int(x >= 12), # quartile superieur\n", + " lambda x: int(x < 4), # quartile inferieur\n", + " lambda x: x % 2, # parite\n", + " lambda x: int(x % 4 == 0), # congruence mod 4\n", + "]\n", + "verdicts_may_panel = {}\n", + "for i, f in enumerate(f_panel_may):\n", + " v = huang_conjecture_test(may_states, n_symbols_may, f)\n", + " verdicts_may_panel[f\"f_{i}\"] = v['verdict']\n", + " print(f\" f_{i} : verdict = {v['verdict']}, ratio = {v['ratio']:.3f}\")\n", + "\n", + "print(\"\\n=== Distribution des verdicts sur le panel May ===\")\n", + "for verdict, count in pd.Series(list(verdicts_may_panel.values())).value_counts().items():\n", + " print(f\" {verdict:>13} : {count}/5\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "ict-15b-empirical-exo3-md", + "metadata": { + "papermill": { + "duration": 0.002903, + "end_time": "2026-09-26T23:44:43.428110+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.425207+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Exercice 3 -- Comparaison ICT-15b vs ICT-15d (verdict de Cech)\n", + "\n", + "ICT-15d (#7744, PR #9334) applique la **cochaine de Cech ponderee** aux memes quatre\n", + "substrats : chaque proxy devient une section locale sur des fenetres contigues, et\n", + "`cech_obstruction_verdict` rend `NON_TRIVIAL`, `TRIVIAL` ou `INCONCLUSIVE` selon que les\n", + "sections se recollent ou non en une mesure globale unique.\n", + "\n", + "> **Correction d'attribution.** Une version anterieure de cet enonce pretait a ICT-15d un\n", + "> verdict `NOISE` et un « collapse SVD rang 1 » qui aurait touche les quatre substrats.\n", + "> Les deux affirmations sont a rejeter, mais pas pour la meme raison.\n", + ">\n", + "> `NOISE` n'appartient pas au vocabulaire de `cech_obstruction_verdict` : c'est un verdict\n", + "> d'ICT-15**c** (`ict.meta_proxy`). L'attribution etait donc simplement fausse.\n", + ">\n", + "> Le « rang 1 », lui, n'est pas une invention : il est **faux la ou il etait attribue, et\n", + "> vrai ailleurs**. Les rangs effectifs publies par ICT-15d valent 2 ou 3 -- jamais 1. Mais\n", + "> la cellule ci-dessous, sur les trajectoires *de ce notebook*, mesure bel et bien un\n", + "> effondrement en rang 1 sur `axelrod`. L'ancien enonce generalisait donc a quatre substrats\n", + "> et au mauvais notebook un phenomene reel mais **local**. C'est la forme d'erreur la plus\n", + "> couteuse a detecter, parce qu'un lecteur qui verifie un seul cas peut tomber sur celui qui\n", + "> confirme.\n", + "\n", + "**Pourquoi la cellule recalcule au lieu de citer.** Les substrats d'ICT-15d sont regeneres\n", + "dans *son* notebook ; recopier ses verdicts ici comparerait deux instruments sur deux jeux\n", + "de trajectoires differents, et la colonne MATCH/DIVERGE ne voudrait rien dire. La cellule\n", + "ci-dessous applique donc le meme module (`ict.cech_obstruction`) aux trajectoires **de ce\n", + "notebook** -- celles-la memes sur lesquelles ICT-15b vient de se prononcer. Les deux\n", + "instruments voient alors strictement la meme chose, ce qui est la seule condition sous\n", + "laquelle un desaccord est informatif.\n", + "\n", + "**Question** : les deux instruments s'accordent-ils substrat par substrat, et lorsqu'ils\n", + "divergent, lequel des deux est le plus credible sur ce substrat-la ?\n", + "\n", + "Deux lectures a departager par la mesure, pas par preference :\n", + "\n", + "- **ICT-15b discrimine ou Cech renonce** -- le scalaire local simple (`s_max`) survit la ou\n", + " la decomposition multi-dimensionnelle manque de matiere. Argument pour la canonicite de la\n", + " sensibilite.\n", + "- **Les deux renoncent ensemble** -- la structure Markovienne sous-jacente est trop pauvre\n", + " pour porter l'un ou l'autre. C'est alors un verdict sur le **substrat**, pas sur les\n", + " instruments.\n", + "\n", + "Un substrat degenere (peu d'etats visites, trajectoire quasi-constante) doit etre traite a\n", + "part : un accord entre deux instruments qui n'ont rien a mesurer n'atteste rien.\n", + "\n", + "**Piege a ne pas manquer dans la sortie ci-dessous.** Le ratio `s2/s1` n'est pas un\n", + "indicateur monotone du verdict : `TRIVIAL` y est atteint par **deux routes opposees**. Un\n", + "ratio proche de 1 signale des valeurs singulieres equilibrees (aucune direction ne domine) ;\n", + "un ratio proche de 0 signale au contraire un effondrement sur une seule direction. Les deux\n", + "donnent `TRIVIAL`, parce que le verdict est porte par l'obstruction `cob`, pas par le ratio.\n", + "Lire `s2/s1` comme un score de « qualite » conduit donc a ranger ensemble deux situations\n", + "qui n'ont rien de commun -- et c'est exactement l'erreur que la correction d'attribution\n", + "ci-dessus documente.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ict-15b-empirical-exo3-stub", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-26T23:44:43.435734Z", + "iopub.status.busy": "2026-09-26T23:44:43.435492Z", + "iopub.status.idle": "2026-09-26T23:44:43.490452Z", + "shell.execute_reply": "2026-09-26T23:44:43.489436Z" + }, + "papermill": { + "duration": 0.059922, + "end_time": "2026-09-26T23:44:43.491285+00:00", + "exception": false, + "start_time": "2026-09-26T23:44:43.431363+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Verdict de Cech recalcule sur les trajectoires de CE notebook ===\n", + " gray_scott : TRIVIAL | s2/s1=1.0000 | rank=3 | cob=0.0000 | n_windows=30\n", + " axelrod : TRIVIAL | s2/s1=0.0000 | rank=1 | cob=0.0000 | n_windows=30\n", + " grokking : NON_TRIVIAL | s2/s1=0.6627 | rank=3 | cob=0.7767 | n_windows=30\n", + " may : NON_TRIVIAL | s2/s1=0.4081 | rank=3 | cob=0.5992 | n_windows=30\n", + "\n", + "Exercice a completer : table de comparaison + conclusion.\n" + ] + } + ], + "source": [ + "# Exercice 3 -- Comparaison ICT-15b (Huang) vs ICT-15d (Cech) sur LES MEMES trajectoires.\n", + "#\n", + "# Echafaudage fourni : on calcule le verdict de Cech avec le module reel\n", + "# `ict.cech_obstruction` (meme recette qu'ICT-15d : sections -> classe -> verdict).\n", + "# TODO etudiant : construire la table de comparaison et conclure (cf enonce ci-dessus).\n", + "\n", + "from ict import cech_obstruction as CO\n", + "\n", + "# Les trois proxys d'ICT-15d, reconstruits ici sur les modules deja importes (SP, SE).\n", + "def _spec_gap(states, n_symbols):\n", + " return float(SP.spectral_summary(states, n_symbols)['spectral_gap'])\n", + "\n", + "def _sens_mean(states, n_symbols):\n", + " return float(SE.sensitivity_distribution(states, n_symbols, lambda x: x)['mean'])\n", + "\n", + "def _sens_max(states, n_symbols):\n", + " return float(SE.sensitivity_distribution(states, n_symbols, lambda x: x)['max'])\n", + "\n", + "PROXIES_CECH = {\"spectral_gap\": _spec_gap, \"sens_mean\": _sens_mean, \"sens_max\": _sens_max}\n", + "N_SYMBOLS = {\"gray_scott\": n_symbols_gs, \"axelrod\": n_symbols_ax,\n", + " \"grokking\": n_symbols_gk, \"may\": n_symbols_may}\n", + "\n", + "cech_par_substrat = {}\n", + "print(\"=== Verdict de Cech recalcule sur les trajectoires de CE notebook ===\")\n", + "for nom, states in all_states.items():\n", + " n_total = len(states)\n", + " window_size = max(2, n_total // 30) # ~30 fenetres, comme ICT-15d\n", + " sections = CO.proxy_sections(states, N_SYMBOLS[nom], window_size, PROXIES_CECH)\n", + " rep = CO.cech_obstruction_class(sections)\n", + " verdict = CO.cech_obstruction_verdict(rep)\n", + " cech_par_substrat[nom] = {\"verdict\": verdict, \"report\": rep}\n", + " print(f\" {nom:>10} : {verdict:>13} | s2/s1={rep['s2_over_s1']:.4f} \"\n", + " f\"| rank={rep['effective_rank']} | cob={rep['mean_coboundary']:.4f} \"\n", + " f\"| n_windows={rep['n_windows']}\")\n", + "\n", + "# TODO etudiant : table de comparaison ICT-15b vs ICT-15d.\n", + "# Pour chaque substrat, mettre en regard verdicts[nom]['verdict'] (Huang, vocabulaire\n", + "# consistent/inconsistent/inconclusive) et cech_par_substrat[nom]['verdict'] (Cech,\n", + "# vocabulaire NON_TRIVIAL/TRIVIAL/INCONCLUSIVE). Les deux vocabulaires ne sont PAS\n", + "# comparables terme a terme : c'est a vous de definir ce que « s'accorder » veut dire\n", + "# ici, et de le justifier -- une comparaison de chaines brutes n'aurait aucun sens.\n", + "# TODO etudiant : conclure selon les deux lectures de l'enonce, en isolant les substrats\n", + "# degeneres (regarder n_visited dans `verdicts[nom]` avant de conclure quoi que ce soit).\n", + "print(\"\")\n", + "print(\"Exercice a completer : table de comparaison + conclusion.\")\n" + ] } ], "metadata": { @@ -1770,14 +1742,14 @@ }, "papermill": { "default_parameters": {}, - "duration": 9.107525, - "end_time": "2026-09-26T22:10:51.258221+00:00", + "duration": 7.331272, + "end_time": "2026-09-26T23:44:43.842777+00:00", "environment_variables": {}, "exception": null, "input_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", "output_path": "ICT-15g-EmpiricalHuangExploitation.ipynb", "parameters": {}, - "start_time": "2026-09-26T22:10:42.150696+00:00", + "start_time": "2026-09-26T23:44:36.511505+00:00", "version": "2.7.0" } },