GameTheory 3b : Chambres, murs, codimension — les jeux à égalités comme objets botaniques
Troisième volet géométrique du chantier des jeux 2×2 — après GameTheory-03-Topology2x2-Python (la topologie des 576 jeux stricts et la grammaire des swaps) et GameTheory-03g-Deux-Especes-de-Fleches-Python (quand un swap préserve-t-il les équilibres), ce notebook décrit l’espace lui-même dans lequel ces transformations se déplacent.
La thèse, en une phrase : un jeu à égalités (tie game) n’est pas un jeu « plus flou » ou « plus général » qu’un jeu strict — c’est un objet de dimension inférieure, un mur où des chambres se touchent.
La lecture géométrique vient de la formalisation de Bruns & Kimmich (rapportée, cf. §Sources) :
les jeux stricts — aucune égalité de paiements — sont les chambres : les composantes ouvertes de l’espace des paiements ;
les jeux à égalités sont les murs : des strates de codimension ≥ 1 sur lesquelles plusieurs chambres se raccordent ;
une transformation élémentaire n’est pas un saut abstrait d’un jeu à un autre : elle traverse une face.
chambre → mur → chambre voisine
Un « objet botanique » — un jeu à égalités depuis lequel plusieurs prolongements sont possibles — n’est donc pas une définition assouplie : c’est habiter le bord. La différence entre les deux notions est la différence entre relâcher un axiome et se placer sur une strate de codimension 1.
Plan : §1 énumère les strates (les 75 ordres faibles par joueur, classés par codimension) ; §2 mesure l’incidence chambre-mur (chaque mur sépare exactement deux chambres) et le graphe des chambres ; §3 traverse un mur sur un cas complet, puis relit la grammaire des swaps de GT-21 en longueurs de Coxeter ; §4 implémente make tie / break tie, les deux opérations de Bruns-Kimmich.
Conventions reprises de GT-3/GT-21 : un jeu 2×2 ordinal = deux tables de paiements (Ligne, Colonne), chacune un 4-uplet \((r_{11}, r_{12}, r_{21}, r_{22})\) de valeurs ; jeu strict = chaque table est une permutation de \(\{1,2,3,4\}\).
0. Configuration
Notebook pur standard library (itertools, collections) — aucune dépendance. Comme GT-21, tout ce qui est affirmé ici est calculé dans ce notebook ; ce qui vient de la littérature sans dérivation locale est rapporté comme dette (§Sources).
L’espace des paiements d’un joueur est \(\mathbb{R}^4\) (une coordonnée par case de sa table 2×2). Ce qui compte pour un jeu ordinal n’est pas la valeur numérique d’une coordonnée mais son rang relativement aux trois autres. Un point de cet espace code donc un ordre faible (weak order) sur les 4 cases : soit un ordre total (les 4 valeurs distinctes — une chambre), soit un ordre avec des ex æquo (un mur).
La représentation canonique : un 4-uplet \(t\) où \(t_i = 1 + (\text{nombre de valeurs distinctes strictement inférieures à } t_i)\). Ainsi \((2,2,4,5)\), \((1,1,3,4)\) et \((7,7,8,9)\) codent le même ordre faible — deux cases liées en bas, deux cases liées au-dessus — et partagent la clé canonique \((1,1,2,3)\).
Le discret \(\{1,2,3,4\}\) de GT-3/GT-21 est le cas particulier sans ex æquo : les 24 permutations de \((1,2,3,4)\).
# === Section 1.1 : enumeration des ordres faibles sur 4 cases ===def canonique(t):"""Cle canonique d'un 4-uplet : relabelage croissant des valeurs distinctes.""" vals =sorted(set(t))returntuple(vals.index(v) +1for v in t)# Enumeration : tous les 4-uplets de {1..4} (256), projetes sur leur cle canoniqueordres_faibles =sorted({canonique(t) for t in product(range(1, 5), repeat=4)})print("Ordres faibles sur 4 cases :", len(ordres_faibles))print(" stricts (chambres potentielles) :", sum(1for t in ordres_faibles iflen(set(t)) ==4))print(" avec ex aequo (murs potentiels) :", sum(1for t in ordres_faibles iflen(set(t)) <4))
Ordres faibles sur 4 cases : 75
stricts (chambres potentielles) : 24
avec ex aequo (murs potentiels) : 51
Lecture de la sortie committée : 75 ordres faibles — c’est le nombre de Fubini\(a(4)\), le compte des partitions ordonnées d’un ensemble à 4 éléments. Ils se partagent en 24 ordres totaux (les permutations — les chambres au sens strict, inchangées depuis GT-3) et 51 ordres avec ex æquo (les murs, par joueur).
Ce simple compte situe le changement de regard : le discret de GT-3 (\(24^2 = 576\) jeux stricts) vivait dans un espace où les égalités étaient exclues par construction. En admettant les ex æquo dans la représentation, l’espace passe de \(576\) à \(75^2 = 5625\) jeux à rangs — et ces nouveaux points ne sont pas des « jeux imprécis » : ce sont des strates. Reste à leur donner une dimension.
1.2 Codimension : compter des égalités indépendantes
La codimension d’une strate est le nombre d’équations indépendantes qui la définissent — la dimension perdue. Pour un ordre faible, ce n’est pas le nombre de paires égales mais le complément du nombre de blocs :
\[\text{codim}(t) = 4 - \#\text{blocs}(t).\]
Un bloc de taille 3 (triple égalité) porte 3 paires égales mais seulement 2 équations indépendantes (\(x_a = x_b\) et \(x_b = x_c\) suffisent, la troisième s’en déduit). Confondre paires et équations est l’erreur classique — le code suivant les compte séparément pour montrer qu’elles divergent.
# === Section 1.2 : codimension vraie vs nombre de paires egales ===def nb_blocs(t):returnlen(set(t))def nb_paires_egales(t):returnsum(m * (m -1) //2for m in Counter(t).values())def codim(t):return4- nb_blocs(t)print("Type de blocs | codim | paires | exemples")print("-"*64)par_type = defaultdict(list)for t in ordres_faibles: signature =tuple(sorted(Counter(t).values(), reverse=True)) par_type[signature].append(t)for sig insorted(par_type, reverse=True): ex = par_type[sig] paires_moy =sum(nb_paires_egales(t) for t in ex) //len(ex) exemples =str(ex[0]) + (", "+str(ex[1]) iflen(ex) >1else"")print(f"blocs {str(sig):10s} ({len(ex):2d} ordres) | {4-len(sig)} | {paires_moy} | {exemples}")print()dist_codim = Counter(codim(t) for t in ordres_faibles)print("Distribution par codimension (par joueur) :", dict(sorted(dist_codim.items())))print("Verification de la somme : 24 + 36 + 14 + 1 =", sum(dist_codim.values()), "= 75 ordres faibles")
Lecture de la sortie committée : la taxonomy par taille de blocs croise les deux mesures.
blocs
codim
paires égales
compte
\((1,1,1,1)\)
0
0
24 — les chambres
\((2,1,1)\)
1
1
36 — les murs simples
\((2,2)\)
2
2
6
\((3,1)\)
2
3
8
\((4)\)
3
6
1
Les deux lignes en gras portent la leçon : le triple ex æquo (les 8 cas \((3,1)\)) diverge — 3 paires mais codimension 2 — et le quadruple ex æquo porte 6 paires pour codimension 3. La codimension est l’auche correcte : elle mesure la dimension perdue, pas le nombre de coïncidences.
L’image botanique se précise : les murs de codimension 1 sont des cloisons (36 par joueur), ceux de codimension 2 des arêtes où les cloisons se rencontrent (6+8 = 14), celui de codimension 3 un sommet (1). Un objet botanique n’est pas « un jeu imprécis » : c’est un point de l’espace des paiements situé sur cette architecture.
1.3 Les 5 625 jeux à rangs, par codimension
Un jeu complet = une paire d’ordres faibles (Ligne, Colonne). La codimension du jeu est la somme des deux : un mur de Ligne dans une chambre de Colonne est un mur de codim 1 ; deux murs simultanés donnent codim 2 ; etc.
# === Section 1.3 : distribution des jeux par codimension totale ===jeux = [(r, c) for r in ordres_faibles for c in ordres_faibles]dist_jeux = Counter(codim(r) + codim(c) for r, c in jeux)print("Jeux a rangs (paires d'ordres faibles) :", len(jeux))print()print("codim | jeux | remarque")print("-"*56)remarques = {0: "les 576 chambres strictes (univers GT-3 / GT-21)",1: "murs simples : un seul ex aequo, d'un seul cote",2: "murs doubles : deux ex aequo (eventuellement croises)",6: "les deux tables entierement plates (jeu unique)"}for k insorted(dist_jeux):print(f" {k} | {dist_jeux[k]:5d} | {remarques.get(k, '')}")print()print("Total :", sum(dist_jeux.values()), "= 75 x 75 attendu")print("Chambres strictes :", dist_jeux[0], "-- coherentes avec GT-3 (576) et GT-21")
Jeux a rangs (paires d'ordres faibles) : 5625
codim | jeux | remarque
--------------------------------------------------------
0 | 576 | les 576 chambres strictes (univers GT-3 / GT-21)
1 | 1728 | murs simples : un seul ex aequo, d'un seul cote
2 | 1968 | murs doubles : deux ex aequo (eventuellement croises)
3 | 1056 |
4 | 268 |
5 | 28 |
6 | 1 | les deux tables entierement plates (jeu unique)
Total : 5625 = 75 x 75 attendu
Chambres strictes : 576 -- coherentes avec GT-3 (576) et GT-21
Lecture de la sortie committée : l’univers des jeux à rangs compte 5 625 états. Les 576 chambres strictes — tout l’univers de GT-3 et de GT-21 — n’en occupent que 10,2 %. Les 1 728 jeux de codimension 1 sont les murs simples ; 1 968 de codim 2 ; le reste s’étage jusqu’au jeu totalement plat (codim 6), unique, où chaque joueur est indifférent entre les quatre cases.
Autrement dit : le discret dans lequel la série a travaillé jusqu’ici était le squelette ouvert d’un édifice dont les murs, arêtes et sommets — 89,8 % des états à rangs — n’avaient pas de nom. La suite leur donne un rôle structurel : ce sont eux qui raccordent les chambres.
2. L’incidence chambre-mur
2.1 Chaque mur simple sépare exactement deux chambres
Un mur de codimension 1 (un seul ex æquo, d’un seul côté) est une cloison : la briser dans un sens ou dans l’autre donne exactement deux chambres. Réciproquement, depuis une chambre, quels murs touche-t-on ? Pas tous : pour que deux cases puissent se rencontrer, il faut qu’aucune autre valeur ne soit strictement comprise entre les leurs — sinon le mouvement croiserait d’autres murs d’abord. Les facettes d’une chambre correspondent aux paires de valeurs adjacentes dans son ordre.
Le code suivant mesure l’incidence dans les deux directions.
# === Section 2.1 : incidence double-face chambre <-> mur ===chambres = [t for t in ordres_faibles if codim(t) ==0] # 24 permutationsmurs_simples = [t for t in ordres_faibles if codim(t) ==1] # 36def briser_le_tie(t):"""Les deux chambres strictes adjacentes au mur simple t (cote de t seul).""" c = Counter(t) v_tie = [k for k, m in c.items() if m ==2][0] i, j = [p for p inrange(4) if t[p] == v_tie] # les deux cases liees below =sorted([p for p inrange(4) if t[p] < v_tie], key=lambda p: t[p]) above =sorted([p for p inrange(4) if t[p] > v_tie], key=lambda p: t[p])# chambre A : i passe devant j ; chambre B : j devant i -- au NIVEAU du tiedef rangs(ordre_positions): rk = [0] *4for k, p inenumerate(ordre_positions): rk[p] = k +1returntuple(rk) A = rangs(below + [i, j] + above) B = rangs(below + [j, i] + above)return A, B# mur -> chambresincidences_mur = {t: briser_le_tie(t) for t in murs_simples}toutes_distinctes =all(a != b for a, b in incidences_mur.values())print("Murs simples par cote :", len(murs_simples))print("Chaque mur touche exactement 2 chambres distinctes :", toutes_distinctes)# chambre -> murs (facettes)facettes = defaultdict(list)for t, (a, b) in incidences_mur.items(): facettes[a].append(t) facettes[b].append(t)print("Facettes par chambre :", dict(Counter(len(v) for v in facettes.values())),"(3 attendu : les 3 paires de valeurs adjacentes)")
Murs simples par cote : 36
Chaque mur touche exactement 2 chambres distinctes : True
Facettes par chambre : {3: 24} (3 attendu : les 3 paires de valeurs adjacentes)
Lecture de la sortie committée : la double incidence est exacte.
Mur → chambres : chacun des 36 murs simples d’un côté touche exactement 2 chambres distinctes — les deux résolutions de son ex æquo. Une cloison n’a jamais trois pièces de chaque côté.
Chambre → murs : chacune des 24 chambres a exactement 3 facettes — les 3 paires de valeurs adjacentes de son ordre. Une paire non adjacente (les valeurs 1 et 3, avec 2 entre elles) ne définit pas une facette : pour amener 1 et 3 à l’égalité, il faut d’abord traverser le mur où 1 rencontre 2.
C’est la structure d’arrangement d’hyperplans de l’espace des paiements (les murs étant les hyperplans \(x_i = x_j\)) — calculée ici sans en invoquer la théorie : les comptes parlent d’eux-mêmes. Au niveau du jeu complet (deux côtés), chaque chambre a donc \(3 + 3 = 6\) facettes, et le nombre de murs simples du jeu vaut \(2 \times 36 \times 24 = 1728\).
Remarque de parité avec GT-21 : le théorème « le mur ne compte que s’il est habité » de GT-21 portait sur les meilleures réponses (quelles stratégies habitent la colonne traversée) ; ici l’habitation est géométrique — quelles chambres touchent le mur. Les deux lectures se complètent : GT-21 dit quand un swap change les équilibres, GT-3b dit où le swap se déplace.
2.2 Le graphe des chambres : connexité et diamètre
Déclarer que les murs « raccordent » les chambres donne un graphe : les sommets sont les 576 chambres, une arête par mur simple traversé. La bonne nouvelle pour la grammaire des swaps : ce graphe est connexe — n’importe quel jeu strict est atteignable depuis n’importe quel autre en traversant des murs un à un.
# === Section 2.2 : BFS sur le graphe des chambres ===def swap_valeurs_adjacentes(t, k):"""Echange les cases portant les valeurs k et k+1 (traversee de la facette k<->k+1).""" pk, pk1 = t.index(k), t.index(k +1) l =list(t) l[pk], l[pk1] = l[pk1], l[pk]returntuple(l)adjacences = {t: [swap_valeurs_adjacentes(t, k) for k in (1, 2, 3)] for t in chambres}# BFS cote 1 joueur, depuis (1,2,3,4)depart = (1, 2, 3, 4)dist = {depart: 0}q = deque([depart])while q: u = q.popleft()for v in adjacences[u]:if v notin dist: dist[v] = dist[u] +1 q.append(v)print("Cote 1 joueur : connexe =", len(dist) ==24, "| diametre =", max(dist.values()))print(" repartition des distances :", dict(sorted(Counter(dist.values()).items())))# BFS jeu complet : (row, col), 576 sommetsdep2 = ((1, 2, 3, 4), (1, 2, 3, 4))dist2 = {dep2: 0}q2 = deque([dep2])while q2: (ur, uc) = q2.popleft() d_cur = dist2[(ur, uc)] voisins_row = [(swap_valeurs_adjacentes(ur, k), uc) for k in (1, 2, 3)] voisins_col = [(ur, swap_valeurs_adjacentes(uc, k)) for k in (1, 2, 3)]for v in voisins_row + voisins_col:if v notin dist2: dist2[v] = d_cur +1 q2.append(v)print()print("Jeu complet : connexe =", len(dist2) ==576, "| diametre =", max(dist2.values()))print(" repartition :", dict(sorted(Counter(dist2.values()).items())))print(" aretes = 576 x 6 / 2 =", 576*6//2, "-- a comparer aux 1728 murs simples du 1.3")
Lecture de la sortie committée : le graphe des chambres est connexe, de diamètre 6 par côté et 12 pour le jeu complet — le pire cas étant l’ordre exactement renversé des deux tables (\(6 + 6\) inversions).
Deux régularités lisibles dans la sortie :
la distribution des distances d’un côté, \(\{0{:}1, 1{:}3, 2{:}5, 3{:}6, 4{:}5, 5{:}3, 6{:}1\}\), est symétrique : le mot le plus long (l’ordre renversé) est unique, comme le plus court (l’identité) ;
au niveau du jeu, chaque chambre a 6 voisins (3 facettes par côté), et le compte d’arêtes \(576 \times 6 / 2 = 1728\) coïncide exactement avec le nombre de murs simples comptés au §1.3 — chaque mur simple est une arête du graphe, chaque arête est la traversée d’un mur. Le pont entre le comptage de strates (§1) et la connectivité (§2) est un double-comptage propre.
Conséquence pour la série : le discret \(\{1,2,3,4\}\) de GT-3 n’était pas un artefact de commodité — c’est un transversal des chambres (un point par chambre), et la connexité ci-dessus garantit que la grammaire des swaps adjacents suffit à relier tout l’univers strict.
3. Traverser un mur : chambre → mur → chambre
3.1 Un cas complet, matrices à l’appui
Prenons le Dilemme du Prisonnier dans l’encodage ordinal de GT-21 — Ligne \((3,1,4,2)\), Colonne \((3,4,1,2)\) — et suivons le swap de valeurs adjacentes \(R(3,4)\) (Ligne échange les cases portant 3 et 4). Ce swap traverse la facette où les deux cases porteuses deviennent égales : le mur \(r_{11} = r_{21}\).
# === Section 3.1 : traverser le mur r11=r21 depuis le Dilemme du Prisonnier ===def afficher_jeu(nom, row, col):print(nom)print(f" Ligne | {row[0]:>2}{row[1]:<2}| Colonne | {col[0]:>2}{col[1]:<2}|")print(f" | {row[2]:>2}{row[3]:<2}| | {col[2]:>2}{col[3]:<2}|")print()def faire_le_tie(t, k):"""Coalescence des valeurs k et k+1 -> mur canonique (make_tie du 4.1, cote seul)."""return canonique(tuple(k if v == k +1else v for v in t))# La chambre de depart : le PD (encodage GT-21)pd_row, pd_col = (3, 1, 4, 2), (3, 4, 1, 2)afficher_jeu("CHAMBRE A -- Dilemme du Prisonnier (strict)", pd_row, pd_col)# Le mur : coalescence des valeurs 3 et 4 de Ligne (cases r11 et r21)mur_row = faire_le_tie(pd_row, 3)afficher_jeu("MUR (codim 1) -- Ligne indifferent r11 = r21", mur_row, pd_col)# La chambre d'arrivee : resolution du tie dans l'autre senschambre_B_row = swap_valeurs_adjacentes(pd_row, 3)afficher_jeu("CHAMBRE B -- apres traversee (swap R(3,4))", chambre_B_row, pd_col)print("Verification : mur =", mur_row)print(" briser_le_tie(mur) redonne les deux faces :", briser_le_tie(mur_row))print(" chambre A :", canonique(pd_row), " chambre B :", canonique(chambre_B_row))
Lecture de la sortie committée : le triplet complet chambre A → mur → chambre B est exhibé avec les trois matrices — l’acceptation de l’exercice 2 est satisfaite et démontrée :
chambre A : le PD strict, où \(r_{21} = 4 > r_{11} = 3\) (Ligne gagne plus à dévier) ;
mur : le jeu à égalité où \(r_{11} = r_{21}\) — Ligne est exactement indifférent entre ses deux stratégies quand Colonne joue à gauche ; c’est le point de bascule où la défection cesse d’être strictement meilleure en première colonne ;
chambre B : l’ordre renversé de la paire \((3,4)\) — le swap \(R(3,4)\) de GT-21.
La dernière ligne vérifie mécaniquement la cohérence : le briser_le_tie du §2.1 appliqué au mur redonne bien les deux chambres — A et B — comme les deux faces de la cloison. Le swap de GT-21, redéfini géométriquement, est la traversée de ce mur : rien d’autre.
Fenêtre pédagogique : sur le mur, l’ensemble des meilleures réponses de Ligne en première colonne grossit (de 1 à 2 choix), puis redevient singulier de l’autre côté — avec l’autre choix. Un mur est exactement le lieu où la structure des meilleures réponses change de cardinal — la version locale du « mur habité » de GT-21.
3.2 La grammaire des swaps relue en longueurs de Coxeter
GT-21 étudiait six swaps par côté : \(R(a,b)\) pour toutes les paires de valeurs. La géométrie les sépare en deux familles :
\(|a-b| = 1\) (valeurs adjacentes) : le swap traverse un seul mur — une facette ;
\(|a-b| \geq 2\) : les valeurs sont séparées par d’autres — le swap est un raccourci qui enjambe plusieurs murs.
La longueur exacte (nombre de traversées de facettes) d’une transposition de valeurs à distance \(d\) est \(2d-1\).
# === Section 3.2 : les swaps GT-21 en longueurs de Coxeter ===print("Swap | traversees de murs | statut")print("-"*50)for (a, b) in [(1, 2), (2, 3), (3, 4), (1, 3), (2, 4), (1, 4)]: d =abs(a - b) statut ="facette (1 mur)"if d ==1elsef"raccourci ({2*d-1} murs enjambes)"print(f"R({a},{b}) | {2*d-1} | {statut}")# Verification : R(1,3) = R(1,2) puis R(2,3) puis R(1,2)def appliquer_swap(t, a, b):returntuple(b if v == a else (a if v == b else v) for v in t)t0 = (1, 2, 3, 4)direct = appliquer_swap(t0, 1, 3)compose = appliquer_swap(appliquer_swap(appliquer_swap(t0, 1, 2), 2, 3), 1, 2)print()print("R(1,3) applique a (1,2,3,4) :", direct)print("R(1,2) puis R(2,3) puis R(1,2) :", compose)print("Egalite (le raccourci = 3 facettes) :", direct == compose)
Lecture de la sortie committée : la grammaire de GT-21 se recompose géométriquement.
les trois swaps adjacents\(R(1,2)\), \(R(2,3)\), \(R(3,4)\) sont les générateurs : chacun traverse exactement un mur (une facette). Avec leurs homologues Colonne, ils engendrent tout le graphe des 576 chambres (§2.2) ;
les trois raccourcis\(R(1,3)\), \(R(2,4)\), \(R(1,4)\) enjambent respectivement 3, 3 et 5 murs. La décomposition est vérifiée dans la sortie : \(R(1,3) = R(1,2) \circ R(2,3) \circ R(1,2)\) — le raccourci et la cascade de facettes aboutissent au même 4-uplet, mais la cascade rencontre les murs intermédiaires (des jeux à égalités où la structure des meilleures réponses peut basculer), quand le raccourci les saute.
C’est la réponse géométrique à une question laissée ouverte par GT-21 : pourquoi certains swaps « ne comptent-ils » pas (préservation des équilibres) ? Parce qu’un swap n’agit sur les équilibres qu’à travers les murs qu’il traverse qui sont effectivement habités (au sens meilleures réponses de GT-21). Les facettes rencontrées par la cascade sont autant d’occasions de bascule ; le raccourci n’échantillonne que l’état final.
4. Make tie / break tie : les deux opérations de Bruns-Kimmich
4.1 Les opérations, implémentées
La description géométrique s’accompagne de deux opérations duuales (rapportées de Bruns-Kimmich, implémentées ici) :
make tie : depuis une chambre, rapprocher deux valeurs adjacentes jusqu’à l’égalité — on pose le jeu sur un mur (codim +1) ;
break tie : depuis un mur, séparer l’ex æquo dans un sens ou dans l’autre — on retombe dans l’une des deux chambres adjacentes (codim −1).
Ce sont exactement les briques des §2-3, promues au rang d’API.
# === Section 4.1 : make_tie / break_tie, operations duales ===def make_tie(jeu, cote, k):"""Coalesce les valeurs k et k+1 du cote donne -> jeu sur un mur (codim +1).""" row, col = jeu t = faire_le_tie(row, k) if cote =="ligne"else faire_le_tie(col, k)return (t, col) if cote =="ligne"else (row, t)def break_tie(jeu, cote, sens):"""Separe le premier ex aequo du cote donne, ordre 'haut' ou 'bas' -> chambre (codim -1).""" row, col = jeu t = row if cote =="ligne"else col c = Counter(t) v = [k for k, m in c.items() if m ==2]ifnot v:return jeu # pas d'ex aequo : operation identite i, j =sorted(p for p inrange(4) if t[p] == v[0]) l =list(t) l[i], l[j] = (v[0], v[0] +1) if sens =="haut"else (v[0] +1, v[0]) t2 = canonique(l)return (t2, col) if cote =="ligne"else (row, t2)# Demonstration : aller-retour complet depuis le PDpd = ((3, 1, 4, 2), (3, 4, 1, 2))mur = make_tie(pd, "ligne", 3)retour_haut = break_tie(mur, "ligne", "haut")retour_bas = break_tie(mur, "ligne", "bas")print("Chambre (PD) :", pd)print("make_tie(ligne, 3) :", mur, " (codim", codim(mur[0]) + codim(mur[1]), ")")print("break_tie(haut) :", retour_haut, "-> retrouve le PD :", retour_haut == pd)print("break_tie(bas) :", retour_bas, "-> l'autre chambre (chambre B du 3.1)")print()print("Le mur porte bien 2 sorties distinctes :", retour_haut != retour_bas)
Lecture de la sortie committée : l’aller-retour est mécaniquement vérifié. make_tie fait perdre une dimension (le jeu quitte l’ouvert des chambres pour la cloison), break_tie la rend — dans un des deux sens : la sortie haut retrouve le PD d’origine, la sortie bas atterrit dans la chambre B du §3.1. Les deux sorties sont distinctes : c’est la matérialisation calculée du « plusieurs prolongements sont possibles » de la thèse botanique.
Un jeu à égalités n’est donc pas une spécification incomplète d’un jeu strict : c’est un objet dont le type même est différent — un point de l’architecture, avec ses deux faces — et dont le prolongement exige un choix supplémentaire (un sens). Toute la différence entre assouplir une définition et habiter le bord.
4.2 Trois archétypes au bout des murs
Bruns-Kimmich (rapporté) décrivent les jeux 2×2 primitifs comme engendrés depuis des murs par make/break tie, sous trois archétypes : indépendance, coordination, échange. Nos implémentations permettent d’en donner des instanciations calculées — la définition exacte des archétypes dans la source relève de la dette de sources (§Sources) ; ce qui suit instancie chaque nom par un mur de géométrie naturelle, obtenu par make_tie et vérifié par break_tie.
# === Section 4.2 : trois instanciations (RAPPORTEES, cf. Sources) ===print("Archetype | mur obtenu (Ligne | Colonne) | geometrie du tie")print("-"*90)# Independance : mur vertical Ligne (r11 = r21) -- Ligne indifferent entre ses# deux strategies quand Colonne joue a gauchebase_ind = ((1, 3, 2, 4), (1, 3, 2, 4))mur_ind = make_tie(base_ind, "ligne", 1)print(f"Independance | {str(mur_ind[0]):18s} | {str(mur_ind[1]):18s} | vertical (r11 = r21)")# Coordination : double mur anti-diagonal (r12 = r21 chez les deux joueurs)base_co = ((1, 2, 3, 4), (1, 2, 3, 4))mur_co = make_tie(make_tie(base_co, "ligne", 2), "colonne", 2)print(f"Coordination | {str(mur_co[0]):18s} | {str(mur_co[1]):18s} | anti-diagonal x2, codim {codim(mur_co[0]) + codim(mur_co[1])}")# Echange : mur horizontal Ligne (r11 = r12) -- le gain de Ligne en haut ne# depend pas de la colonne de Colonnebase_ech = ((1, 2, 3, 4), (2, 1, 4, 3))mur_ech = make_tie(base_ech, "ligne", 1)print(f"Echange | {str(mur_ech[0]):18s} | {str(mur_ech[1]):18s} | horizontal (r11 = r12)")print()print("Chaque mur se brise dans 2 sens -> chaque archetype borde 2 familles de jeux stricts.")print("(Instanciations de notre cru ; la definition source des archetypes : dette, cf. Sources.)")
Archetype | mur obtenu (Ligne | Colonne) | geometrie du tie
------------------------------------------------------------------------------------------
Independance | (1, 2, 1, 3) | (1, 3, 2, 4) | vertical (r11 = r21)
Coordination | (1, 2, 2, 3) | (1, 2, 2, 3) | anti-diagonal x2, codim 2
Echange | (1, 1, 2, 3) | (2, 1, 4, 3) | horizontal (r11 = r12)
Chaque mur se brise dans 2 sens -> chaque archetype borde 2 familles de jeux stricts.
(Instanciations de notre cru ; la definition source des archetypes : dette, cf. Sources.)
Lecture de la sortie committée : chaque archétype est matérialisé par un jeu mur obtenu par calcul depuis un jeu strict :
indépendance — mur vertical de Ligne (\(r_{11} = r_{21}\)) : Ligne exactement indifférent entre ses deux stratégies face à la colonne gauche ; brisé vers le haut ou le bas, ce mur fabrique les jeux où Ligne a une préférence stricte — c’est le voisinage des décisions unilatérales ;
coordination — double mur anti-diagonal (codim 2, une arête de l’architecture) : les deux joueurs lisent leur duel sur la même paire de cases ; brisé dans le même sens des deux côtés → coordination pure, en sens opposés → conflit — le voisinage des jeux de rencontre ;
échange — mur horizontal de Ligne (\(r_{11} = r_{12}\)) : le gain de Ligne en haut ne dépend pas de l’action de Colonne ; brisé, il fabrique les jeux où l’issue dépend du croisement des deux décisions — le voisinage des marchandages.
Ces instanciations calculées bornent honnêtement ce que ce notebook établit : les opérations, les comptes, les incidences. La généalogie complète des 2×2 par archétypes — les trois primitives de Bruns-Kimmich — est rapportée, non dérivée : elle exige la source primaire (§Sources, dette n°4).
Exercices
Exercice 1 — Énumérer les murs par codimension
Reproduisez et étendez le comptage du §1 : énumérez les 75 ordres faibles, comptez-les par codimension, puis par type de blocs (tailles décroissantes). Vérifiez que la somme des comptes par type redonne 75, et que chaque type de mur \((2,1,1)\), \((2,2)\), \((3,1)\), \((4)\) est non vide.
Indice : la signature de blocs s’obtient avec Counter ; la codimension est 4 - len(set(t)). Pour le compte par type, regroupez par tuple(sorted(Counter(t).values(), reverse=True)).
Étape 1 : énumérer les 75 clés canoniques (§1.1). Étape 2 : grouper par signature. Étape 3 : afficher le compte par signature et vérifier la somme.
# Exercice 1 : enumeration des murs par codimension et par type de blocs# TODO etudiant : reproduire la table du 1.2 (75 ordres faibles, 4 signatures de murs)# Indice : signature = tuple(sorted(Counter(t).values(), reverse=True))resultat_ex1 = {} # TODO etudiant : {signature: nombre d'ordres faibles}print("Exercice 1 : a completer (compte par type de blocs)")
Exercice 1 : a completer (compte par type de blocs)
Exercice 2 — Traverser : exhiber un triplet complet
Choisissez un jeu strict qui n’est pas le PD (par exemple le jeu de la poule mouillée — vérifiez son encodage ordinal avant de l’utiliser), une de ses facettes, et exhibez le triplet (chambre A, mur, chambre B) complet avec les trois matrices, comme au §3.1.
Indice : une facette = une paire de valeurs adjacentes \((k, k+1)\) ; le mur s’obtient par faire_le_tie(table, k) ; la chambre B par swap_valeurs_adjacentes(table, k) ; vérifiez enfin que briser_le_tie(mur) contient bien les deux chambres.
Étape 1 : poser les tables du jeu choisi. Étape 2 : choisir \(k\) et construire le mur et la chambre B. Étape 3 : vérifier la double incidence avec briser_le_tie.
# Exercice 2 : exhiber chambre -> mur -> chambre pour un autre jeu# TODO etudiant : remplir les trois matrices et la verificationchambre_A =None# TODO etudiant : (row, col) du jeu strict choisimur_ex2 =None# TODO etudiant : le mur traverse (via faire_le_tie)chambre_B =None# TODO etudiant : la chambre d'arrivee (via swap_valeurs_adjacentes)print("Exercice 2 : a completer (triplet chambre-mur-chambre)")
Exercice 2 : a completer (triplet chambre-mur-chambre)
Exercice 3 — Make tie / break tie : vers les archétypes
Depuis le jeu Stag Hunt de GT-21 (Ligne \((4,1,3,2)\), Colonne \((4,3,1,2)\)), construisez par make_tie un mur de chaque type : un mur Ligne, un mur Colonne, puis un double mur (codim 2). Pour chacun, appliquez break_tie dans les deux sens et observez les deux chambres de sortie — vous venez de cartographier le voisinage d’un jeu de coordination.
Indice : le double mur s’obtient en composant deux make_tie successifs (comme au §4.2 pour la coordination). Les deux sens de break_tie doivent redonner deux jeux stricts distincts.
Étape 1 : construire les trois murs. Étape 2 : pour chacun, briser dans les deux sens. Étape 3 : vérifier que chaque paire de sorties est distincte et stricte.
# Exercice 3 : voisinage de Stag Hunt par make_tie / break_tie# TODO etudiant : les trois murs (ligne, colonne, double) et leurs sortiesmurs_ex3 =None# TODO etudiant : {nom_du_mur: jeu_mur}sorties_ex3 =None# TODO etudiant : {nom_du_mur: (sortie_haut, sortie_bas)}print("Exercice 3 : a completer (voisinage de Stag Hunt)")
Exercice 3 : a completer (voisinage de Stag Hunt)
Conclusion
Ce que ce notebook établit (tout calculé, tout vérifié dans les sorties) :
l’univers des jeux 2×2 à rangs compte \(75^2 = 5625\) états, dont les 576 jeux stricts ne sont que les chambres ouvertes (10,2 %) — le reste est l’architecture : 1728 murs simples, 1968 strates de codim 2, jusqu’au jeu totalement plat (codim 6, unique) ;
l’incidence est exacte : chaque mur simple sépare exactement 2 chambres, chaque chambre a exactement 3 facettes par côté — et les 1728 arêtes du graphe des chambres coïncident mur pour mur avec les 1728 strates de codim 1 ;
le graphe des chambres est connexe, de diamètre 6 par côté (12 pour le jeu) — avec la distribution symétrique des distances \(\{1,3,5,6,5,3,1\}\) ;
la grammaire des swaps de GT-21 se recompose : les 3 swaps adjacents sont des traversées de facettes (1 mur), les 3 autres des raccourcis (3, 3 et 5 murs enjambés), avec \(R(1,3) = R(1,2) \circ R(2,3) \circ R(1,2)\) vérifié ;
make tie / break tie sont implémentées et l’aller-retour est vérifié : un jeu à égalités est un objet biface, pas une définition relâchée.
Ce qui reste ouvert — les quatre dettes de dérivation, à honorer depuis les sources primaires avant toute affirmation publique : le quotient \(576 \to 144\) (facteur exact à re-dériver), l’action du groupe \(S_4 \times S_4\), le tore à 37 trous, et la vérification firsthand des trois arXiv. Ce notebook ne les affirme pas : il les porte comme dette.
La phrase à retenir : un objet botanique n’est pas un objet plus flou — c’est un objet de dimension inférieure, depuis lequel plusieurs prolongements sont possibles.
Sources et dettes
Bruns & Kimmich — la description géométrique (chambres/murs/strates, make/break tie, archétypes) est rapportée de leur formalisation des jeux 2×2, non dérivée de la source primaire ici (dette n°4). Tout ce que le notebook affirme chiffré (75, 5625, 1728, 3, 2, 6, 12) est calculé localement et reproductible en ré-exécutant.
Robinson & Goforth — le tableau périodique des jeux 2×2 ; ancêtre Rapoport & Guyer. (L’attribution « Gale et Morris » qui circule dans certains transcripts est une hallucination corrigée.)
Dettes ouvertes (HARD) : (1) quotient 576→144 à re-dériver ; (2) groupe \(S_4 \times S_4\) et son action ; (3) tore à 37 trous ; (4) arXiv 2309.15981, 2102.00053, 1704.02230 — identités vérifiées firsthand (passe #11168 du 2026-08-31 : Tohmé & Viglizzo 2023 · Czechowski & Piliouras 2021 · Hedges 2017) ; lecture intégrale ouverte.
Vocabulaire : volontairement minimal — chambres, murs, strates, codimension, facettes. Aucun vocabulaire faisceautique au-delà de ce que le notebook calcule.