Belirli bir büyüklükteki grupları sayma


21

Gruplar

Anahtar cebirinde bir grup tuple olan , bir dizi ve bir fonksiyonudur şu tutar, öyle ki:G G × G G(G,,*)G,*G,xG,G,

  • Tüm , , .G ( x y ) z = x ( y z )x,y,zG,(x*y)*z=x*(y*z)

  • Bir elemanı vardır olarak , öyle ki tüm olarak , .G x G x e = xeG,xG,x*e=x

  • Her biri için in , bir element vardır de , öyle ki .G y G x y = exG,yG,x*y=e

Sipariş bir grubun elemanlarının sayısı olarak tanımlanır .G(G,,*)G,

Her kesinlikle pozitif tamsayı , en az bir sıra grubu var . Örneğin, böyle bir gruptur, burada ve x + _ny = (x + y) \ mod n .n, ( Cı- n , + n ) Cı- N = { 0 , . . . , n - 1 } x + n y = ( x + y )nn(Cn,+n)Cn={0,...,n-1}x+ny=(x+y)şıkn

İzomorfik gruplar

Let G,: ={1,2} ve tanımlamak * ile x*y=(xxy)şık3 . Sonra 1*1=1=2*2 ve 1*2=2=2*1 .

Aynı şekilde, 0+20=0=1+21 ve 0+21=1=1+20 .

Grupların (G,,*) ve (C_2, + _ 2) öğelerinin ve işlemlerinin (C2,+2)farklı isimleri olmasına rağmen, gruplar aynı yapıyı paylaşır.

İki grup (G,1,*1) ve (G,2,*2) olduğu söylenir izomorfik bir bijection mevcutsa ϕ:G1G2 şekilde ϕ(x1y)=ϕ(x)2ϕ(y) tüm x için phi (y) , G_1x,y içinde y .G1

Aynı düzendeki tüm gruplar izomorfik değildir. Örneğin, Klein grubu , izomorfik olmayan bir grup (C4,+4) .

Görev

Bir negatif olmayan bir sayıyı kabul eden bir program ya da işlev Yazın n giriş ve baskılar veya getiriler düzenin izomorfik olmayan grupların sayısı olarak n .

Test durumları

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

( OEIS A000001'den alınmıştır )

Ek kurallar

  • Yürütme süresi veya bellek kullanımı konusunda herhangi bir sınırlama yoktur.

  • Mathematica'nınki gibi bu görevi önemsiz kılan yerleşik FiniteGroupCountyapılara izin verilmez.

  • Standart kuralları geçerlidir.


14
Tabii ki Mathematica'nın bunun için bir yerleşimi var. : /
Alex A.

1
(Sandbox yayının yorumunda gelen Peter aktaran OEIS Evrimi ): formülüne "Eğer bakarsanız '' ve 'mesela programı' bölümleri A000001 , A000003, A000019 sonra uzman yerleşiklerini kullanmayan bir cevap gerektirir çok araştırma. " (Vurgu madeni.);)
Martin Ender

12
Bazıları, yerleşik Mathematica'nın bulunmadığını söylüyor, ancak bu hala araştırmaya tabi. Diğer efsaneler Mathematica'nın programcıların zihnini okuyarak yerleşikleri yarattığını söylüyor , ancak bu henüz doğrulanmadı.
kusur

1
@flawr belgelenmemiş monkeys_on_typewritersyerleşik belgelenen yerleşik tarafından kapsanmayan her şeyi kapsar.
Seviye Nehri St

Neden (1 + 1)% 3 2 değil?
Cabbie407

Yanıtlar:


16

CJam, 189 187 bayt

Bunu açıklamak zor olacak ... Zamanın karmaşıklığı garanti edilir O(scary).

