การนับกลุ่มของขนาดที่กำหนด


21

กลุ่ม

ในพีชคณิตนามธรรมกลุ่มคือ tuple โดยที่Gเป็นเซตและเป็นฟังก์ชั่นG × G Gดังต่อไปนี้:(G,)GG×GG

  • สำหรับทุกในG , ( x * Y ) * Z = x * ( Y * Z )x,y,zG(xy)z=x(yz)

  • มีองค์ประกอบที่มีอยู่ในGเช่นว่าทุกxในG , x * E = xeGxGxe=x

  • สำหรับแต่ละในGมีอยู่องค์ประกอบYในGเช่นว่าx * Y =อีxGyGxy=e

การสั่งซื้อของกลุ่มถูกกำหนดให้เป็นจำนวนขององค์ประกอบของG(G,)G G

สำหรับแต่ละจำนวนเต็มบวกอย่างเคร่งครัดมีอยู่อย่างน้อยหนึ่งกลุ่มของการสั่งซื้อn ยกตัวอย่างเช่น( C n , + n )เป็นกลุ่มดังกล่าวที่C n = { 0 , . . , n - 1 }และx + n y = ( x + y )nn(Cn,+n)Cn={0,...,n1} .x+ny=(x+y)modn

กลุ่ม Isomorphic

ให้และกำหนดโดยx y = ( x × y )G:={1,2} . จากนั้น 1 * 1 = 1 = 2 * 2และ 1 * 2 = 2 = 2 * 1xy=(x×y)mod311=1=2212=2=21

Likewise, 0+20=0=1+21 and 0+21=1=1+20.

Although the elements and operations of the groups (G,) and (C2,+2) have different names, the groups share the same structure.

สองกลุ่มและ( G 2 , 2 )ถูกกล่าวว่าเป็นไอโซมอร์ฟิคหากมี bijection ϕ : G 1G 2เช่นนั้นϕ ( x 1 y ) = ϕ ( x ) 2 ϕ ( y )(G1,1)(G2,2)ϕ:G1G2ϕ(x1y)=ϕ(x)2ϕ(y) for all x,y in G1.

กลุ่มทั้งหมดที่มีลำดับเดียวกันนั้นไม่ใช่ isomorphic ยกตัวอย่างเช่นกลุ่มไคลน์เป็นกลุ่มของการสั่งซื้อ 4 ที่ไม่ได้เป็นไป isomorphic )(C4,+4)

งาน

เขียนโปรแกรมหรือฟังก์ชั่นที่ยอมรับจำนวนเต็มไม่เป็นลบnเป็น input และพิมพ์หรือส่งกลับจำนวนของกลุ่มที่ไม่ใช่ isomorphic ของการสั่งซื้อn

กรณีทดสอบ

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 )

กฎเพิ่มเติม

  • ไม่มีการ จำกัด เวลาดำเนินการหรือการใช้หน่วยความจำ

  • บิวด์อินที่FiniteGroupCountไม่ได้รับอนุญาตให้ทำภารกิจนี้เช่น Mathematica

  • ใช้กฎมาตรฐานของ


14
Of course Mathematica has a builtin for this. :/
Alex A.

1
Quoting Peter (from a comment on the sandbox post of Evolution of OEIS): "If you look at the "formula" and "program" sections for e.g. A000001, A000003, A000019 then an answer which doesn't use specialised builtins will require a lot of research." (Emphasis mine.) ;)
Martin Ender

12
Some say that there is no builtin Mathematica does not have, but this is still subject to research. Other myths say that Mathematica creates the builtins by reading the programmers mind, but this too has not yet been confirmed.
flawr

1
@flawr the undocumented monkeys_on_typewriters builtin covers everything not covered by the documented builtins.
Level River St

Why is (1+1)%3 not 2?
Cabbie407

คำตอบ:


16

CJam, 189 187 bytes

This one's gonna be tough to explain... Time complexity is guaranteed to be 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=},,}{!!}?

If you're brave enough, try it online. On my crappy laptop I can get up to 6 with the Java interpreter or 5 in the online interpreter.

Explanation

I don't have a big math background (just finished high school, starting CS at uni next week). So bear with me if I make mistakes, state the obvious, or do things in horribly inefficent ways.

