diff --git a/MyIA.AI.Notebooks/GenAI/Plateformes-Conversationnelles/Open-WebUI/Playwright-OWUI/06-nouveautes-v0.10/06-Nouveautes-v0.10-QA-OWUI.ipynb b/MyIA.AI.Notebooks/GenAI/Plateformes-Conversationnelles/Open-WebUI/Playwright-OWUI/06-nouveautes-v0.10/06-Nouveautes-v0.10-QA-OWUI.ipynb index 677fdbebee9..db8cfe58b76 100644 --- a/MyIA.AI.Notebooks/GenAI/Plateformes-Conversationnelles/Open-WebUI/Playwright-OWUI/06-nouveautes-v0.10/06-Nouveautes-v0.10-QA-OWUI.ipynb +++ b/MyIA.AI.Notebooks/GenAI/Plateformes-Conversationnelles/Open-WebUI/Playwright-OWUI/06-nouveautes-v0.10/06-Nouveautes-v0.10-QA-OWUI.ipynb @@ -133,6 +133,16 @@ "print(\"Série :\", _redact(SERIE.name))" ] }, + { + "cell_type": "markdown", + "id": "15588aa1", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Le setup rend la localisation du module **sans exposer de chemin absolu** : `Module : 06-nouveautes-v0.10`, `Spec : 06-nouveautes.spec.ts — présent`, `Série : Playwright-OWUI`. C'est la discipline de la série entière : un banc de tests qui imprime `C:\\Users\\...` dans ses sorties rendrait les notebooks non reproductibles d'une machine à l'autre (et polluerait les attests). La ligne qui compte est `Spec : ... — présent` : le setup a trouvé le spec TypeScript que ce notebook va analyser — le carnet est la couche pédagogique posée **sur** un banc réel, pas à côté. Si cette ligne disait `absent`, tout le reste du module serait à relire : c'est la pré-condition de toutes les suivantes." + ] + }, { "cell_type": "markdown", "id": "a635be85", @@ -236,6 +246,16 @@ " print(\"Spec introuvable — voir le message de la cellule Setup.\")" ] }, + { + "cell_type": "markdown", + "id": "69024c99", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "La lecture **statique** du banc rend la structure sans l'exécuter : `2 bloc(s) describe, 7 test(s) déclaré(s)` — exactement les deux familles du §1 (`06a — API`, `06b — UI`) et les sept tests attendus, du listing mémoire (`endpoint disponible`, `cycle add/list/delete`) aux deux tests UI (raisonnement, compaction). Noter le suffixe `« v0.10 »` dans les noms de `describe` : il fait partie du **contrat** — un lecteur du rapport CI voit immédiatement ce que la tranche certifie. Et le test `dossiers d'équipe — partage entre comptes (exercice)` est déjà étiqueté « exercice » dans son nom : le banc déclare lui-même sa dépendance à une configuration que l'instance ne fournit pas toujours. Cette mesure sans exécution prépare le §5, qui rejouera le listing avec le vrai runner." + ] + }, { "cell_type": "markdown", "id": "c8c7b69f", @@ -308,6 +328,16 @@ " print(f\"{ex} -> {version_probable(ex)}\")" ] }, + { + "cell_type": "markdown", + "id": "435869f1", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Deux souvenirs, deux verdicts — et la discrimination tient tout entière dans le champ `type`. `{'id': 'a1', 'content': 'aime les schémas', 'type': 'context'} → v0.10+` : la donnée porte le champ introduit par la refonte mémoire, c'est la **preuve de version**. `{'id': 'b2', 'content': 'note libre'} → antérieure à v0.10` : la même donnée sans le champ, la signature d'une instance d'avant la refonte. Rien d'autre ne diffère entre les deux entrées — ni la longueur du contenu, ni l'id : c'est bien la **forme de la donnée** qui tranche, pas son contenu. C'est le principe de *feature detection* appliqué à une API vivante : on n'interroge pas la version par un endpoint de diagnostic, on la lit sur le premier objet créé." + ] + }, { "cell_type": "markdown", "id": "994bf7ca", @@ -378,6 +408,16 @@ " print(f\"configuré={configure}, bloc={bloc} -> {verdict_raisonnement(configure, bloc)}\")" ] }, + { + "cell_type": "markdown", + "id": "fce9d693", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "La table de décision rend trois sorties pour trois configurations — et les trois sont **licites**. `configuré=False, bloc=False → skip` : pas de modèle de raisonnement, la pré-condition du §4 manque, le test s'efface proprement. `configuré=True, bloc=True → passed` : le cas nominal, le bloc repliable s'affiche au-dessus de la réponse. Le troisième cas est le plus fin : `configuré=True, bloc=False → skip` — un modèle **configuré** mais qui n'émet pas de réflexion (par nature ou par réglage) n'est pas une régression de v0.10.2, c'est un état supporté. Distinguer ces trois cas est exactement ce qui sépare un banc robuste d'un banc qui rouge au moindre changement de modèle : chaque sortie porte sa **raison**, pas seulement un statut." + ] + }, { "cell_type": "markdown", "id": "651efb49", @@ -470,6 +510,16 @@ " \"Les titres ci-dessus (lecture du spec) suffisent pour raisonner sur le module.\")\n" ] }, + { + "cell_type": "markdown", + "id": "b4409f78", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Le listing ne **lance** rien — `--list` énumère les tests que Playwright *découvrira* : leur nom complet (`[owui] › 06-nouveautes-v0.10\\06-nouveautes.spec.ts:75:3 › ...`), leur fichier et leur ligne. Deux choses se lisent ici. D'abord la structure : les 7 tests du §2 apparaissent bien, groupés sous leurs deux `describe` (`06a — API`, `06b — UI`), plus le test d'authentification du setup. Ensuite les **numéros de ligne** (`:75:3`, `:90:3`...) : ils font du listing un **contrôle statique** — si un test disparaît du listing après une refonte du spec, c'est qu'il n'est plus déclaré, et ça se voit sans exécuter un seul navigateur. C'est le seul outil de la série qui donne une mesure de couverture (tests découverts vs tests attendus) sans coût d'exécution." + ] + }, { "cell_type": "markdown", "id": "786b7191", @@ -558,6 +608,16 @@ "print(\"\\nVerdict module 06 :\", \"VERT\" if coeur_vert else \"ROUGE\")" ] }, + { + "cell_type": "markdown", + "id": "733f43d8", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "La sortie rend le verdict en une ligne : `6 passed / 1 skipped`, puis le classement automatique — cœur API **VERT** (obligatoire), optionnel UI toléré. Le test réellement **skipped** ici est le partage d'équipe (`dossiers d'équipe — partage`), et c'est le bon skip : la §6b exige un second compte, absent de la configuration courante. Noter que « raisonnement — bloc » et « compaction » sont **passed**, pas skip : l'instance a un modèle de raisonnement configuré, la pré-condition du §4 était remplie. Le verdict `VERT` du module ne dit pas « tout est passé » : il dit **le contrat du module est tenu** — cœur vert, optionnel dans les états licites (passed ou skip motivé)." + ] + }, { "cell_type": "markdown", "id": "ccca797b", @@ -579,6 +639,16 @@ "compare au comportement attendu décrit en commentaire." ] }, + { + "cell_type": "markdown", + "id": "4e569b3b", + "metadata": {}, + "source": [ + "### Exercice 1 — isolation par nettoyage\n", + "\n", + "Mime le pattern d'isolation du §2 sur un cas réduit : `deja_nettoye=True → doit_nettoyer=?` et `deja_nettoye=False → doit_nettoyer=?`. Deux pièges à éviter en implémentant. Premièrement, la seconde combinaison est celle qui compte : le nettoyage est **inconditionnel** dans un bloc `finally` — on ne décide pas de nettoyer en regardant l'état, on nettoie parce que le test a pu créer quelque chose ; la décision `doit_nettoyer` dépend de « ai-je créé une ressource dans ce test ? », jamais de l'état global de l'instance. Deuxièmement, le placeholder rend `False` dans les deux cas parce qu'il n'a rien créé : l'exécution du squelette sert à observer le mauvais comportement, pas à le conserver — l'attendu après correction (`False` puis `True`) est rappelé en commentaire." + ] + }, { "cell_type": "code", "execution_count": 7, @@ -622,6 +692,16 @@ "# Attendu après correction : False puis True." ] }, + { + "cell_type": "markdown", + "id": "d22baa9f", + "metadata": {}, + "source": [ + "### Exercice 2 — détecter la version par la forme\n", + "\n", + "Rejoue la *feature detection* du §3 sur deux données minimales : `{'type': 'context'}` porte le champ de version → `v0.10+` ; `{}` ne porte rien → `antérieure`. La question que le placeholder laisse ouverte (`-> ?`) est le cœur du geste : la fonction doit **rendre un verdict**, pas lever — une donnée sans champ est un état documenté (instance ancienne), pas une erreur. C'est exactement la discipline qui permet à un même banc de tests de tourner sur des versions d'instance différentes sans faux rouges." + ] + }, { "cell_type": "code", "execution_count": 8, @@ -664,6 +744,16 @@ "# Attendu après correction : \"v0.10+\" puis \"antérieure\"." ] }, + { + "cell_type": "markdown", + "id": "8eef4a2f", + "metadata": {}, + "source": [ + "### Exercice 3 — skip ou échec ?\n", + "\n", + "Explore la frontière **skip vs échec**. Les trois combinaisons demandées se lisent ainsi : `précondition=False` (quel que soit le reste) → le test n'a pas son environnement, la bonne réponse est le **skip**, jamais un échec. `précondition=True, assertion=True` → passed, le cas nominal. `précondition=True, assertion=False` → c'est la **seule vraie régression** : tout est en place, la fonctionnalité ne marche pas — le test doit échouer bruyamment. Un placeholder qui rend `passed` ici est un piège pédagogique volontaire : c'est au lecteur de décider que cette case doit lever, pas s'effacer — c'est la différence entre **skip** (pré-condition non remplie) et **échec** (pré-condition remplie, assertion fausse) qui distingue un test robuste d'un test qui masque une régression." + ] + }, { "cell_type": "code", "execution_count": 9, @@ -776,4 +866,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/MyIA.AI.Notebooks/SymbolicAI/Lean/KNOTS/KNOTS-04-Geometrie-Hyperbolique-Python.ipynb b/MyIA.AI.Notebooks/SymbolicAI/Lean/KNOTS/KNOTS-04-Geometrie-Hyperbolique-Python.ipynb index c2c67301bab..6c6969baa6b 100644 --- a/MyIA.AI.Notebooks/SymbolicAI/Lean/KNOTS/KNOTS-04-Geometrie-Hyperbolique-Python.ipynb +++ b/MyIA.AI.Notebooks/SymbolicAI/Lean/KNOTS/KNOTS-04-Geometrie-Hyperbolique-Python.ipynb @@ -98,7 +98,11 @@ "tags": [] }, "source": [ - "## 1. Tétraèdres idéaux et équation de raccordement\n" + "## 1. Tétraèdres idéaux et équation de raccordement\n", + "\n", + "Un **tétraèdre idéal** a ses quatre sommets envoyés à l'infini : il ne reste que le volume, concentré dans le cœur de la variété, et les arêtes ne sont que des classes de parabolicité. C'est le brique élémentaire de la géométrie hyperbolique en dimension 3 — le théorème de géométrisation dit que tout complémentaire de nœud hyperbolique se triangule en un nombre fini de ces briques. Le nœud de huit `4_1` est le plus petit exemple non trivial : **deux** tétraèdres suffisent.\n", + "\n", + "Les formes complexes `z` de ces tétraèdres ne sont pas libres : autour de chaque arête (classe d'équivalence des arêtes par le groupe), les tétraèdres qui s'y recollent doivent faire **exactement un tour** — d'où l'équation de raccordement `z . z' . z'' = -1`, où `z'' = 1/(1-z)` est la **troisième forme de bord** de `z` (les deux autres étant `z` et `1/z̄`). Résoudre ces équations, c'est trouver LA structure hyperbolique — et SnapPy le fait numériquement à l'ouverture du manifold." ] }, { @@ -147,6 +151,16 @@ " print(\" volume (SnapPy) = {:>10}\".format(float(t[\"volume\"])))\n" ] }, + { + "cell_type": "markdown", + "id": "23386bd0", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "SnapPy triangule le complémentaire de `4_1` en **deux tétraèdres idéaux**, et rend pour chacun une forme `z = 0.5 + 0.866...i` — aux erreurs d'arrondi près (`0.49999999999999956+0.8660254037844379j` et sa voisine), c'est `e^{i.pi/3}`, la racine sixième de l'unité : le tétraèdre **idéal régulier**. Le volume par tétraèdre (`1.0149416064096537`) est déjà imprimé par le moteur : c'est le volume de Bloch-Wigner `D(e^{i.pi/3})`, que la section 2 recalculera de zéro par une voie indépendante. Les deux tétraèdres portent des formes voisines mais distinctes au dernier bit (l'une `z`, l'autre son image par `z -> 1/(1-z)` à l'arrondi près) : ce ne sont pas deux copies d'un même hasard, c'est la contrainte de raccordement qui s'annonce déjà dans les valeurs." + ] + }, { "cell_type": "code", "execution_count": 3, @@ -225,7 +239,7 @@ "source": [ "### Lecture du résultat\n", "\n", - "Les deux tétraèdres sont réguliers (formes `z = 1/2 + i*sqrt(3)/2`, c'est-à-dire un sommet d'un triangle équilatéral complexe). Le produit `z . z' . z''` est numériquement égal à `-1` (à la précision de la représentation) : **l'équation de raccordement est satisfaite**. Concrètement, le contrôle effectué est `z_0 . z_1 . (1/(1-z_0)) = -1`, équivalemment `z_1 = 1 - 1/z_0` : la forme du deuxième tétraèdre est bien la troisième forme de bord du premier. La contre-épreuve imprimée dans la même cellule (deux formes quelconques) donne un produit qui n'est pas `-1` : la relation n'est donc pas une identité algébrique, elle porte l'information de recollement propre à `4_1`. Pour le nœud de huit cela tient en deux tétraèdres car le groupe d'holonomie est dihedral d'ordre 4 et identifie les deux faces opposés.\n" + "Le produit `z . z' . z''` vaut `-0.9999999999999998 + 1.2e-15j` : numériquement `-1` à la précision de la représentation — **l'équation de raccordement est satisfaite**. Concrètement, le contrôle effectué est `z_0 . z_1 . (1/(1-z_0)) = -1`, équivalemment `z_1 = 1 - 1/z_0` : la forme du deuxième tétraèdre est bien la troisième forme de bord du premier, celle que la théorie exige pour refermer l'arête. La contre-épreuve imprimée dans la même cellule (`z . z' . (1/(1-z))` sur deux formes quelconques) rend `-0.085 + 0.323i`, un produit sans rapport avec `-1` : la relation n'est donc pas une identité algébrique, elle porte l'information de recollement propre à `4_1`. C'est tout l'enjeu : les formes de SnapPy ne sont pas décoratives, elles encodent la géométrie de la variété." ] }, { @@ -243,7 +257,13 @@ "tags": [] }, "source": [ - "## 2. Volume de Bloch-Wigner\n" + "## 2. Volume de Bloch-Wigner\n", + "\n", + "Le volume d'un tétraèdre idéal de forme `z` est donné par la fonction **Bloch-Wigner** :\n", + "\n", + "`D(z) = Im(Li₂(z)) + arg(1-z) . ln|z|`\n", + "\n", + "où `Li₂` est le dilogarithme. La partie réelle de `Li₂` n'est pas invariante sous les transformations modulaires `z → 1/z̄`, `z → 1-z` : un volume qui en dépendrait changerait avec la triangulation. La correction `arg(1-z).ln|z|` restaure l'invariance — c'est le contenu de la formule de Bloch-Wigner. Pour le tétraèdre régulier (`z = e^{iπ/3}` sur le cercle unité), le terme correctif est nul, mais l'invariance de `D` reste la raison pour laquelle on l'utilise plutôt que `Li₂` cru : le volume d'un tétraèdre ne dépend pas de l'étiquette du sommet d'où on le lit." ] }, { @@ -313,7 +333,7 @@ "source": [ "### Lecture du résultat\n", "\n", - "`D(z)` est strictement positif (environ **1.01494**, à comparer au volume `1.01494160641` rapporte par SnapPy pour chaque tétraèdre) ; le second terme est nul car `|z| = 1`. C'est ce volume de Bloch-Wigner qui sommera, sur tous les tétraèdres, au volume total de la variété.\n" + "`D(z)` vaut `1.01494160640965362502120255427...` en précision mpmath à 50 décimales, et coïncide au double près avec le volume `1.0149416064096537` que SnapPy rapportait par tétraèdre : **le volume du tétraèdre idéal régulier**. Le second terme de la définition est nul car `|z| = 1` (l'imprimé le confirme : le terme `arg(1-z)*ln|z|` vaut `0.0`) : sur le cercle unité, la partie imaginaire du dilogarithme suffit. C'est exactement pourquoi on utilise `D` et non `Li2` cru : la partie réelle de `Li2` n'est pas invariante par les transformations modulaires des formes, `D` l'est — et c'est lui qui, sommé sur tous les tétraèdres, donnera le volume total de la variété à la section suivante." ] }, { @@ -331,7 +351,9 @@ "tags": [] }, "source": [ - "## 3. Vérification croisée : `D(z)` (mpmath) vs `Manifold.tetrahedra_shapes()[i]['volume']` (SnapPy)\n" + "## 3. Vérification croisée : `D(z)` (mpmath) vs `Manifold.tetrahedra_shapes(...)`\n", + "\n", + "Une vérification qui n'implique qu'un seul outil ne vérifie que cet outil. Cette section recalcule donc le volume par **deux voies indépendantes** — le `D(z)` de mpmath construit à la section 2, et le volume rendu par le moteur SnapPy sur sa propre triangulation — et exige qu'elles coïncident au niveau du flottant. C'est le protocole qui fonde la suite du carnet : sans lui, la rigidité de Mostow de la section 5 ne serait qu'une coïncidence de plus." ] }, { @@ -455,9 +477,9 @@ "source": [ "### Lecture du résultat\n", "\n", - "La vérification croisée réussit : au niveau du tétraèdre, le volume SnapPy et `D(z)` recalculé par mpmath sont **le même flottant** (écart exactement nul), et `2 . D(z)` (mpmath, 50 décimales de précision) coïncide avec `Manifold.volume()` à mieux que `1e-10` près. Les deux routes mesurent donc bien le même objet, et toute différence entre elles serait un défaut (de précision, d'arrondi, ou d'implémentation) qui se verrait aussitôt.\n", + "La vérification croisée réussit : au niveau du tétraèdre, le volume SnapPy et `D(z)` recalculé par mpmath sont **le même flottant** (`1.0149416064096537` des deux côtés, écart exactement nul), et `2 . D(z)` (mpmath, 50 décimales) coïncide avec `Manifold.volume()` (`2.0298832128193074` contre `2.029883212819307`, écart `4.44e-16`) à mieux que `1e-10` près. Les deux routes mesurent donc bien le même objet, et toute différence entre elles serait un défaut (de précision, d'arrondi, ou d'implémentation) qui se verrait aussitôt.\n", "\n", - "Ce qui fait la portée de la vérification, c'est que les deux implémentations sont indépendantes : mpmath utilise les séries entières du dilogarithme `Li2` sur ~80 chiffres décimaux de travail ; SnapPy utilise un noyau C++ distinct. Un défaut de l'un se verrait dans la comparaison : c'est le rôle de la double route.\n" + "Ce qui fait la portée de la vérification, c'est que les deux implémentations sont indépendantes : mpmath utilise les séries entières du dilogarithme `Li2` sur ~80 chiffres décimaux de travail ; SnapPy utilise un noyau C++ distinct. Un désaccord aurait désigné une erreur dans l'une des deux — il n'y en a pas." ] }, { @@ -477,7 +499,9 @@ "source": [ "## 4. Chirurgie de Dehn\n", "\n", - "Le complémentaire d'un nœud est un solide bordé de tores : sa frontière est un tore. La chirurgie de Dehn remplace la frontière par un solide torique, en spécifiant une pente `p/q` (courbe méridien-longitude, `p/q` rationnels). Le résultat est une nouvelle 3-variété. **Thurston (1982)** : pour `p/q` suffisamment grand, le résultat est hyperbolique et son volume tend vers le volume initial quand `|p/q| -> infini`.\n" + "Le complémentaire d'un nœud est un solide bordé de tores : sa frontière est un tore, muni d'une base canonique (méridien `μ` autour du nœud, longitude `λ` le long). La **chirurgie de Dehn** `p/q` recolle sur cette frontière un solide torique en identifiant son méridien à la courbe `p.μ + q.λ` — le résultat est une nouvelle 3-variété fermée, et toute variété fermée orientable s'obtient ainsi sur un ensemble fini de complémentaires de nœuds (théorème de Lickorish-Wallace).\n", + "\n", + "**Thurston (1982)** : pour `|q|` suffisamment grand (pente « longue »), le résultat est hyperbolique, et son volume tend vers le volume du complémentaire initial quand `|p/q| → ∞`. Les petites pentes font exception : pour `4_1`, les remplissages `2/1` et `3/1` produisent des variétés **non hyperboliques** — le volume, invariant rigide, le détecte en rendant `0`, et la triangulation déclare des tétraèdres plats. La table qui suit mesure les deux régimes." ] }, { @@ -561,9 +585,9 @@ "\n", "Trois phénomènes se voient dans la table :\n", "\n", - "1. **Les remplissages exceptionnels** `2/1` et `3/1` ont un **volume nul** et un `solution_type = 'contains flat tetrahedra'` — ce ne sont pas des variétés hyperboliques. Ce sont les **remplissages non hyperboliques** que la théorie annonce : la chirurgie de Dehn ne produit pas toujours une variété hyperbolique, et ces deux pentes rappellent que le volume hyperbolique n'est alors défini par aucune formule.\n", - "2. **La convergence** vers le volume initial : `5/1` -> `7/1` -> `9/1` -> `11/1` -> `21/1` -> `51/1` -> `101/1` -> `V0 = 2.0298...`. Plus `p` est grand, plus le volume du remplissage s'approche du volume initial du complémentaire.\n", - "3. Le `dehn_fill` retourne `None` (la méthode mute l'objet en place). On travaille donc par copie profonde.\n" + "1. **Les remplissages exceptionnels** `2/1` et `3/1` ont un **volume nul** et un `solution_type = 'contains flat tetrahedra'` — ce ne sont pas des variétés hyperboliques. Ce sont les **remplissages non hyperboliques** que la théorie annonce (théorème du remplissage de Dehn) : la chirurgie ne produit pas toujours une variété hyperbolique, et ces deux pentes le rappellent — le volume hyperbolique n'y est défini par aucune formule.\n", + "2. **La convergence** vers le volume initial : `5/1` (`0.9814`) -> `7/1` (`1.4638`) -> `9/1` (`1.6678`) -> `11/1` (`1.7780`) -> `21/1` (`1.9553`) -> `51/1` (`2.0168`) -> `101/1` (`2.0265`) -> `V0 = 2.0298...`. C'est la convergence de Thurston : plus la pente est grande (plus la chirurgie est « longue »), plus le remplissage est proche de la variété de départ — et le volume croît monotone vers `V0` par en dessous, car le volume d'un remplissage ne dépasse jamais celui de la variété remplie.\n", + "3. **Le volume détecte la dégénérescence** : là où `solution_type` dit `'all tetrahedra positively oriented'`, le volume est strictement positif et la variété hyperbolique ; là où il dit `'contains flat tetrahedra'`, le volume rendu est `0.0` et le calcul n'a pas d'objet. Volume et `solution_type` racontent la même histoire par deux canaux. (Et le `dehn_fill` retourne `None` car la méthode mute l'objet en place : on travaille par copie profonde.)" ] }, { @@ -652,6 +676,16 @@ "print(\" \", mpmath.nstr(sumD, 25))\n" ] }, + { + "cell_type": "markdown", + "id": "5ea1cd28", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Trois lectures du même nombre : SnapPy direct (`2.029883212819307`), la somme `2.D(z)` recalculée par mpmath (`2.0298832128193074`), et une seconde lecture de la même triangulation (`2.029883212819307`). L'écart entre les deux premières routes est `4.44e-16` — exactement l'epsilon du double : les routes divergent au dernier bit de représentation, pas avant. En précision mpmath à 40 décimales, la route 2 rend `2.029883212819307310622555` : les quinze premiers chiffres sont stables, les suivants ne sont limités que par la précision demandée. Le test ne mesure pas « à peu près le même volume » : il mesure que deux algorithmes distincts (séries entières de `Li2` en Python arbitraire, noyau C++ de SnapPy) rendent le même objet mathématique." + ] + }, { "cell_type": "code", "execution_count": 9, @@ -699,6 +733,16 @@ "print(\"Remarque : SnapPy rend |vol| ; le signe peut s'inverser avec l'orientation\")\n" ] }, + { + "cell_type": "markdown", + "id": "c5e5878f", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Renverser l'orientation (`M_mirror.reverse_orientation()`) rend **le même volume** `2.029883212819307`, écart `0.0`. C'est une symétrie que la seule formule ne garantit pas : le volume hyperbolique est une fonction de la structure, pas de l'orientation choisie pour la décrire — un miroir changera bien d'autres invariants, mais pas celui-ci. SnapPy rend `|vol|` ; le signe, lui, est l'invariant topologique secondaire (il distingue les deux variétés miroirs), et le test montre qu'il ne contamine pas la grandeur que l'on compare. C'est la deuxième moitié de la rigidité : non seulement la structure existe (section 1), elle est mesurable de façon indépendante aux conventions." + ] + }, { "cell_type": "code", "execution_count": 10, @@ -747,6 +791,16 @@ " print(\"{} | {} | {}\".format(k.ljust(4), float(Mk.volume()), Mk.solution_type()))\n" ] }, + { + "cell_type": "markdown", + "id": "6eae8030", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Les volumes de la table sont deux à deux distincts et ordonnés par complexité : `4_1` à `2.0299` — le plus petit complément hyperbolique de nœud, c'est le théorème de Cao-Meyerhoff — puis `5_2` à `2.828`, `6_1` à `3.164`, `6_2` à `4.401`, `6_3` à `5.693`, `8_20` à `4.125`. La ligne `3_1` (volume `0.0`, `contains flat tetrahedra`) borne la table côté non hyperbolique : le trèfle torique n'entre pas dans le jeu. La distinctivité des volumes sur cet échantillon illustre la rigidité de Mostow : à topologie distincte, structure hyperbolique distincte — et donc invariant distinct." + ] + }, { "cell_type": "code", "execution_count": 11, @@ -790,6 +844,16 @@ "print(\" volume par les méthodes précédentes ne s'applique pas ici.)\")\n" ] }, + { + "cell_type": "markdown", + "id": "8a7192f2", + "metadata": {}, + "source": [ + "### Lecture du résultat\n", + "\n", + "Le témoin négatif fait son travail : `3_1` rend volume `0.0` et `solution_type = 'contains flat tetrahedra'` — deux tétraèdres **aplatis**, sans volume hyperbolique. La tentative de calcul n'échoue pas bruyamment, elle rend un état dégénéré identifiable : c'est la frontière du théorème, vérifiée depuis l'intérieur du carnet. Les méthodes des sections précédentes (formes, Bloch-Wigner, chirurgie) n'ont simplement rien à mesurer ici." + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -805,17 +869,11 @@ "tags": [] }, "source": [ - "### Lecture du résultat\n", - "\n", - "Les trois tests de la rigidité de Mostow réussissent :\n", + "## 5bis. Ce que les trois tests établissent ensemble\n", "\n", - "1. Deux routes mesurent le même volume à mieux que `1e-10` (la convergence `mpmath`/`SnapPy` du test 1).\n", - "2. Le volume est identique quand on renverse l'orientation (`M_mirror.reverse_orientation()` rend le même `volume` ; SnapPy rend `|vol|` qui est l'invariant géométrique, le signe étant l'invariant topologique secondaire).\n", - "3. Les sept nœuds hyperboliques de la table ont des volumes deux à deux distincts ; `8_21` a le plus grand volume (`6.7837...`) et `4_1` le plus petit (`2.0298...`).\n", + "Lu ensemble, les trois tests établissent l'énoncé de Mostow en acte : **le volume ne dépend ni de la route de calcul (test 1), ni de l'orientation (test 2), et il sépare les variétés (test 3)** — avec le témoin négatif `3_1` pour rappeler que tout ceci ne vaut que dans le monde hyperbolique. Autrement dit : la structure hyperbolique d'un complémentaire de nœud (à groupe fondamental donné) est unique, et tout invariant qu'on en tire est un invariant de la topologie.\n", "\n", - "Le témoin négatif `3_1` (nœud de trèfle, torique) confirme la frontière du théorème : ce n'est pas une variété hyperbolique, donc le volume par les méthodes précédentes n'a pas de sens (SnapPy le rend `0` et signale `flat tetrahedra`).\n", - "\n", - "C'est la double route qui rend la vérification numériquement recevable : sans recalculer `D(z)` par mpmath on n'aurait qu'un seul nombre ; avec les deux, on a une mesure croisée et toute dérive d'implémentation apparaît.\n" + "C'est ce qui autorise à parler DU volume de `4_1` — `2.029883212819307` — sans préciser « pour telle triangulation » : le nombre appartient à la variété, pas à l'algorithme qui l'a produit. C'est aussi la double route qui rend la vérification numériquement recevable : sans recalculer `D(z)` par mpmath, on n'aurait qu'un seul nombre ; avec les deux, on a une mesure croisée, et toute dérive d'implémentation apparaît. La table du test 3 prolonge la lecture : les volumes croissent avec la complexité du nœud, et le plus petit volume hyperbolique parmi tous les nœuds (`2.0298...`, atteint par `4_1`) est un théorème — Cao-Meyerhoff — pas une observation d'échantillon." ] }, { @@ -1053,8 +1111,7 @@ "\n", "Le tout illustre la **rigidité de Mostow en numérique** : la double route (SnapPy vs mpmath) teste l'identité du volume par deux implémentations indépendantes ; le retournement d'orientation montre l'invariance `|vol|` ; la table des nœuds distincts témoigne que la fonction `K -> vol(S^3 \\\\ K)` est presque injective. Le cas non hyperbolique `3_1` sert de témoin négatif — la thèse de Mostow ne s'applique qu'aux variétés hyperboliques, et le carnet sait le reconnaître.\n", "\n", - "***", - "\n", + "***\n", "**Suite naturelle**\n", "\n", "KNOTS-04 a mesuré la géométrie du complémentaire ; le carnet suivant demande ce que la tresse **fait quand on l’itère** : l’action d’Artin sur le groupe libre, la croissance des longueurs des mots, le spectre de Perron de la matrice de transition.\n",