qi:N_3>{,aN*]N({{:L;N,X)-e!{X)_@+L@@t}%{X2+<z{_fe=:(:+}%:+!},}%:+}fX{:G;N3m*{_~{G@==}:F~F\1m>~F\F=}%:*},:L,({LX=LX)>1$f{\_@a\a+Ne!\f{\:M;~{M\f=z}2*\Mff==}:|{;}|}\a+}fX]:~$e`{0=1=},,}{!!}?

Yeterince cesursanız, çevrimiçi deneyin . Berbat dizüstü bilgisayarımda Java tercümanı ile 6'ya veya çevrimiçi tercümandan 5'e kadar alabilirim.

açıklama

Büyük bir matematik geçmişim yok (liseyi yeni bitirdim, CS'ye gelecek hafta üniversitede başlıyor). Öyleyse eğer hata yaparsam, açıkça söylersem ya da korkunç derecede etkisiz şekillerde şeyler yaparsam, yanımda ol.

Benim yaklaşımım kaba bir kuvvettir, ancak biraz daha zeki yapmaya çalıştım. Ana adımlar:

  1. Tüm olası işleçleri bir grup n için üretin (yani, tüm n gruplarını numaralandırın );
  2. Olası bijections tüm üret j düzenin iki grup arasında n ;
  3. Adım 1 ve 2'deki sonuçları kullanarak, iki sıra grubu n arasındaki tüm izomorfizmleri belirleyin ;
  4. 3. adımdaki sonucu kullanarak, izomorfizme kadar olan grup sayısını sayın.

Her adımın nasıl yapıldığına bakmadan önce, yoldan bazı önemsiz kodlar alalım:

qi:N_             e# Get input as integer, store in N, make a copy
     3>{...}    ? e# If N > 3, do... (see below)
            {!!}  e# Else, push !!N (0 if N=0, 1 otherwise)

Aşağıdaki algoritma n <4 ile düzgün çalışmıyor , 0 ila 3 arasındaki durumlar çift olumsuzlama ile ele alınıyor.

Şu andan itibaren, bir grubun elemanları {1, a, b, c, ...} şeklinde yazılacaktır , burada 1 kimlik elemanıdır. CJam uygulamasında, karşılık gelen elemanlar {0, 1, 2, 3, ...} olup , burada 0 , kimlik elemanıdır.

Let emri grubu için tüm olası operatörleri Yazma 1. adımdan itibaren başlamak n tüm geçerli üreten eşdeğerdir n × n Cayley tablolar . İlk satır ve sütun önemsiz: her ikisi de {1, a, b, c, ...} (soldan sağa, yukarıdan aşağıya).

      e# N is on the stack (duplicated before the if)
,a    e# Generate first row [0 1 2 3 ...] and wrap it in a list
  N*  e# Repeat row N times (placeholders for next rows)
    ] e# Wrap everything in a list
      e# First column will be taken care of later

Bir Cayley tablasının da azaltılmış bir Latin karesi olduğunu bilmek (iptal etme özelliğinden dolayı) sırayla olası tabloların oluşturulmasına izin verir. İkinci satırdan başlayarak (dizin 1), ilk sütunu dizinin değerine sabit tutmak için o satır için tüm benzersiz izinleri oluştururuz .

N({                                 }fX e# For X in [0 ... N-2]:
   {                            }%      e#   For each table in the list:
    :L;                                 e#     Assign the table to L and pop it off the stack
       N,                               e#     Push [0 ... N-1]
         X)                             e#     Push X+1
           -                            e#     Remove X+1 from [0 ... N-1]
            e!                          e#     Generate all the unique permutations of this list
              {         }%              e#     For each permutation:
               X)_                      e#       Push two copies of X+1
                  @+                    e#       Prepend X+1 to the permutation
                    L@@t                e#       Store the permutation at index X+1 in L
                          {...},        e#     Filter permutations (see below)
                                  :+    e#   Concatenate the generated tables to the table list

Elbette ki tüm bu permütasyonlar geçerli değildir: her satır ve sütun tüm elemanları bir kez içermelidir. Bu amaçla bir filtre bloğu kullanılır (gerçek bir değer permütasyonu tutar, sahte bir tanesi onu kaldırır):

X2+                 e# Push X+2
   <                e# Slice the permutations to the first X+2 rows
    z               e# Transpose rows and columns
     {        }%    e# For each column:
      _fe=          e#   Count occurences of each element
          :(        e#   Subtract 1 from counts
            :+      e#   Sum counts together
                :+  e# Sum counts from all columns together
                  ! e# Negate count sum:
                    e#   if the sum is 0 (no duplicates) the permutation is kept
                    e#   if the sum is not zero the permutation is filtered away

Üretim döngüsünün içine filtre uyguladığımı unutmayın: bu, kodu biraz daha uzun yapar (farklı oluşturma ve filtrelemeye kıyasla), ancak performansı büyük ölçüde artırır. Boyut kümesi permütasyon sayısı n olan n! , bu yüzden kısa çözüm çok fazla hafıza ve zaman gerektirecektir.

Geçerli Cayley tablolarının listesi operatörleri numaralandırmaya doğru atılmış büyük bir adımdır, ancak 2B yapı olduğundan, 3B özelliği olan ilişkilendirmeyi kontrol edemez. Yani bir sonraki adım ilişkisel olmayan fonksiyonları filtrelemektir.

{                                 }, e# For each table, keep table if result is true:
 :G;                                 e#   Store table in G, pop it off the stack
    N3m*                             e#   Generate triples [0 ... N-1]^3
        {                     }%     e#   For each triple [a b c]:
         _~                          e#     Make a copy, unwrap top one
           {    }:F                  e#     Define function F(x,y):
            G@==                     e#       x∗y (using table G)
                   ~F                e#     Push a∗(b∗c)
                     \1m>            e#     Rotate triple right by 1
                         ~           e#     Unwrap rotated triple
                          F\F        e#     Push (a∗b)∗c
                             =       e#     Push 1 if a∗(b∗c) == (a∗b)∗c (associative), 0 otherwise
                                :*   e#   Multiply all the results together
                                     e#   1 (true) only if F was associative for every [a b c]

Uf! Çok fazla iş, ama şimdi tüm n sıra gruplarını sıraladık (ya da daha iyisi, üzerindeki işlemler - ancak küme sabittir, yani aynı şey). Sonraki adım: izomorfizmleri bulun. Bir izomorfizm, bu iki grup arasında ∗ (x ∗ y) = φ (x) ∗ ∗ (y) şeklinde bir çekişmedir . CJam'da bu teklifleri oluşturmak önemsiz: Ne!bunu yapacak. Onları nasıl kontrol edebiliriz? Çözümüm, x ∗ y için Cayley tablasının iki kopyasından başlıyor . Bir kopyada φ , tüm öğelere, satır veya sütunların sırasına dokunmadan uygulanır. Bu, φ (x ∗ y) için tablo oluşturur . Oldukları gibi diğer birinde elemanları bırakılır, ancak satırlar ve sütunlar aracılığıyla eşlenir cp . Yani, satır / sütunx satır / sütun x (x) olur . Bu, φ (x) ∗ φ (y) için tablo oluşturur . Şimdi iki tabloya sahip olduğumuza göre, onları karşılaştırmalıyız: eğer aynılarsa, bir izomorfizm bulduk.

Elbette, izomorfizmi test etmek için grup çiftleri oluşturmamız gerekiyor. Grupların bütün 2 kombinasyonuna ihtiyacımız var . Görünüşe göre CJam, kombinasyonlar için operatöre sahip değil. Bunları her grubu alarak ve yalnızca listedeki takip eden öğelerle birleştirerek üretebiliriz. Eğlenceli gerçek: 2 kombinasyon sayısı n × (n - 1) / 2'dir , bu aynı zamanda ilk n - 1 doğal sayının toplamıdır . Bu sayılara üçgen sayı denir: kağıttaki algoritmayı deneyin, her sabit eleman için bir satır ve nedenini göreceksiniz.

:L                          e# List of groups is on stack, store in L
  ,(                        e# Push len(L)-1
    {                  }fX  e# For X in [0 ... len(L)-2]:
     LX=                    e#   Push the group L[X]
        LX)>                e#   Push a slice of L excluding the first X+1 elements
            1$              e#   Push a copy of L[X]
              f{...}        e#   Pass each [L[X] Y] combination to ... (see below)
                            e#   The block will give back a list of Y for isomorphic groups
                    \a+     e#   Append L[X] to the isomorphic groups
                          ] e# Wrap everything in a list

Düzeltmeleri Yukarıdaki kod çiftinin, ilk elemanı L [X] , ve diğer gruplarla birleştirir (edelim bu her bir çağrı Y ). Parite, birazdan göstereceğim izomorfizm test bloğuna geçer. Blok değerlerinin bir listesini geri verir Y olan L [X] izomorf Y . Daha sonra bu listeye L [X] eklenir. Listelerin neden bu şekilde ayarlandığını anlamadan önce, izomorfizm testine bakalım:

\_@                                      e# Push a copy of Y
   a\a+                                  e# L[X] Y -> [L[X] Y]
       Ne!                               e# Generate all bijective mappings
          \f{                    }       e# For each bijection ([L[X] Y] extra parameter):
             \:M;                        e#   Store the mapping in M, pop it off the stack
                 ~                       e#   [L[X] Y] -> L[X] Y
                  {     }2*              e#   Repeat two times (on Y):
                   M\f=                  e#     Map rows (or transposed columns)
                       z                 e#     Transpose rows and columns
                                         e#     This generates φ(x) ∗ φ(y)
                           \Mff=         e#   Map elements of L[X], generates φ(x ∗ y)
                                =        e#   Push 1 if the tables are equal, 0 otherwise
                                  :|     e#   Push 1 if at least a mapping was isomorphic, 0 otherwise
                                    {;}| e#   If no mapping was isomorphic, pop the copy of Y off the stack

Harika, şimdi [{L [0], Y1, Y2, ...}, {L [1], Y1, ...}, ...] gibi setlerin bir listesi var . Buradaki fikir, herhangi bir iki kümenin ortak olarak en az bir elemente sahip olması durumunda, geçiş özelliğine göre, iki kümedeki tüm grupların izomorfik olmasıdır. Tek bir sette toplanabilirler. As L [X] tarafından oluşturulan kombinasyonlarda asla görünmeyeceğini L [X + ...] , izomorfizmleri her set toplayarak ardına benzersiz yüzeyi olacak. Bu nedenle, izomorfizm sayısını elde etmek için, tüm izomorf gruplarında kaç grubun tam olarak bir kez göründüğünü saymak yeterlidir. Bunu yapmak için, setleri açarım, böylece [L [0], Y1, Y2, ..., L [1], Y1, ...] gibi görünürler , aynı grubun kümelerini oluşturmak için listeyi sıralarlar ve en sonunda RLE kodla.

:~            e# Unwrap sets of isomorphic groups
  $           e# Sort list
   e`         e# RLE-encode list
     {    },  e# Filter RLE elements:
      0=      e#   Get number of occurrences
        1=    e#   Keep element if occurrences == 1
            , e# Push length of filtered list
              e# This is the number of groups up to isomorphism

