Automate de Collatz – Règles simplifiées
Tableau des règles
28 mars 2025 | màj le 21 avril 2025
Règle
gauche-droite
|
Action |
V-V |
Se déplace vers P + 1 |
V-F |
Se déplace vers P + 2 (voir règle V-F plus bas) |
F-V |
Reste en place |
F-F |
Reste en place et crée un nouveau pion à P + 1 |
- Ce qui détermine la règle à utiliser est uniquement la réponse à cette question : le pion considéré a-t-il un voisin de gauche/de droite distant de lui d'une seule cellule ? Cette réponse est Vrai ou Faux (V ou F). Le premier/dernier pion n'a pas de voisin de gauche/de droite, alors nous établissons plus bas une convention à son sujet.
- La distance entre deux pions consécutifs est représentée par le nombre de cellules vides qui les séparent. C'est pourquoi ils sont disposés sur les barres séparatrices et non dans les cellules.
- La variable P contient la position du pion avant son déplacement. Donc P + 1 désigne la cellule (ou barre) immédiatement à sa droite. Un pion ne se déplace jamais vers la gauche.
- V (Vrai) : voisin immédiat à une distance = 1, ou pas de voisin gauche (premier pion).
- F (Faux) : voisin immédiat à une distance > 1, ou pas de voisin droit (dernier pion).
- Règle V-F : le pion avance jusqu’à la première barre libre distante d'au moins 2 cellules, en supprimant tout pion rencontré.