My approach is a brute force, though I tried to make it a little more clever. The main steps are:

  1. Generate all the possible operands for a group of order n (i.e., enumerate all groups of order n);
  2. Generate all the possible bijections φ between two groups of order n;
  3. ใช้ผลที่ได้จากขั้นตอนที่ 1 และ 2 ที่กำหนด isomorphisms ทั้งหมดระหว่างสองกลุ่มของการสั่งซื้อn ;
  4. ใช้ผลลัพธ์จากขั้นตอนที่ 3 นับจำนวนกลุ่มจนถึงมอร์ฟิซึ่มส์

ก่อนที่จะดูวิธีการทำแต่ละขั้นตอนเราจะได้โค้ดเล็ก ๆ น้อย ๆ มาก่อน:

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)

อัลกอริทึมต่อไปนี้ทำงานไม่ถูกต้องกับn <4กรณีจาก 0 ถึง 3 ถูกจัดการด้วยการปฏิเสธคู่

จากนี้ไปองค์ประกอบของกลุ่มจะถูกเขียนเป็น{1, a, b, c, ... }โดยที่1คือองค์ประกอบตัวตน ในการใช้งาน CJam องค์ประกอบที่สอดคล้องกันคือ{0, 1, 2, 3, ... }โดยที่0คือองค์ประกอบตัวตน

เริ่มต้น Let 's จากขั้นตอนที่ 1 การเขียนผู้ประกอบการที่เป็นไปได้ทั้งหมดสำหรับกลุ่มของการสั่งซื้อnเทียบเท่ากับการสร้างทั้งหมดที่ถูกต้องn × n ตารางเคย์ลี แถวและคอลัมน์แรกนั้นเล็กน้อย: ทั้งคู่เป็น{1, a, b, c, ... } (จากซ้ายไปขวา, ขึ้น - ลง - ลง)

      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

รู้ว่าตาราง Cayley ยังเป็นตารางละตินลดลง(เนื่องจากคุณสมบัติการยกเลิก) ช่วยให้การสร้างตารางที่เป็นไปได้ทีละแถว เริ่มต้นจากแถวที่สอง (ดัชนี 1) เราสร้างการเรียงสับเปลี่ยนที่ไม่ซ้ำกันทั้งหมดสำหรับแถวนั้นโดยคงคอลัมน์แรกไว้ที่ค่าของดัชนี

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

ไม่ใช่การเรียงสับเปลี่ยนทั้งหมดที่ถูกต้องแน่นอน: แต่ละแถวและคอลัมน์จะต้องมีองค์ประกอบทั้งหมดเพียงหนึ่งครั้งเท่านั้น บล็อกตัวกรองถูกใช้เพื่อจุดประสงค์นี้ (ความจริงตามตัวอักษรจะเก็บรักษาการเปลี่ยนรูปเอาไว้ไม่ว่าจะเป็นการลบทิ้งก็ตาม):

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

โปรดทราบว่าฉันกำลังกรองภายในลูปการสร้าง: สิ่งนี้ทำให้โค้ดยาวขึ้นเล็กน้อย (เทียบกับการสร้างและการกรองที่แตกต่างกัน) แต่ปรับปรุงประสิทธิภาพอย่างมาก จำนวนการเรียงสับเปลี่ยนของชุดขนาดnคือn!ดังนั้นวิธีแก้ปัญหาที่สั้นกว่านั้นจะต้องใช้หน่วยความจำและเวลามาก

รายการตาราง Cayley ที่ถูกต้องเป็นขั้นตอนที่ยอดเยี่ยมในการแจกแจงผู้ประกอบการ แต่เป็นโครงสร้าง 2 มิติจึงไม่สามารถตรวจสอบการเชื่อมโยงได้ซึ่งเป็นคุณสมบัติ 3 มิติ ดังนั้นขั้นตอนต่อไปคือการกรองฟังก์ชั่นที่ไม่เกี่ยวข้อง

{                                 }, 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]