Hepsi bu kadar millet.


2
Bu bir açıklama heck. Güzel.
The_Basset_Hound

1
@The_Basset_Hound ... aaave şimdi bitti;)
Andrea Biondo

Kendi cevabımın rekabet dışı olduğunu düşünüyorum, bu yüzden bunu kabul ettim.
Dennis,

4

CJam, 73 bayt

0ri:Re!Rm*{:Tz0=R,=[R,Te_]m!{~ff{T==}e_}/=&},{:T,e!{:PPff{T==P#}}%$}%Q|,+

Yukarıdaki kodun zaman karmaşıklığı, O (n! N ) değerinden daha kötü .

N = 4 girişi çevrimiçi tercüman için zaten çok fazla .

Java yorumlayıcısını kullanarak, yeterli RAM ve sabrınız varsa, n = 5 girişi mümkün olabilir.

Grupları bulmak

N numaralı bir gruba (G, order ) göz önüne alındığında , φ (e) = 0 olacak şekilde rasgele bir önyargı seçebiliriz : G -> C n .

φ bir bölgesinin izomorfizm olur (G *) ve (Cı- n , * ') , biz tanımlarsak *' ile X *' y = φ (φ -1 (x) * φ -1 (y)) .

Her grup operatörleri çalışma yeterli Bu araçlar C , n , öyle ki 0 nötr bir elementtir.

Bir grup operatörün temsil edecek * de C , n dikdörtgen dizi ile T boyutlarının NxN öyle ki , T [x] [y] = x * y .

Bu tür bir dizi oluşturmak için, bir permütasyon seçerek başlayabilir C , n onun her biri için , n satır.

Bu şekilde, 0 hepsi var olacaktır sıralar (şart olmamakla birlikte tüm sütunlar üçüncü koşul (bir ters varlığı) yerine getirilecektir yani) ne olursa olsun , e olabilir.

Biz gidermek e = 0 ilk gerektirerek kolon bölgesinin T eşittir C , n . Özellikle, ikinci koşul (nötr bir elementin varlığı) geçerli olacaktır.

T'nin bir grup operatörüne karşılık geldiğini doğrulamak için, geriye kalan tek şey, ilk koşulun (ilişkiselliğin) geçerli olduğunu doğrulamaktır. Bu kontrol ile tüketilerek yapılabileceğini T [T [x] [y]] [z] == T [x] [T [y] [z]] tüm x, y, z de C , n .

İzomorfik olmayan grupları sayma

Grupları bulmak için yukarıdaki yöntem bazı izomorfik gruplar verecektir. Hangilerinin izomorfik olduğunu belirlemek yerine, her biri için tüm izomorfik grupların ailesini oluştururuz.

Bu, tüm ject : C n -> C n bijeksiyonlarını yineleyerek ve Tφ [x] [y] = φ -1 (T [φ (x)] [φ (y ile tanımlanmış ilişkili T dizisi) belirleyerek başarılabilir. )]) .

Tek yapılması gereken farklı ailelerin sayısını saymak.

Kod ne yapar?

0         e# Push 0. For input 0, the remaining code will crash, leaving
          e# this 0 on the stack.
ri:R      e# Read an integer from STDIN and save it in R.
e!        e# Push all permutations of [0 ... R-1].
Rm*       e# Push all arrays of 6 permutations of [0 ... R-1].
{         e# Filter; for each array:
  :T      e#   Save it in T.
  z0=R,=  e#   Check if the first column equals [0 ... R-1].
  [R,Te_] e#   Push [0 ... R-1] and a flattened T.
  m!{     e#   For both pairs (any order):
    ~     e#     Unwrap the pair.
    ff{   e#     For each X in the first: For each Y in the second:
      T== e#       Push T[X][Y].
    }     e#
  }/      e#
  =       e#   Check for equality, i.e., associativity.
  &       e#   Bitwise AND with the previous Boolean
},        e# Keep T iff the result was truthy.
{         e# For each kept array:
  :T      e#   Save it in T
  ,e!     e#   Push all permutations of [0 ... R-1].
  {       e#   For each permutation:
    :PP   e#     Save it in P. Push a copy.
    ff{   e#     For each X in P: For each Y in P:
      T== e#       Push T[X][Y].
      P#  e#       Find its index in P.
    }     e#
  }%      e#
  $       e#   Sort the results.
}%        e#
Q|,       e# Deduplicate and count.
+         e# Add the result to the 0 on the stack.

Güzel. "Aptal" bir kaba çalıştım ama 5'e ulaşmak zordu, bu yüzden byte'lar için işlem yaptım.
Andrea Biondo,

1

Python 2 , 515 507 bayt

  • Dennis sayesinde sekiz bayt kurtarıldı .
def F(n):
 def f(k,*s):n==len(set(s))and S.add(s);{k and f(~-k,j,*s)for j in I}
 def c(k,*G):k and{s in G or c(~-k,s,*G)for s in S}or(I in G)&all((o(x,y)in G)&any(I==o(z,x)for z in G)for x in G for y in G)and A.add(G)
 S=set();A=S-S;I=tuple(range(n));o=lambda x,y:tuple(y[x[j]]for j in I);i=lambda G,H:any(all(o(H[B[i]],H[B[j]])==H[B[[k for k in I if G[k]==o(G[i],G[j])][0]]]for i in I for j in I)for B in S);f(n);c(n);K=list(A);[G in K and{G!=H and i(G,H)and K.remove(H)for H in K}for G in A];return len(K)

Çevrimiçi deneyin!


n Σnn

Bağlantı ayrıntılı sürümü .


Emir sve Gmadde mi? Değilse def f(k,*s):...f(~-k,j,*s)...ve kullanabilirsiniz def c(k,*G):...c(~-k,s,*G).....
Dennis

@Dennis Onlar değil; Teşekkürler.
Jonathan Frech
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.