Grupy
W algebrze abstrakcyjnej grupa jest krotką , gdzie jest zbiorem, a jest funkcją tak że następujące:
Dla wszystkich w , .
Istnieje element na , że dla wszystkich w , .
Dla każdego , w , istnieje element na w taki sposób, .
Kolejność grupy jest zdefiniowana jako liczba elementów .
Dla każdej ściśle dodatniej liczby całkowitej istnieje co najmniej jedna grupa rzędu n . Na przykład, ( C, N , + n ) jest taką grupą, w której C n = { 0 , . . . , n - 1 } i x + n y = ( x + y ) .
Grupy izomorficzne
Niech i zdefiniuj ∗ przez x ∗ y = ( x × y ) . Następnie 1 ∗ 1 = 1 = 2 ∗ 2 i 1 ∗ 2 = 2 = 2 ∗ 1 .
Podobnie i 0 + 2 1 = 1 = 1 + 2 0 .
Chociaż elementy i operacje grup i ( C 2 , + 2 ) mają różne nazwy, grupy mają tę samą strukturę.
Mówi się, że dwie grupy i ( G 2 , ∗ 2 ) są izomorficzne, jeśli istnieje bijection ϕ : G 1 → G 2 taki, że ϕ ( x ∗ 1 y ) = ϕ ( x ) ∗ 2 ϕ ( y ) dla wszystkich x , y w G 1 .
Nie wszystkie grupy tego samego rzędu są izomorficzne. Na przykład grupa Kleina jest grupą rzędu 4, która nie jest izomorficzna w stosunku do .
Zadanie
Napisz program lub funkcję, która przyjmuje nieujemną liczbę całkowitą n jako dane wejściowe i wypisuje lub zwraca liczbę nieizomorficznych grup rzędu n .
Przypadki testowe
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
(pochodzi z OEIS A000001 )
Dodatkowe zasady
Nie ma żadnych limitów czasu wykonania ani użycia pamięci.
Wbudowane, które trywializują to zadanie, takie jak Mathematica
FiniteGroupCount
, nie są dozwolone.Obowiązują standardowe zasady gry w golfa .
źródło
monkeys_on_typewriters
wbudowane narzędzie obejmuje wszystko, czego nie obejmuje udokumentowane wbudowane oprogramowanie.Odpowiedzi:
CJam,
189187 bajtówTrudno to wytłumaczyć ... Gwarantowana jest złożoność czasu
O(scary)
.Jeśli masz dość odwagi, wypróbuj go online . Na moim kiepskim laptopie mogę uzyskać do 6 przy pomocy interpretera Java lub 5 przy tłumaczu online.
Wyjaśnienie
Nie mam dużego doświadczenia matematycznego (właśnie skończyłem szkołę średnią, zaczynając CS na uniwersytecie w przyszłym tygodniu). Więc miejcie mnie przy sobie, jeśli popełniam błędy, stwierdzam to, co oczywiste lub robię rzeczy w okropnie nieskuteczny sposób.
Moje podejście to brutalna siła, choć starałem się uczynić to trochę bardziej sprytnym. Główne kroki to:
Zanim spojrzymy na to, jak wykonuje się każdy krok, usuńmy z tego jakiś trywialny kod:
Poniższy algorytm nie działa poprawnie dla n <4 , przypadki od 0 do 3 są obsługiwane z podwójną negacją.
Odtąd elementy grupy będą zapisywane jako {1, a, b, c, ...} , gdzie 1 to element tożsamości. W implementacji CJam odpowiednimi elementami są {0, 1, 2, 3, ...} , gdzie 0 to element tożsamości.
Zacznijmy od kroku 1. Zapisanie wszystkich możliwych operatorów dla grupy rzędu n jest równoważne wygenerowaniu wszystkich prawidłowych tabel Cayley n × n . Pierwszy wiersz i kolumna są trywialne: oba są {1, a, b, c, ...} (od lewej do prawej, od góry do dołu).
Wiedza, że tabela Cayleya jest również zmniejszonym kwadratem łacińskim (ze względu na właściwość anulowania) pozwala generować możliwe tabele wiersz po rzędzie. Zaczynając od drugiego wiersza (indeks 1), generujemy wszystkie unikalne permutacje dla tego wiersza, utrzymując pierwszą kolumnę ustawioną na wartość indeksu.
Oczywiście nie wszystkie te permutacje są ważne: każdy wiersz i kolumna musi zawierać wszystkie elementy dokładnie jeden raz. W tym celu stosuje się blok filtra (prawdziwa wartość utrzymuje permutację, a fałsz ją usuwa):
Zauważ, że filtruję wewnątrz pętli generacyjnej: powoduje to, że kod jest nieco dłuższy (w porównaniu do odrębnego generowania i filtrowania), ale znacznie poprawia wydajność. Liczba permutacji zestawu wielkości n wynosi n! , więc krótsze rozwiązanie wymagałoby dużo pamięci i czasu.
Lista prawidłowych tabel Cayleya jest wielkim krokiem w kierunku wyliczenia operatorów, ale ponieważ jest strukturą 2D, nie może sprawdzić powiązania, które jest właściwością 3D. Kolejnym krokiem jest odfiltrowanie funkcji niepowiązanych.
Uff! Dużo pracy, ale teraz wyliczyliśmy wszystkie grupy rzędu n (lub lepiej, operacje na nim - ale zestaw jest ustalony, więc to samo). Następny krok: znajdź izomorfizmy. Izomorfizm to zderzenie między dwiema tymi grupami, tak że φ (x ∗ y) = φ (x) ∗ φ (y) . Generowanie tych bijectów w CJam jest banalne:
Ne!
zrobi to. Jak możemy to sprawdzić? Moje rozwiązanie zaczyna się od dwóch kopii tabeli Cayleya dla x ∗ y . Na jednym egzemplarzu φ jest stosowany do wszystkich elementów, bez zmiany kolejności wierszy lub kolumn. To generuje tabelę dla φ (x ∗ y) . Z drugiej strony elementy pozostały takie, jakie są, ale wiersze i kolumny są odwzorowane przez φ . To znaczy wiersz / kolumnax staje się wierszem / kolumną φ (x) . To generuje tabelę dla φ (x) ∗ φ (y) . Teraz, gdy mamy dwie tabele, musimy je po prostu porównać: jeśli są takie same, znaleźliśmy izomorfizm.Oczywiście musimy również wygenerować pary grup do przetestowania izomorfizmu. Potrzebujemy wszystkich 2 kombinacji grup. Wygląda na to, że CJam nie ma operatora dla kombinacji. Możemy je wygenerować, biorąc każdą grupę i łącząc ją tylko z następującymi po niej elementami na liście. Ciekawostka: liczba 2 kombinacji to n × (n - 1) / 2 , co jest również sumą pierwszych n - 1 liczb naturalnych. Takie liczby nazywane są liczbami trójkątnymi: wypróbuj algorytm na papierze, jeden rząd na stały element, a zobaczysz dlaczego.
Powyższy kod naprawia pierwszy element pary, L [X] , i łączy go z innymi grupami (nazwijmy każdy z tych Y ). Przekazuje parę do bloku testowego izomorfizmu, który zaraz pokażę. Blok oddaje listę wartości Y dla których L [X] jest izomorficzny Y . Następnie L [X] jest dołączany do tej listy. Zanim zrozumiemy, dlaczego listy są ustawione w taki sposób, spójrzmy na test izomorficzny:
Świetnie, teraz mamy listę zestawów takich jak [{L [0], Y1, Y2, ...}, {L [1], Y1, ...}, ...] . Chodzi o to, że według własności przechodnich, jeśli dowolne dwa zestawy mają co najmniej jeden wspólny element, wówczas wszystkie grupy w dwóch zestawach są izomorficzne. Można je agregować w jeden zestaw. Ponieważ L [X] nigdy nie pojawi się w kombinacjach generowanych przez L [X + ...] , po agregacji każdy zestaw izomorfizmów będzie miał jeden unikalny element. Aby więc uzyskać liczbę izomorfizmów, wystarczy policzyć, ile grup pojawia się dokładnie raz we wszystkich zestawach grup izomorficznych. Aby to zrobić, rozpakowuję zestawy, aby wyglądały jak [L [0], Y1, Y2, ..., L [1], Y1, ...] , posortuj listę, aby utworzyć klastry tej samej grupy i na końcu Kodowanie RLE.
To wszystko, ludzie.
źródło
CJam, 73 bajty
Złożoność czasowa powyższego kodu jest gorsza niż O (n! N ) .
Wartość wejściowa n = 4 jest już za duża dla tłumacza online .
Używając interpretera Java , wejście n = 5 może być możliwe, jeśli masz wystarczająco dużo pamięci RAM i cierpliwości.
Znajdowanie grup
Biorąc pod uwagę grupę (G, ∗) rzędu n , możemy wybrać dowolny bijection φ: G -> C n taki, że φ (e) = 0 .
φ stanie się izomorfizmem (G, ∗) i (C n , ∗ '), jeśli zdefiniujemy ∗' przez x ∗ 'y = φ (φ -1 (x) ∗ φ -1 (y)) .
Oznacza to, że wystarczy zbadać wszystkich operatorów grup w C n , aby 0 było elementem neutralnym.
Będziemy reprezentować operator grupy ∗ w C n przez prostokątny układ T o wymiarach n × n taki, że T [x] [y] = x ∗ y .
Aby wygenerować taką tablicę, możemy zacząć od wybrania permutacji C n dla każdego z jej n wierszy.
W ten sposób, 0 będzie obecny we wszystkich rzędach (ale niekoniecznie wszystkich kolumnach ), co oznacza, że trzeci warunek (istnienie odwrotności) zostaną spełnione, niezależnie e może być.
Można ustalić e = 0 , wymagając, że pierwsza kolumna z T jest równy C n . W szczególności utrzyma się drugi warunek (istnienie elementu neutralnego).
Aby sprawdzić, czy T odpowiada operatorowi grupy, wystarczy sprawdzić, czy spełniony jest pierwszy warunek (asocjatywność). Można to zrobić wyczerpująco, sprawdzając, czy T [T [x] [y]] [z] == T [x] [T [y] [z]] dla wszystkich x, y, z w C n .
Zliczanie grup nieizomorficznych
Powyższa metoda znajdowania grup da pewne grupy izomorficzne. Zamiast identyfikować, które z nich są izomorficzne, generujemy rodzinę wszystkich grup izomorficznych dla każdej z nich.
Można tego dokonać, iterując wszystkie bijectie φ: C n -> C n i określając powiązaną tablicę Tφ , zdefiniowaną przez Tφ [x] [y] = φ -1 (T [φ (x)] [φ (y )]) .
Pozostało tylko zliczyć liczbę różnych rodzin.
Co robi kod
źródło
Python 2 ,
515507 bajtówWypróbuj online!
Wykorzystanie równoważności między liczbą nieizomorficznych podgrup rzędun z Σn oraz liczba izomorficznych klas równoważności skończonych grup rzędu n .
Link do pełnej wersji .
źródło
s
iG
znaczenie? Jeśli nie, możesz użyćdef f(k,*s):...f(~-k,j,*s)...
idef c(k,*G):...c(~-k,s,*G)....
.