From f4b43d076188325dc763d198904bfcd7fd89b606 Mon Sep 17 00:00:00 2001 From: jsboige Date: Fri, 18 Sep 2026 13:07:20 +0200 Subject: [PATCH 1/4] feat(iit,#16225): RRXOR conforme litterature (MSP 36) + Mess3 canonique par defaut, ICT-37 re-execute - bench_factorise.RRXOR reecrit : machine Mealy 5 etats (Riechers & Crutchfield 2018, arXiv:1706.00883 Fig. 4), triplets (r1, r2, r1 XOR r2) -- l'ancienne version modelisait le XOR de bits iid (processus iid, sans structure) - mixed_state.build_msp : conventions Moore ET Mealy (edge_tensor), elagage des aretes de probabilite nulle, alphabet stocke, n_distinct_total - msp_rrxor : union fermee a 36 croyances (31 transitoires + 5 recurrentes) -- valeur exacte de la litterature p. 17 Fig. 7 - Alias Mess3 = Mess3Canonical : un seul generateur par defaut, alphabet discret non revelateur ; ObsCoupled garde en comparateur explicite - Tests : 36 verifie, dissociation "croyances distinctes, meme next-token" (36 croyances -> 11 predictions), bruteforce generique, non-Dirac canonique - ICT-37 : generateurs importes (plus d'inline), attribution corrigee (singh 1994 -> Marzen & Crutchfield 2017), demo MSP, verdicts recalcules : Ex.2 0.908/R2 0.886 (plus de 1.000 tautologique), Ex.3 dissociation 0.335 (avant 0.008 impute a tort au bruit), next-token a son plafond mesure 0.667 Co-Authored-By: Claude Sonnet 5 --- .../ICT-Series/ICT-37-FLens-BeliefState.ipynb | 757 ++++++++++++------ .../IIT/ICT-Series/ict/bench_factorise.py | 121 +-- .../IIT/ICT-Series/ict/mixed_state.py | 152 ++-- .../ict/tests/test_bench_factorise.py | 129 ++- .../ict/tests/test_mess3_canonical.py | 49 +- .../ICT-Series/ict/tests/test_mixed_state.py | 68 +- 6 files changed, 876 insertions(+), 400 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb index 2a8794ce21..1edd192c5b 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb @@ -3,7 +3,16 @@ { "cell_type": "markdown", "id": "9572779c", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.013866, + "end_time": "2026-09-18T11:00:30.887054+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:30.873188+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "# ICT-37 - F-Lens : mode belief-state, probing lineaire et geometrie predictive held-out\n", "\n", @@ -63,7 +72,17 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "ae39ac6f", + "metadata": { + "papermill": { + "duration": 0.004409, + "end_time": "2026-09-18T11:00:30.897193+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:30.892784+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "## Voisins et positionnement\n", "\n", @@ -98,8 +117,7 @@ "**Renvoi interne.** La notion d'état prédictif que ces hypothèses sondent est celle de la mécanique\n", "computationnelle de Crutchfield, enseignée dans la série en\n", "[ICT-17 — EpsilonMachine](./ICT-17-EpsilonMachine.ipynb) — à lire avant ce notebook pour qui veut la\n", - "construction de l'objet, celui-ci n'en testant que l'accessibilité linéaire.\n", - "" + "construction de l'objet, celui-ci n'en testant que l'accessibilité linéaire.\n" ] }, { @@ -108,11 +126,19 @@ "id": "dd1ac0ab", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:23.885679Z", - "iopub.status.busy": "2026-09-11T23:15:23.885393Z", - "iopub.status.idle": "2026-09-11T23:15:23.891350Z", - "shell.execute_reply": "2026-09-11T23:15:23.890680Z" - } + "iopub.execute_input": "2026-09-18T11:00:30.910352Z", + "iopub.status.busy": "2026-09-18T11:00:30.909784Z", + "iopub.status.idle": "2026-09-18T11:00:30.923690Z", + "shell.execute_reply": "2026-09-18T11:00:30.922284Z" + }, + "papermill": { + "duration": 0.021547, + "end_time": "2026-09-18T11:00:30.925065+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:30.903518+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { @@ -150,18 +176,26 @@ "id": "85657928", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:23.893379Z", - "iopub.status.busy": "2026-09-11T23:15:23.893028Z", - "iopub.status.idle": "2026-09-11T23:15:23.961968Z", - "shell.execute_reply": "2026-09-11T23:15:23.961298Z" - } + "iopub.execute_input": "2026-09-18T11:00:30.938096Z", + "iopub.status.busy": "2026-09-18T11:00:30.937544Z", + "iopub.status.idle": "2026-09-18T11:00:31.275902Z", + "shell.execute_reply": "2026-09-18T11:00:31.274346Z" + }, + "papermill": { + "duration": 0.347341, + "end_time": "2026-09-18T11:00:31.277172+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:30.929831+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "numpy version: 2.4.3\n" + "numpy version: 2.4.2\n" ] } ], @@ -177,7 +211,16 @@ { "cell_type": "markdown", "id": "7c991a9d", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.004277, + "end_time": "2026-09-18T11:00:31.286230+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.281953+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "## Primitives numpy-only\n", "\n", @@ -201,11 +244,19 @@ "id": "1ea45876", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:23.964612Z", - "iopub.status.busy": "2026-09-11T23:15:23.964362Z", - "iopub.status.idle": "2026-09-11T23:15:23.986741Z", - "shell.execute_reply": "2026-09-11T23:15:23.986113Z" - } + "iopub.execute_input": "2026-09-18T11:00:31.297448Z", + "iopub.status.busy": "2026-09-18T11:00:31.296967Z", + "iopub.status.idle": "2026-09-18T11:00:31.333860Z", + "shell.execute_reply": "2026-09-18T11:00:31.332318Z" + }, + "papermill": { + "duration": 0.044725, + "end_time": "2026-09-18T11:00:31.335141+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.290416+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { @@ -273,19 +324,41 @@ { "cell_type": "markdown", "id": "282febcd", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.00663, + "end_time": "2026-09-18T11:00:31.346594+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.339964+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ - "## Generateurs de processus synthetiques\n", - "\n", - "Deux processus a **belief state ground-truth exact** :\n", - "\n", - "### Mess3 (HMM 3 etats)\n", - "Processus classique de la litterature belief-state learning (singh et al. 1994). Trois etats caches s_t dans {0, 1, 2} avec matrice de transition symetrique p_stay = 0.95. L'**etat cache** est le belief ground-truth ; l'observation est couplee directement a l'etat (obs = etat).\n", - "\n", - "### RRXOR (Random Relational XOR)\n", - "Processus introduit par #15478 pour tester une geometrie **non reductible au next-token**. L'etat cache est la parite du bit d'observation precedent ; le bit courant est l'observation. Le next-token (bit courant) ne determine pas entierement le belief (parite du bit precedent), ce qui cree une dissociation testable.\n", - "\n", - "Les deux generateurs sont **numpy-only** et fonctionnent sans aucune dependance externe.\n" + "## Generateurs de processus synthetiques (conformes #16225)\n", + "\n", + "Deux processus a **belief ground-truth exact**, importes du module `ict` --\n", + "plus aucune redefinition inline :\n", + "\n", + "### Mess3 (HMM 3 etats, emissions ternaires discretes)\n", + "Processus de **Marzen & Crutchfield (2017)**, *Nearly maximally predictive\n", + "features and their dimensions* (reference [20] de arXiv:2405.15943). Trois\n", + "etats caches, persistance p_stay = 0.95, alphabet ternaire discret `{0, 1, 2}`\n", + "dont l'emission **ne revele pas l'etat** (emission_diag = 0.5). Le belief\n", + "ground-truth est la distribution filtree `P(s_t | obs_0..t)` -- un point du\n", + "2-simplexe, pas l'etat cache.\n", + "\n", + "### RRXOR (Riechers & Crutchfield 2018, arXiv:1706.00883)\n", + "Le processus repete les triplets `(r1, r2, r1 XOR r2)` : correlations par\n", + "paires nulles, spectre plat, mais contrainte de triplet deterministe.\n", + "Epsilon-machine a **5 etats causaux** (machine Mealy : emissions sur les\n", + "aretes). Sa mixed-state presentation compte **36 croyances distinctes**\n", + "(31 transitoires + 5 recurrentes, litterature p. 17 Fig. 7) -- et plusieurs\n", + "de ces croyances partagent la **meme prediction next-token** : c'est la\n", + "dissociation que l'exercice 3 mesure.\n", + "\n", + "Les deux generateurs viennent de `ict/bench_factorise.py` (numpy-only) et la\n", + "primitive MSP de `ict/mixed_state.py` (BFS `sequence -> croyance`)." ] }, { @@ -294,69 +367,63 @@ "id": "c5121db9", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:23.989836Z", - "iopub.status.busy": "2026-09-11T23:15:23.989433Z", - "iopub.status.idle": "2026-09-11T23:15:24.008695Z", - "shell.execute_reply": "2026-09-11T23:15:24.008118Z" - } + "iopub.execute_input": "2026-09-18T11:00:31.357273Z", + "iopub.status.busy": "2026-09-18T11:00:31.356806Z", + "iopub.status.idle": "2026-09-18T11:00:31.476174Z", + "shell.execute_reply": "2026-09-18T11:00:31.475000Z" + }, + "papermill": { + "duration": 0.126002, + "end_time": "2026-09-18T11:00:31.477409+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.351407+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Mess3 : 100 steps, etats uniques = [0 1 2], obs uniques = [0 1 2]\n", - "RRXOR : 100 steps, parites uniques = [0 1], obs uniques = [0 1]\n", - "X_pre.shape = (100, 32)\n" + "Mess3 : 100 steps, etats uniques = [0 1 2], obs uniques = [0 1 2]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RRXOR : 99 steps, etats d'arrivee uniques = [0 1 2 3 4]\n", + "RRXOR : triplets (r1, r2, r1 XOR r2) valides : True\n" ] } ], "source": [ - "def make_mess3_transitions():\n", - " \"\"\"Matrice de transition Mess3 (3 etats) - symetrique.\"\"\"\n", - " p_stay = 0.95\n", - " p_leave = (1.0 - p_stay) / 2.0\n", - " T = np.array([\n", - " [p_stay, p_leave, p_leave],\n", - " [p_leave, p_stay, p_leave],\n", - " [p_leave, p_leave, p_stay],\n", - " ])\n", - " return T\n", - "\n", - "\n", - "def sample_mess3(n_steps, rng, T):\n", - " \"\"\"Echantillonne un trajectory Mess3 (obs = etat).\"\"\"\n", - " n_states = T.shape[0]\n", - " states = np.zeros(n_steps, dtype=int)\n", - " obs = np.zeros(n_steps, dtype=int)\n", - " states[0] = rng.integers(0, n_states)\n", - " obs[0] = states[0]\n", - " for t in range(1, n_steps):\n", - " states[t] = rng.choice(n_states, p=T[states[t - 1]])\n", - " obs[t] = states[t]\n", - " return states, obs\n", - "\n", - "\n", - "def make_rrxor(n_steps, rng):\n", - " \"\"\"RRXOR : parite ground-truth, next-token = obs courante.\"\"\"\n", - " obs = rng.integers(0, 2, n_steps).astype(int)\n", - " beliefs = np.zeros(n_steps, dtype=int)\n", - " beliefs[0] = 0\n", - " for t in range(1, n_steps):\n", - " beliefs[t] = int(obs[t - 1])\n", - " return beliefs, obs\n", - "\n", - "\n", - "def simulate_residual(states, dim, layer, rng):\n", - " \"\"\"Simule des activations de dimension dim a partir des etats.\n", - " layer : 'pre' (activations brutes) ou 'post' (LayerNorm-like).\n", + "import os\n", + "import sys\n", + "\n", + "# Generateurs conformes importes du module ict (plus de version inline).\n", + "sys.path.insert(0, os.getcwd())\n", + "from ict.bench_factorise import Mess3Canonical, RRXOR\n", + "from ict.mixed_state import msp_mess3, msp_rrxor\n", + "\n", + "MESS3 = Mess3Canonical()\n", + "RRXOR_GEN = RRXOR()\n", + "\n", + "\n", + "def simulate_residual(B, dim, layer, rng):\n", + " \"\"\"Simule des activations a partir d'une matrice de croyances B (N, K).\n", + "\n", + " Lineaire en B : X = B @ W ou W est (K, dim). Un belief Dirac sur l'etat i\n", + " redonne X = W_i (le regime orthogonal de l'exercice 1 est le cas\n", + " particulier croyance synchronisee). layer : 'pre' (bruit additif fort)\n", + " ou 'post' (normalisation L2 + bruit faible, style LayerNorm).\n", " \"\"\"\n", - " n = len(states)\n", - " n_states = int(states.max()) + 1\n", - " W = rng.standard_normal((n_states, dim)) * 0.5\n", - " X = W[states]\n", + " K = B.shape[1]\n", + " W = rng.standard_normal((K, dim)) * 0.5\n", + " X = B @ W\n", " if layer == \"pre\":\n", - " X = X * np.sqrt(states + 1)[:, None]\n", " X += rng.standard_normal(X.shape) * 0.3\n", " elif layer == \"post\":\n", " norms = np.linalg.norm(X, axis=1, keepdims=True) + 1e-6\n", @@ -365,21 +432,112 @@ " return X\n", "\n", "\n", - "# Test rapide des generateurs\n", + "# Test rapide des generateurs conformes\n", "rng = np.random.default_rng(42)\n", - "T = make_mess3_transitions()\n", - "states_m, obs_m = sample_mess3(100, rng, T)\n", - "states_r, obs_r = make_rrxor(100, rng)\n", - "X_pre = simulate_residual(states_m, DIM, \"pre\", rng)\n", + "states_m, obs_m = MESS3.sample(100, int(rng.integers(0, 2**31 - 1)))\n", + "states_r, obs_r = RRXOR_GEN.sample(99, int(rng.integers(0, 2**31 - 1)))\n", "print(f\"Mess3 : 100 steps, etats uniques = {np.unique(states_m)}, obs uniques = {np.unique(obs_m)}\")\n", - "print(f\"RRXOR : 100 steps, parites uniques = {np.unique(states_r)}, obs uniques = {np.unique(obs_r)}\")\n", - "print(f\"X_pre.shape = {X_pre.shape}\")\n" + "print(f\"RRXOR : 99 steps, etats d'arrivee uniques = {np.unique(states_r)}\")\n", + "k = (len(obs_r) // 3) * 3\n", + "print(f\"RRXOR : triplets (r1, r2, r1 XOR r2) valides : {bool(np.all(obs_r[2:k:3] == obs_r[0:k:3] ^ obs_r[1:k:3]))}\")" + ] + }, + { + "cell_type": "markdown", + "id": "ad86258c", + "metadata": { + "papermill": { + "duration": 0.004491, + "end_time": "2026-09-18T11:00:31.486597+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.482106+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Mixed-state presentation : la geometrie exacte du banc\n", + "\n", + "La primitive `ict/mixed_state.py` enumere par BFS l'arbre `sequence -> croyance` :\n", + "cardinal par profondeur, union fermee, et le test fondateur de la dissociation —\n", + "des **croyances distinctes** partagent la **meme prediction next-token**." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "c012ed24", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-18T11:00:31.496656Z", + "iopub.status.busy": "2026-09-18T11:00:31.496138Z", + "iopub.status.idle": "2026-09-18T11:00:31.530935Z", + "shell.execute_reply": "2026-09-18T11:00:31.526505Z" + }, + "papermill": { + "duration": 0.041911, + "end_time": "2026-09-18T11:00:31.532120+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.490209+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MSP Mess3, croyances par profondeur : [1, 3, 9, 27]\n", + "MSP RRXOR, croyances par profondeur : [1, 2, 4, 8, 12, 17, 17, 17]\n", + "MSP RRXOR, union des croyances distinctes : 36 (litterature : 36 = 31 transitoires + 5 recurrentes)\n", + "36 croyances pour 11 predictions next-token distinctes : la carte belief -> next-token est non injective\n", + "Groupe le plus large : 10 croyances distinctes -> meme next-token (uniforme 1/2, 1/2)\n", + "Invariants MSP Mess3 : True []\n", + "Invariants MSP RRXOR : True []\n" + ] + } + ], + "source": [ + "# Mixed-state presentation : enumeration BFS sequence -> croyance (#16225)\n", + "# Mess3 : croissance 3^k. RRXOR : union FERMEE a 36 croyances distinctes.\n", + "msp3 = msp_mess3(max_depth=4)\n", + "mspr = msp_rrxor()\n", + "print(\"MSP Mess3, croyances par profondeur :\", [msp3.n_distinct(d) for d in range(msp3.depth)])\n", + "print(\"MSP RRXOR, croyances par profondeur :\", [mspr.n_distinct(d) for d in range(mspr.depth)])\n", + "print(f\"MSP RRXOR, union des croyances distinctes : {mspr.n_distinct_total()} (litterature : 36 = 31 transitoires + 5 recurrentes)\")\n", + "\n", + "# Dissociation : des croyances DISTINCTES partagent la meme prediction next-token\n", + "Wsum = RRXOR_GEN.edge_tensor().sum(axis=1) # Wsum[s, y] = P(y | etat causal s)\n", + "groups = {}\n", + "for level in mspr.nodes:\n", + " for b in level:\n", + " pred = tuple(np.round(b @ Wsum, 6))\n", + " groups.setdefault(pred, set()).add(tuple(np.round(b, 6)))\n", + "n_beliefs = sum(len(g) for g in groups.values())\n", + "print(f\"{n_beliefs} croyances pour {len(groups)} predictions next-token distinctes : la carte belief -> next-token est non injective\")\n", + "example = max(groups.values(), key=len)\n", + "print(f\"Groupe le plus large : {len(example)} croyances distinctes -> meme next-token (uniforme 1/2, 1/2)\")\n", + "\n", + "ok3, f3 = msp3.verify_invariants(MESS3.beliefs)\n", + "okr, fr = mspr.verify_invariants(RRXOR_GEN.beliefs)\n", + "print(f\"Invariants MSP Mess3 : {ok3} {f3}\")\n", + "print(f\"Invariants MSP RRXOR : {okr} {fr}\")" ] }, { "cell_type": "markdown", "id": "cf8016e8", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.004723, + "end_time": "2026-09-18T11:00:31.541342+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.536619+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "## Exercice 1 - Regime orthogonal (sanity check)\n", "\n", @@ -387,20 +545,29 @@ "\n", "C'est le **regime trivial** : on verifie que les primitives fonctionnent et que le protocole capture bien la linearite du belief. Tout ecart significatif constitue un **bug dans les primitives** ou le protocole.\n", "\n", - "**Verdict attendu** : H1 (accuracy_belief - accuracy_shuffle >= 0.3) SUPPORTED. H2 (pre-LN > post-LN) attendue SUPPORTED car les activations pre-LN ont des magnitudes variables par etat, ce qui aide la separation lineaire.\n" + "**Verdict attendu** : H1 (accuracy_belief - accuracy_shuffle >= 0.3) SUPPORTED. H2 (pre-LN > post-LN) est une question ouverte : avec l'encodage lineaire en belief (post-#16225), la normalisation post-L2 n'ecrase plus l'echelle des directions -- le sens se lit sur la mesure, pas sur une attente.\n", + "" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "a3788d4c", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:24.011464Z", - "iopub.status.busy": "2026-09-11T23:15:24.011128Z", - "iopub.status.idle": "2026-09-11T23:15:24.370618Z", - "shell.execute_reply": "2026-09-11T23:15:24.370067Z" - } + "iopub.execute_input": "2026-09-18T11:00:31.552654Z", + "iopub.status.busy": "2026-09-18T11:00:31.552028Z", + "iopub.status.idle": "2026-09-18T11:00:33.745332Z", + "shell.execute_reply": "2026-09-18T11:00:33.744161Z" + }, + "papermill": { + "duration": 2.200274, + "end_time": "2026-09-18T11:00:33.746228+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:31.545954+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { @@ -408,11 +575,11 @@ "output_type": "stream", "text": [ "=== Exercice 1 - Regime orthogonal ===\n", - "Accuracy belief (pre-LN) : 1.000 +/- 0.000\n", + "Accuracy belief (pre-LN) : 0.998 +/- 0.001\n", "Accuracy belief (post-LN) : 1.000 +/- 0.000\n", - "Accuracy shuffle baseline : 0.355\n", - "Gap (pre - shuffle) : 0.644\n", - "Gap (post - shuffle) : 0.645\n", + "Accuracy shuffle baseline : 0.345\n", + "Gap (pre - shuffle) : 0.653\n", + "Gap (post - shuffle) : 0.655\n", "H1 (orthogonal) : SUPPORTED\n", "H2 (orthogonal) : NOT_SUPPORTED (pre-LN > post-LN)\n" ] @@ -423,10 +590,12 @@ "shuffle_results = []\n", "for seed in RNG_SEEDS:\n", " rng = np.random.default_rng(seed)\n", - " T = make_mess3_transitions()\n", - " states, obs = sample_mess3(N_TRAIN + N_TEST, rng, T)\n", - " X_pre = simulate_residual(states, DIM, \"pre\", rng)\n", - " X_post = simulate_residual(states, DIM, \"post\", rng)\n", + " gen_seed = int(rng.integers(0, 2**31 - 1))\n", + " states, obs = MESS3.sample(N_TRAIN + N_TEST, gen_seed)\n", + " # Regime Dirac : croyance synchronisee sur l'etat (one-hot) -- sanity check\n", + " B = np.eye(MESS3.n_states)[states]\n", + " X_pre = simulate_residual(B, DIM, \"pre\", rng)\n", + " X_post = simulate_residual(B, DIM, \"post\", rng)\n", "\n", " # Split train/test\n", " X_pre_train, X_pre_test = X_pre[:N_TRAIN], X_pre[N_TRAIN:]\n", @@ -467,241 +636,333 @@ "H1_orth = gap_pre >= 0.3\n", "H2_orth = acc_pre_mean > acc_post_mean\n", "print(f\"H1 (orthogonal) : {'SUPPORTED' if H1_orth else 'NOT_SUPPORTED'}\")\n", - "print(f\"H2 (orthogonal) : {'SUPPORTED' if H2_orth else 'NOT_SUPPORTED'} (pre-LN > post-LN)\")\n" + "print(f\"H2 (orthogonal) : {'SUPPORTED' if H2_orth else 'NOT_SUPPORTED'} (pre-LN > post-LN)\")" ] }, { "cell_type": "markdown", "id": "d29b71f2", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.004057, + "end_time": "2026-09-18T11:00:33.753883+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:33.749826+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ - "## Exercice 2 - Regime Mess3 (HMM realiste, belief ground-truth exact)\n", + "## Exercice 2 - Regime Mess3 canonique (emissions non revelatrices)\n", "\n", - "Le belief est l'etat cache d'un HMM 3 etats a persistance elevee (p_stay = 0.95). L'observation est couplee a l'etat (Mess3 : obs = etat).\n", + "Le banc est desormais le **Mess3 canonique** (Marzen & Crutchfield 2017) :\n", + "alphabet ternaire discret dont l'emission ne revele pas l'etat. Le belief\n", + "ground-truth est la distribution filtree exacte `P(s_t | obs_0..t)` sur le\n", + "2-simplexe -- calculee par `MESS3.beliefs(obs)` (filtration forward numpy).\n", "\n", - "**Question** : est-ce que le probe lineaire peut recuperer le belief ?\n", - "C'est la version **canonique** du test : un transformer entraine sur Mess3 apprend une representation interne alignee au belief exact (cf. litterature singh 1994).\n", + "**Question** : le probe lineaire recupere-t-il le belief **vectoriel**\n", + "(coordonnees du simplexe) depuis le residual stream simule ?\n", "\n", - "**Verdict attendu** : H1 SUPPORTED (accuracy > shuffle de >= 0.3).\n", + "**Ce qui change vs la version obs = etat** : l'ancienne equivalence\n", + "next-token == belief par construction est LEVEE (c'etait l'artefact\n", + "denonce par #16225 -- accuracy 1.000 tautologique). Le probe next-token\n", + "predira une observation **stochastique** : son plafond est\n", + "`E[max_y P(y_{t+1} | b_t)]`, mesure ci-dessous.\n", "\n", - "**Sub-test** : next-token baseline - predire l'observation suivante au lieu du belief. Sur Mess3, next-token == etat, donc ce baseline est **equivalent au belief** par construction. On le mentionne pour reference ; la dissociation next-token vs belief est testee sur RRXOR (Ex. 3).\n" + "**Verdict attendu** : H1 SUPPORTED (accuracy argmax belief - shuffle >= 0.3)." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "83d6443f", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:24.373940Z", - "iopub.status.busy": "2026-09-11T23:15:24.373501Z", - "iopub.status.idle": "2026-09-11T23:15:24.814896Z", - "shell.execute_reply": "2026-09-11T23:15:24.814094Z" - } + "iopub.execute_input": "2026-09-18T11:00:33.762270Z", + "iopub.status.busy": "2026-09-18T11:00:33.761789Z", + "iopub.status.idle": "2026-09-18T11:00:36.274277Z", + "shell.execute_reply": "2026-09-18T11:00:36.273024Z" + }, + "papermill": { + "duration": 2.518017, + "end_time": "2026-09-18T11:00:36.275473+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:33.757456+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "=== Exercice 2 - Regime Mess3 (HMM realiste) ===\n", - "Accuracy belief held-out : 1.000 +/- 0.000\n", - "Accuracy next-token held-out: 1.000 +/- 0.000\n", - "Gap belief - shuffle : 0.644\n", - "Note Mess3 : next-token == etat par construction (obs couplee)\n", + "=== Exercice 2 - Regime Mess3 canonique (emissions non revelatrices) ===\n", + "Accuracy belief (argmax) held-out : 0.908 +/- 0.006\n", + "R2 belief (3 coordonnees simplexe): 0.886\n", + "Accuracy next-token held-out : 0.349 +/- 0.019\n", + "Plafond next-token mesure : 0.408\n", + "Gap belief - shuffle : 0.563\n", "H1 (Mess3 belief vs shuffle) : SUPPORTED\n", - "Equivalence belief/next-tok : OUI (attendu)\n" + "Note : equivalence next-token == belief LEVEE -- l'observation ne revele plus l'etat (#16225)\n" ] } ], "source": [ "results_mess3_belief = []\n", "results_mess3_nexttok = []\n", + "results_mess3_r2 = []\n", + "ceiling_next_mess3 = []\n", "\n", "for seed in RNG_SEEDS:\n", " rng = np.random.default_rng(seed)\n", - " T = make_mess3_transitions()\n", - " states, obs = sample_mess3(N_TRAIN + N_TEST, rng, T)\n", - "\n", - " X = simulate_residual(states, DIM, \"pre\", rng)\n", - " X_train, X_test = X[:N_TRAIN], X[N_TRAIN:]\n", - " y_train_belief = states[:N_TRAIN]\n", - " y_test_belief = states[N_TRAIN:]\n", - "\n", - " W_belief, b_belief = solve_ols_ridge(X_train, y_train_belief, lam=1.0)\n", - " y_pred_belief = np.clip(np.round(X_test @ W_belief + b_belief).astype(int), 0, N_HIDDEN - 1)\n", - " results_mess3_belief.append(float(np.mean(y_test_belief == y_pred_belief)))\n", - "\n", - " y_train_next = obs[:N_TRAIN]\n", - " y_test_next = obs[N_TRAIN:]\n", - " W_next, b_next = solve_ols_ridge(X_train, y_train_next, lam=1.0)\n", - " y_pred_next = np.clip(np.round(X_test @ W_next + b_next).astype(int), 0, N_HIDDEN - 1)\n", - " results_mess3_nexttok.append(float(np.mean(y_test_next == y_pred_next)))\n", + " gen_seed = int(rng.integers(0, 2**31 - 1))\n", + " # +1 pas : le probe next-token predit obs[t+1]\n", + " states, obs = MESS3.sample(N_TRAIN + N_TEST + 1, gen_seed)\n", + " beliefs = MESS3.beliefs(obs) # ground-truth exact : filtration forward\n", + "\n", + " X = simulate_residual(beliefs, DIM, \"pre\", rng)\n", + " X_train, X_test = X[:N_TRAIN], X[N_TRAIN:N_TRAIN + N_TEST]\n", + " B_train, B_test = beliefs[:N_TRAIN], beliefs[N_TRAIN:N_TRAIN + N_TEST]\n", + "\n", + " # Probe belief : regression Ridge sur les 3 coordonnees du simplexe\n", + " W_belief, b_belief = solve_ols_ridge(X_train, B_train, lam=1.0)\n", + " B_pred = X_test @ W_belief + b_belief\n", + " results_mess3_belief.append(float(np.mean(B_pred.argmax(axis=1) == B_test.argmax(axis=1))))\n", + " ss_res = float(((B_pred - B_test) ** 2).sum())\n", + " ss_tot = float(((B_test - B_test.mean(axis=0)) ** 2).sum())\n", + " results_mess3_r2.append(1.0 - ss_res / ss_tot)\n", + "\n", + " # Probe next-token : predire l'observation suivante (ternaire, stochastique)\n", + " y_next_train = obs[1:N_TRAIN + 1].astype(float)\n", + " y_next_test = obs[N_TRAIN + 1:N_TRAIN + N_TEST + 1]\n", + " W_next, b_next = solve_ols_ridge(X_train, y_next_train, lam=1.0)\n", + " y_pred_next = np.clip(np.round(X_test @ W_next + b_next).astype(int), 0, 2)\n", + " results_mess3_nexttok.append(float(np.mean(y_next_test == y_pred_next)))\n", + "\n", + " # Plafond next-token mesure : E[max_y P(y_{t+1} | b_t)] sur le held-out\n", + " P_next = (B_test @ MESS3.transition_matrix()) @ MESS3.emission_matrix()\n", + " ceiling_next_mess3.append(float(P_next.max(axis=1).mean()))\n", "\n", "\n", "mean_belief = float(np.mean(results_mess3_belief))\n", "std_belief = float(np.std(results_mess3_belief))\n", + "mean_r2 = float(np.mean(results_mess3_r2))\n", "mean_next = float(np.mean(results_mess3_nexttok))\n", "std_next = float(np.std(results_mess3_nexttok))\n", + "mean_ceiling = float(np.mean(ceiling_next_mess3))\n", "gap = mean_belief - acc_shuf_mean\n", "\n", - "print(\"=== Exercice 2 - Regime Mess3 (HMM realiste) ===\")\n", - "print(f\"Accuracy belief held-out : {mean_belief:.3f} +/- {std_belief:.3f}\")\n", - "print(f\"Accuracy next-token held-out: {mean_next:.3f} +/- {std_next:.3f}\")\n", - "print(f\"Gap belief - shuffle : {gap:.3f}\")\n", - "print(f\"Note Mess3 : next-token == etat par construction (obs couplee)\")\n", + "print(\"=== Exercice 2 - Regime Mess3 canonique (emissions non revelatrices) ===\")\n", + "print(f\"Accuracy belief (argmax) held-out : {mean_belief:.3f} +/- {std_belief:.3f}\")\n", + "print(f\"R2 belief (3 coordonnees simplexe): {mean_r2:.3f}\")\n", + "print(f\"Accuracy next-token held-out : {mean_next:.3f} +/- {std_next:.3f}\")\n", + "print(f\"Plafond next-token mesure : {mean_ceiling:.3f}\")\n", + "print(f\"Gap belief - shuffle : {gap:.3f}\")\n", "\n", "H1_mess3 = gap >= 0.3\n", - "H_equiv = abs(mean_belief - mean_next) < 0.05\n", "print(f\"H1 (Mess3 belief vs shuffle) : {'SUPPORTED' if H1_mess3 else 'NOT_SUPPORTED'}\")\n", - "print(f\"Equivalence belief/next-tok : {'OUI (attendu)' if H_equiv else 'NON (dissociation inattendue)'}\")\n" + "print(\"Note : equivalence next-token == belief LEVEE -- l'observation ne revele plus l'etat (#16225)\")" ] }, { "cell_type": "markdown", "id": "1b79b65f", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.005294, + "end_time": "2026-09-18T11:00:36.285912+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:36.280618+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ - "## Exercice 3 - RRXOR : dissociation belief vs next-token\n", - "\n", - "RRXOR est concu pour **dissocier** belief et next-token : le next-token (bit courant) ne determine pas entierement le belief (parite du bit precedent).\n", - "\n", - "**Prediction** : un probe sur le **belief** (parite du bit precedent) doit performer significativement mieux qu'un probe sur le **next-token** (bit courant), car le belief contient de l'information que le next-token ne porte pas.\n", - "\n", - "**Verdict attendu** : H1 (belief >> shuffle baseline 0.5) SUPPORTED, H3 (belief > next-token par >= 0.1 accuracy) SUPPORTED.\n", - "\n", - "Si H3 n'est pas SUPPORTED, deux explications possibles :\n", - "- Le bruit dans `simulate_residual` est trop fort et noie l'information.\n", - "- La dimension 32 est insuffisante pour encoder la parite.\n", - "\n", - "Dans les deux cas, c'est un **INCONCLUSIVE** honnete, pas un SUPPORTED maquille.\n" + "## Exercice 3 - RRXOR conforme : dissociation belief vs next-token\n", + "\n", + "Le RRXOR de la litterature (Riechers & Crutchfield 2018) repete les triplets\n", + "`(r1, r2, r1 XOR r2)`. Sa MSP compte **36 croyances distinctes**, et la\n", + "cellule de demo l'a montre : la carte belief -> next-token est **non\n", + "injective** -- des croyances distinctes partagent la meme prediction. C'est\n", + "exactement la structure que l'ancien banc (parite du bit precedent, 2 etats)\n", + "ne pouvait pas produire.\n", + "\n", + "**Protocole** : le residual stream simule encode lineairement le belief\n", + "vecteur (5 coordonnees). Le probe belief regresse ces coordonnees ; le probe\n", + "next-token predit le bit suivant, **stochastique** depuis G/A (uniforme) et\n", + "deterministe depuis X -- plafond `E[max_y P(y | b_t)]` ~ 2/3 en regime\n", + "stationnaire, mesure ci-dessous.\n", + "\n", + "**Prediction** : le probe belief depasse le probe next-token d'au moins 0.1\n", + "(H3) -- le belief porte la phase du processus, le next-token n'en porte\n", + "qu'une projection. Un H3 NOT_SUPPORTED sur CE banc serait un vrai resultat\n", + "(plus d'artefact de generateur a invoquer)." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "1bda9232", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:24.817366Z", - "iopub.status.busy": "2026-09-11T23:15:24.816995Z", - "iopub.status.idle": "2026-09-11T23:15:24.863505Z", - "shell.execute_reply": "2026-09-11T23:15:24.862906Z" - } + "iopub.execute_input": "2026-09-18T11:00:36.297566Z", + "iopub.status.busy": "2026-09-18T11:00:36.297161Z", + "iopub.status.idle": "2026-09-18T11:00:36.817396Z", + "shell.execute_reply": "2026-09-18T11:00:36.816275Z" + }, + "papermill": { + "duration": 0.528431, + "end_time": "2026-09-18T11:00:36.818887+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:36.290456+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "=== Exercice 3 - RRXOR : belief vs next-token ===\n", - "Accuracy belief held-out : 0.844 +/- 0.006\n", - "Accuracy next-token held-out: 0.836 +/- 0.005\n", - "Gap belief - 0.5 (shuffle) : 0.344\n", - "Dissociation belief - next : 0.008\n", + "=== Exercice 3 - RRXOR conforme : belief vs next-token ===\n", + "Accuracy belief (argmax) held-out : 1.000 +/- 0.000\n", + "R2 belief (5 coordonnees) : 0.931\n", + "Accuracy next-token held-out : 0.665 +/- 0.006\n", + "Plafond next-token mesure : 0.667\n", + "Gap belief - 0.5 (shuffle) : 0.500\n", + "Dissociation belief - next : 0.335\n", "H1 (RRXOR belief vs shuffle) : SUPPORTED\n", - "H3 (RRXOR belief > next-tok) : NOT_SUPPORTED\n" + "H3 (RRXOR belief > next-tok) : SUPPORTED\n" ] } ], "source": [ "results_rrxor_belief = []\n", "results_rrxor_nexttok = []\n", + "results_rrxor_r2 = []\n", + "ceiling_next_rrxor = []\n", "\n", "for seed in RNG_SEEDS:\n", " rng = np.random.default_rng(seed)\n", - " beliefs, obs = make_rrxor(N_TRAIN + N_TEST, rng)\n", - "\n", - " # Construire activations : on encode le bit courant dans la premiere dim,\n", - " # et la parite dans la deuxieme dim (direction orthogonale). Cela simule un\n", - " # residual stream ou le belief est represente **a cote** du next-token.\n", - " X = np.zeros((len(obs), DIM))\n", - " X[:, 0] = obs.astype(float)\n", - " X[:, 1] = beliefs.astype(float)\n", - " rng_noise = np.random.default_rng(seed + 5000)\n", - " X += rng_noise.standard_normal(X.shape) * 0.5\n", - "\n", - " X_train, X_test = X[:N_TRAIN], X[N_TRAIN:]\n", - " y_train_belief = beliefs[:N_TRAIN]\n", - " y_test_belief = beliefs[N_TRAIN:]\n", - " y_train_next = obs[:N_TRAIN]\n", - " y_test_next = obs[N_TRAIN:]\n", - "\n", - " W_b, b_b = solve_ols_ridge(X_train, y_train_belief, lam=1.0)\n", - " y_pred_belief = np.clip(np.round(X_test @ W_b + b_b).astype(int), 0, 1)\n", - " results_rrxor_belief.append(float(np.mean(y_test_belief == y_pred_belief)))\n", - "\n", - " W_n, b_n = solve_ols_ridge(X_train, y_train_next, lam=1.0)\n", + " gen_seed = int(rng.integers(0, 2**31 - 1))\n", + " states, obs = RRXOR_GEN.sample(N_TRAIN + N_TEST + 1, gen_seed)\n", + " beliefs = RRXOR_GEN.beliefs(obs) # (n, 5) : filtration forward Mealy\n", + "\n", + " X = simulate_residual(beliefs, DIM, \"pre\", rng)\n", + " X_train, X_test = X[:N_TRAIN], X[N_TRAIN:N_TRAIN + N_TEST]\n", + " B_train, B_test = beliefs[:N_TRAIN], beliefs[N_TRAIN:N_TRAIN + N_TEST]\n", + "\n", + " # Probe belief : regression sur les 5 coordonnees, accuracy en argmax\n", + " W_b, b_b = solve_ols_ridge(X_train, B_train, lam=1.0)\n", + " B_pred = X_test @ W_b + b_b\n", + " results_rrxor_belief.append(float(np.mean(B_pred.argmax(axis=1) == B_test.argmax(axis=1))))\n", + " ss_res = float(((B_pred - B_test) ** 2).sum())\n", + " ss_tot = float(((B_test - B_test.mean(axis=0)) ** 2).sum())\n", + " results_rrxor_r2.append(1.0 - ss_res / ss_tot)\n", + "\n", + " # Probe next-token : predire le bit suivant (stochastique depuis G/A)\n", + " y_next_train = obs[1:N_TRAIN + 1].astype(float)\n", + " y_next_test = obs[N_TRAIN + 1:N_TRAIN + N_TEST + 1]\n", + " W_n, b_n = solve_ols_ridge(X_train, y_next_train, lam=1.0)\n", " y_pred_next = np.clip(np.round(X_test @ W_n + b_n).astype(int), 0, 1)\n", - " results_rrxor_nexttok.append(float(np.mean(y_test_next == y_pred_next)))\n", + " results_rrxor_nexttok.append(float(np.mean(y_next_test == y_pred_next)))\n", + "\n", + " # Plafond next-token mesure : E[max_y P(y_{t+1} | b_t)] sur le held-out\n", + " Wsum = RRXOR_GEN.edge_tensor().sum(axis=1) # P(y | etat causal s)\n", + " P_next = B_test @ Wsum\n", + " ceiling_next_rrxor.append(float(P_next.max(axis=1).mean()))\n", "\n", "\n", "mean_b = float(np.mean(results_rrxor_belief))\n", "std_b = float(np.std(results_rrxor_belief))\n", + "mean_r2_r = float(np.mean(results_rrxor_r2))\n", "mean_n = float(np.mean(results_rrxor_nexttok))\n", "std_n = float(np.std(results_rrxor_nexttok))\n", + "mean_ceiling_r = float(np.mean(ceiling_next_rrxor))\n", "gap_b = mean_b - 0.5\n", "dissociation = mean_b - mean_n\n", "\n", - "print(\"=== Exercice 3 - RRXOR : belief vs next-token ===\")\n", - "print(f\"Accuracy belief held-out : {mean_b:.3f} +/- {std_b:.3f}\")\n", - "print(f\"Accuracy next-token held-out: {mean_n:.3f} +/- {std_n:.3f}\")\n", - "print(f\"Gap belief - 0.5 (shuffle) : {gap_b:.3f}\")\n", - "print(f\"Dissociation belief - next : {dissociation:.3f}\")\n", + "print(\"=== Exercice 3 - RRXOR conforme : belief vs next-token ===\")\n", + "print(f\"Accuracy belief (argmax) held-out : {mean_b:.3f} +/- {std_b:.3f}\")\n", + "print(f\"R2 belief (5 coordonnees) : {mean_r2_r:.3f}\")\n", + "print(f\"Accuracy next-token held-out : {mean_n:.3f} +/- {std_n:.3f}\")\n", + "print(f\"Plafond next-token mesure : {mean_ceiling_r:.3f}\")\n", + "print(f\"Gap belief - 0.5 (shuffle) : {gap_b:.3f}\")\n", + "print(f\"Dissociation belief - next : {dissociation:.3f}\")\n", "\n", "H1_rrxor = gap_b >= 0.2\n", "H3_rrxor = dissociation >= 0.1\n", "print(f\"H1 (RRXOR belief vs shuffle) : {'SUPPORTED' if H1_rrxor else 'NOT_SUPPORTED'}\")\n", - "print(f\"H3 (RRXOR belief > next-tok) : {'SUPPORTED' if H3_rrxor else 'NOT_SUPPORTED'}\")\n" + "print(f\"H3 (RRXOR belief > next-tok) : {'SUPPORTED' if H3_rrxor else 'NOT_SUPPORTED'}\")" ] }, { "cell_type": "markdown", "id": "a1a576de", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.005092, + "end_time": "2026-09-18T11:00:36.829577+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:36.824485+00:00", + "status": "completed" + }, + "tags": [] + }, "source": [ "## Verdict global\n", "\n", - "| Hypothese | Regime orthogonal (Ex.1) | Mess3 (Ex.2) | RRXOR (Ex.3) |\n", + "| Hypothese | Regime orthogonal (Ex.1) | Mess3 canonique (Ex.2) | RRXOR conforme (Ex.3) |\n", "|-----------|:-----------------------:|:------------:|:-------------:|\n", "| **H1** belief >> shuffle | SUPPORTED si gap >= 0.3 | SUPPORTED si gap >= 0.3 | SUPPORTED si gap >= 0.2 |\n", "| **H2** pre-LN > post-LN | applicable orthogonal | - | - |\n", - "| **H3** belief >> next-token | - | equivalence par construction | SUPPORTED si dissociation >= 0.1 |\n", + "| **H3** belief >> next-token | - | plafond next-token mesure | SUPPORTED si dissociation >= 0.1 |\n", "\n", "**Lecture** :\n", "- Le **regime orthogonal** valide les primitives : le probe Ridge recupere quasi-parfaitement le belief quand l'information est lineairement encodee.\n", - "- Le **regime Mess3** valide l'application au HMM realiste : le probe atteint une accuracy nettement superieure au shuffle baseline, et reste equivalent au next-token (qui par construction = belief sur Mess3).\n", - "- Le **regime RRXOR** teste la **dissociation** : si le probe belief performe mieux que le probe next-token, c'est la signature d'un belief encode **distinctement** du next-token dans le residual stream.\n", + "- Le **regime Mess3 canonique** applique le probe a un HMM dont l'observation **ne revele pas l'etat** : le belief est un point du simplexe, recupere par regression vectorielle (R2), et le probe next-token plafonne a `E[max_y P(y|b)]` mesure -- l'equivalence tautologique de l'ancienne version obs = etat est levee (#16225).\n", + "- Le **regime RRXOR conforme** teste la **dissociation** sur la structure de la litterature : 36 croyances distinctes dont plusieurs partagent la meme prediction next-token (MSP non injective, see demo). Le probe belief doit performer au-dela du plafond next-token.\n", "\n", "## Limites\n", "\n", "1. **Regime orthogonal est trivial** : c'est un sanity check, pas un resultat scientifique. Il valide les primitives et le protocole.\n", - "2. **Mess3 obs == belief par construction** : la dissociation belief/next-token n'est pas testable sur Mess3 ; RRXOR comble ce manque.\n", + "2. **Banc simule, pas transformer reel** : `simulate_residual` encode lineairement le belief ; la migration vers des activations reelles (Epic #15475) reste le test decisif.\n", "3. **Bruit Gaussien additif** : on n'a pas explore de regimes ou le bruit est structure (correle aux etats) ou non-stationnaire.\n", "4. **Dimension 32** : suffisant pour 3-5 etats caches ; pour des HMM plus larges (10+ etats), il faudrait augmenter `DIM` et possiblement utiliser un probe non-lineaire (mais ce notebook reste numpy-only).\n", "\n", "## Migration future\n", "\n", - "Quand le contrat de trace v1 (Epic #15475 instrument) sera livre, ce notebook pourra charger des activations reelles (NPZ) au lieu des activations simulees. La signature `simulate_residual(states, dim, layer, rng)` est compatible avec un futur `load_real_activations(npz_path, layer)`.\n", + "Quand le contrat de trace v1 (Epic #15475 instrument) sera livre, ce notebook pourra charger des activations reelles (NPZ) au lieu des activations simulees. La signature `simulate_residual(B, dim, layer, rng)` est compatible avec un futur `load_real_activations(npz_path, layer)`.\n", "\n", "## Références\n", "\n", - "- **arXiv:2602.02385** — *Transformers Learn Factored Representations* : base directe de la réimplémentation numpy-only de ce notebook (régimes orthogonal / Mess3 / RRXOR, probes linéaires).\n", - "- **arXiv:2405.15943** — Shai et al., *Transformers Represent Belief State Geometry in their Residual Stream* : papier fondateur du théorème de géométrie belief-state linéairement représentée dans le residual stream, que la section Mess3 (belief ground-truth exact sur le 2-simplexe) vérifie empiriquement.\n", - "- **Dépôt ZM** — `Zeinab-Mohammadi/pytorch-AI-interpretability-transformer_ZM` : architecture minimale de référence (transformer from-scratch ~101K params, banc Mess3, probes belief R² > 0.989), explicitement dérivée d'arXiv:2602.02385 — point de comparaison pour la migration future vers des activations réelles (cf. Epic #15475).\n" + "- **arXiv:2405.15943** — Shai et al., *Transformers Represent Belief State Geometry in their Residual Stream* : papier fondateur du théorème de géométrie belief-state linéairement représentée dans le residual stream ; §2.2 définit la mise à jour `eta' = eta T^(x) / (eta T^(x) 1)` et §3.2 le RRXOR à 36 états de croyance.\n", + "- **Marzen & Crutchfield 2017** — *Nearly maximally predictive features and their dimensions*, Phys. Rev. E 95(5):051301(R) : origine du processus Mess3 (correction d'attribution #16225 — l'ancienne mention « singh et al. 1994 » était erronée).\n", + "- **Riechers & Crutchfield 2018** — *Spectral Simplicity of Apparent Complexity, Part II* ([arXiv:1706.00883](https://arxiv.org/abs/1706.00883)) : définition du RRXOR (triplets r1, r2, r1 XOR r2), epsilon-machine à 5 états, S-MSP à 36 croyances (Fig. 4 et 7).\n", + "- **arXiv:2602.02385** — *Transformers Learn Factored Representations* : base de la réimplémentation numpy-only (régimes orthogonal / probes linéaires).\n", + "- **Dépôt ZM** — `Zeinab-Mohammadi/pytorch-AI-interpretability-transformer_ZM` : architecture minimale de référence, point de comparaison pour la migration future vers des activations réelles (cf. Epic #15475)." ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "89386e8a", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T23:15:24.866332Z", - "iopub.status.busy": "2026-09-11T23:15:24.865976Z", - "iopub.status.idle": "2026-09-11T23:15:24.870731Z", - "shell.execute_reply": "2026-09-11T23:15:24.870178Z" - } + "iopub.execute_input": "2026-09-18T11:00:36.841980Z", + "iopub.status.busy": "2026-09-18T11:00:36.841507Z", + "iopub.status.idle": "2026-09-18T11:00:36.852266Z", + "shell.execute_reply": "2026-09-18T11:00:36.851062Z" + }, + "papermill": { + "duration": 0.018732, + "end_time": "2026-09-18T11:00:36.853396+00:00", + "exception": false, + "start_time": "2026-09-18T11:00:36.834664+00:00", + "status": "completed" + }, + "tags": [] }, "outputs": [ { @@ -712,13 +973,14 @@ "VERDICT FINAL - ICT-37-FLens-BeliefState\n", "============================================================\n", "Ex.1 orthogonal : H1=SUPPORTED, H2=NOT_SUPPORTED\n", - "Ex.2 Mess3 : H1=SUPPORTED, equivalence belief/next-tok=OUI\n", - "Ex.3 RRXOR : H1=SUPPORTED, H3=NOT_SUPPORTED\n", + "Ex.2 Mess3 canonique : H1=SUPPORTED, R2 belief=0.886, plafond next-token=0.408\n", + "Ex.3 RRXOR conforme : H1=SUPPORTED, H3=SUPPORTED\n", "\n", - "-> Conclusion : H1 SUPPORTED, H3 INCONCLUSIVE\n", - " Le probe recupere le belief, mais la dissociation vs next-token\n", - " n'est pas observee. Cause probable : bruit Gaussien trop fort ou\n", - " dimension 32 insuffisante pour encoder la parite.\n" + "-> Conclusion : SUPPORTED sur les hypotheses principales (H1, H3)\n", + " Le probe lineaire recupere le belief state (vectoriel) de Mess3\n", + " canonique et de RRXOR conforme ; la dissociation est SUPPORTED :\n", + " le belief porte la phase du processus, le next-token n'en porte\n", + " qu'une projection (plafond mesure, non un artefact du banc).\n" ] } ], @@ -729,25 +991,28 @@ "\n", "verdict_lines = []\n", "verdict_lines.append(f\"Ex.1 orthogonal : H1={'SUPPORTED' if H1_orth else 'NOT_SUPPORTED'}, H2={'SUPPORTED' if H2_orth else 'NOT_SUPPORTED'}\")\n", - "verdict_lines.append(f\"Ex.2 Mess3 : H1={'SUPPORTED' if H1_mess3 else 'NOT_SUPPORTED'}, equivalence belief/next-tok={'OUI' if H_equiv else 'NON'}\")\n", - "verdict_lines.append(f\"Ex.3 RRXOR : H1={'SUPPORTED' if H1_rrxor else 'NOT_SUPPORTED'}, H3={'SUPPORTED' if H3_rrxor else 'NOT_SUPPORTED'}\")\n", + "verdict_lines.append(f\"Ex.2 Mess3 canonique : H1={'SUPPORTED' if H1_mess3 else 'NOT_SUPPORTED'}, R2 belief={mean_r2:.3f}, plafond next-token={mean_ceiling:.3f}\")\n", + "verdict_lines.append(f\"Ex.3 RRXOR conforme : H1={'SUPPORTED' if H1_rrxor else 'NOT_SUPPORTED'}, H3={'SUPPORTED' if H3_rrxor else 'NOT_SUPPORTED'}\")\n", "\n", "for line in verdict_lines:\n", " print(line)\n", "\n", "if H1_orth and H1_mess3 and H1_rrxor:\n", " if H3_rrxor:\n", - " print(\"\\n-> Conclusion : SUPPORTED sur les 3 hypotheses principales (H1, H3)\")\n", - " print(\" Le probe lineaire recupere le belief state de Mess3 et RRXOR ;\")\n", - " print(\" la dissociation RRXOR est SUPPORTED - le belief porte une information\")\n", - " print(\" que le next-token ne porte pas.\")\n", + " print(\"\\n-> Conclusion : SUPPORTED sur les hypotheses principales (H1, H3)\")\n", + " print(\" Le probe lineaire recupere le belief state (vectoriel) de Mess3\")\n", + " print(\" canonique et de RRXOR conforme ; la dissociation est SUPPORTED :\")\n", + " print(\" le belief porte la phase du processus, le next-token n'en porte\")\n", + " print(\" qu'une projection (plafond mesure, non un artefact du banc).\")\n", " else:\n", - " print(\"\\n-> Conclusion : H1 SUPPORTED, H3 INCONCLUSIVE\")\n", - " print(\" Le probe recupere le belief, mais la dissociation vs next-token\")\n", - " print(\" n'est pas observee. Cause probable : bruit Gaussien trop fort ou\")\n", - " print(\" dimension 32 insuffisante pour encoder la parite.\")\n", + " print(\"\\n-> Conclusion : H1 SUPPORTED, H3 NOT_SUPPORTED\")\n", + " print(f\" Dissociation mesuree : {dissociation:.3f} (seuil 0.1).\")\n", + " print(\" Sur le banc conforme #16225 (MSP 36 croyances, croyances\")\n", + " print(\" distinctes a next-token identique), ce resultat est un vrai\")\n", + " print(\" resultat d'experience -- il n'y a plus de defaut de generateur\")\n", + " print(\" a invoquer ; la cause serait du cote de l'encodage simule.\")\n", "else:\n", - " print(\"\\n-> Conclusion : NOT_SUPPORTED sur au moins une hypothese - voir details ci-dessus.\")\n" + " print(\"\\n-> Conclusion : NOT_SUPPORTED sur au moins une hypothese - voir details ci-dessus.\")" ] } ], @@ -767,7 +1032,19 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.3" + "version": "3.13.7" + }, + "papermill": { + "default_parameters": {}, + "duration": 10.13258, + "end_time": "2026-09-18T11:00:37.226289+00:00", + "environment_variables": {}, + "exception": null, + "input_path": "ICT-37-FLens-BeliefState.ipynb", + "output_path": "ICT-37-FLens-BeliefState.ipynb", + "parameters": {}, + "start_time": "2026-09-18T11:00:27.093709+00:00", + "version": "2.7.0" } }, "nbformat": 4, diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py index c7019bbd68..6439308a85 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py @@ -119,14 +119,6 @@ def beliefs(self, obs: Array) -> Array: return out -# Alias historique : l'ancien nom ``Mess3`` est preserve pour ne pas casser -# les imports existants, mais il designe maintenant le banc DEPRECIE -# (gaussien, observation couplee). Le nouveau banc canonique s'appelle -# ``Mess3`` aussi mais precede l'ancien dans ce fichier ; voir :class:`Mess3` -# ci-dessous. -Mess3 = Mess3_ObsCoupled # noqa: F811 — alias de compatibilite, voir NOTE ci-dessus - - @dataclass(frozen=True) class Mess3Canonical: """Mess3 canonique (Marzen & Crutchfield 2017) : POMDP a 3 etats @@ -231,64 +223,101 @@ def beliefs(self, obs: Array) -> Array: return out +# Alias canonique (#16225) : ``Mess3`` designe le generateur CONFORME a la +# litterature -- alphabet discret ternaire qui ne revele pas l'etat cache. +# Le banc gaussien historique reste disponible sous son nom explicite +# ``Mess3_ObsCoupled`` pour les comparaisons de probe sur signaux continus. +Mess3 = Mess3Canonical # noqa: F811 — un seul generateur Mess3 par defaut + + @dataclass(frozen=True) class RRXOR: - """XOR recursif : bits iid ``b_t``, observation ``y_t = b_{t-1} XOR b_t``. - - Etat cache au pas t : la paire ``(b_{t-1}, b_t)``, 4 etats ordonnes - ``00, 01, 10, 11``. L'observation etant deterministe dans l'etat, le - belief exact apres observation vit sur les 2 etats coherents avec - ``y_t``, uniformes (les entrees sont iid uniformes). + """RRXOR (Riechers & Crutchfield 2018, arXiv:1706.00883v1, Fig. 4). + + Le processus repete trois etapes : (i) un 0 ou 1 equiprobable ``r1``, + (ii) un autre 0 ou 1 equiprobable ``r2``, (iii) le XOR des deux derniers + symboles ``r1 XOR r2``. Correlations par paires nulles, spectre plat : + toute la structure vit dans la contrainte de triplet. + + L'epsilon-machine compte **5 etats causaux** et est **Mealy** : les + emissions vivent sur les aretes, pas dans les etats. Etats ordonnes : + + - ``0`` = G (phase de reset, va emettre ``r1``), + - ``1`` = A0, ``2`` = A1 (memorise ``r1``), + - ``3`` = X0, ``4`` = X1 (memorise ``r1 XOR r2``, va emettre le XOR). + + Aretes : ``G -(r1, 1/2)-> A_{r1}`` ; ``A_{r1} -(r2, 1/2)-> X_{r1 XOR r2}`` ; + ``X_v -(v, 1)-> G``. La MSP depuis le prior stationnaire compte 36 + croyances distinctes (31 transitoires + 5 recurrentes, cf. p. 17 de + l'article) : le regime transitoire resout l'ambiguite de phase du + processus periodise d'ordre 3. + + Note : la version anterieure de cette classe modelisait + ``y_t = b_{t-1} XOR b_t`` sur bits iid -- un processus **iid** (les XOR + adjacents de bits iid sont independants), sans aucune structure. Le banc + ne meritait pas son nom ; cette version est conforme a la litterature. """ - n_states: int = 4 + n_states: int = 5 name: str = "rrxor" + def edge_tensor(self) -> Array: + """Tenseur W[s, s', y] = P(transiter s -> s' en emettant y) (Mealy).""" + w = np.zeros((5, 5, 2)) + w[0, 1, 0] = 0.5; w[0, 2, 1] = 0.5 # G -> A_{r1} + w[1, 3, 0] = 0.5; w[1, 4, 1] = 0.5 # A0 -> X_{0 XOR r2} + w[2, 4, 0] = 0.5; w[2, 3, 1] = 0.5 # A1 -> X_{1 XOR r2} + w[3, 0, 0] = 1.0 # X0 emet 0 -> G + w[4, 0, 1] = 1.0 # X1 emet 1 -> G + return w + def transition_matrix(self) -> Array: - """T[(a,b) -> (b,c)] = 1/2 pour c dans {0,1} : le bit frais est iid uniforme.""" - t = np.zeros((4, 4)) - for a in (0, 1): - for b in (0, 1): - for c in (0, 1): - t[2 * a + b, 2 * b + c] = 0.5 - return t + """T[s, s'] = somme des emissions de l'arete (machine agregnee).""" + return self.edge_tensor().sum(axis=2) def stationary(self) -> Array: - return np.full(4, 0.25) - - def emission_matrix(self) -> Array: - """E[i, y] = P(y_t = y | etat i) : deterministe, y = a XOR b.""" - e = np.zeros((4, 2)) - for a in (0, 1): - for b in (0, 1): - e[2 * a + b, a ^ b] = 1.0 - return e + """Distribution stationnaire : (1/3 sur G, 1/6 sur chaque autre etat).""" + out = np.full(5, 1.0 / 6.0) + out[0] = 1.0 / 3.0 + return out def sample(self, n: int, seed: int) -> Tuple[Array, Array]: - """Echantillonne n bits iid + l'observation XOR ; retourne (etats (b_{t-1}, b_t), y).""" + """Echantillonne n symboles ; retourne (etats d'arrivee par pas, observations).""" + if n < 1: + raise ProcessError("RRXOR.sample attend n >= 1") rng = np.random.default_rng(seed) - bits = rng.integers(0, 2, size=n + 1) - states = 2 * bits[:-1] + bits[1:] - obs = bits[:-1] ^ bits[1:] + states = np.empty(n, dtype=np.int64) + obs = np.empty(n, dtype=np.int64) + s = 0 # G + for k in range(n): + if s == 0: # emet r1 + y = int(rng.integers(0, 2)) + s = 1 + y # A_{r1} + elif s in (1, 2): # emet r2 + y = int(rng.integers(0, 2)) + s = 3 + ((1 if s == 2 else 0) ^ y) # X_{r1 XOR r2} + else: # X : emet le XOR memorise + y = s - 3 + s = 0 + obs[k] = y + states[k] = s return states, obs def beliefs(self, obs: Array) -> Array: - """Filtration forward exacte sur les 4 etats ; observation binaire deterministe. + """Filtration forward exacte sur les aretes (Mealy). - Le premier pas n'a pas d'observation antecedente : prior stationnaire - (l'etat (b_{-1}, b_0) n'est jamais observable via y_0 seul). + ``out[k] = P(s_k | y_0..y_k)`` ou ``s_k`` est l'etat d'arrivee du + symbole ``y_k`` ; mise a jour ``b <- normaliser(b @ W[:, :, y])`` + depuis le prior stationnaire sur l'etat emetteur initial. """ if obs.ndim != 1 or not np.all(np.isin(obs, (0, 1))): raise ProcessError("RRXOR.beliefs attend une serie binaire 1D") - t = self.transition_matrix() - e = self.emission_matrix() - prior = self.stationary() - out = np.empty((len(obs), 4)) - b = prior + w = self.edge_tensor() + b = self.stationary() + out = np.empty((len(obs), 5)) for k in range(len(obs)): - pred = b @ t if k > 0 else b - w = pred * e[:, int(obs[k])] - b = w / w.sum() + v = b @ w[:, :, int(obs[k])] + b = v / v.sum() out[k] = b return out diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/mixed_state.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/mixed_state.py index 9e5f40571b..3d500aff4e 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/mixed_state.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/mixed_state.py @@ -50,12 +50,21 @@ class MixedStatePresentation: """ nodes: Tuple[Tuple[Array, ...], ...] # nodes[depth] = tuple de Array - edges: Tuple[Tuple[Tuple[int, ...], ...], ...] # edges[depth][i] = indices des filles de nodes[depth][i] + edges: Tuple[Tuple[Tuple[int, ...], ...], ...] # edges[depth][i] = indices des filles de nodes[depth][i], dans l'ordre de l'alphabet + alphabet: Tuple[int, ...] = () # alphabet des observations, dans l'ordre utilise par le BFS @property def depth(self) -> int: return len(self.nodes) + def n_distinct_total(self) -> int: + """Cardinal de l'union des croyances distinctes sur toutes profondeurs.""" + seen = set() + for level in self.nodes: + for b in level: + seen.add(_round_belief(b)) + return len(seen) + def n_distinct(self, depth: int) -> int: if depth < 0 or depth >= self.depth: raise IndexError( @@ -99,32 +108,30 @@ def verify_invariants(self, forward_beliefs_factory) -> Tuple[bool, List[str]]: # de la trajectoire forward. if self.depth >= 2: try: - # Reconstruction du premier chemin : on suit edges[d][0][*] - obs_seq: List[int] = [] - d = 0 - current_idx = 0 - while d < self.depth - 1 and self.edges[d] and self.edges[d][current_idx]: - next_idx = self.edges[d][current_idx][0] - obs_seq.append(next_idx) - # Avancer vers la fille - d += 1 - current_idx = next_idx # la fille devient parent - obs_array = np.asarray(obs_seq, dtype=np.int64) - fb = forward_beliefs_factory(obs_array) - if fb.ndim == 2 and fb.shape[0] >= 1: - last_fb = fb[-1] - if last_fb.shape == self.nodes[self.depth - 1][0].shape: - key = _round_belief(last_fb) - keys = {_round_belief(b) for b in self.nodes[self.depth - 1]} - if key not in keys: - # Tolerance : au cas ou l'arrondi differe d'une ULP - similar = any( - np.allclose(last_fb, b, atol=1e-5) - for b in self.nodes[self.depth - 1] - ) - if not similar: + # Reconstruction d'un chemin : on suit la premiere fille + # (position 0 = premier symbole de l'alphabet) et le symbole + # correspondant -- edges[d][i] est ordonne par l'alphabet. + if self.alphabet: + obs_seq: List[int] = [] + d = 0 + current_idx = 0 + while d < self.depth - 1 and self.edges[d] and self.edges[d][current_idx]: + next_idx = self.edges[d][current_idx][0] + if next_idx < 0: + break # arete impossible depuis cette croyance + obs_seq.append(int(self.alphabet[0])) + d += 1 + current_idx = next_idx + obs_array = np.asarray(obs_seq, dtype=np.int64) + fb = forward_beliefs_factory(obs_array) + if fb.ndim == 2 and fb.shape[0] == len(obs_seq) and len(obs_seq) >= 1: + last_fb = fb[-1] + target = self.nodes[len(obs_seq)][current_idx] + if last_fb.shape == target.shape: + if not np.allclose(last_fb, target, atol=1e-7): failures.append( - f"forward last belief at depth {self.depth-1} absent de la MSP" + f"forward belief at depth {len(obs_seq)} " + f"diverge du node du chemin reconstruit" ) except Exception as exc: failures.append(f"forward factory leve {type(exc).__name__}: {exc}") @@ -144,31 +151,61 @@ def build_msp( max_depth: int, obs_alphabet: Iterable[int], prior: Array, - transition: Array, - emission: Array, + transition: Array = None, + emission: Array = None, + edge_tensor: Array = None, ) -> MixedStatePresentation: """Construit la MSP par BFS sur l'arbre des sequences d'observations. + Deux conventions d'emission, mutuellement exclusives : + + - **Moore** (``transition`` + ``emission``) : l'etat emet, puis transite. + Mise a jour : ``b' = normaliser((b @ T) * E[:, y])``. Convient a + :class:`Mess3Canonical`. + - **Mealy** (``edge_tensor`` seul) : les emissions vivent sur les aretes, + ``W[s, s', y] = P(s' et y | s)``. Mise a jour : + ``b' = normaliser(b @ W[:, :, y])``. Convient a :class:`RRXOR` + (Riechers & Crutchfield 2018, arXiv:1706.00883v1 : l'epsilon-machine + du RRXOR est Mealy -- l'emission revele l'arete, pas l'etat). + Parametres : - - ``generator`` : instance conforme (Mess3Canonical, RRXOR, ...) - utilisee seulement pour les metadonnees (profondeur max fixee par - l'usage, pas par le generateur). + - ``generator`` : instance conforme (Mess3Canonical, RRXOR, ...). - ``max_depth`` : profondeur maximale de l'arbre. - - ``obs_alphabet`` : iterable des valeurs d'observation possibles - (par exemple ``range(n_states)`` pour Mess3 ou ``(0, 1)`` pour RRXOR). + - ``obs_alphabet`` : iterable des valeurs d'observation possibles. - ``prior`` : distribution a priori sur les etats caches (np.ndarray). - - ``transition`` : matrice de transition T (np.ndarray). - - ``emission`` : matrice d'emission E (np.ndarray, shape ``(n_states, n_obs)``). + - ``transition``/``emission`` : convention Moore. + - ``edge_tensor`` : convention Mealy (priorise sur Moore si fourni). - Retourne : :class:`MixedStatePresentation`. + Retourne : :class:`MixedStatePresentation` (avec ``alphabet`` stocke pour + permettre la reconstruction de chemins dans ``verify_invariants``). """ if max_depth < 1: raise ProcessError("max_depth doit etre >= 1") + if edge_tensor is None and (transition is None or emission is None): + raise ProcessError( + "build_msp exige soit edge_tensor (Mealy), soit transition + emission (Moore)" + ) obs_alphabet = tuple(obs_alphabet) - n_states = prior.shape[0] nodes: List[List[Array]] = [] edges: List[List[Tuple[int, ...]]] = [] + def _child(parent_b: Array, o: int): + """Croyance fille apres l'observation ``o``, ou ``None`` si impossible. + + Une croyance Dirac sur un etat a emission deterministe (cas Mealy : + les X du RRXOR) peut rendre un symbole de probabilite nulle ; + l'arete correspondante n'existe pas dans la MSP. + """ + if edge_tensor is not None: + w = parent_b @ edge_tensor[:, :, int(o)] + else: + pred = parent_b @ transition + w = pred * emission[:, int(o)] + z = w.sum() + if z <= 0.0: + return None + return w / z + # Niveau 0 : prior unique (avant toute observation) nodes.append([prior.copy()]) # edges[0] sera peuple quand on developpe la profondeur 0 vers 1. @@ -183,14 +220,10 @@ def build_msp( for parent_b in nodes[d]: child_indices: List[int] = [] for o in obs_alphabet: - pred = parent_b @ transition - w = pred * emission[:, int(o)] - z = w.sum() - if z <= 0.0: - raise ProcessError( - f"vraisemblance nulle a depth {d}, obs {o}" - ) - child_b = w / z + child_b = _child(parent_b, o) + if child_b is None: + child_indices.append(-1) # arete impossible + continue key = _round_belief(child_b) if key in next_seen: child_idx = next_seen[key] @@ -199,6 +232,11 @@ def build_msp( next_nodes.append(child_b) child_idx = next_seen[key] child_indices.append(child_idx) + if all(ci < 0 for ci in child_indices): + raise ProcessError( + f"generateur degenerate : croyance sans aucune observation " + f"possible a depth {d} (toutes les emissions sont nulles)" + ) current_edges.append(tuple(child_indices)) # Pas de nouvelle node : on s'arrete if not next_nodes: @@ -211,6 +249,7 @@ def build_msp( return MixedStatePresentation( nodes=tuple(tuple(arr for arr in lvl) for lvl in nodes), edges=tuple(tuple(e for e in lvl) for lvl in edges), + alphabet=obs_alphabet, ) @@ -233,24 +272,21 @@ def msp_mess3(max_depth: int = 6) -> MixedStatePresentation: ) -def msp_rrxor(max_depth: int = 6) -> MixedStatePresentation: - """MSP du RRXOR : alphabet binaire, 4 etats caches. +def msp_rrxor(max_depth: int = 8) -> MixedStatePresentation: + """MSP du RRXOR (Riechers & Crutchfield 2018) : alphabet binaire, 5 etats causaux Mealy. - Note : avec prior stationnaire uniforme, la MSP au pas 0 contient 1 - croyance ; au pas 1 (apres 1 observation), elle contient 2 croyances - distinctes (deux valeurs possibles de y determinent le sous-ensemble - d'etats coherents) ; au pas k, le cardinal de la MSP suit la - dynamique de l'arbre binaire. + Depuis le prior stationnaire, l'union des croyances distinctes vaut + **36** : 31 transitoires + 5 recurrentes (les Diracs sur les etats + causaux, atteints en profondeur <= 7). C'est la valeur de la + litterature (arXiv:1706.00883v1, p. 17, Fig. 7) : le regime + transitoire resout l'ambiguite de phase de la modulation periodique + d'ordre 3 -- c'est précisément ce que le notebook ICT-37 montre. """ r = RRXOR() - prior = r.stationary() - T = r.transition_matrix() - E = r.emission_matrix() return build_msp( generator=r, max_depth=max_depth, obs_alphabet=(0, 1), - prior=prior, - transition=T, - emission=E, + prior=r.stationary(), + edge_tensor=r.edge_tensor(), ) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_bench_factorise.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_bench_factorise.py index f87e6cb903..cfb83e6258 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_bench_factorise.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_bench_factorise.py @@ -20,6 +20,8 @@ from ict.bench_factorise import ( FactoredBench, Mess3, + Mess3Canonical, + Mess3_ObsCoupled, ProcessError, RRXOR, belief_simplex_coords, @@ -58,26 +60,39 @@ def test_mess3_sample_reproductible_et_formes(): def test_mess3_parametrage_invalide_rejete(): + # Mess3 = Mess3Canonical (alias #16225) : validation de stay/emission_diag with pytest.raises(ProcessError): Mess3(stay=1.5) with pytest.raises(ProcessError): - Mess3(std=0.0) + Mess3(emission_diag=0.2) # <= 1/n : ne domine plus, casse le regime + # Le banc gaussien historique garde sa propre validation (signaux continus) with pytest.raises(ProcessError): - Mess3(means=(0.0, 1.0)) + Mess3_ObsCoupled(std=0.0) + with pytest.raises(ProcessError): + Mess3_ObsCoupled(means=(0.0, 1.0)) -def _mess3_bruteforce_beliefs(m: Mess3, obs: np.ndarray) -> np.ndarray: +def _mess3_bruteforce_beliefs(m, obs: np.ndarray) -> np.ndarray: """Enumeration exacte (independante du forward) : pour chaque sequence complete d'etats, poids joint = prior * prod(transitions) * prod(likelihoods), puis marginalisation en P(s_k | o_{0..n-1}) — beliefs lisses, a comparer - au forward apres troncature des observations au meme prefixe.""" + au forward apres troncature des observations au meme prefixe. + + Generique : chemin discret via ``emission_matrix`` (Mess3Canonical), + chemin gaussien via ``means``/``std`` (Mess3_ObsCoupled).""" n = len(obs) - means = np.asarray(m.means) prior = m.stationary() t = m.transition_matrix() + if hasattr(m, "emission_matrix") and not hasattr(m, "means"): + e = m.emission_matrix() - def lik(o: float, s: int) -> float: - return math.exp(-0.5 * ((o - means[s]) / m.std) ** 2) + def lik(o, s: int) -> float: + return float(e[s, int(o)]) + else: + means = np.asarray(m.means) + + def lik(o, s: int) -> float: + return math.exp(-0.5 * ((o - means[s]) / m.std) ** 2) weights = np.zeros(m.n_states) for seq in itertools.product(range(m.n_states), repeat=n): @@ -89,7 +104,7 @@ def lik(o: float, s: int) -> float: def test_mess3_beliefs_vs_enumeration_brute(): - m = Mess3(means=(-0.15, 0.0, 0.15), std=0.05, stay=0.9) + m = Mess3(stay=0.9) _, obs = m.sample(8, seed=42) fast_last = m.beliefs(obs)[-1] brute_last = _mess3_bruteforce_beliefs(m, obs) @@ -102,12 +117,32 @@ def test_mess3_beliefs_vs_enumeration_brute(): ) -def test_mess3_beliefs_somment_a_un_et_modes_lisibles(): +def test_mess3_obscoupled_beliefs_vs_enumeration_brute(): + """Le banc gaussien historique garde sa contre-verification bruteforce.""" + m = Mess3_ObsCoupled(means=(-0.15, 0.0, 0.15), std=0.05, stay=0.9) + _, obs = m.sample(8, seed=42) + assert np.allclose(m.beliefs(obs)[-1], _mess3_bruteforce_beliefs(m, obs), atol=1e-10) + + +def test_mess3_beliefs_somment_a_un_et_non_dirac(): + """Sur le banc canonique (#16225), le belief vit dans le simplexe SANS + s'effondrer en Dirac : c'est la propriete que l'ancien banc obs = etat + detruisait (accuracy tautologique 1.000).""" m = Mess3() states, obs = m.sample(500, seed=3) b = m.beliefs(obs) assert np.allclose(b.sum(axis=1), 1.0, atol=1e-12) - # modes bien separees : argmax du belief = etat emis la plupart du temps + max_probs = b.max(axis=1) + # non-Dirac : jamais certain a 100%, mais informes : au-dessus du hasard 1/3 + assert max_probs.max() < 0.999, "le belief canonique ne doit pas etre un Dirac" + assert max_probs.mean() > 1.0 / 3.0, "le belief canonique doit rester informatif" + + +def test_mess3_obscoupled_modes_lisibles(): + """Le banc gaussien historique conserve ses modes bien separees (comparateur).""" + m = Mess3_ObsCoupled() + states, obs = m.sample(500, seed=3) + b = m.beliefs(obs) acc = (b.argmax(axis=1) == states).mean() assert acc > 0.95, f"modes mal separees, accuracy={acc}" @@ -118,40 +153,70 @@ def test_mess3_beliefs_rejette_2d(): # --------------------------------------------------------------------------- -# RRXOR : invariants, beliefs +# RRXOR : conformite litterature (Riechers & Crutchfield 2018, 1706.00883) # --------------------------------------------------------------------------- -def test_rrxor_invariant_xor_et_etats(): +def test_rrxor_triplets_xor_alignes(): + """Le processus repete (r1, r2, r1 XOR r2) : le 3e symbole de chaque + triplet est le XOR des deux precedents -- sur toute trajectoire.""" + r = RRXOR() + states, obs = r.sample(300, seed=11) + k = (len(obs) // 3) * 3 + assert np.array_equal(obs[2:k:3], obs[0:k:3] ^ obs[1:k:3]) + assert set(np.unique(states)) <= {0, 1, 2, 3, 4} + + +def test_rrxor_correlations_par_paires_nulles(): + """Propriete litterature : correlations par paires nulles (spectre plat) + -- toute la structure vit dans la contrainte de triplet.""" r = RRXOR() - states, obs = r.sample(200, seed=11) - # y_t = a XOR b avec etat = 2a + b - a, b = states // 2, states % 2 - assert np.array_equal(a ^ b, obs) - assert set(np.unique(states)) <= {0, 1, 2, 3} + _, obs = r.sample(60000, seed=42) + p1 = obs[1:] + p0 = obs[:-1] + corr = np.corrcoef(p0.astype(float), p1.astype(float))[0, 1] + assert abs(corr) < 0.02 + # ... mais le triplet, lui, est deterministe : structure masquee + k = (len(obs) // 3) * 3 + assert np.array_equal(obs[2:k:3], obs[0:k:3] ^ obs[1:k:3]) def test_rrxor_transition_stationnaire(): r = RRXOR() t = r.transition_matrix() assert np.allclose(t.sum(axis=1), 1.0) - assert np.allclose(t @ r.stationary(), r.stationary()) - # chaque etat a exactement 2 successeurs equiprobables - assert np.all((t > 0).sum(axis=1) == 2) - assert np.allclose(t[t > 0], 0.5) + assert np.allclose(r.stationary() @ t, r.stationary()) + # G et A ont 2 successeurs equiprobables ; X est deterministe vers G + for s in (0, 1, 2): + assert (t[s] > 0).sum() == 2 + np.testing.assert_allclose(t[s][t[s] > 0], 0.5, atol=1e-12) + np.testing.assert_allclose(t[3, 0], 1.0, atol=1e-12) + np.testing.assert_allclose(t[4, 0], 1.0, atol=1e-12) + + +def test_rrxor_beliefs_filtration_aretes(): + """La filtration forward Mealy : b' = normaliser(b @ W[:, :, y]). + Controle sur sequence (0, 0) : la croyance doit coder l'alignement de + phase -- prediction suivante P(y=0) = 2/3, pas 1/2.""" + r = RRXOR() + b = r.beliefs(np.array([0, 0])) + assert np.allclose(b.sum(axis=1), 1.0, atol=1e-12) + W = r.edge_tensor() + p0 = float((b[-1] @ W[:, :, 0]).sum()) + assert p0 == pytest.approx(2.0 / 3.0, abs=1e-10) + # les etats incompatibles avec le chemin sont exclus + assert b[-1][2] == pytest.approx(0.0, abs=1e-12) # A1 exclu par r1 = 0 -def test_rrxor_beliefs_sur_2_etats_coherents(): +def test_rrxor_beliefs_synchronise_vers_dirac(): + """Depuis le prior stationnaire, un long prefix suffit a synchroniser : + la croyance converge vers un Dirac sur un etat causal (5 etats + recurrents de la S-MSP, cf. litterature p. 17).""" r = RRXOR() - states, obs = r.sample(100, seed=5) + _, obs = r.sample(300, seed=7) b = r.beliefs(obs) - assert np.allclose(b.sum(axis=1), 1.0, atol=1e-12) - e = r.emission_matrix() - for k in range(len(obs)): - coherent = e[:, int(obs[k])] > 0 - assert coherent.sum() == 2 - assert b[k, coherent] == pytest.approx(0.5) - assert b[k, ~coherent] == pytest.approx(0.0, abs=1e-15) + entropie_finale = float(-(b[-1] * np.log(np.clip(b[-1], 1e-12, 1))).sum()) + assert entropie_finale < 1e-6 def test_rrxor_beliefs_rejette_non_binaire(): @@ -170,7 +235,7 @@ def test_bench_observation_jointe_et_beliefs_produit(): assert run["obs_joint"].shape == (30, 2) assert np.array_equal(run["obs_joint"][:, 0], run["obs_a"]) bel = bench.beliefs(run["obs_a"], run["obs_b"]) - na, nb = 3, 4 + na, nb = 3, 5 assert bel["belief_joint"].shape == (30, na * nb) recompose = bel["belief_joint"].reshape(30, na, nb) assert np.allclose(recompose, bel["belief_a"][:, :, None] * bel["belief_b"][:, None, :]) @@ -179,7 +244,7 @@ def test_bench_observation_jointe_et_beliefs_produit(): def test_bench_deux_mess3_independants(): """L'option « deux Mess3 independants » de l'issue : meme architecture, facteurs homogenes.""" - bench = FactoredBench(Mess3(means=(-0.15, 0.0, 0.15)), Mess3(means=(1.0, 1.2, 1.4), name="mess3_b")) + bench = FactoredBench(Mess3_ObsCoupled(means=(-0.15, 0.0, 0.15)), Mess3_ObsCoupled(means=(1.0, 1.2, 1.4), name="mess3_b")) run = bench.sample(20, seed_a=0, seed_b=9) bel = bench.beliefs(run["obs_a"], run["obs_b"]) assert bel["belief_joint"].shape == (20, 9) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mess3_canonical.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mess3_canonical.py index ba91499373..7646d934b7 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mess3_canonical.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mess3_canonical.py @@ -138,29 +138,50 @@ def test_mess3_alias_is_obs_coupled(self): legacy (obs couplee a l'etat). C'est un alias de compatibilite ; le banc NON-Dirac est :class:`Mess3Canonical` (DEPRECIE pour la geometrie de croyance).""" - assert Mess3 is Mess3_ObsCoupled + assert Mess3 is Mess3Canonical class TestRRXOR: - def test_emission_matrix_is_deterministic(self): - """RRXOR : y = b_{t-1} XOR b_t est deterministe. - La matrice d'emission E[i, y] = 1.0 si y = a XOR b (etat i = 2a+b).""" + """RRXOR conforme a la litterature (Riechers & Crutchfield 2018, + arXiv:1706.00883v1, Fig. 4) : machine Mealy a 5 etats causaux, + emissions sur les aretes, triplets (r1, r2, r1 XOR r2).""" + + def test_edge_tensor_rows_stochastic(self): + """Chaque etat emet exactement une loi sur (fille, symbole).""" + r = RRXOR() + W = r.edge_tensor() + assert W.shape == (5, 5, 2) + np.testing.assert_allclose(W.sum(axis=(1, 2)), np.ones(5), atol=1e-12) + + def test_edge_tensor_xor_edges_deterministic(self): + """Les aretes X -> G portent le XOR memorise, de facon deterministe.""" r = RRXOR() - E = r.emission_matrix() - assert E.shape == (4, 2) - # etat 00 -> y=0 ; etat 01 -> y=1 ; etat 10 -> y=1 ; etat 11 -> y=0 - np.testing.assert_allclose(E[0], [1.0, 0.0], atol=1e-10) - np.testing.assert_allclose(E[1], [0.0, 1.0], atol=1e-10) - np.testing.assert_allclose(E[2], [0.0, 1.0], atol=1e-10) - np.testing.assert_allclose(E[3], [1.0, 0.0], atol=1e-10) - - def test_stationary_is_uniform(self): + W = r.edge_tensor() + # X0 -> G emet 0 ; X1 -> G emet 1 (probabilite 1) + np.testing.assert_allclose(W[3, 0, 0], 1.0, atol=1e-12) + np.testing.assert_allclose(W[4, 0, 1], 1.0, atol=1e-12) + np.testing.assert_allclose(W[3, :, :].sum(), 1.0, atol=1e-12) + np.testing.assert_allclose(W[4, :, :].sum(), 1.0, atol=1e-12) + + def test_stationary_third_on_reset(self): + """Stationnaire : 1/3 sur G (phase de reset), 1/6 sur chaque autre.""" r = RRXOR() s = r.stationary() - np.testing.assert_allclose(s, np.full(4, 0.25), atol=1e-10) + np.testing.assert_allclose(s, np.array([1/3, 1/6, 1/6, 1/6, 1/6]), atol=1e-12) + np.testing.assert_allclose(s @ r.transition_matrix(), s, atol=1e-12) def test_beliefs_sum_to_one(self): r = RRXOR() obs = np.array([0, 1, 0, 1, 1]) b = r.beliefs(obs) np.testing.assert_allclose(b.sum(axis=1), np.ones(5), atol=1e-8) + + def test_beliefs_two_zeros_then_prediction(self): + """Controle litterature : P(y3 = 0 | (0, 0)) = 2/3 -- le filtre + Mealy doit reproduire l'enumeration directe (l'ancien banc iid + donnait 1/2).""" + r = RRXOR() + b = r.beliefs(np.array([0, 0])) + W = r.edge_tensor() + p0 = float((b[-1] @ W[:, :, 0]).sum()) + assert p0 == pytest.approx(2.0 / 3.0, abs=1e-10) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mixed_state.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mixed_state.py index e09b480f30..87e927696e 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mixed_state.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_mixed_state.py @@ -6,8 +6,10 @@ Ces tests verifient que : - la MSP du banc :class:`Mess3Canonical` (non-Dirac) croit en 3^k croyances distinctes jusqu'a profondeur k=3 (1, 3, 9, 27), -- la MSP du banc :class:`RRXOR` plafonne a 2 croyances (alphabet binaire, - observation deterministe y = a XOR b), +- la MSP du banc :class:`RRXOR` conforme (Riechers & Crutchfield 2018, + arXiv:1706.00883v1) compte **36** croyances distinctes en union : + 31 transitoires + 5 recurrentes (les Diracs causaux) -- la valeur + exacte de la litterature (p. 17, Fig. 7), - les invariants canoniques (somme=1 par ligne, entropie non-croissante par profondeur, concordance avec la filtration forward) tiennent. """ @@ -46,14 +48,60 @@ def test_growth_is_3_to_the_k(self): class TestMSPRRXOR: - """RRXOR : alphabet binaire (y = XOR de 2 bits) -> 2 croyances - distinctes apres la premiere observation. La MSP ne croît pas avec k.""" - - def test_two_beliefs_per_depth_after_first(self): - msp = msp_rrxor(max_depth=5) - assert msp.n_distinct(0) == 1 - for d in range(1, 5): - assert msp.n_distinct(d) == 2, f"depth {d} != 2" + """RRXOR conforme (Riechers & Crutchfield 2018) : S-MSP de 36 croyances. + + L'union des croyances distinctes depuis le prior stationnaire vaut 36 : + 31 transitoires (resolution de l'ambiguite de phase de la modulation + periodique d'ordre 3) + 5 recurrentes (les Diracs sur les etats causaux). + Valeur de litterature : arXiv:1706.00883v1, p. 17, Fig. 7.""" + + def test_union_is_36_literature_value(self): + """Le critere d'acceptation de l'issue #16225 : 36 croyances.""" + msp = msp_rrxor() + assert msp.n_distinct_total() == 36 + + def test_five_recurrent_diracs_reached(self): + """Les 5 Diracs causaux sont des croyances de la MSP (recurrentes).""" + msp = msp_rrxor() + keys = {_round_belief(b) for level in msp.nodes for b in level} + for i in range(5): + e = np.zeros(5) + e[i] = 1.0 + assert _round_belief(e) in keys, f"Dirac {i} absent de la MSP" + + def test_growth_then_closure(self): + """Croissance 1, 2, 4, 8, 12 par profondeur puis fermeture : plus + aucune croyance nouvelle apres profondeur 7 (regime synchronise).""" + msp = msp_rrxor(max_depth=10) + per_level = [msp.n_distinct(d) for d in range(msp.depth)] + assert per_level[:5] == [1, 2, 4, 8, 12] + # fermeture : le cardinal par niveau se stabilise + assert per_level[7] == per_level[8] == per_level[9] + assert msp.n_distinct_total() == 36 + + def test_distinct_beliefs_same_next_token(self): + """Dissociation de la litterature : des croyances DISTINCTES partagent + la meme distribution next-token (arXiv:2405.15943 §3.2 -- c'est ce qui + fonde la separation belief/next-token que ICT-37 mesure).""" + r = RRXOR() + msp = msp_rrxor() + Wsum = r.edge_tensor().sum(axis=1) # Wsum[s, y] = P(y | etat s) + + def next_token_dist(b): + return tuple(np.round(b @ Wsum, 8)) + + groups = {} + for level in msp.nodes: + for b in level: + groups.setdefault(next_token_dist(b), []).append(_round_belief(b)) + # 36 croyances pour moins de 36 predictions : la carte belief -> + # next-token est non injective + assert len(groups) < msp.n_distinct_total() + # cas explicite : prior stationnaire et les deux croyances de + # profondeur 1 (apres obs 0 et apres obs 1) -- trois croyances + # distinctes, meme prediction (1/2, 1/2) + uniform = groups.get((0.5, 0.5), []) + assert len({tuple(b) for b in uniform}) >= 3 class TestMSPInvariants: From 5283902a8595395289c38c1b7e9b0a4177623823 Mon Sep 17 00:00:00 2001 From: jsboige Date: Fri, 18 Sep 2026 14:53:39 +0200 Subject: [PATCH 2/4] fix(iit,#16225): integration batterie + ICT-40 -- generateurs legacy explicites Le rebase sur main expose deux consommateurs calibres sur les generateurs legacy (arrives via #16230) : test_intervention_battery (bras SAE selectivite 2/16 seeds avec le RRXOR conforme -- le dictionary se melange au flux binaire desormais structure) et ICT-40 (Mess3().means/.std n'existe pas sur le canonique). Correctif miroir du traitement Mess3_ObsCoupled : - bench_factorise : ancien banc reintegre sous RRXOR_Iid (DEPRECIE, conserve pour reproductibilite batterie #15480/#16230 et ICT-40) - test_intervention_battery : epingle a FactoredBench(Mess3_ObsCoupled(), RRXOR_Iid()) = banc de calibration verbatim, 12/12 verts, aucun seuil recalcule - ICT-40 : cellules 2/4 epinglees aux memes noms + note provenance cellule 3, re-execute integralement (16/16 cellules, 0 erreur ; verdicts et p-values identiques aux outputs committes -- vloss par seed egaux a 3 decimales ; seule derive : wall-times et floats a la 3e-18e decimale, torch 2.13.0->2.14.0) Artefact mesure et consigne (grain separe, porteur batterie) : la selectivite SAE SUPPORTED de la batterie sur banc legacy depend du facteur B structureless. Suite ICT complete : 929 passed. Co-Authored-By: Claude Sonnet 5 --- .../ICT-40a-TriangulationCausale.ipynb | 467 ++++++++++++------ .../IIT/ICT-Series/ict/bench_factorise.py | 60 +++ .../ict/tests/test_intervention_battery.py | 11 +- 3 files changed, 381 insertions(+), 157 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb index b6fef24fcd..cd3960466b 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb @@ -4,6 +4,13 @@ "cell_type": "markdown", "id": "8d4c2888de87", "metadata": { + "papermill": { + "duration": 0.00308, + "end_time": "2026-09-18T12:47:02.125242+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:02.122162+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -64,10 +71,17 @@ "id": "947d75acd4f2", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T11:59:43.883140Z", - "iopub.status.busy": "2026-09-15T11:59:43.882879Z", - "iopub.status.idle": "2026-09-15T11:59:43.892753Z", - "shell.execute_reply": "2026-09-15T11:59:43.891701Z" + "iopub.execute_input": "2026-09-18T12:47:02.133320Z", + "iopub.status.busy": "2026-09-18T12:47:02.133057Z", + "iopub.status.idle": "2026-09-18T12:47:02.140583Z", + "shell.execute_reply": "2026-09-18T12:47:02.139863Z" + }, + "papermill": { + "duration": 0.011597, + "end_time": "2026-09-18T12:47:02.141161+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:02.129564+00:00", + "status": "completed" }, "tags": [] }, @@ -120,10 +134,17 @@ "id": "ea85e07e2c80", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T11:59:43.909701Z", - "iopub.status.busy": "2026-09-15T11:59:43.909339Z", - "iopub.status.idle": "2026-09-15T11:59:46.858265Z", - "shell.execute_reply": "2026-09-15T11:59:46.857361Z" + "iopub.execute_input": "2026-09-18T12:47:02.147357Z", + "iopub.status.busy": "2026-09-18T12:47:02.147107Z", + "iopub.status.idle": "2026-09-18T12:47:09.668073Z", + "shell.execute_reply": "2026-09-18T12:47:09.667419Z" + }, + "papermill": { + "duration": 7.524784, + "end_time": "2026-09-18T12:47:09.668673+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:02.143889+00:00", + "status": "completed" }, "tags": [] }, @@ -132,7 +153,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "device : cuda | torch 2.13.0+cu126 | numpy 2.4.6\n" + "device : cuda | torch 2.14.0+cu126 | numpy 2.4.2\n" ] } ], @@ -152,7 +173,7 @@ "\n", "import torch\n", "\n", - "from ict.bench_factorise import FactoredBench, Mess3, RRXOR\n", + "from ict.bench_factorise import FactoredBench, Mess3_ObsCoupled, RRXOR_Iid\n", "from ict.sae_dictionary import train_sae, factor_selectivity\n", "from ict.causal_engine import (InterventionSpec, apply_intervention,\n", " interchange_panels, random_target_matched,\n", @@ -174,12 +195,19 @@ "cell_type": "markdown", "id": "74f64c9218d8", "metadata": { + "papermill": { + "duration": 0.002602, + "end_time": "2026-09-18T12:47:09.674204+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:09.671602+00:00", + "status": "completed" + }, "tags": [] }, "source": [ "## 1. Banc factorise et tokenisation\n", "\n", - "`FactoredBench(Mess3, RRXOR)` (#15478) : le facteur A est un Mess3 (3 etats\n", + "`FactoredBench(Mess3_ObsCoupled, RRXOR_Iid)` (#15478 ; generateurs legacy epingles par #16225, qui fait de `Mess3` le canonique non-fuitif et reecrit `RRXOR` en Mealy conforme) : le facteur A est un Mess3 (3 etats\n", "caches, emissions gaussiennes de moyennes -0.15/0/0.15), le facteur B un\n", "RRXOR (4 etats caches = paires de bits consecutifs, observation = XOR brut).\n", "Les deux tournent en parallele, independants : `sample` fournit les\n", @@ -197,10 +225,17 @@ "id": "d1f92ee61d71", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T11:59:46.874741Z", - "iopub.status.busy": "2026-09-15T11:59:46.874317Z", - "iopub.status.idle": "2026-09-15T11:59:48.039904Z", - "shell.execute_reply": "2026-09-15T11:59:48.038878Z" + "iopub.execute_input": "2026-09-18T12:47:09.681880Z", + "iopub.status.busy": "2026-09-18T12:47:09.681535Z", + "iopub.status.idle": "2026-09-18T12:47:10.207544Z", + "shell.execute_reply": "2026-09-18T12:47:10.206737Z" + }, + "papermill": { + "duration": 0.531617, + "end_time": "2026-09-18T12:47:10.208352+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:09.676735+00:00", + "status": "completed" }, "tags": [] }, @@ -217,8 +252,8 @@ } ], "source": [ - "bench = FactoredBench(factor_a=Mess3(), factor_b=RRXOR())\n", - "GRID = TokenizerConfig().grid(Mess3().means, Mess3().std)\n", + "bench = FactoredBench(factor_a=Mess3_ObsCoupled(), factor_b=RRXOR_Iid())\n", + "GRID = TokenizerConfig().grid(Mess3_ObsCoupled().means, Mess3_ObsCoupled().std)\n", "VOCAB = 2 * TokenizerConfig().n_bins\n", "\n", "demo = bench.sample(20_000, seed_a=0, seed_b=9000)\n", @@ -238,6 +273,13 @@ "cell_type": "markdown", "id": "d671ef552c91", "metadata": { + "papermill": { + "duration": 0.002867, + "end_time": "2026-09-18T12:47:10.214530+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:10.211663+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -263,10 +305,17 @@ "id": "926bb9a5fbf0", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T11:59:48.054428Z", - "iopub.status.busy": "2026-09-15T11:59:48.054173Z", - "iopub.status.idle": "2026-09-15T13:15:47.440286Z", - "shell.execute_reply": "2026-09-15T13:15:47.439168Z" + "iopub.execute_input": "2026-09-18T12:47:10.221240Z", + "iopub.status.busy": "2026-09-18T12:47:10.220870Z", + "iopub.status.idle": "2026-09-18T12:50:08.644963Z", + "shell.execute_reply": "2026-09-18T12:50:08.643830Z" + }, + "papermill": { + "duration": 178.428653, + "end_time": "2026-09-18T12:50:08.645889+00:00", + "exception": false, + "start_time": "2026-09-18T12:47:10.217236+00:00", + "status": "completed" }, "tags": [] }, @@ -275,43 +324,43 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : 2285s | vloss 1.843 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 0 : 31s | vloss 1.843 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 1 : 2075s | vloss 1.682 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 1 : 29s | vloss 1.682 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 2 : 45s | vloss 1.984 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 2 : 30s | vloss 1.984 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 3 : 61s | vloss 1.931 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 3 : 30s | vloss 1.931 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 4 : 49s | vloss 1.873 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 4 : 30s | vloss 1.873 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 5 : 45s | vloss 1.808 | fenetres 2497 (tr 1744, ev 750)\n", - "Entrainement et capture termines en 4559s.\n" + "seed 5 : 29s | vloss 1.808 | fenetres 2497 (tr 1744, ev 750)\n", + "Entrainement et capture termines en 178s.\n" ] } ], @@ -355,6 +404,13 @@ "cell_type": "markdown", "id": "dc9cb724a8ff", "metadata": { + "papermill": { + "duration": 0.00372, + "end_time": "2026-09-18T12:50:08.653632+00:00", + "exception": false, + "start_time": "2026-09-18T12:50:08.649912+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -377,10 +433,17 @@ "id": "a7e9744deb36", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:15:47.457315Z", - "iopub.status.busy": "2026-09-15T13:15:47.456843Z", - "iopub.status.idle": "2026-09-15T13:15:53.246507Z", - "shell.execute_reply": "2026-09-15T13:15:53.244349Z" + "iopub.execute_input": "2026-09-18T12:50:08.662295Z", + "iopub.status.busy": "2026-09-18T12:50:08.661885Z", + "iopub.status.idle": "2026-09-18T12:50:14.050415Z", + "shell.execute_reply": "2026-09-18T12:50:14.049471Z" + }, + "papermill": { + "duration": 5.394131, + "end_time": "2026-09-18T12:50:14.051390+00:00", + "exception": false, + "start_time": "2026-09-18T12:50:08.657259+00:00", + "status": "completed" }, "tags": [] }, @@ -464,6 +527,13 @@ "cell_type": "markdown", "id": "846613118325", "metadata": { + "papermill": { + "duration": 0.003382, + "end_time": "2026-09-18T12:50:14.058712+00:00", + "exception": false, + "start_time": "2026-09-18T12:50:14.055330+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -485,10 +555,17 @@ "id": "ff7f136b7a97", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:15:53.284731Z", - "iopub.status.busy": "2026-09-15T13:15:53.284190Z", - "iopub.status.idle": "2026-09-15T13:18:35.658381Z", - "shell.execute_reply": "2026-09-15T13:18:35.656797Z" + "iopub.execute_input": "2026-09-18T12:50:14.067182Z", + "iopub.status.busy": "2026-09-18T12:50:14.066864Z", + "iopub.status.idle": "2026-09-18T12:51:46.094285Z", + "shell.execute_reply": "2026-09-18T12:51:46.093385Z" + }, + "papermill": { + "duration": 92.033074, + "end_time": "2026-09-18T12:51:46.095158+00:00", + "exception": false, + "start_time": "2026-09-18T12:50:14.062084+00:00", + "status": "completed" }, "tags": [] }, @@ -497,7 +574,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : fvu 0.047 | l0 8.0 | feature A #17 AUC_A 0.995 AUC_B 0.502 (z_A 109.2)\n" + "seed 0 : fvu 0.047 | l0 8.0 | feature A #17 AUC_A 0.995 AUC_B 0.502 (z_A 109.3)\n" ] }, { @@ -532,7 +609,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 5 : fvu 0.059 | l0 8.0 | feature A #24 AUC_A 0.972 AUC_B 0.509 (z_A 106.2)\n" + "seed 5 : fvu 0.059 | l0 8.0 | feature A #24 AUC_A 0.972 AUC_B 0.509 (z_A 106.4)\n" ] } ], @@ -586,6 +663,13 @@ "cell_type": "markdown", "id": "c679470027c8", "metadata": { + "papermill": { + "duration": 0.00514, + "end_time": "2026-09-18T12:51:46.105883+00:00", + "exception": false, + "start_time": "2026-09-18T12:51:46.100743+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -609,10 +693,17 @@ "id": "a65fec91f4b0", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:18:35.687968Z", - "iopub.status.busy": "2026-09-15T13:18:35.687601Z", - "iopub.status.idle": "2026-09-15T13:18:35.701316Z", - "shell.execute_reply": "2026-09-15T13:18:35.699832Z" + "iopub.execute_input": "2026-09-18T12:51:46.117634Z", + "iopub.status.busy": "2026-09-18T12:51:46.117389Z", + "iopub.status.idle": "2026-09-18T12:51:46.125993Z", + "shell.execute_reply": "2026-09-18T12:51:46.125267Z" + }, + "papermill": { + "duration": 0.01606, + "end_time": "2026-09-18T12:51:46.127033+00:00", + "exception": false, + "start_time": "2026-09-18T12:51:46.110973+00:00", + "status": "completed" }, "tags": [] }, @@ -704,10 +795,17 @@ "id": "969977118f34", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:18:35.718320Z", - "iopub.status.busy": "2026-09-15T13:18:35.717753Z", - "iopub.status.idle": "2026-09-15T13:18:35.926783Z", - "shell.execute_reply": "2026-09-15T13:18:35.925461Z" + "iopub.execute_input": "2026-09-18T12:51:46.136044Z", + "iopub.status.busy": "2026-09-18T12:51:46.135707Z", + "iopub.status.idle": "2026-09-18T12:51:46.216410Z", + "shell.execute_reply": "2026-09-18T12:51:46.215501Z" + }, + "papermill": { + "duration": 0.086399, + "end_time": "2026-09-18T12:51:46.217345+00:00", + "exception": false, + "start_time": "2026-09-18T12:51:46.130946+00:00", + "status": "completed" }, "tags": [] }, @@ -716,26 +814,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : overlap reel 0.573 | null q95 0.360 | ecart -0.213 | angle principal 83.4 deg | NON separe\n", + "seed 0 : overlap reel 0.572 | null q95 0.360 | ecart -0.212 | angle principal 83.3 deg | NON separe\n", "seed 1 : overlap reel 0.529 | null q95 0.368 | ecart -0.161 | angle principal 87.0 deg | NON separe\n", - "seed 2 : overlap reel 0.521 | null q95 0.366 | ecart -0.155 | angle principal 89.6 deg | NON separe\n", - "seed 3 : overlap reel 0.531 | null q95 0.379 | ecart -0.152 | angle principal 89.3 deg | NON separe\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "seed 4 : overlap reel 0.513 | null q95 0.376 | ecart -0.138 | angle principal 85.9 deg | NON separe\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "seed 5 : overlap reel 0.569 | null q95 0.341 | ecart -0.228 | angle principal 83.3 deg | NON separe\n", + "seed 2 : overlap reel 0.525 | null q95 0.366 | ecart -0.158 | angle principal 89.5 deg | NON separe\n", + "seed 3 : overlap reel 0.531 | null q95 0.379 | ecart -0.152 | angle principal 89.3 deg | NON separe\n", + "seed 4 : overlap reel 0.513 | null q95 0.376 | ecart -0.138 | angle principal 85.9 deg | NON separe\n", + "seed 5 : overlap reel 0.568 | null q95 0.341 | ecart -0.227 | angle principal 83.2 deg | NON separe\n", "\n", - "H4 : {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.15799831330597827, 'ci95': (-0.22013759197735802, -0.14456199996191), 'p_signflip': 1.0, 'n_seeds_positive': 0, 'n_seeds': 6}\n" + "H4 : {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.1597800103366925, 'ci95': (-0.21929652100278793, -0.14463552331105037), 'p_signflip': 1.0, 'n_seeds_positive': 0, 'n_seeds': 6}\n" ] } ], @@ -771,6 +857,13 @@ "cell_type": "markdown", "id": "317695a90b34", "metadata": { + "papermill": { + "duration": 0.005006, + "end_time": "2026-09-18T12:51:46.227485+00:00", + "exception": false, + "start_time": "2026-09-18T12:51:46.222479+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -819,10 +912,17 @@ "id": "50ca78b41133", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:18:35.950945Z", - "iopub.status.busy": "2026-09-15T13:18:35.950465Z", - "iopub.status.idle": "2026-09-15T13:19:19.489159Z", - "shell.execute_reply": "2026-09-15T13:19:19.487767Z" + "iopub.execute_input": "2026-09-18T12:51:46.236751Z", + "iopub.status.busy": "2026-09-18T12:51:46.236454Z", + "iopub.status.idle": "2026-09-18T12:52:05.638227Z", + "shell.execute_reply": "2026-09-18T12:52:05.637590Z" + }, + "papermill": { + "duration": 19.407016, + "end_time": "2026-09-18T12:52:05.639068+00:00", + "exception": false, + "start_time": "2026-09-18T12:51:46.232052+00:00", + "status": "completed" }, "tags": [] }, @@ -831,7 +931,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "profil J-Lens a dose fixee (8 coordonnees A x 4 bandes) en 44s\n", + "profil J-Lens a dose fixee (8 coordonnees A x 4 bandes) en 19s\n", "coords A gelees par seed : {0: (9, 11, 15, 42, 51, 53, 56, 61), 1: (18, 24, 26, 39, 45, 49, 52, 56), 2: (1, 7, 11, 14, 38, 53, 60, 61), 3: (5, 12, 14, 24, 30, 44, 49, 54), 4: (15, 16, 29, 30, 39, 44, 52, 60), 5: (15, 17, 20, 24, 25, 41, 47, 51)}\n", "effectifs donneurs A/B (seed 0) : {'L0_pre': (252, 256), 'L0_post': (252, 256), 'L1_pre': (252, 256), 'L1_post': (252, 256)}\n", "\n", @@ -842,8 +942,8 @@ "L1_post 0.0154 0.0087 0.0090 0.0076 0.0186 0.0092 0.0091\n", "etendue inter-couches par bande (seed 0) : {'bande0': 0.0, 'bande1': 0.0, 'bande2': 0.0001, 'bande3': 0.0569}\n", "\n", - "H2 couches (porteuse vs autres) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0032444271344385326, 'ci95': (-0.0018852281611722189, 0.01478232303685871), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", - "H2 dissociation (A-cf vs B-cf a la porteuse) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.003067948249187811, 'ci95': (0.0014604224048485022, 0.005484325438707359), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n" + "H2 couches (porteuse vs autres) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0032444230985910734, 'ci95': (-0.001885239608469728, 0.014782325378662866), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", + "H2 dissociation (A-cf vs B-cf a la porteuse) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0030679449282357053, 'ci95': (0.0014604187303133113, 0.005484326301139621), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n" ] } ], @@ -979,6 +1079,13 @@ "cell_type": "markdown", "id": "f565700fc114", "metadata": { + "papermill": { + "duration": 0.003543, + "end_time": "2026-09-18T12:52:05.646470+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:05.642927+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -1011,10 +1118,17 @@ "id": "e995c92afddd", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:19.529008Z", - "iopub.status.busy": "2026-09-15T13:19:19.528728Z", - "iopub.status.idle": "2026-09-15T13:19:40.767618Z", - "shell.execute_reply": "2026-09-15T13:19:40.765850Z" + "iopub.execute_input": "2026-09-18T12:52:05.654760Z", + "iopub.status.busy": "2026-09-18T12:52:05.654441Z", + "iopub.status.idle": "2026-09-18T12:52:14.457128Z", + "shell.execute_reply": "2026-09-18T12:52:14.456039Z" + }, + "papermill": { + "duration": 8.808143, + "end_time": "2026-09-18T12:52:14.458028+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:05.649885+00:00", + "status": "completed" }, "tags": [] }, @@ -1030,13 +1144,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : bras causaux en 4s cumules\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "seed 0 : bras causaux en 2s cumules\n", "seed 1 : controle aleatoire apparie (rel_tol=0.5)\n" ] }, @@ -1044,13 +1152,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 1 : bras causaux en 7s cumules\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "seed 1 : bras causaux en 3s cumules\n", "seed 2 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1058,13 +1160,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 2 : bras causaux en 11s cumules\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "seed 2 : bras causaux en 5s cumules\n", "seed 3 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1072,13 +1168,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 3 : bras causaux en 14s cumules\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "seed 3 : bras causaux en 6s cumules\n", "seed 4 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1086,13 +1176,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 4 : bras causaux en 18s cumules\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "seed 4 : bras causaux en 7s cumules\n", "seed 5 : controle aleatoire apparie (rel_tol=0.5)\n" ] }, @@ -1100,10 +1184,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 5 : bras causaux en 21s cumules\n", + "seed 5 : bras causaux en 9s cumules\n", "\n", "Manipulation (dz_f a dose max, cible vs sham) :\n", - " cible : [1.618, 2.149, 1.513, 1.796, 1.809, 1.428]\n", + " cible : [1.619, 2.149, 1.513, 1.796, 1.809, 1.431]\n", " sham : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", " verdict selectivite (cible, dose max) : ['selective', 'selective', 'selective', 'selective', 'selective', 'selective']\n" ] @@ -1246,10 +1330,17 @@ "id": "62a3ae252bdd", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:40.788452Z", - "iopub.status.busy": "2026-09-15T13:19:40.787885Z", - "iopub.status.idle": "2026-09-15T13:19:40.808013Z", - "shell.execute_reply": "2026-09-15T13:19:40.807023Z" + "iopub.execute_input": "2026-09-18T12:52:14.468841Z", + "iopub.status.busy": "2026-09-18T12:52:14.468565Z", + "iopub.status.idle": "2026-09-18T12:52:14.483262Z", + "shell.execute_reply": "2026-09-18T12:52:14.482416Z" + }, + "papermill": { + "duration": 0.021108, + "end_time": "2026-09-18T12:52:14.484004+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:14.462896+00:00", + "status": "completed" }, "tags": [] }, @@ -1258,11 +1349,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "H1 cible-vs-B : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.03445607198159517, 'ci95': (0.015533366603772913, 0.0511677006023256), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n", - "H1 cible-vs-rand: {'verdict': 'INCONCLUSIVE', 'median_diff': 0.01589936803066236, 'ci95': (-0.007336197645861138, 0.04333051922947317), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", + "H1 cible-vs-B : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.034151581980343126, 'ci95': (0.015383038552251642, 0.051149462157821), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n", + "H1 cible-vs-rand: {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015952579200993112, 'ci95': (-0.007308046698200614, 0.04372304540464446), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", "\n", - "H3 selectivite comportementale (dacc_B - dacc_A > 0) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0038442460317460337, 'ci95': (-0.0183531746031746, 0.02504960317460318), 'p_signflip': 0.40625, 'n_seeds_positive': 3, 'n_seeds': 6}\n", - "H3 inflation de CE cible vs random (doit rester moderee) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015672829002141953, 'ci95': (-0.014095409773290157, 0.033396000042557716), 'p_signflip': 0.1875, 'n_seeds_positive': 4, 'n_seeds': 6}\n", + "H3 selectivite comportementale (dacc_B - dacc_A > 0) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0027281746031746048, 'ci95': (-0.019965277777777776, 0.024677579365079368), 'p_signflip': 0.5, 'n_seeds_positive': 3, 'n_seeds': 6}\n", + "H3 inflation de CE cible vs random (doit rester moderee) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015778010711073875, 'ci95': (-0.013896409422159195, 0.03339990507811308), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6}\n", "H3 lien dose (dd_a croissant le long des doses) : {'verdict': 'SUPPORTED', 'n_seeds_monotone': 6, 'n_seeds': 6, 'frac': 1.0}\n" ] } @@ -1299,6 +1390,13 @@ "cell_type": "markdown", "id": "64845f92da03", "metadata": { + "papermill": { + "duration": 0.00355, + "end_time": "2026-09-18T12:52:14.491444+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:14.487894+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -1317,10 +1415,17 @@ "id": "0a5c2b1e735a", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:40.835693Z", - "iopub.status.busy": "2026-09-15T13:19:40.835286Z", - "iopub.status.idle": "2026-09-15T13:19:51.831549Z", - "shell.execute_reply": "2026-09-15T13:19:51.830085Z" + "iopub.execute_input": "2026-09-18T12:52:14.499540Z", + "iopub.status.busy": "2026-09-18T12:52:14.499256Z", + "iopub.status.idle": "2026-09-18T12:52:18.031505Z", + "shell.execute_reply": "2026-09-18T12:52:18.030814Z" + }, + "papermill": { + "duration": 3.53733, + "end_time": "2026-09-18T12:52:18.032214+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:14.494884+00:00", + "status": "completed" }, "tags": [] }, @@ -1329,12 +1434,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "batterie belief-panel en 11s\n", - " sae/etat {'verdict': 'INCONCLUSIVE', 'median_diff': 0.12165859381564634, 'ci95': (-0.0375250019681809, 0.1802289466535566), 'p_signflip': 0.0625, 'n_seeds_positive': 4, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.5625281174397818, 'ci95': (0.422898885809735, 0.706840810087542), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.0056312308094025945, 'ci95': (-0.04226798472083827, 0.1627296864673662), 'p_signflip': 0.59375, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 0.59375}, 'p_holm': 0.25}\n", - " sae/comportement {'verdict': 'INCONCLUSIVE', 'median_diff': 0.13951696242663345, 'ci95': (0.07487153147253214, 0.1947666143620865), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.25038191952986494, 'ci95': (0.16223478438996586, 0.30445636385133495), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0844826797353593, 'ci95': (0.03269697149072118, 0.127275605097055), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'p_holm': 0.25}, 'p_holm': 0.25, 'fvu_median': 0.46504579684296843}\n", + "batterie belief-panel en 4s\n", + " sae/etat {'verdict': 'INCONCLUSIVE', 'median_diff': 0.12165859381564645, 'ci95': (-0.03752500196818098, 0.18022894665355646), 'p_signflip': 0.0625, 'n_seeds_positive': 4, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.562528117439782, 'ci95': (0.4228988858097348, 0.7068408100875421), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.005631230809402435, 'ci95': (-0.04226798472083841, 0.16272968646736619), 'p_signflip': 0.59375, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 0.59375}, 'p_holm': 0.25}\n", + " sae/comportement {'verdict': 'INCONCLUSIVE', 'median_diff': 0.13951696242663336, 'ci95': (0.07487153147253206, 0.19476661436208656), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.25038191952986477, 'ci95': (0.1622347843899657, 0.304456363851335), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0844826797353593, 'ci95': (0.032696971490721344, 0.1272756050970548), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'p_holm': 0.25}, 'p_holm': 0.25, 'fvu_median': 0.46504579684296843}\n", " sae/dose {'verdict': 'SUPPORTED', 'n_seeds_monotone': 6, 'n_seeds': 6, 'frac': 1.0}\n", - " flens/etat {'verdict': 'INCONCLUSIVE', 'median_diff': 0.808079522433053, 'ci95': (0.7590436869033668, 0.8757118462962381), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.9274416080186617, 'ci95': (0.8589968685378264, 1.0005027324258957), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.04991630359227012, 'ci95': (-0.20529384023094682, 0.06690054154950476), 'p_signflip': 0.75, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 1.0}, 'p_holm': 0.25}\n", - " flens/comportement {'verdict': 'INCONCLUSIVE', 'median_diff': 0.20259811785429827, 'ci95': (0.18286991673133898, 0.21721281431723466), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.33812853743905247, 'ci95': (0.307470412593868, 0.3639793902532218), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.006486185308910236, 'ci95': (-0.030601671453326013, 0.03547048200706229), 'p_signflip': 0.5, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 1.0}, 'p_holm': 0.25, 'fvu_median': 0.6112672822792983}\n", + " flens/etat {'verdict': 'INCONCLUSIVE', 'median_diff': 0.808079522433053, 'ci95': (0.7590436869033668, 0.8757118462962381), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.9274416080186617, 'ci95': (0.8589968685378264, 1.0005027324258957), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.04991630359227017, 'ci95': (-0.20529384023094682, 0.06690054154950476), 'p_signflip': 0.75, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 1.0}, 'p_holm': 0.25}\n", + " flens/comportement {'verdict': 'INCONCLUSIVE', 'median_diff': 0.20259811785429793, 'ci95': (0.1828699167313389, 0.2172128143172348), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.33812853743905225, 'ci95': (0.30747041259386787, 0.3639793902532218), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.006486185308910125, 'ci95': (-0.030601671453325763, 0.035470482007062626), 'p_signflip': 0.5, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 1.0}, 'p_holm': 0.25, 'fvu_median': 0.6112672822792983}\n", " flens/dose {'verdict': 'SUPPORTED', 'n_seeds_monotone': 6, 'n_seeds': 6, 'frac': 1.0}\n" ] } @@ -1353,6 +1458,13 @@ "cell_type": "markdown", "id": "9aa2cd879082", "metadata": { + "papermill": { + "duration": 0.004023, + "end_time": "2026-09-18T12:52:18.040870+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.036847+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -1368,10 +1480,17 @@ "id": "eab6e32ebf6e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:51.875067Z", - "iopub.status.busy": "2026-09-15T13:19:51.874671Z", - "iopub.status.idle": "2026-09-15T13:19:51.881067Z", - "shell.execute_reply": "2026-09-15T13:19:51.879652Z" + "iopub.execute_input": "2026-09-18T12:52:18.049174Z", + "iopub.status.busy": "2026-09-18T12:52:18.048854Z", + "iopub.status.idle": "2026-09-18T12:52:18.052968Z", + "shell.execute_reply": "2026-09-18T12:52:18.052269Z" + }, + "papermill": { + "duration": 0.009162, + "end_time": "2026-09-18T12:52:18.053506+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.044344+00:00", + "status": "completed" }, "tags": [] }, @@ -1405,10 +1524,17 @@ "id": "c575422a5c5c", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:51.906386Z", - "iopub.status.busy": "2026-09-15T13:19:51.905857Z", - "iopub.status.idle": "2026-09-15T13:19:51.912258Z", - "shell.execute_reply": "2026-09-15T13:19:51.911057Z" + "iopub.execute_input": "2026-09-18T12:52:18.061378Z", + "iopub.status.busy": "2026-09-18T12:52:18.061130Z", + "iopub.status.idle": "2026-09-18T12:52:18.065056Z", + "shell.execute_reply": "2026-09-18T12:52:18.064416Z" + }, + "papermill": { + "duration": 0.00873, + "end_time": "2026-09-18T12:52:18.065697+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.056967+00:00", + "status": "completed" }, "tags": [] }, @@ -1444,10 +1570,17 @@ "id": "f43f6dcee7a5", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:51.931289Z", - "iopub.status.busy": "2026-09-15T13:19:51.930901Z", - "iopub.status.idle": "2026-09-15T13:19:51.938384Z", - "shell.execute_reply": "2026-09-15T13:19:51.935881Z" + "iopub.execute_input": "2026-09-18T12:52:18.074394Z", + "iopub.status.busy": "2026-09-18T12:52:18.074126Z", + "iopub.status.idle": "2026-09-18T12:52:18.077941Z", + "shell.execute_reply": "2026-09-18T12:52:18.077350Z" + }, + "papermill": { + "duration": 0.009223, + "end_time": "2026-09-18T12:52:18.078581+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.069358+00:00", + "status": "completed" }, "tags": [] }, @@ -1482,6 +1615,13 @@ "cell_type": "markdown", "id": "8182dcceb441", "metadata": { + "papermill": { + "duration": 0.003822, + "end_time": "2026-09-18T12:52:18.086790+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.082968+00:00", + "status": "completed" + }, "tags": [] }, "source": [ @@ -1499,10 +1639,17 @@ "id": "b1dc680a842e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-15T13:19:51.965751Z", - "iopub.status.busy": "2026-09-15T13:19:51.965406Z", - "iopub.status.idle": "2026-09-15T13:19:51.982364Z", - "shell.execute_reply": "2026-09-15T13:19:51.980727Z" + "iopub.execute_input": "2026-09-18T12:52:18.097086Z", + "iopub.status.busy": "2026-09-18T12:52:18.096718Z", + "iopub.status.idle": "2026-09-18T12:52:18.109624Z", + "shell.execute_reply": "2026-09-18T12:52:18.108757Z" + }, + "papermill": { + "duration": 0.020159, + "end_time": "2026-09-18T12:52:18.110873+00:00", + "exception": false, + "start_time": "2026-09-18T12:52:18.090714+00:00", + "status": "completed" }, "tags": [] }, @@ -1513,26 +1660,26 @@ "text": [ "============================================================================\n", "H1 :\n", - " cible_vs_B INCONCLUSIVE med +0.0345 [+0.0155, +0.0512] p 0.0625 (Holm 0.1250)\n", - " cible_vs_random INCONCLUSIVE med +0.0159 [-0.0073, +0.0433] p 0.1875 (Holm 0.1875)\n", + " cible_vs_B INCONCLUSIVE med +0.0342 [+0.0154, +0.0511] p 0.0625 (Holm 0.1250)\n", + " cible_vs_random INCONCLUSIVE med +0.0160 [-0.0073, +0.0437] p 0.1875 (Holm 0.1875)\n", "H2 :\n", " couches_porteuse_vs_autres INCONCLUSIVE med +0.0032 [-0.0019, +0.0148] p 0.1875 (Holm 0.1875)\n", " dissociation_A_vs_B INCONCLUSIVE med +0.0031 [+0.0015, +0.0055] p 0.0625 (Holm 0.1250)\n", "H3 :\n", - " selectivite_comportementale INCONCLUSIVE med +0.0038 [-0.0184, +0.0250] p 0.4062\n", - " preservation_perplexite INCONCLUSIVE med +0.0157 [-0.0141, +0.0334] p 0.1875\n", + " selectivite_comportementale INCONCLUSIVE med +0.0027 [-0.0200, +0.0247] p 0.5000\n", + " preservation_perplexite INCONCLUSIVE med +0.0158 [-0.0139, +0.0334] p 0.1875\n", " lien_dose SUPPORTED (6/6 seeds monotones)\n", "H4 :\n", - " separation_geometrique NOT_SUPPORTED med -0.1580 [-0.2201, -0.1446] p 1.0000\n", + " separation_geometrique NOT_SUPPORTED med -0.1598 [-0.2193, -0.1446] p 1.0000\n", "============================================================================\n", "\n", "Accord et dissociation par instrument :\n", " F-Lens couches porteuses A/B : L1_post / L0_pre\n", " J-Lens effet A-cf par couche (median) : {'L0_pre': 0.0063, 'L0_post': 0.0039, 'L1_pre': 0.0039, 'L1_post': 0.0091}\n", - " SAE manipulation dz_f (cible, dose max) vs sham : [1.618, 2.149, 1.513, 1.796, 1.809, 1.428] / [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", + " SAE manipulation dz_f (cible, dose max) vs sham : [1.619, 2.149, 1.513, 1.796, 1.809, 1.431] / [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", "\n", "Sortie de reference (extrait verbatim) :\n", - "{\"notebook\": \"ICT-40-TriangulationCausale\", \"issue\": 15480, \"config\": {\"seeds\": [0, 1, 2, 3, 4, 5], \"n_bench\": 40000, \"seq_len\": 64, \"hop\": 16, \"steps\": 3000, \"k_sae\": 48, \"topk_sae\": 8, \"doses\": [0.25, 0.5, 0.75, 1.0], \"jlens_k\": 8, \"layer_a\": \"L1_post\", \"layer_b\": \"L0_pre\"}, \"vloss\": {\"0\": 1.8433, \"1\": 1.6821, \"2\": 1.9838, \"3\": 1.9307, \"4\": 1.8726, \"5\": 1.808}, \"verdicts\": {\"H1\": {\"cible_vs_B\": \"INCONCLUSIVE\", \"cible_vs_random\": \"INCONCLUSIVE\"}, \"H2\": {\"couches_porteuse_vs_autres\": \"INCONCLUSIVE\", \"dissociation_A_vs_B\": \"INCONCLUSIVE\"}, \"H3\": {\"selectivite_comportementale\": \"INCONCLUSIVE\", \"preservation_perplexite\": \"INCONCLUSIVE\", \"lien_dose\": \"SUPPORTED\"}, \"H4\": {\"separation_geometrique\": \"NOT_SUPPORTED\"}}, \"panel_sha256_seed0\": \"0f54f34ac3e5db7934e55f573841972ec785e3cc9d0fe635aec4bc103192b6f5\"}\n" + "{\"notebook\": \"ICT-40-TriangulationCausale\", \"issue\": 15480, \"config\": {\"seeds\": [0, 1, 2, 3, 4, 5], \"n_bench\": 40000, \"seq_len\": 64, \"hop\": 16, \"steps\": 3000, \"k_sae\": 48, \"topk_sae\": 8, \"doses\": [0.25, 0.5, 0.75, 1.0], \"jlens_k\": 8, \"layer_a\": \"L1_post\", \"layer_b\": \"L0_pre\"}, \"vloss\": {\"0\": 1.8433, \"1\": 1.6821, \"2\": 1.9838, \"3\": 1.9307, \"4\": 1.8726, \"5\": 1.808}, \"verdicts\": {\"H1\": {\"cible_vs_B\": \"INCONCLUSIVE\", \"cible_vs_random\": \"INCONCLUSIVE\"}, \"H2\": {\"couches_porteuse_vs_autres\": \"INCONCLUSIVE\", \"dissociation_A_vs_B\": \"INCONCLUSIVE\"}, \"H3\": {\"selectivite_comportementale\": \"INCONCLUSIVE\", \"preservation_perplexite\": \"INCONCLUSIVE\", \"lien_dose\": \"SUPPORTED\"}, \"H4\": {\"separation_geometrique\": \"NOT_SUPPORTED\"}}, \"panel_sha256_seed0\": \"8e6bde4d12c4a256e3ff50167232e4aeb37f33611dec6c7d28f6369083d4aa9c\"}\n" ] } ], @@ -1620,9 +1767,21 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.15" + "version": "3.13.7" + }, + "papermill": { + "default_parameters": {}, + "duration": 318.689738, + "end_time": "2026-09-18T12:52:19.229015+00:00", + "environment_variables": {}, + "exception": null, + "input_path": "ICT-40-TriangulationCausale.ipynb", + "output_path": "ICT-40-out.ipynb", + "parameters": {}, + "start_time": "2026-09-18T12:47:00.539277+00:00", + "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py index 6439308a85..c57033ebae 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/bench_factorise.py @@ -322,6 +322,66 @@ def beliefs(self, obs: Array) -> Array: return out +@dataclass(frozen=True) +class RRXOR_Iid: + """RRXOR legacy : bits iid ``b_t``, observation ``y_t = b_{t-1} XOR b_t``. + + DEPRECIE : les XOR adjacents de bits iid sont eux-memes iid -- ce banc + ne portait AUCUNE structure et ne meritait pas le nom RRXOR (cf. + :class:`RRXOR`, conforme a Riechers & Crutchfield 2018). Conserve pour + la REPRODUCTIBILITE de la batterie d'intervention (#15480/#16230) et du + pilote ICT-40, calibres sur ce banc ; toute nouvelle etude doit utiliser + :class:`RRXOR`. + """ + + n_states: int = 4 + name: str = "rrxor_iid" + + def transition_matrix(self) -> Array: + """T[(a,b) -> (b,c)] = 1/2 pour c dans {0,1} : le bit frais est iid uniforme.""" + t = np.zeros((4, 4)) + for a in (0, 1): + for b in (0, 1): + for c in (0, 1): + t[2 * a + b, 2 * b + c] = 0.5 + return t + + def stationary(self) -> Array: + return np.full(4, 0.25) + + def emission_matrix(self) -> Array: + """E[i, y] = P(y_t = y | etat i) : deterministe, y = a XOR b.""" + e = np.zeros((4, 2)) + for a in (0, 1): + for b in (0, 1): + e[2 * a + b, a ^ b] = 1.0 + return e + + def sample(self, n: int, seed: int) -> Tuple[Array, Array]: + """Echantillonne n bits iid + l'observation XOR ; retourne (etats (b_{t-1}, b_t), y).""" + rng = np.random.default_rng(seed) + bits = rng.integers(0, 2, size=n + 1) + states = 2 * bits[:-1] + bits[1:] + obs = bits[:-1] ^ bits[1:] + return states, obs + + def beliefs(self, obs: Array) -> Array: + """Filtration forward exacte sur les 4 etats ; observation binaire deterministe.""" + if obs.ndim != 1 or not np.all(np.isin(obs, (0, 1))): + raise ProcessError("RRXOR_Iid.beliefs attend une serie binaire 1D") + t = self.transition_matrix() + e = self.emission_matrix() + prior = self.stationary() + out = np.empty((len(obs), 4)) + b = prior + for k in range(len(obs)): + pred = b @ t if k > 0 else b + w = pred * e[:, int(obs[k])] + b = w / w.sum() + out[k] = b + return out + + @dataclass class FactoredBench: """Banc a deux facteurs independants, factorisation latente connue. diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_intervention_battery.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_intervention_battery.py index 003ad58dcb..5c791e4ee8 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_intervention_battery.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/tests/test_intervention_battery.py @@ -47,7 +47,7 @@ import pytest from ict import intervention_battery as ib -from ict.bench_factorise import FactoredBench, Mess3, RRXOR +from ict.bench_factorise import FactoredBench, Mess3_ObsCoupled, RRXOR_Iid # Budget CPU commente : 16 seeds x (SAE 250 pas sur (490, 12) + 2 bras x 8 # interventions x mesureurs lstsq minuscules + verdicts) ~ 2-4 s total (le @@ -65,7 +65,12 @@ def _batterie() -> ib.BatteryResult: de fixture -- convention de la serie).""" global _BATTERIE if _BATTERIE is None: - bench = FactoredBench(Mess3(), RRXOR(), name="mess3xrrxor") + bench = FactoredBench(Mess3_ObsCoupled(), RRXOR_Iid(), name="mess3xrrxor") + # Batterie = test de MECANISME, epinglee au banc de sa calibration + # (#15480/#16230) : gaussien obs-couple x RRXOR_Iid, les DEUX + # generateurs legacy explicites (#16225 renomme Mess3 et reecrit + # RRXOR ; recalibrer la batterie sur les generateurs conformes est + # un grain SEPARE, porteur : batterie d'intervention). _BATTERIE = ib.run_battery( bench, seeds=SEEDS, n=N, sae_kwargs=SAE_KWARGS, top_m_flens=5 ) @@ -302,7 +307,7 @@ def test_verdicts_complets(): # --------------------------------------------------------------------------- # def test_determinisme(): - bench = FactoredBench(Mess3(), RRXOR(), name="mess3xrrxor") + bench = FactoredBench(Mess3_ObsCoupled(), RRXOR_Iid(), name="mess3xrrxor") r1 = ib.run_battery(bench, seeds=(0, 1), n=300, sae_kwargs=SAE_KWARGS, top_m_flens=5) r2 = ib.run_battery(bench, seeds=(0, 1), n=300, From 067857be05b998ed69c11edfe18bcad557a375a7 Mon Sep 17 00:00:00 2001 From: jsboige Date: Fri, 18 Sep 2026 23:03:16 +0200 Subject: [PATCH 3/4] fix(iit,#16225): re-arme le garde J-Lens post-palier 40a/40b Le renommage main 7098f01287 (#16691/#16717) laissait test_ict_jlens_layers.py pointant l'ancien nom ICT-40-TriangulationCausale ; le garde s'auto-skippait (notebook absent) = silencieusement inerte. Path corrige vers ICT-40a -- 9/9 verts au head rebase. Co-Authored-By: Claude Sonnet 5 --- scripts/tests/test_ict_jlens_layers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests/test_ict_jlens_layers.py b/scripts/tests/test_ict_jlens_layers.py index f88f3c962a..87ab6f7f75 100644 --- a/scripts/tests/test_ict_jlens_layers.py +++ b/scripts/tests/test_ict_jlens_layers.py @@ -197,7 +197,7 @@ def test_is_full_panel(): # --------------------------------------------------------------------- # _NB = (Path(__file__).resolve().parents[2] / "MyIA.AI.Notebooks" / "IIT" - / "ICT-Series" / "ICT-40-TriangulationCausale.ipynb") + / "ICT-Series" / "ICT-40a-TriangulationCausale.ipynb") def _jlens_cell_source(): From b1ea8c98716abe15924b8e445806a7a201ceee4d Mon Sep 17 00:00:00 2001 From: jsboige Date: Mon, 21 Sep 2026 17:02:34 +0200 Subject: [PATCH 4/4] fix(iit,#16225): re-execution des deux notebooks du delta au head courant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le commit 5283902a859 a modifie la source de deux cellules de code d'ICT-40a (cellules 3 et 5) apres la trace papermill embarquee (2026-09-18T12:52:19Z). La preuve d'execution portee par le corps de la PR ne decrivait donc plus la tete : le report « par identite de blob » qui l'avait transferee jusqu'a c3ba7462b59a est tombe le meme jour (C.2). Re-execution des deux notebooks du delta par l'outil canonique (scripts/notebook_tools/notebook_tools.py execute), dans le worktree de la PR : - ICT-40a : 16/16 cellules code, execution_count 1..16 sans trou, 0 cellule sans sortie, 0 sortie d'erreur, trace 2026-09-21T15:01:08Z, exception null. - ICT-37 : 9/9 cellules code, execution_count 1..9, memes conditions, trace 2026-09-21T15:01:58Z, exception null. Verdicts idempotents : 0/16 cellule dont un jeton de verdict a change (H1/H2/H3 INCONCLUSIVE, H4 et separation_geometrique NOT_SUPPORTED ; p_signflip, p Holm, ci95 inchanges a la precision rapportee). La derive residuelle est un flottant de 3e-4e decimale, signature d'un ordre de reduction BLAS non epingle. Les durees murales imprimees par ICT-40a refletent la charge de la machine (15 runners CI restaures le meme jour sur ce parc, load average ~9-11 pour 16 CPU), pas une propriete du notebook : le premier run a ete refait seul pour ne pas committer un chiffre gonfle par un second notebook en vol, et les deux valeurs sont conservees ci-dessus pour que l'ecart reste lisible. Les chemins de metadata.papermill sont ramenes au basename par le hook scrub-papermill-paths (metadata seule, source et sorties intactes). See #16225 Co-Authored-By: Claude Sonnet 5 --- .../ICT-Series/ICT-37-FLens-BeliefState.ipynb | 211 ++++----- .../ICT-40a-TriangulationCausale.ipynb | 413 ++++++++++-------- 2 files changed, 338 insertions(+), 286 deletions(-) diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb index 1edd192c5b..af865f3161 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb @@ -5,10 +5,10 @@ "id": "9572779c", "metadata": { "papermill": { - "duration": 0.013866, - "end_time": "2026-09-18T11:00:30.887054+00:00", + "duration": 0.004496, + "end_time": "2026-09-21T15:01:50.912039+00:00", "exception": false, - "start_time": "2026-09-18T11:00:30.873188+00:00", + "start_time": "2026-09-21T15:01:50.907543+00:00", "status": "completed" }, "tags": [] @@ -65,7 +65,16 @@ { "cell_type": "markdown", "id": "statut-epistemique", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.002885, + "end_time": "2026-09-21T15:01:50.918621+00:00", + "exception": false, + "start_time": "2026-09-21T15:01:50.915736+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." ] @@ -75,10 +84,10 @@ "id": "ae39ac6f", "metadata": { "papermill": { - "duration": 0.004409, - "end_time": "2026-09-18T11:00:30.897193+00:00", + "duration": 0.004613, + "end_time": "2026-09-21T15:01:50.926292+00:00", "exception": false, - "start_time": "2026-09-18T11:00:30.892784+00:00", + "start_time": "2026-09-21T15:01:50.921679+00:00", "status": "completed" }, "tags": [] @@ -126,16 +135,16 @@ "id": "dd1ac0ab", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:30.910352Z", - "iopub.status.busy": "2026-09-18T11:00:30.909784Z", - "iopub.status.idle": "2026-09-18T11:00:30.923690Z", - "shell.execute_reply": "2026-09-18T11:00:30.922284Z" + "iopub.execute_input": "2026-09-21T15:01:50.935722Z", + "iopub.status.busy": "2026-09-21T15:01:50.935288Z", + "iopub.status.idle": "2026-09-21T15:01:50.958472Z", + "shell.execute_reply": "2026-09-21T15:01:50.957075Z" }, "papermill": { - "duration": 0.021547, - "end_time": "2026-09-18T11:00:30.925065+00:00", + "duration": 0.029732, + "end_time": "2026-09-21T15:01:50.959902+00:00", "exception": false, - "start_time": "2026-09-18T11:00:30.903518+00:00", + "start_time": "2026-09-21T15:01:50.930170+00:00", "status": "completed" }, "tags": [] @@ -176,16 +185,16 @@ "id": "85657928", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:30.938096Z", - "iopub.status.busy": "2026-09-18T11:00:30.937544Z", - "iopub.status.idle": "2026-09-18T11:00:31.275902Z", - "shell.execute_reply": "2026-09-18T11:00:31.274346Z" + "iopub.execute_input": "2026-09-21T15:01:50.973275Z", + "iopub.status.busy": "2026-09-21T15:01:50.972695Z", + "iopub.status.idle": "2026-09-21T15:01:51.132256Z", + "shell.execute_reply": "2026-09-21T15:01:51.131054Z" }, "papermill": { - "duration": 0.347341, - "end_time": "2026-09-18T11:00:31.277172+00:00", + "duration": 0.168699, + "end_time": "2026-09-21T15:01:51.133647+00:00", "exception": false, - "start_time": "2026-09-18T11:00:30.929831+00:00", + "start_time": "2026-09-21T15:01:50.964948+00:00", "status": "completed" }, "tags": [] @@ -213,10 +222,10 @@ "id": "7c991a9d", "metadata": { "papermill": { - "duration": 0.004277, - "end_time": "2026-09-18T11:00:31.286230+00:00", + "duration": 0.003191, + "end_time": "2026-09-21T15:01:51.140371+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.281953+00:00", + "start_time": "2026-09-21T15:01:51.137180+00:00", "status": "completed" }, "tags": [] @@ -244,16 +253,16 @@ "id": "1ea45876", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:31.297448Z", - "iopub.status.busy": "2026-09-18T11:00:31.296967Z", - "iopub.status.idle": "2026-09-18T11:00:31.333860Z", - "shell.execute_reply": "2026-09-18T11:00:31.332318Z" + "iopub.execute_input": "2026-09-21T15:01:51.149648Z", + "iopub.status.busy": "2026-09-21T15:01:51.149204Z", + "iopub.status.idle": "2026-09-21T15:01:51.184347Z", + "shell.execute_reply": "2026-09-21T15:01:51.183177Z" }, "papermill": { - "duration": 0.044725, - "end_time": "2026-09-18T11:00:31.335141+00:00", + "duration": 0.042125, + "end_time": "2026-09-21T15:01:51.185461+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.290416+00:00", + "start_time": "2026-09-21T15:01:51.143336+00:00", "status": "completed" }, "tags": [] @@ -326,10 +335,10 @@ "id": "282febcd", "metadata": { "papermill": { - "duration": 0.00663, - "end_time": "2026-09-18T11:00:31.346594+00:00", + "duration": 0.005079, + "end_time": "2026-09-21T15:01:51.194598+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.339964+00:00", + "start_time": "2026-09-21T15:01:51.189519+00:00", "status": "completed" }, "tags": [] @@ -367,16 +376,16 @@ "id": "c5121db9", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:31.357273Z", - "iopub.status.busy": "2026-09-18T11:00:31.356806Z", - "iopub.status.idle": "2026-09-18T11:00:31.476174Z", - "shell.execute_reply": "2026-09-18T11:00:31.475000Z" + "iopub.execute_input": "2026-09-21T15:01:51.205740Z", + "iopub.status.busy": "2026-09-21T15:01:51.205157Z", + "iopub.status.idle": "2026-09-21T15:01:53.252532Z", + "shell.execute_reply": "2026-09-21T15:01:53.250382Z" }, "papermill": { - "duration": 0.126002, - "end_time": "2026-09-18T11:00:31.477409+00:00", + "duration": 2.054713, + "end_time": "2026-09-21T15:01:53.254338+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.351407+00:00", + "start_time": "2026-09-21T15:01:51.199625+00:00", "status": "completed" }, "tags": [] @@ -386,14 +395,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mess3 : 100 steps, etats uniques = [0 1 2], obs uniques = [0 1 2]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", + "Mess3 : 100 steps, etats uniques = [0 1 2], obs uniques = [0 1 2]\n", "RRXOR : 99 steps, etats d'arrivee uniques = [0 1 2 3 4]\n", "RRXOR : triplets (r1, r2, r1 XOR r2) valides : True\n" ] @@ -447,10 +449,10 @@ "id": "ad86258c", "metadata": { "papermill": { - "duration": 0.004491, - "end_time": "2026-09-18T11:00:31.486597+00:00", + "duration": 0.005479, + "end_time": "2026-09-21T15:01:53.266403+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.482106+00:00", + "start_time": "2026-09-21T15:01:53.260924+00:00", "status": "completed" }, "tags": [] @@ -469,16 +471,16 @@ "id": "c012ed24", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:31.496656Z", - "iopub.status.busy": "2026-09-18T11:00:31.496138Z", - "iopub.status.idle": "2026-09-18T11:00:31.530935Z", - "shell.execute_reply": "2026-09-18T11:00:31.526505Z" + "iopub.execute_input": "2026-09-21T15:01:53.279029Z", + "iopub.status.busy": "2026-09-21T15:01:53.278376Z", + "iopub.status.idle": "2026-09-21T15:01:53.298733Z", + "shell.execute_reply": "2026-09-21T15:01:53.297230Z" }, "papermill": { - "duration": 0.041911, - "end_time": "2026-09-18T11:00:31.532120+00:00", + "duration": 0.028799, + "end_time": "2026-09-21T15:01:53.300092+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.490209+00:00", + "start_time": "2026-09-21T15:01:53.271293+00:00", "status": "completed" }, "tags": [] @@ -530,10 +532,10 @@ "id": "cf8016e8", "metadata": { "papermill": { - "duration": 0.004723, - "end_time": "2026-09-18T11:00:31.541342+00:00", + "duration": 0.005411, + "end_time": "2026-09-21T15:01:53.310784+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.536619+00:00", + "start_time": "2026-09-21T15:01:53.305373+00:00", "status": "completed" }, "tags": [] @@ -545,8 +547,7 @@ "\n", "C'est le **regime trivial** : on verifie que les primitives fonctionnent et que le protocole capture bien la linearite du belief. Tout ecart significatif constitue un **bug dans les primitives** ou le protocole.\n", "\n", - "**Verdict attendu** : H1 (accuracy_belief - accuracy_shuffle >= 0.3) SUPPORTED. H2 (pre-LN > post-LN) est une question ouverte : avec l'encodage lineaire en belief (post-#16225), la normalisation post-L2 n'ecrase plus l'echelle des directions -- le sens se lit sur la mesure, pas sur une attente.\n", - "" + "**Verdict attendu** : H1 (accuracy_belief - accuracy_shuffle >= 0.3) SUPPORTED. H2 (pre-LN > post-LN) est une question ouverte : avec l'encodage lineaire en belief (post-#16225), la normalisation post-L2 n'ecrase plus l'echelle des directions -- le sens se lit sur la mesure, pas sur une attente.\n" ] }, { @@ -555,16 +556,16 @@ "id": "a3788d4c", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:31.552654Z", - "iopub.status.busy": "2026-09-18T11:00:31.552028Z", - "iopub.status.idle": "2026-09-18T11:00:33.745332Z", - "shell.execute_reply": "2026-09-18T11:00:33.744161Z" + "iopub.execute_input": "2026-09-21T15:01:53.323600Z", + "iopub.status.busy": "2026-09-21T15:01:53.323054Z", + "iopub.status.idle": "2026-09-21T15:01:55.190398Z", + "shell.execute_reply": "2026-09-21T15:01:55.189072Z" }, "papermill": { - "duration": 2.200274, - "end_time": "2026-09-18T11:00:33.746228+00:00", + "duration": 1.87537, + "end_time": "2026-09-21T15:01:55.191343+00:00", "exception": false, - "start_time": "2026-09-18T11:00:31.545954+00:00", + "start_time": "2026-09-21T15:01:53.315973+00:00", "status": "completed" }, "tags": [] @@ -644,10 +645,10 @@ "id": "d29b71f2", "metadata": { "papermill": { - "duration": 0.004057, - "end_time": "2026-09-18T11:00:33.753883+00:00", + "duration": 0.003308, + "end_time": "2026-09-21T15:01:55.198313+00:00", "exception": false, - "start_time": "2026-09-18T11:00:33.749826+00:00", + "start_time": "2026-09-21T15:01:55.195005+00:00", "status": "completed" }, "tags": [] @@ -678,16 +679,16 @@ "id": "83d6443f", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:33.762270Z", - "iopub.status.busy": "2026-09-18T11:00:33.761789Z", - "iopub.status.idle": "2026-09-18T11:00:36.274277Z", - "shell.execute_reply": "2026-09-18T11:00:36.273024Z" + "iopub.execute_input": "2026-09-21T15:01:55.209920Z", + "iopub.status.busy": "2026-09-21T15:01:55.209431Z", + "iopub.status.idle": "2026-09-21T15:01:57.815382Z", + "shell.execute_reply": "2026-09-21T15:01:57.813973Z" }, "papermill": { - "duration": 2.518017, - "end_time": "2026-09-18T11:00:36.275473+00:00", + "duration": 2.613335, + "end_time": "2026-09-21T15:01:57.816434+00:00", "exception": false, - "start_time": "2026-09-18T11:00:33.757456+00:00", + "start_time": "2026-09-21T15:01:55.203099+00:00", "status": "completed" }, "tags": [] @@ -770,10 +771,10 @@ "id": "1b79b65f", "metadata": { "papermill": { - "duration": 0.005294, - "end_time": "2026-09-18T11:00:36.285912+00:00", + "duration": 0.00522, + "end_time": "2026-09-21T15:01:57.826902+00:00", "exception": false, - "start_time": "2026-09-18T11:00:36.280618+00:00", + "start_time": "2026-09-21T15:01:57.821682+00:00", "status": "completed" }, "tags": [] @@ -806,16 +807,16 @@ "id": "1bda9232", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:36.297566Z", - "iopub.status.busy": "2026-09-18T11:00:36.297161Z", - "iopub.status.idle": "2026-09-18T11:00:36.817396Z", - "shell.execute_reply": "2026-09-18T11:00:36.816275Z" + "iopub.execute_input": "2026-09-21T15:01:57.840012Z", + "iopub.status.busy": "2026-09-21T15:01:57.839607Z", + "iopub.status.idle": "2026-09-21T15:01:58.352283Z", + "shell.execute_reply": "2026-09-21T15:01:58.351230Z" }, "papermill": { - "duration": 0.528431, - "end_time": "2026-09-18T11:00:36.818887+00:00", + "duration": 0.520961, + "end_time": "2026-09-21T15:01:58.353187+00:00", "exception": false, - "start_time": "2026-09-18T11:00:36.290456+00:00", + "start_time": "2026-09-21T15:01:57.832226+00:00", "status": "completed" }, "tags": [] @@ -902,10 +903,10 @@ "id": "a1a576de", "metadata": { "papermill": { - "duration": 0.005092, - "end_time": "2026-09-18T11:00:36.829577+00:00", + "duration": 0.004867, + "end_time": "2026-09-21T15:01:58.362319+00:00", "exception": false, - "start_time": "2026-09-18T11:00:36.824485+00:00", + "start_time": "2026-09-21T15:01:58.357452+00:00", "status": "completed" }, "tags": [] @@ -950,16 +951,16 @@ "id": "89386e8a", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T11:00:36.841980Z", - "iopub.status.busy": "2026-09-18T11:00:36.841507Z", - "iopub.status.idle": "2026-09-18T11:00:36.852266Z", - "shell.execute_reply": "2026-09-18T11:00:36.851062Z" + "iopub.execute_input": "2026-09-21T15:01:58.372611Z", + "iopub.status.busy": "2026-09-21T15:01:58.372227Z", + "iopub.status.idle": "2026-09-21T15:01:58.381096Z", + "shell.execute_reply": "2026-09-21T15:01:58.379838Z" }, "papermill": { - "duration": 0.018732, - "end_time": "2026-09-18T11:00:36.853396+00:00", + "duration": 0.016283, + "end_time": "2026-09-21T15:01:58.382067+00:00", "exception": false, - "start_time": "2026-09-18T11:00:36.834664+00:00", + "start_time": "2026-09-21T15:01:58.365784+00:00", "status": "completed" }, "tags": [] @@ -1036,17 +1037,17 @@ }, "papermill": { "default_parameters": {}, - "duration": 10.13258, - "end_time": "2026-09-18T11:00:37.226289+00:00", + "duration": 10.494752, + "end_time": "2026-09-21T15:01:58.843150+00:00", "environment_variables": {}, "exception": null, "input_path": "ICT-37-FLens-BeliefState.ipynb", "output_path": "ICT-37-FLens-BeliefState.ipynb", "parameters": {}, - "start_time": "2026-09-18T11:00:27.093709+00:00", + "start_time": "2026-09-21T15:01:48.348398+00:00", "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb index cd3960466b..552ee72941 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40a-TriangulationCausale.ipynb @@ -5,10 +5,10 @@ "id": "8d4c2888de87", "metadata": { "papermill": { - "duration": 0.00308, - "end_time": "2026-09-18T12:47:02.125242+00:00", + "duration": 0.00722, + "end_time": "2026-09-21T14:50:29.758069+00:00", "exception": false, - "start_time": "2026-09-18T12:47:02.122162+00:00", + "start_time": "2026-09-21T14:50:29.750849+00:00", "status": "completed" }, "tags": [] @@ -60,7 +60,16 @@ { "cell_type": "markdown", "id": "statut-epistemique", - "metadata": {}, + "metadata": { + "papermill": { + "duration": 0.004874, + "end_time": "2026-09-21T14:50:29.767695+00:00", + "exception": false, + "start_time": "2026-09-21T14:50:29.762821+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." ] @@ -71,16 +80,16 @@ "id": "947d75acd4f2", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:47:02.133320Z", - "iopub.status.busy": "2026-09-18T12:47:02.133057Z", - "iopub.status.idle": "2026-09-18T12:47:02.140583Z", - "shell.execute_reply": "2026-09-18T12:47:02.139863Z" + "iopub.execute_input": "2026-09-21T14:50:29.782276Z", + "iopub.status.busy": "2026-09-21T14:50:29.781762Z", + "iopub.status.idle": "2026-09-21T14:50:29.794528Z", + "shell.execute_reply": "2026-09-21T14:50:29.793264Z" }, "papermill": { - "duration": 0.011597, - "end_time": "2026-09-18T12:47:02.141161+00:00", + "duration": 0.021768, + "end_time": "2026-09-21T14:50:29.795708+00:00", "exception": false, - "start_time": "2026-09-18T12:47:02.129564+00:00", + "start_time": "2026-09-21T14:50:29.773940+00:00", "status": "completed" }, "tags": [] @@ -134,16 +143,16 @@ "id": "ea85e07e2c80", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:47:02.147357Z", - "iopub.status.busy": "2026-09-18T12:47:02.147107Z", - "iopub.status.idle": "2026-09-18T12:47:09.668073Z", - "shell.execute_reply": "2026-09-18T12:47:09.667419Z" + "iopub.execute_input": "2026-09-21T14:50:29.810356Z", + "iopub.status.busy": "2026-09-21T14:50:29.809928Z", + "iopub.status.idle": "2026-09-21T14:50:35.529720Z", + "shell.execute_reply": "2026-09-21T14:50:35.528574Z" }, "papermill": { - "duration": 7.524784, - "end_time": "2026-09-18T12:47:09.668673+00:00", + "duration": 5.728763, + "end_time": "2026-09-21T14:50:35.530708+00:00", "exception": false, - "start_time": "2026-09-18T12:47:02.143889+00:00", + "start_time": "2026-09-21T14:50:29.801945+00:00", "status": "completed" }, "tags": [] @@ -196,10 +205,10 @@ "id": "74f64c9218d8", "metadata": { "papermill": { - "duration": 0.002602, - "end_time": "2026-09-18T12:47:09.674204+00:00", + "duration": 0.006289, + "end_time": "2026-09-21T14:50:35.541243+00:00", "exception": false, - "start_time": "2026-09-18T12:47:09.671602+00:00", + "start_time": "2026-09-21T14:50:35.534954+00:00", "status": "completed" }, "tags": [] @@ -225,16 +234,16 @@ "id": "d1f92ee61d71", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:47:09.681880Z", - "iopub.status.busy": "2026-09-18T12:47:09.681535Z", - "iopub.status.idle": "2026-09-18T12:47:10.207544Z", - "shell.execute_reply": "2026-09-18T12:47:10.206737Z" + "iopub.execute_input": "2026-09-21T14:50:35.552514Z", + "iopub.status.busy": "2026-09-21T14:50:35.552024Z", + "iopub.status.idle": "2026-09-21T14:50:36.321000Z", + "shell.execute_reply": "2026-09-21T14:50:36.320172Z" }, "papermill": { - "duration": 0.531617, - "end_time": "2026-09-18T12:47:10.208352+00:00", + "duration": 0.775409, + "end_time": "2026-09-21T14:50:36.321724+00:00", "exception": false, - "start_time": "2026-09-18T12:47:09.676735+00:00", + "start_time": "2026-09-21T14:50:35.546315+00:00", "status": "completed" }, "tags": [] @@ -274,10 +283,10 @@ "id": "d671ef552c91", "metadata": { "papermill": { - "duration": 0.002867, - "end_time": "2026-09-18T12:47:10.214530+00:00", + "duration": 0.003434, + "end_time": "2026-09-21T14:50:36.328942+00:00", "exception": false, - "start_time": "2026-09-18T12:47:10.211663+00:00", + "start_time": "2026-09-21T14:50:36.325508+00:00", "status": "completed" }, "tags": [] @@ -305,16 +314,16 @@ "id": "926bb9a5fbf0", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:47:10.221240Z", - "iopub.status.busy": "2026-09-18T12:47:10.220870Z", - "iopub.status.idle": "2026-09-18T12:50:08.644963Z", - "shell.execute_reply": "2026-09-18T12:50:08.643830Z" + "iopub.execute_input": "2026-09-21T14:50:36.338007Z", + "iopub.status.busy": "2026-09-21T14:50:36.337754Z", + "iopub.status.idle": "2026-09-21T14:56:04.294999Z", + "shell.execute_reply": "2026-09-21T14:56:04.293302Z" }, "papermill": { - "duration": 178.428653, - "end_time": "2026-09-18T12:50:08.645889+00:00", + "duration": 327.970375, + "end_time": "2026-09-21T14:56:04.302709+00:00", "exception": false, - "start_time": "2026-09-18T12:47:10.217236+00:00", + "start_time": "2026-09-21T14:50:36.332334+00:00", "status": "completed" }, "tags": [] @@ -324,43 +333,43 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : 31s | vloss 1.843 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 0 : 56s | vloss 1.843 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 1 : 29s | vloss 1.682 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 1 : 50s | vloss 1.682 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 2 : 30s | vloss 1.984 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 2 : 53s | vloss 1.984 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 3 : 30s | vloss 1.931 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 3 : 57s | vloss 1.931 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 4 : 30s | vloss 1.873 | fenetres 2497 (tr 1744, ev 750)\n" + "seed 4 : 57s | vloss 1.873 | fenetres 2497 (tr 1744, ev 750)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "seed 5 : 29s | vloss 1.808 | fenetres 2497 (tr 1744, ev 750)\n", - "Entrainement et capture termines en 178s.\n" + "seed 5 : 56s | vloss 1.808 | fenetres 2497 (tr 1744, ev 750)\n", + "Entrainement et capture termines en 328s.\n" ] } ], @@ -405,10 +414,10 @@ "id": "dc9cb724a8ff", "metadata": { "papermill": { - "duration": 0.00372, - "end_time": "2026-09-18T12:50:08.653632+00:00", + "duration": 0.007764, + "end_time": "2026-09-21T14:56:04.318525+00:00", "exception": false, - "start_time": "2026-09-18T12:50:08.649912+00:00", + "start_time": "2026-09-21T14:56:04.310761+00:00", "status": "completed" }, "tags": [] @@ -433,16 +442,16 @@ "id": "a7e9744deb36", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:50:08.662295Z", - "iopub.status.busy": "2026-09-18T12:50:08.661885Z", - "iopub.status.idle": "2026-09-18T12:50:14.050415Z", - "shell.execute_reply": "2026-09-18T12:50:14.049471Z" + "iopub.execute_input": "2026-09-21T14:56:04.339217Z", + "iopub.status.busy": "2026-09-21T14:56:04.338440Z", + "iopub.status.idle": "2026-09-21T14:56:14.204968Z", + "shell.execute_reply": "2026-09-21T14:56:14.203564Z" }, "papermill": { - "duration": 5.394131, - "end_time": "2026-09-18T12:50:14.051390+00:00", + "duration": 9.879083, + "end_time": "2026-09-21T14:56:14.206378+00:00", "exception": false, - "start_time": "2026-09-18T12:50:08.657259+00:00", + "start_time": "2026-09-21T14:56:04.327295+00:00", "status": "completed" }, "tags": [] @@ -528,10 +537,10 @@ "id": "846613118325", "metadata": { "papermill": { - "duration": 0.003382, - "end_time": "2026-09-18T12:50:14.058712+00:00", + "duration": 0.006945, + "end_time": "2026-09-21T14:56:14.220529+00:00", "exception": false, - "start_time": "2026-09-18T12:50:14.055330+00:00", + "start_time": "2026-09-21T14:56:14.213584+00:00", "status": "completed" }, "tags": [] @@ -555,16 +564,16 @@ "id": "ff7f136b7a97", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:50:14.067182Z", - "iopub.status.busy": "2026-09-18T12:50:14.066864Z", - "iopub.status.idle": "2026-09-18T12:51:46.094285Z", - "shell.execute_reply": "2026-09-18T12:51:46.093385Z" + "iopub.execute_input": "2026-09-21T14:56:14.239359Z", + "iopub.status.busy": "2026-09-21T14:56:14.238764Z", + "iopub.status.idle": "2026-09-21T14:59:51.898564Z", + "shell.execute_reply": "2026-09-21T14:59:51.896985Z" }, "papermill": { - "duration": 92.033074, - "end_time": "2026-09-18T12:51:46.095158+00:00", + "duration": 217.677271, + "end_time": "2026-09-21T14:59:51.905482+00:00", "exception": false, - "start_time": "2026-09-18T12:50:14.062084+00:00", + "start_time": "2026-09-21T14:56:14.228211+00:00", "status": "completed" }, "tags": [] @@ -664,10 +673,10 @@ "id": "c679470027c8", "metadata": { "papermill": { - "duration": 0.00514, - "end_time": "2026-09-18T12:51:46.105883+00:00", + "duration": 0.008856, + "end_time": "2026-09-21T14:59:51.922246+00:00", "exception": false, - "start_time": "2026-09-18T12:51:46.100743+00:00", + "start_time": "2026-09-21T14:59:51.913390+00:00", "status": "completed" }, "tags": [] @@ -693,16 +702,16 @@ "id": "a65fec91f4b0", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:51:46.117634Z", - "iopub.status.busy": "2026-09-18T12:51:46.117389Z", - "iopub.status.idle": "2026-09-18T12:51:46.125993Z", - "shell.execute_reply": "2026-09-18T12:51:46.125267Z" + "iopub.execute_input": "2026-09-21T14:59:51.942428Z", + "iopub.status.busy": "2026-09-21T14:59:51.941799Z", + "iopub.status.idle": "2026-09-21T14:59:51.959342Z", + "shell.execute_reply": "2026-09-21T14:59:51.957924Z" }, "papermill": { - "duration": 0.01606, - "end_time": "2026-09-18T12:51:46.127033+00:00", + "duration": 0.028835, + "end_time": "2026-09-21T14:59:51.960639+00:00", "exception": false, - "start_time": "2026-09-18T12:51:46.110973+00:00", + "start_time": "2026-09-21T14:59:51.931804+00:00", "status": "completed" }, "tags": [] @@ -795,16 +804,16 @@ "id": "969977118f34", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:51:46.136044Z", - "iopub.status.busy": "2026-09-18T12:51:46.135707Z", - "iopub.status.idle": "2026-09-18T12:51:46.216410Z", - "shell.execute_reply": "2026-09-18T12:51:46.215501Z" + "iopub.execute_input": "2026-09-21T14:59:51.979170Z", + "iopub.status.busy": "2026-09-21T14:59:51.978581Z", + "iopub.status.idle": "2026-09-21T14:59:52.203690Z", + "shell.execute_reply": "2026-09-21T14:59:52.202200Z" }, "papermill": { - "duration": 0.086399, - "end_time": "2026-09-18T12:51:46.217345+00:00", + "duration": 0.236351, + "end_time": "2026-09-21T14:59:52.204969+00:00", "exception": false, - "start_time": "2026-09-18T12:51:46.130946+00:00", + "start_time": "2026-09-21T14:59:51.968618+00:00", "status": "completed" }, "tags": [] @@ -815,13 +824,25 @@ "output_type": "stream", "text": [ "seed 0 : overlap reel 0.572 | null q95 0.360 | ecart -0.212 | angle principal 83.3 deg | NON separe\n", - "seed 1 : overlap reel 0.529 | null q95 0.368 | ecart -0.161 | angle principal 87.0 deg | NON separe\n", + "seed 1 : overlap reel 0.529 | null q95 0.368 | ecart -0.161 | angle principal 87.0 deg | NON separe\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 2 : overlap reel 0.525 | null q95 0.366 | ecart -0.158 | angle principal 89.5 deg | NON separe\n", "seed 3 : overlap reel 0.531 | null q95 0.379 | ecart -0.152 | angle principal 89.3 deg | NON separe\n", - "seed 4 : overlap reel 0.513 | null q95 0.376 | ecart -0.138 | angle principal 85.9 deg | NON separe\n", + "seed 4 : overlap reel 0.513 | null q95 0.376 | ecart -0.138 | angle principal 85.9 deg | NON separe\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 5 : overlap reel 0.568 | null q95 0.341 | ecart -0.227 | angle principal 83.2 deg | NON separe\n", "\n", - "H4 : {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.1597800103366925, 'ci95': (-0.21929652100278793, -0.14463552331105037), 'p_signflip': 1.0, 'n_seeds_positive': 0, 'n_seeds': 6}\n" + "H4 : {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.15976774049718054, 'ci95': (-0.21923126849186206, -0.1445781909523138), 'p_signflip': 1.0, 'n_seeds_positive': 0, 'n_seeds': 6}\n" ] } ], @@ -858,10 +879,10 @@ "id": "317695a90b34", "metadata": { "papermill": { - "duration": 0.005006, - "end_time": "2026-09-18T12:51:46.227485+00:00", + "duration": 0.007637, + "end_time": "2026-09-21T14:59:52.220850+00:00", "exception": false, - "start_time": "2026-09-18T12:51:46.222479+00:00", + "start_time": "2026-09-21T14:59:52.213213+00:00", "status": "completed" }, "tags": [] @@ -912,16 +933,16 @@ "id": "50ca78b41133", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:51:46.236751Z", - "iopub.status.busy": "2026-09-18T12:51:46.236454Z", - "iopub.status.idle": "2026-09-18T12:52:05.638227Z", - "shell.execute_reply": "2026-09-18T12:52:05.637590Z" + "iopub.execute_input": "2026-09-21T14:59:52.240511Z", + "iopub.status.busy": "2026-09-21T14:59:52.239918Z", + "iopub.status.idle": "2026-09-21T15:00:40.823397Z", + "shell.execute_reply": "2026-09-21T15:00:40.821941Z" }, "papermill": { - "duration": 19.407016, - "end_time": "2026-09-18T12:52:05.639068+00:00", + "duration": 48.601778, + "end_time": "2026-09-21T15:00:40.830672+00:00", "exception": false, - "start_time": "2026-09-18T12:51:46.232052+00:00", + "start_time": "2026-09-21T14:59:52.228894+00:00", "status": "completed" }, "tags": [] @@ -931,7 +952,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "profil J-Lens a dose fixee (8 coordonnees A x 4 bandes) en 19s\n", + "profil J-Lens a dose fixee (8 coordonnees A x 4 bandes) en 49s\n", "coords A gelees par seed : {0: (9, 11, 15, 42, 51, 53, 56, 61), 1: (18, 24, 26, 39, 45, 49, 52, 56), 2: (1, 7, 11, 14, 38, 53, 60, 61), 3: (5, 12, 14, 24, 30, 44, 49, 54), 4: (15, 16, 29, 30, 39, 44, 52, 60), 5: (15, 17, 20, 24, 25, 41, 47, 51)}\n", "effectifs donneurs A/B (seed 0) : {'L0_pre': (252, 256), 'L0_post': (252, 256), 'L1_pre': (252, 256), 'L1_post': (252, 256)}\n", "\n", @@ -942,8 +963,8 @@ "L1_post 0.0154 0.0087 0.0090 0.0076 0.0186 0.0092 0.0091\n", "etendue inter-couches par bande (seed 0) : {'bande0': 0.0, 'bande1': 0.0, 'bande2': 0.0001, 'bande3': 0.0569}\n", "\n", - "H2 couches (porteuse vs autres) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0032444230985910734, 'ci95': (-0.001885239608469728, 0.014782325378662866), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", - "H2 dissociation (A-cf vs B-cf a la porteuse) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0030679449282357053, 'ci95': (0.0014604187303133113, 0.005484326301139621), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n" + "H2 couches (porteuse vs autres) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.003244422446517728, 'ci95': (-0.001885234429827147, 0.01478230833684533), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", + "H2 dissociation (A-cf vs B-cf a la porteuse) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.003067946806795722, 'ci95': (0.0014604203429824363, 0.005484322596676801), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n" ] } ], @@ -1080,10 +1101,10 @@ "id": "f565700fc114", "metadata": { "papermill": { - "duration": 0.003543, - "end_time": "2026-09-18T12:52:05.646470+00:00", + "duration": 0.008306, + "end_time": "2026-09-21T15:00:40.847644+00:00", "exception": false, - "start_time": "2026-09-18T12:52:05.642927+00:00", + "start_time": "2026-09-21T15:00:40.839338+00:00", "status": "completed" }, "tags": [] @@ -1118,16 +1139,16 @@ "id": "e995c92afddd", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:05.654760Z", - "iopub.status.busy": "2026-09-18T12:52:05.654441Z", - "iopub.status.idle": "2026-09-18T12:52:14.457128Z", - "shell.execute_reply": "2026-09-18T12:52:14.456039Z" + "iopub.execute_input": "2026-09-21T15:00:40.865190Z", + "iopub.status.busy": "2026-09-21T15:00:40.864590Z", + "iopub.status.idle": "2026-09-21T15:00:59.223296Z", + "shell.execute_reply": "2026-09-21T15:00:59.221845Z" }, "papermill": { - "duration": 8.808143, - "end_time": "2026-09-18T12:52:14.458028+00:00", + "duration": 18.369181, + "end_time": "2026-09-21T15:00:59.224556+00:00", "exception": false, - "start_time": "2026-09-18T12:52:05.649885+00:00", + "start_time": "2026-09-21T15:00:40.855375+00:00", "status": "completed" }, "tags": [] @@ -1144,7 +1165,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 0 : bras causaux en 2s cumules\n", + "seed 0 : bras causaux en 3s cumules\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 1 : controle aleatoire apparie (rel_tol=0.5)\n" ] }, @@ -1152,7 +1179,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 1 : bras causaux en 3s cumules\n", + "seed 1 : bras causaux en 7s cumules\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 2 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1160,7 +1193,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 2 : bras causaux en 5s cumules\n", + "seed 2 : bras causaux en 9s cumules\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 3 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1168,7 +1207,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 3 : bras causaux en 6s cumules\n", + "seed 3 : bras causaux en 12s cumules\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 4 : controle aleatoire apparie (rel_tol=0.25)\n" ] }, @@ -1176,7 +1221,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 4 : bras causaux en 7s cumules\n", + "seed 4 : bras causaux en 15s cumules\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "seed 5 : controle aleatoire apparie (rel_tol=0.5)\n" ] }, @@ -1184,10 +1235,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "seed 5 : bras causaux en 9s cumules\n", + "seed 5 : bras causaux en 18s cumules\n", "\n", "Manipulation (dz_f a dose max, cible vs sham) :\n", - " cible : [1.619, 2.149, 1.513, 1.796, 1.809, 1.431]\n", + " cible : [1.619, 2.149, 1.513, 1.797, 1.809, 1.431]\n", " sham : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", " verdict selectivite (cible, dose max) : ['selective', 'selective', 'selective', 'selective', 'selective', 'selective']\n" ] @@ -1330,16 +1381,16 @@ "id": "62a3ae252bdd", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:14.468841Z", - "iopub.status.busy": "2026-09-18T12:52:14.468565Z", - "iopub.status.idle": "2026-09-18T12:52:14.483262Z", - "shell.execute_reply": "2026-09-18T12:52:14.482416Z" + "iopub.execute_input": "2026-09-21T15:00:59.246334Z", + "iopub.status.busy": "2026-09-21T15:00:59.245709Z", + "iopub.status.idle": "2026-09-21T15:00:59.272693Z", + "shell.execute_reply": "2026-09-21T15:00:59.271390Z" }, "papermill": { - "duration": 0.021108, - "end_time": "2026-09-18T12:52:14.484004+00:00", + "duration": 0.040019, + "end_time": "2026-09-21T15:00:59.273944+00:00", "exception": false, - "start_time": "2026-09-18T12:52:14.462896+00:00", + "start_time": "2026-09-21T15:00:59.233925+00:00", "status": "completed" }, "tags": [] @@ -1349,11 +1400,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "H1 cible-vs-B : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.034151581980343126, 'ci95': (0.015383038552251642, 0.051149462157821), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n", - "H1 cible-vs-rand: {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015952579200993112, 'ci95': (-0.007308046698200614, 0.04372304540464446), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", + "H1 cible-vs-B : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.03415223448759254, 'ci95': (0.015387268060927953, 0.051171946295776094), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6} | p Holm 0.125\n", + "H1 cible-vs-rand: {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015967850208906436, 'ci95': (-0.0073041828655429405, 0.043723447055806296), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6} | p Holm 0.1875\n", "\n", - "H3 selectivite comportementale (dacc_B - dacc_A > 0) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0027281746031746048, 'ci95': (-0.019965277777777776, 0.024677579365079368), 'p_signflip': 0.5, 'n_seeds_positive': 3, 'n_seeds': 6}\n", - "H3 inflation de CE cible vs random (doit rester moderee) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.015778010711073875, 'ci95': (-0.013896409422159195, 0.03339990507811308), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6}\n", + "H3 selectivite comportementale (dacc_B - dacc_A > 0) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0029761904761904786, 'ci95': (-0.02021329365079365, 0.024801587301587304), 'p_signflip': 0.5, 'n_seeds_positive': 3, 'n_seeds': 6}\n", + "H3 inflation de CE cible vs random (doit rester moderee) : {'verdict': 'INCONCLUSIVE', 'median_diff': 0.01577979139983654, 'ci95': (-0.013895385898649693, 0.03341432195156813), 'p_signflip': 0.1875, 'n_seeds_positive': 5, 'n_seeds': 6}\n", "H3 lien dose (dd_a croissant le long des doses) : {'verdict': 'SUPPORTED', 'n_seeds_monotone': 6, 'n_seeds': 6, 'frac': 1.0}\n" ] } @@ -1391,10 +1442,10 @@ "id": "64845f92da03", "metadata": { "papermill": { - "duration": 0.00355, - "end_time": "2026-09-18T12:52:14.491444+00:00", + "duration": 0.008338, + "end_time": "2026-09-21T15:00:59.291453+00:00", "exception": false, - "start_time": "2026-09-18T12:52:14.487894+00:00", + "start_time": "2026-09-21T15:00:59.283115+00:00", "status": "completed" }, "tags": [] @@ -1415,16 +1466,16 @@ "id": "0a5c2b1e735a", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:14.499540Z", - "iopub.status.busy": "2026-09-18T12:52:14.499256Z", - "iopub.status.idle": "2026-09-18T12:52:18.031505Z", - "shell.execute_reply": "2026-09-18T12:52:18.030814Z" + "iopub.execute_input": "2026-09-21T15:00:59.312070Z", + "iopub.status.busy": "2026-09-21T15:00:59.311529Z", + "iopub.status.idle": "2026-09-21T15:01:05.955118Z", + "shell.execute_reply": "2026-09-21T15:01:05.953635Z" }, "papermill": { - "duration": 3.53733, - "end_time": "2026-09-18T12:52:18.032214+00:00", + "duration": 6.655508, + "end_time": "2026-09-21T15:01:05.956277+00:00", "exception": false, - "start_time": "2026-09-18T12:52:14.494884+00:00", + "start_time": "2026-09-21T15:00:59.300769+00:00", "status": "completed" }, "tags": [] @@ -1434,7 +1485,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "batterie belief-panel en 4s\n", + "batterie belief-panel en 7s\n", " sae/etat {'verdict': 'INCONCLUSIVE', 'median_diff': 0.12165859381564645, 'ci95': (-0.03752500196818098, 0.18022894665355646), 'p_signflip': 0.0625, 'n_seeds_positive': 4, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.562528117439782, 'ci95': (0.4228988858097348, 0.7068408100875421), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'NOT_SUPPORTED', 'median_diff': -0.005631230809402435, 'ci95': (-0.04226798472083841, 0.16272968646736619), 'p_signflip': 0.59375, 'n_seeds_positive': 3, 'n_seeds': 6, 'p_holm': 0.59375}, 'p_holm': 0.25}\n", " sae/comportement {'verdict': 'INCONCLUSIVE', 'median_diff': 0.13951696242663336, 'ci95': (0.07487153147253206, 0.19476661436208656), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'vs_sham': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.25038191952986477, 'ci95': (0.1622347843899657, 0.304456363851335), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6}, 'vs_random': {'verdict': 'INCONCLUSIVE', 'median_diff': 0.0844826797353593, 'ci95': (0.032696971490721344, 0.1272756050970548), 'p_signflip': 0.0625, 'n_seeds_positive': 6, 'n_seeds': 6, 'p_holm': 0.25}, 'p_holm': 0.25, 'fvu_median': 0.46504579684296843}\n", " sae/dose {'verdict': 'SUPPORTED', 'n_seeds_monotone': 6, 'n_seeds': 6, 'frac': 1.0}\n", @@ -1459,10 +1510,10 @@ "id": "9aa2cd879082", "metadata": { "papermill": { - "duration": 0.004023, - "end_time": "2026-09-18T12:52:18.040870+00:00", + "duration": 0.008999, + "end_time": "2026-09-21T15:01:05.974040+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.036847+00:00", + "start_time": "2026-09-21T15:01:05.965041+00:00", "status": "completed" }, "tags": [] @@ -1480,16 +1531,16 @@ "id": "eab6e32ebf6e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:18.049174Z", - "iopub.status.busy": "2026-09-18T12:52:18.048854Z", - "iopub.status.idle": "2026-09-18T12:52:18.052968Z", - "shell.execute_reply": "2026-09-18T12:52:18.052269Z" + "iopub.execute_input": "2026-09-21T15:01:05.997457Z", + "iopub.status.busy": "2026-09-21T15:01:05.996854Z", + "iopub.status.idle": "2026-09-21T15:01:06.005119Z", + "shell.execute_reply": "2026-09-21T15:01:06.003702Z" }, "papermill": { - "duration": 0.009162, - "end_time": "2026-09-18T12:52:18.053506+00:00", + "duration": 0.023752, + "end_time": "2026-09-21T15:01:06.006560+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.044344+00:00", + "start_time": "2026-09-21T15:01:05.982808+00:00", "status": "completed" }, "tags": [] @@ -1524,16 +1575,16 @@ "id": "c575422a5c5c", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:18.061378Z", - "iopub.status.busy": "2026-09-18T12:52:18.061130Z", - "iopub.status.idle": "2026-09-18T12:52:18.065056Z", - "shell.execute_reply": "2026-09-18T12:52:18.064416Z" + "iopub.execute_input": "2026-09-21T15:01:06.025126Z", + "iopub.status.busy": "2026-09-21T15:01:06.024706Z", + "iopub.status.idle": "2026-09-21T15:01:06.032264Z", + "shell.execute_reply": "2026-09-21T15:01:06.030772Z" }, "papermill": { - "duration": 0.00873, - "end_time": "2026-09-18T12:52:18.065697+00:00", + "duration": 0.017757, + "end_time": "2026-09-21T15:01:06.033433+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.056967+00:00", + "start_time": "2026-09-21T15:01:06.015676+00:00", "status": "completed" }, "tags": [] @@ -1570,16 +1621,16 @@ "id": "f43f6dcee7a5", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:18.074394Z", - "iopub.status.busy": "2026-09-18T12:52:18.074126Z", - "iopub.status.idle": "2026-09-18T12:52:18.077941Z", - "shell.execute_reply": "2026-09-18T12:52:18.077350Z" + "iopub.execute_input": "2026-09-21T15:01:06.049172Z", + "iopub.status.busy": "2026-09-21T15:01:06.048589Z", + "iopub.status.idle": "2026-09-21T15:01:06.056472Z", + "shell.execute_reply": "2026-09-21T15:01:06.055158Z" }, "papermill": { - "duration": 0.009223, - "end_time": "2026-09-18T12:52:18.078581+00:00", + "duration": 0.017859, + "end_time": "2026-09-21T15:01:06.057747+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.069358+00:00", + "start_time": "2026-09-21T15:01:06.039888+00:00", "status": "completed" }, "tags": [] @@ -1616,10 +1667,10 @@ "id": "8182dcceb441", "metadata": { "papermill": { - "duration": 0.003822, - "end_time": "2026-09-18T12:52:18.086790+00:00", + "duration": 0.009435, + "end_time": "2026-09-21T15:01:06.077400+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.082968+00:00", + "start_time": "2026-09-21T15:01:06.067965+00:00", "status": "completed" }, "tags": [] @@ -1639,16 +1690,16 @@ "id": "b1dc680a842e", "metadata": { "execution": { - "iopub.execute_input": "2026-09-18T12:52:18.097086Z", - "iopub.status.busy": "2026-09-18T12:52:18.096718Z", - "iopub.status.idle": "2026-09-18T12:52:18.109624Z", - "shell.execute_reply": "2026-09-18T12:52:18.108757Z" + "iopub.execute_input": "2026-09-21T15:01:06.102496Z", + "iopub.status.busy": "2026-09-21T15:01:06.101910Z", + "iopub.status.idle": "2026-09-21T15:01:06.120983Z", + "shell.execute_reply": "2026-09-21T15:01:06.119567Z" }, "papermill": { - "duration": 0.020159, - "end_time": "2026-09-18T12:52:18.110873+00:00", + "duration": 0.034264, + "end_time": "2026-09-21T15:01:06.122210+00:00", "exception": false, - "start_time": "2026-09-18T12:52:18.090714+00:00", + "start_time": "2026-09-21T15:01:06.087946+00:00", "status": "completed" }, "tags": [] @@ -1660,26 +1711,26 @@ "text": [ "============================================================================\n", "H1 :\n", - " cible_vs_B INCONCLUSIVE med +0.0342 [+0.0154, +0.0511] p 0.0625 (Holm 0.1250)\n", + " cible_vs_B INCONCLUSIVE med +0.0342 [+0.0154, +0.0512] p 0.0625 (Holm 0.1250)\n", " cible_vs_random INCONCLUSIVE med +0.0160 [-0.0073, +0.0437] p 0.1875 (Holm 0.1875)\n", "H2 :\n", " couches_porteuse_vs_autres INCONCLUSIVE med +0.0032 [-0.0019, +0.0148] p 0.1875 (Holm 0.1875)\n", " dissociation_A_vs_B INCONCLUSIVE med +0.0031 [+0.0015, +0.0055] p 0.0625 (Holm 0.1250)\n", "H3 :\n", - " selectivite_comportementale INCONCLUSIVE med +0.0027 [-0.0200, +0.0247] p 0.5000\n", + " selectivite_comportementale INCONCLUSIVE med +0.0030 [-0.0202, +0.0248] p 0.5000\n", " preservation_perplexite INCONCLUSIVE med +0.0158 [-0.0139, +0.0334] p 0.1875\n", " lien_dose SUPPORTED (6/6 seeds monotones)\n", "H4 :\n", - " separation_geometrique NOT_SUPPORTED med -0.1598 [-0.2193, -0.1446] p 1.0000\n", + " separation_geometrique NOT_SUPPORTED med -0.1598 [-0.2192, -0.1446] p 1.0000\n", "============================================================================\n", "\n", "Accord et dissociation par instrument :\n", " F-Lens couches porteuses A/B : L1_post / L0_pre\n", " J-Lens effet A-cf par couche (median) : {'L0_pre': 0.0063, 'L0_post': 0.0039, 'L1_pre': 0.0039, 'L1_post': 0.0091}\n", - " SAE manipulation dz_f (cible, dose max) vs sham : [1.619, 2.149, 1.513, 1.796, 1.809, 1.431] / [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", + " SAE manipulation dz_f (cible, dose max) vs sham : [1.619, 2.149, 1.513, 1.797, 1.809, 1.431] / [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", "\n", "Sortie de reference (extrait verbatim) :\n", - "{\"notebook\": \"ICT-40-TriangulationCausale\", \"issue\": 15480, \"config\": {\"seeds\": [0, 1, 2, 3, 4, 5], \"n_bench\": 40000, \"seq_len\": 64, \"hop\": 16, \"steps\": 3000, \"k_sae\": 48, \"topk_sae\": 8, \"doses\": [0.25, 0.5, 0.75, 1.0], \"jlens_k\": 8, \"layer_a\": \"L1_post\", \"layer_b\": \"L0_pre\"}, \"vloss\": {\"0\": 1.8433, \"1\": 1.6821, \"2\": 1.9838, \"3\": 1.9307, \"4\": 1.8726, \"5\": 1.808}, \"verdicts\": {\"H1\": {\"cible_vs_B\": \"INCONCLUSIVE\", \"cible_vs_random\": \"INCONCLUSIVE\"}, \"H2\": {\"couches_porteuse_vs_autres\": \"INCONCLUSIVE\", \"dissociation_A_vs_B\": \"INCONCLUSIVE\"}, \"H3\": {\"selectivite_comportementale\": \"INCONCLUSIVE\", \"preservation_perplexite\": \"INCONCLUSIVE\", \"lien_dose\": \"SUPPORTED\"}, \"H4\": {\"separation_geometrique\": \"NOT_SUPPORTED\"}}, \"panel_sha256_seed0\": \"8e6bde4d12c4a256e3ff50167232e4aeb37f33611dec6c7d28f6369083d4aa9c\"}\n" + "{\"notebook\": \"ICT-40-TriangulationCausale\", \"issue\": 15480, \"config\": {\"seeds\": [0, 1, 2, 3, 4, 5], \"n_bench\": 40000, \"seq_len\": 64, \"hop\": 16, \"steps\": 3000, \"k_sae\": 48, \"topk_sae\": 8, \"doses\": [0.25, 0.5, 0.75, 1.0], \"jlens_k\": 8, \"layer_a\": \"L1_post\", \"layer_b\": \"L0_pre\"}, \"vloss\": {\"0\": 1.8433, \"1\": 1.6821, \"2\": 1.9838, \"3\": 1.9307, \"4\": 1.8726, \"5\": 1.808}, \"verdicts\": {\"H1\": {\"cible_vs_B\": \"INCONCLUSIVE\", \"cible_vs_random\": \"INCONCLUSIVE\"}, \"H2\": {\"couches_porteuse_vs_autres\": \"INCONCLUSIVE\", \"dissociation_A_vs_B\": \"INCONCLUSIVE\"}, \"H3\": {\"selectivite_comportementale\": \"INCONCLUSIVE\", \"preservation_perplexite\": \"INCONCLUSIVE\", \"lien_dose\": \"SUPPORTED\"}, \"H4\": {\"separation_geometrique\": \"NOT_SUPPORTED\"}}, \"panel_sha256_seed0\": \"2ba4c28483e3359e2d372668bc47dc515f026dab55acc3910c20df292262eb2a\"}\n" ] } ], @@ -1771,14 +1822,14 @@ }, "papermill": { "default_parameters": {}, - "duration": 318.689738, - "end_time": "2026-09-18T12:52:19.229015+00:00", + "duration": 640.657323, + "end_time": "2026-09-21T15:01:08.221021+00:00", "environment_variables": {}, "exception": null, - "input_path": "ICT-40-TriangulationCausale.ipynb", - "output_path": "ICT-40-out.ipynb", + "input_path": "ICT-40a-TriangulationCausale.ipynb", + "output_path": "ICT-40a-TriangulationCausale.ipynb", "parameters": {}, - "start_time": "2026-09-18T12:47:00.539277+00:00", + "start_time": "2026-09-21T14:50:27.563698+00:00", "version": "2.7.0" } },