วุ้ย งานจำนวนมาก แต่ตอนนี้เราได้แจกแจงคำสั่งกลุ่มทั้งหมดn (หรือดีกว่าการดำเนินการบน - แต่ชุดได้รับการแก้ไขดังนั้นมันจึงเป็นสิ่งเดียวกัน) ขั้นตอนถัดไป: ค้นหามอร์ฟ มอร์ฟเป็น bijection ระหว่างสองกลุ่มเหล่านั้นเช่นว่าφ (x * y) = φ (x) * φ (y) การสร้าง bijections เหล่านั้นใน CJam นั้นเป็นเรื่องเล็กน้อย: Ne!จะทำมัน เราจะตรวจสอบพวกเขาได้อย่างไร ทางออกของฉันเริ่มต้นจากสองสำเนาของตารางสำหรับเคย์ลีx * y ที่ ในหนึ่งสำเนาφจะถูกนำไปใช้กับองค์ประกอบทั้งหมดโดยไม่ต้องสัมผัสคำสั่งของแถวหรือคอลัมน์ นี้จะสร้างตารางสำหรับφ (x * y) ในอีกองค์ประกอบหนึ่งจะถูกทิ้งให้เป็นเช่นนั้น แต่แถวและคอลัมน์ถูกแมปผ่านxกลายเป็นแถว / คอลัมน์ φ นั่นคือแถว / คอลัมน์φ (x) สิ่งนี้สร้างตารางสำหรับφ (x) ∗ φ (y)(y) ตอนนี้เรามีสองตารางเราก็ต้องเปรียบเทียบมัน: ถ้าพวกมันเหมือนกันเราได้พบมอร์ฟิซึ่มส์

แน่นอนว่าเราต้องสร้างคู่ของกลุ่มเพื่อทดสอบมอร์ฟ เราต้องการชุดค่าผสม 2 ชุดทั้งหมด ดูเหมือนว่า CJam ไม่มีโอเปอเรเตอร์สำหรับการรวมกัน เราสามารถสร้างพวกมันได้โดยนำแต่ละกลุ่มมารวมกับองค์ประกอบที่ตามมาในรายการเท่านั้น ข้อเท็จจริงที่น่าสนุก: จำนวนชุดค่าผสม 2 ชุดคือn × (n - 1) / 2ซึ่งเป็นผลรวมของจำนวนธรรมชาติแรกn - 1 ตัวเลขดังกล่าวเรียกว่าหมายเลขรูปสามเหลี่ยม: ลองใช้อัลกอริทึมบนกระดาษหนึ่งแถวต่อองค์ประกอบคงที่และคุณจะเห็นว่าทำไม

: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

รหัสด้านบนแก้ไของค์ประกอบแรกของคู่L [X]และรวมเข้ากับกลุ่มอื่น ๆ (ลองเรียกแต่ละอันของY ) มันผ่านทั้งคู่ไปยังบล็อกทดสอบมอร์ฟิซึ่มส์ที่ฉันจะแสดงในช่วงเวลาหนึ่ง บล็อกให้กลับรายการค่าของYซึ่งL [X]เป็น isomorphic จะY จากนั้นL [X]จะถูกผนวกเข้ากับรายการนี้ ก่อนที่จะเข้าใจว่าเหตุใดจึงมีการตั้งค่ารายการในลักษณะนี้มาดูการทดสอบมอร์ฟิซึ่มส์:

\_@                                      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

ยิ่งขณะนี้เรามีรายชื่อของชุดเช่น[{L [0], Y1, Y2, ... }, {L [1], Y1, ... } ... ] ความคิดที่นี่คือว่าโดยคุณสมบัติสกรรมกริยาถ้าสองชุดใดมีองค์ประกอบอย่างน้อยหนึ่งที่เหมือนกันแล้วทุกกลุ่มในสองชุดมี isomorphic สามารถรวมเป็นชุดเดียว เนื่องจากL [X]จะไม่ปรากฏในชุดค่าผสมที่สร้างโดยL [X + ... ]หลังจากรวมชุดของมอร์ฟอร์มิซึ่มแต่ละชุดจะมีองค์ประกอบที่ไม่ซ้ำใคร ดังนั้นเพื่อให้ได้จำนวน isomorphisms ก็เพียงพอที่จะนับจำนวนกลุ่มที่ปรากฏขึ้นหนึ่งครั้งในกลุ่ม isomorphic ทุกชุด เมื่อต้องการทำสิ่งนี้ฉันถอดชุดเพื่อให้ดูเหมือน[L [0], Y1, Y2, ... , L [1], Y1, ... ]เรียงลำดับรายการเพื่อสร้างกลุ่มของกลุ่มเดียวกันและในที่สุด RLE เข้ารหัสมัน

:~            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

นั่นคือทั้งหมดที่คน


2
นั่นคือหนึ่งในคำอธิบาย ดี
The_Basset_Hound

1
@The_Basset_Hound ... aaaand เสร็จแล้ว;)
Andrea Biondo

ฉันคิดว่าคำตอบของฉันไม่ใช่การแข่งขันดังนั้นฉันจึงยอมรับคำตอบนี้
Dennis

4

CJam, 73 ไบต์

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