Après un déplacement, le pion 0 conserve sa position 0 (la liste de positions est toujours réduite après chaque itération de l'automate). Dans notre exemple, étant donné que sa position absolue s'est incrémentée de 4, la position relative de tous ses successeurs est décrémentée d'autant lors de la réduction de la liste. L’automate est maintenant dans l’état 2^0+2^1+2^3+2^6+2^7+2^8 = 459.
- Notez que les deux règles régissant respectivement le premier et le dernier pion ne sont pas symétriques. Par convention, la première est V-x et la seconde x-F.
- Très important : la liste de positions est parcourue du dernier pion vers le premier. De ce fait, on ne peut pas établir la règle à laquelle un pion donné est soumis si on a déjà déplacé son voisin de droite. C'est la différence importante entre la manipulation des pions et la mise en oeuvre de l'algorithme Python, car ce dernier calcule le voisinage de chaque "pion" – en se basant sur sa position et celle de ses deux voisins – puis ajoute sa nouvelle position à la liste des résultats (au départ vide). La liste contenant les positions initiales et celle contenant les nouvelles positions sont donc distinctes. Bien sûr, la liste résultante devient la liste initiale à l'itération suivante. Ce problème a été résolu dans la page de l'automate par l'ajout de guides, ou "pions fantômes", qui marquent la position initiale des pions et la conservent tout au long de l'itération en mode manuel.
Lien avec la conjecture de Collatz (ou de Syracuse)
- Décomposons un entier impair en somme de puissances de 2, par exemple $89 = 2^0+2^3+2^4+2^6$.
- Dans l'automate, la liste des exposants devient celle de la position de chaque pion relativement au premier, qui représente $2^0=1$ et assure ainsi de ne traiter qu'avec des entiers impairs : $[0, 3, 4, 6]$.
- Dans une suite de Collatz, le successeur impair de $89$ est $3 \times 89+1=268$, puis $268/2=134$, puis $134/2=67$. Il faut donc 3 itérations de l'algorithme de Collatz pour passer de $89$ à $67$, représenté par $[0,1,6]$.
- De son côté, l'automate transforme $[0, 3, 4, 6]$ en $[0,1,6]$ en une seule itération.
L'algorithme de Collatz et l'automate donneront toujours strictement le même résultat impair, mais le second n'effectuera pour cela aucun calcul.
Mais que devient le cycle trivial dans cette histoire ? Nous avons dit que par convention les premier et dernier pions sont respectivement Vrai à gauche et Faux à droite, en raison de l'absence de voisin sur un côté. De ce fait, le pion unique obéit à la règle V-F, qui le fera indéfiniment avancer de deux cellules (P+2). Comme ce pion représente $2^0=1$, nous obtenons bien une répétition non-stop du 1 final.
Une infinité de possibilités
Si n est un entier impair non multiple de 3, nous savons qu'il possède une infinité de prédécesseurs impairs immédiats dans le contexte des suites de Collatz, ce qui signifie qu'une infinité d'entiers impairs ont n pour successeur immédiat. Une infinité de configurations de pions, ou états de l'automate, conduiront par conséquent à n'importe quelle configuration donnée à l'itération suivante. Voici un exemple illustrant le fait que 111, 445, 1781, 7125, 28501, 114005, ... sont des prédécesseurs de 167 :
État final
Il est important de comprendre ce qui à la dernière itération de l'automate provoque la suppression de tous les pions sauf un : l'avant-dernière itération laisse toujours plusieurs pions (le plus souvent 2) espacés deux à deux de 2 cellules (vous pouvez tester N = 349525). Cette configuration particulière est telle qu'à la prochaine itération, tous les pions sauf un seront éliminés. L'état de l'automate contenant 2 pions espacés de 2 cellules est n = 2^0+2^2 = 5. Avec 3 pions, l'automate est dans l'état n = 2^0+2^2+2^4 = 21. Avec 4 pions il sera dans l'état n = 2^0+2^2+2^4+2^6 = 85. Etc. On sait que 5, 21, 85, 341, ... sont des prédécesseurs impairs de 1 dans une suite de Collatz. À l'étape suivante ils deviendront 3n + 1 = 16, 64, 256, 1024, ..., des puissances de 2 paires qui descendront directement vers 1 à la suite d'une série de divisions par 2.
Tout en haut de la page de l'automate, tapez la liste de diffences 2,2,2,... et validez. Vous constaterez qu'à la première itération, tous ces pions, quel que soit leur nombre, seront supprimés (sauf bien sûr un). Plus important que le pion unique restant à la fin, c'est ce regroupement final des pions dont il faudrait comprendre la cause. L'automate vise ce regroupement, en quelque sorte ; il le construit étape par étape. Le 1 final est uniquement la conséquence de ce fait.
Liens
Mise en oeuvre des règles simplifiées dans une application Python (cliquez sur "Créer une copie" pour permettre son édition)
Version originale animée de l'automate
Représentation booléenne du voisinage d'un pion
Voici le code Python permettant de transformer la liste des positions de chaque pion en la liste suivante dans son évolution vers une liste à un seul élément (en l'occurrence le 1 final). Vous pouvez utiliser le premier lien ci-dessus pour le tester.
def iterer(positions):
"""
Fonction destinée à l'automate utilisant les drapeaux gauche1/droite1
(Vrai si voisin distant d'une cellule, Faux autrement).
"""
resultats = set()
n = len(positions)
for i in reversed(range(n)): # on commence par le dernier pion
pion = positions[i]
# bord gauche : forcer True pour i == 0 (aucun voisin gauche), sinon test d'adjacence
gauche1 = (i == 0) or (positions[i] - positions[i-1] == 1)
# bord droit : forcer False pour i == n-1 (aucun voisin droite), sinon test d'adjacence.
# Grâce au 'and', pas d’erreur pour i == n-1, le résultat sera Faux
droite1 = (i < n-1) and (positions[i+1] - positions[i] == 1)
if gauche1 and droite1: # cas V-V
resultats.add(pion + 1)
elif gauche1 and not droite1: # cas V-F
cible = pion + 2
while cible in resultats:
resultats.discard(cible)
cible += 1
resultats.add(cible)
elif not gauche1 and droite1: # cas F-V
resultats.add(pion)
else: # cas F-F
resultats.update([pion, pion + 1])
return sorted(resultats)
# Exemple d'entrée : positions = [0, 2, 12, 13, 15, 16] → 110597
# Résultat retourné : [0, 8, 12, 14] → 20737
# Dans une suite de Collatz, 20737 est bien le successeur impair de 110597
Un peu d'histoire
Pour mesurer l'évolution de cet algorithme depuis sa création en 2020, voici sa première approche fonctionnelle (en JavaScript). L'incroyable simplicité de la dernière version (en Python) en devient d'autant plus visible.
function transforme(S) {
if (!Array.isArray(S)) return "Erreur";
var L = S.length-1, b = false, c, d, i;
// Insérer le nouveau terme S[L]+1 à l'indice L+1.
function inserNouv() {
if (!b) S.splice(L+1,0,S[L]+1);
}
// Règles 1 et 2.
while (L > 1) {
if (S[L] - S[L-1] == 1) {
S[L] += (b ? 1 : 2); // b true ? oui, ajouter 1 : non, ajouter 2
b = true
} else {
inserNouv();
b = false
}
L--
}
inserNouv(); // L = 1, indice non traité par la boucle (non prise en compte de m = min(S)).
// Règle 3. m = m+2, puis vérifier que min(S) est bien au début de la liste.
// Si ce n'est pas le cas il est en seconde position --> inverser les 2 premiers termes.
S[0] += 2;
if (S[0] > S[1]) {
[S[0],S[1]] = [S[1],S[0]]
}
// Règle 4. Suppression des doublons. Deux termes identiques étant toujours consécutifs,
// leur différence est 0.
d = S.slice(1).map((x,i) => x-S[i]); // Différences entre les termes de S.
b = true;
while (b) {
i = d.lastIndexOf(0); // Indice du dernier 0 dans d. Renvoie -1 si aucun 0.
if (i !== -1) {
d.splice(i,1); // Supprimer ce 0
// On boucle parce que les doublons peuvent être chaînés.
c = true;
while (c) {
if (S[i] == S[i+1]) {
S.splice(i,1); // Supprimer le terme de S à la position i.
S[i]++ // Le terme suivant prend sa place. L'incrémenter.
} else c = false
}
} else b = false
}
return S
}
// Soustraction de la valeur du premier terme (le minimum) de tous les termes
function reduire(arr) {
const min = Math.min(...arr);
return arr.map(v => v - min);
}
// Le paramètre de la fonction transforme est une liste triée d'au moins deux entiers naturels,
// tous distincts, le premier étant toujours 0. Voici un exemple :
console.log(reduire(transforme([0, 2, 12, 13, 15, 16])));
// Tout comme la fonction Python ci-dessus, affiche [0, 8, 12, 14]
Conclusion
Certains se demanderont à quoi peut bien servir cet automate. La réponse est simple : si quelqu'un parvient à démontrer que les règles qui le gouvernent le conduisent à supprimer tous ses éléments sauf un, alors la conjecture de Collatz sera elle aussi démontrée.