Groupes
En algèbre abstraite, un groupe est un tuple , où est un ensemble et est une fonction telle que:
Pour tout dans , .
Il existe un élément dans tel que pour tout dans , .
Pour chaque dans , il existe un élément dans tel que .G y G x ∗ y = e
L' ordre d'un groupe est défini comme étant le nombre d'éléments de .G
Pour chaque entier strictement positif , il existe au moins un groupe d'ordre . Par exemple, est un tel groupe, où et x + _ny = (x + y) \ mod n .n ( C n , + n ) C n = { 0 , . . . , n - 1 } x + n y = ( x + y )
Groupes isomorphes
Soit et définissons par . Alors et .
De même, et .
Bien que les éléments et les opérations des groupes et aient des noms différents, les groupes partagent la même structure.
On dit que deux groupes et sont isomorphes s'il existe une bijection telle que pour tous les dans .
Tous les groupes du même ordre ne sont pas isomorphes. Par exemple, le groupe de Klein est un groupe d'ordre 4 qui n'est pas isomorphe à .
Tâche
Écrivez un programme ou une fonction qui accepte un entier non négatif n en entrée et imprime ou renvoie le nombre de groupes non isomorphes d'ordre n .
Cas de test
Input Output
0 0
1 1
2 1
3 1
4 2
5 1
6 2
7 1
8 5
9 2
10 2
11 1
12 5
13 1
14 2
15 1
16 14
17 1
18 5
19 1
20 5
(extrait de OEIS A000001 )
Règles supplémentaires
Il n'y a aucune limite sur le temps d'exécution ou l'utilisation de la mémoire.
Les éléments intégrés qui banalisent cette tâche, tels que Mathematica
FiniteGroupCount
, ne sont pas autorisés.Les règles de code-golf standard s'appliquent.
la source
monkeys_on_typewriters
documenté couvre tout ce qui n'est pas couvert par les modules intégrés documentés.Réponses:
CJam,
189187 octetsCelui-ci va être difficile à expliquer ... La complexité du temps est garantie
O(scary)
.Si vous êtes assez courageux, essayez-le en ligne . Sur mon portable merdique, je peux obtenir jusqu'à 6 avec l'interpréteur Java ou 5 dans l'interpréteur en ligne.
Explication
Je n'ai pas une grande formation en mathématiques (je viens de terminer mes études secondaires, je commence CS à l'université la semaine prochaine). Alors, soyez indulgent avec moi si je fais des erreurs, si j'énonce une évidence ou si je fais les choses de manière horriblement inefficace.
Mon approche est une force brute, bien que j'aie essayé de la rendre un peu plus intelligente. Les principales étapes sont les suivantes:
Avant d'examiner comment chaque étape est effectuée, retirons du code trivial:
L'algorithme suivant ne fonctionne pas correctement avec n <4 , les cas de 0 à 3 sont traités avec une double négation.
Désormais, les éléments d'un groupe seront écrits comme {1, a, b, c, ...} , où 1 est l'élément d'identité. Dans l'implémentation CJam, les éléments correspondants sont {0, 1, 2, 3, ...} , où 0 est l'élément d'identité.
Commençons par l'étape 1. L'écriture de tous les opérateurs possibles pour un groupe d'ordre n équivaut à générer toutes les tables Cayley n × n valides . La première ligne et la première colonne sont triviales: elles sont toutes les deux {1, a, b, c, ...} (de gauche à droite, de haut en bas).
Savoir qu'une table Cayley est aussi un carré latin réduit (en raison de la propriété d'annulation) permet de générer les tables possibles ligne par ligne. À partir de la deuxième ligne (index 1), nous générons toutes les permutations uniques pour cette ligne, en gardant la première colonne fixée à la valeur de l'index.
Bien sûr, toutes ces permutations ne sont pas valides: chaque ligne et colonne doit contenir tous les éléments exactement une fois. Un bloc filtre est utilisé à cet effet (une valeur véridique conserve la permutation, une fausse la supprime):
Notez que je filtre à l'intérieur de la boucle de génération: cela rend le code un peu plus long (par rapport à la génération et au filtrage distincts), mais améliore considérablement les performances. Le nombre de permutations d'un ensemble de taille n est n! , la solution la plus courte nécessiterait donc beaucoup de mémoire et de temps.
Une liste de tables Cayley valides est une grande étape vers l'énumération des opérateurs, mais étant une structure 2D, elle ne peut pas vérifier l'associativité, qui est une propriété 3D. La prochaine étape consiste donc à filtrer les fonctions non associatives.
Phew! Beaucoup de travail, mais maintenant nous avons énuméré tous les groupes d'ordre n (ou mieux, les opérations dessus - mais l'ensemble est fixe, c'est donc la même chose). Étape suivante: trouver des isomorphismes. Un isomorphisme est une bijection entre deux de ces groupes tels que φ (x ∗ y) = φ (x) ∗ φ (y) . Générer ces bijections dans CJam est trivial: le
Ne!
fera. Comment pouvons-nous les vérifier? Ma solution part de deux copies de la table Cayley pour x ∗ y . Sur une copie, φ est appliqué à tous les éléments, sans toucher à l'ordre des lignes ou des colonnes. Cela génère le tableau pour φ (x ∗ y) . Sur l'autre les éléments sont laissés comme ils sont, mais les lignes et les colonnes sont mises en correspondance par φ . Autrement dit, la ligne / colonnex devient la ligne / colonne φ (x) . Cela génère le tableau pour φ (x) ∗ φ (y) . Maintenant que nous avons les deux tableaux, il suffit de les comparer: s'ils sont les mêmes, nous avons trouvé un isomorphisme.Bien sûr, nous devons également générer les paires de groupes pour tester l'isomorphisme. Nous avons besoin de toutes les 2 combinaisons des groupes. On dirait que CJam n'a pas d'opérateur pour les combinaisons. Nous pouvons les générer en prenant chaque groupe et en le combinant uniquement avec les éléments qui le suivent dans la liste. Fait amusant: le nombre de 2 combinaisons est n × (n - 1) / 2 , qui est également la somme des n - 1 premiers nombres naturels. Ces nombres sont appelés nombres triangulaires: essayez l'algorithme sur papier, une ligne par élément fixe, et vous comprendrez pourquoi.
Le code ci-dessus corrige le premier élément de la paire, L [X] , et le combine avec d'autres groupes (appelons chacun de ces Y ). Il passe la paire à un bloc de test d'isomorphisme que je montrerai dans un instant. Le bloc rend une liste de valeurs de Y pour lesquels L [X] est isomorphe à Y . Ensuite, L [X] est ajouté à cette liste. Avant de comprendre pourquoi les listes sont ainsi configurées, regardons le test d'isomorphisme:
Très bien, nous avons maintenant une liste d'ensembles comme [{L [0], Y1, Y2, ...}, {L [1], Y1, ...}, ...] . L'idée ici est que, par propriété transitive, si deux ensembles ont au moins un élément en commun, alors tous les groupes des deux ensembles sont isomorphes. Ils peuvent être agrégés en un seul ensemble. Comme L [X] n'apparaîtra jamais dans les combinaisons générées par L [X + ...] , après agrégation, chaque ensemble d'isomorphismes aura un élément unique. Ainsi, pour obtenir le nombre d'isomorphismes, il suffit de compter le nombre de groupes qui apparaissent exactement une fois dans tous les ensembles de groupes isomorphes. Pour ce faire, je déballe les ensembles pour qu'ils ressemblent à [L [0], Y1, Y2, ..., L [1], Y1, ...] , trie la liste pour créer des clusters du même groupe et enfin RLE-l'encode.
C'est tout, les amis.
la source
CJam, 73 octets
La complexité temporelle du code ci-dessus est pire que O (n! N ) .
L'entrée n = 4 est déjà trop pour l' interprète en ligne .
En utilisant l' interpréteur Java , l'entrée n = 5 pourrait être possible, si vous avez suffisamment de RAM et de patience.
Trouver des groupes
Étant donné un groupe (G, ∗) d'ordre n , nous pouvons choisir une bijection arbitraire φ: G -> C n telle que φ (e) = 0 .
φ deviendra un isomorphisme de (G, ∗) et (C n , ∗ ') si nous définissons ∗' par x ∗ 'y = φ (φ -1 (x) ∗ φ -1 (y)) .
Cela signifie qu'il suffit d'étudier tous les opérateurs de groupe dans C n tels que 0 est l'élément neutre.
Nous représenterons un opérateur de groupe ∗ dans C n par un tableau rectangulaire T de dimensions n × n telles que T [x] [y] = x ∗ y .
Pour générer un tel tableau, nous pouvons commencer par choisir une permutation de C n pour chacune de ses n lignes.
De cette façon, 0 sera présent dans toutes les lignes (mais pas nécessairement toutes les colonnes ), ce qui signifie que la troisième condition (existence d'une inverse) sera remplie, quel que soit e .
On peut fixer e = 0 en exigeant que la première colonne de T soit égale à C n . En particulier, la deuxième condition (existence d'un élément neutre) sera remplie.
Pour vérifier que T correspond à un opérateur de groupe, il ne reste plus qu'à vérifier que la première condition (associativité) est vérifiée . Cela peut être fait de manière exhaustive en vérifiant que T [T [x] [y]] [z] == T [x] [T [y] [z]] pour tout x, y, z dans C n .
Comptage des groupes non isomorphes
La méthode ci-dessus pour trouver des groupes donnera certains groupes isomorphes. Plutôt que d'identifier ceux qui sont isomorphes, nous générons la famille de tous les groupes isomorphes pour chacun d'eux.
Cela peut être réalisé en itérant sur toutes les bijections φ: C n -> C n , et en déterminant le tableau associé Tφ , défini par Tφ [x] [y] = φ -1 (T [φ (x)] [φ (y )]) .
Il ne reste plus qu'à compter le nombre de familles distinctes.
Que fait le code
la source
Python 2 ,
515507 octetsEssayez-le en ligne!
Lien vers la version détaillée .
la source
s
etG
importent-ils? Sinon, vous pouvez utiliserdef f(k,*s):...f(~-k,j,*s)...
etdef c(k,*G):...c(~-k,s,*G)....
.