ความซับซ้อนของเวลาของโค้ดด้านบนนั้นแย่กว่าO (n! n ) )

อินพุทn = 4มีจำนวนมากสำหรับล่ามออนไลน์แล้ว

การใช้ล่าม Java สามารถป้อนn = 5ได้หากคุณมี RAM และความอดทนเพียงพอ

การค้นหากลุ่ม

กำหนดกลุ่ม(G, *)ของคำสั่งnเราสามารถเลือกได้ตามใจชอบ bijection φ: G -> C nดังกล่าวว่าφ (จ) = 0

φจะกลายเป็นมอร์ฟิซึ่มส์ของ(G, ∗)และ(C n , ∗ ')หากเรานิยามโดยx ∗' y = φ (φ -1 (x) φφ -1 (y)) (y))

ซึ่งหมายความว่าพอเพียงที่จะศึกษาตัวดำเนินการของกลุ่มทั้งหมดในC nนั่นคือ0คือองค์ประกอบที่เป็นกลาง

เราจะแสดงโอเปอเรเตอร์กลุ่มในC nด้วยอาร์เรย์สี่เหลี่ยมTของขนาดn × nซึ่งT [x] [y] = x ∗ yy ที่

เพื่อสร้างอาร์เรย์ดังกล่าวเราสามารถเริ่มต้นด้วยการเลือกการเปลี่ยนแปลงของC nสำหรับแต่ละแถวของn

วิธีนี้0จะถูกนำเสนอในทุกแถว ( แต่ไม่จำเป็นต้องทุกคอลัมน์ ) ความหมายว่าภาวะที่สาม (การดำรงอยู่ของสิ่งที่ตรงกันข้าม) จะได้รับการเติมเต็มสิ่งที่อีอาจจะ

เราสามารถแก้ไขE = 0โดยกำหนดว่าครั้งแรกที่คอลัมน์ของTเท่ากับC n โดยเฉพาะอย่างยิ่งเงื่อนไขที่สอง (การดำรงอยู่ขององค์ประกอบที่เป็นกลาง) จะถือ

ในการตรวจสอบว่าTสอดคล้องกับโอเปอเรเตอร์กลุ่มสิ่งที่เหลืออยู่ให้ทำคือการตรวจสอบว่ามีเงื่อนไขแรก (การเชื่อมโยง) สิ่งนี้สามารถทำได้อย่างละเอียดถี่ถ้วนโดยตรวจสอบว่าT [T [x] [y]] [z] == T [x] [T [y] [z]]สำหรับทุกx, y, zในC n n

การนับจำนวนกลุ่มที่ไม่ใช่ isomorphic

วิธีการดังกล่าวข้างต้นสำหรับการค้นหากลุ่มจะให้ผลบางกลุ่ม isomorphic แทนที่จะระบุว่ากลุ่มใด isomorphic เราสร้างตระกูลของกลุ่ม isomorphic ทุกกลุ่ม

สิ่งนี้สามารถทำได้โดยการวนซ้ำทุก bijections φ: C n -> C nและกำหนดอาร์เรย์T associated ที่เกี่ยวข้องซึ่งกำหนดโดยT defined [x] [y] = φ -1 (T [φ (x)] [y (y) )]) .

สิ่งที่เหลืออยู่คือการนับจำนวนตระกูลที่แตกต่างกัน

รหัสทำอะไร

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.

ดี ฉันลองเดรัจฉาน "โง่" แต่มันยากที่จะไปถึง 5 ดังนั้นฉันจึงแลกเปลี่ยนความเร็วเป็นไบต์
Andrea Biondo

1

Python 2 , 515 507 bytes

  • ที่บันทึกไว้แปดไบต์ขอบคุณที่เดนนิส
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)

ลองออนไลน์!


การใช้ความเท่าเทียมกันระหว่างจำนวนของกลุ่มย่อยที่ไม่ได้ isomorphic ของคำสั่ง n ของ  Σn และจำนวนของคลาสความเท่าเทียม isomorphic ของกลุ่ม จำกัด ของคำสั่ง n.

เชื่อมโยงไปยังรุ่นอย่างละเอียด


ทำตามคำสั่งของsและGเรื่อง? ถ้าไม่ได้คุณสามารถใช้และdef f(k,*s):...f(~-k,j,*s)... def c(k,*G):...c(~-k,s,*G)....
Dennis

@ เดนนิสพวกเขาทำไม่ได้; ขอบคุณ
Jonathan Frech
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.