किसी दिए गए आकार के समूह की गणना करना


21

समूह

सार बीजगणित में, एक समूह एक टपल है (G,) है, जहां G एक सेट है और एक समारोह है जी×जीजी ऐसा है कि निम्नलिखित रखती है:

  • सभी के लिए एक्स,y,z में जी , (एक्स*y)*z=एक्स*(y*z)

  • एक तत्व मौजूद है में जी ऐसा है कि सभी के लिए एक्स में जी , एक्स*=एक्स

  • प्रत्येक के लिए एक्स में जी , एक तत्व मौजूद है y में जी ऐसी है कि एक्स*y=

आदेश एक समूह का (जी,*) के तत्वों की संख्या के रूप में परिभाषित किया गया है जी

प्रत्येक कड़ाई से सकारात्मक पूर्णांक n , आदेश का कम से कम एक समूह मौजूद है n। उदाहरण के लिए, (सीn,+n) इस तरह के एक समूह है, जहां है सीn={0,,n-1} और ।एक्स+ny=(एक्स+y)आधुनिकn

आइसोमोर्फिक समूह

चलो और परिभाषित द्वारा । फिर और ।जी: ={1,2}*एक्स*y=(एक्स×y)आधुनिक31*1=1=2*21*2=2=2*1

इसी तरह, और ।0+20=0=1+210+21=1=1+20

यद्यपि समूहों के तत्व और संचालन और अलग-अलग नाम हैं, समूह समान संरचना साझा करते हैं।(जी,*)(सी2,+2)

दो समूहों और कहा जाता है isomorphic अगर वहाँ एक द्विभाजन मौजूद φ : जी 1जी 2 ऐसी है कि φ ( एक्स * 1 y ) = φ ( एक्स ) * 2 φ ( y ) सभी x के लिए , G 1 में y(G1,1)(G2,2)ϕ:G1G2ϕ(x1y)=ϕ(x)2ϕ(y)एक्स,yजी1

एक ही क्रम के सभी समूह आइसोमोर्फिक नहीं हैं। उदाहरण के लिए, क्लेन समूह क्रम 4 का एक समूह है जो लिए आइसोमोर्फिक नहीं है ।(सी4,+4)

कार्य

एक प्रोग्राम या फ़ंक्शन लिखें जो एक गैर-नकारात्मक पूर्णांक n को इनपुट और प्रिंट के रूप में स्वीकार करता है या आदेश 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, की अनुमति नहीं है।

  • मानक नियम लागू होते हैं।


14
बेशक मैथेमेटिका के पास इसके लिए एक बिलिन है। : /
एलेक्स ए।

1
पीटर का उद्धरण ( OEIS के विकास के सैंडबॉक्स पोस्ट पर एक टिप्पणी से ): "यदि आप उदाहरण के लिए A000001 , A000003, A000019 के लिए" सूत्र "और" प्रोग्राम "अनुभागों को देखते हैं, तो एक जवाब जो विशेष अनाज का उपयोग नहीं करता है, को एक की आवश्यकता होगी बहुत शोध। " (जोर मेरा।);)
मार्टिन एंडर

12
कुछ लोग कहते हैं कि कोई भी निर्मित गणितज्ञ के पास नहीं है, लेकिन यह अभी भी अनुसंधान के अधीन है। अन्य मिथकों का कहना है कि गणितज्ञ प्रोग्रामर्स के दिमाग को पढ़कर बिल्डिंस बनाते हैं , लेकिन इसकी भी अभी तक पुष्टि नहीं हुई है।
18

1
@ अनडॉल्वमेंट किए गए बिलिन में monkeys_on_typewritersसब कुछ शामिल है जो डॉक्यूमेंटेड बिल्डिंस द्वारा कवर नहीं किया गया है।
लेवल रिवर सेंट

क्यों (1 + 1)% 3 नहीं 2 है?
कैबी ४०

जवाबों:


16

सीजेएम, 189 187 बाइट्स

यह समझाने वाला कठिन है ... समय की जटिलता की गारंटी है 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=},,}{!!}?

यदि आप पर्याप्त बहादुर हैं, तो इसे ऑनलाइन आज़माएं । अपने भद्दे लैपटॉप पर मैं जावा दुभाषिया के साथ 6 तक या ऑनलाइन दुभाषिया में 5 प्राप्त कर सकता हूं।

व्याख्या

मेरे पास एक बड़ी गणित पृष्ठभूमि नहीं है (बस हाई स्कूल समाप्त होने के बाद, अगले सप्ताह यूनि में सीएस शुरू करना)। इसलिए मेरे साथ सहन करें अगर मैं गलतियाँ करता हूँ, तो स्पष्ट रूप से बताऊँ, या बहुत ही अक्षम तरीके से काम करता हूँ।

मेरा दृष्टिकोण एक क्रूर बल है, हालांकि मैंने इसे थोड़ा और अधिक चतुर बनाने की कोशिश की। मुख्य चरण हैं:

  1. सभी संभव ऑपरेंड उत्पन्न * आदेश के एक समूह के लिए n (यानी, आदेश के सभी समूहों की गणना n );
  2. आदेश एन के दो समूहों के बीच सभी संभावित जीवों bi उत्पन्न ;
  3. चरण 1 और 2 से परिणामों का उपयोग करते हुए, आदेश 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, ए, बी, सी, ...} के रूप में लिखा जाएगा , जहां 1 पहचान तत्व है। सीजेएम कार्यान्वयन में, संबंधित तत्व {0, 1, 2, 3, ...} हैं , जहां 0 पहचान तत्व है।

आइए चरण 1 से शुरू करें। आदेश n के समूह के लिए सभी संभव ऑपरेटरों को लिखना सभी मान्य n × n केली टेबल बनाने के बराबर है । पहली पंक्ति और स्तंभ तुच्छ हैं: वे दोनों {1, ए, बी, सी, ...} (बाएं से दाएं, ऊपर-नीचे) हैं।

      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

यह जानते हुए कि केली तालिका एक कम लैटिन वर्ग (रद्दीकरण संपत्ति के कारण) संभव तालिकाओं को पंक्ति-दर-पंक्ति उत्पन्न करने की अनुमति देता है। दूसरी पंक्ति (इंडेक्स 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 है ! , इसलिए छोटे समाधान के लिए बहुत अधिक स्मृति और समय की आवश्यकता होगी।

वैध केली तालिकाओं की एक सूची ऑपरेटरों की गणना करने की दिशा में एक शानदार कदम है, लेकिन एक 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]

ओह! काम के बहुत सारे, लेकिन अब हमने एन के सभी समूहों को एन (या बेहतर, इस पर संचालन - लेकिन सेट तय हो गया है, इसलिए यह एक ही बात है) की गणना की है। अगला चरण: आइसोमॉर्फिज्म का पता लगाएं। एक आइसोमोर्फिज्म उन दो समूहों के बीच एक जीव है जो x (x) y) = ∗ (x) φ ism (y) है । सीजेम में उन जीवों को उत्पन्न करना तुच्छ है: Ne!यह करेंगे। हम उनकी जाँच कैसे कर सकते हैं? मेरा समाधान xY के लिए केली तालिका की दो प्रतियों से शुरू होता है । एक प्रति पर, φ सभी तत्वों के लिए लागू किया जाता है, पंक्तियों या स्तंभों के आदेश को बिना छुए। यह φ (x। Y) के लिए तालिका बनाता है । दूसरे पर तत्वों को वैसे ही छोड़ दिया जाता है जैसे वे हैं, लेकिन पंक्तियों और स्तंभों को φ के माध्यम से मैप किया जाता है । वह है, पंक्ति / स्तंभx पंक्ति / स्तंभ φ (x) बन जाता है । यह φ (x) φ y (y) के लिए तालिका बनाता है । अब जब हमारे पास दो टेबल हैं, तो हमें उनकी तुलना करना होगा: यदि वे समान हैं, तो हमने एक आइसोमोर्फिज्म पाया है।

बेशक, हम पर भी समरूपता का परीक्षण करने के लिए समूहों के जोड़े उत्पन्न करने की आवश्यकता है। हमें समूहों के सभी 2-संयोजनों की आवश्यकता है । ऐसा लगता है कि सीजेएम के पास संयोजन के लिए कोई ऑपरेटर नहीं है। हम उन्हें प्रत्येक समूह में ले जाकर और सूची में उसका अनुसरण करने वाले तत्वों के साथ जोड़कर उत्पन्न कर सकते हैं। मजेदार तथ्य: 2-संयोजनों की संख्या n × (n - 1) / 2 है , जो कि पहले n - प्राकृतिक संख्याओं का योग भी है । ऐसी संख्याओं को त्रिकोणीय संख्याएं कहा जाता है: पेपर पर एल्गोरिथ्म की कोशिश करें, प्रति पंक्ति एक निश्चित तत्व, और आप देखेंगे कि क्यों।

: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] 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, ...}, ...] । यहाँ विचार यह है कि, सकर्मक संपत्ति द्वारा, यदि किसी भी दो सेट में कम से कम एक तत्व है तो दो सेटों में सभी समूह आइसोमोर्फिक हैं। उन्हें एक सेट में एकत्र किया जा सकता है। जैसा कि L [X] L [X + ...] द्वारा बनाए गए संयोजनों में कभी नहीं दिखाई देगा , आइसोमॉर्फिज्म के प्रत्येक सेट को एकत्र करने के बाद एक अद्वितीय तत्व होगा। इसलिए, आइसोमोर्फिम्स की संख्या प्राप्त करने के लिए, यह गिनना पर्याप्त है कि आइसोमोर्फिम्स समूह के सभी सेटों में एक बार कितने समूह दिखाई देते हैं। ऐसा करने के लिए, मैं सेटों को खोल देता हूं ताकि वे दिखें [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 ... आआआंड यह अब समाप्त हो गया है;)
एंड्रिया

मैं अपने जवाब को गैर-प्रतिस्पर्धी मानता हूं, इसलिए मैंने इसे स्वीकार कर लिया है।
डेनिस

4

सीजेएम, 73 बाइट्स

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

उपरोक्त कोड की समय जटिलता O (n! N ) से भी बदतर है ।

ऑनलाइन इंटरप्रेटर के लिए इनपुट n = 4 पहले से ही बहुत अधिक है ।

जावा दुभाषिया का उपयोग करना , इनपुट n = 5 संभव हो सकता है, अगर आपके पास पर्याप्त रैम और धैर्य है।

समूह खोजना

आदेश n के एक समूह (G, ∗) को देखते हुए , हम एक मनमाना पूर्वाग्रह चुन सकते हैं -: G -> C n ऐसा कि n (e) = 0

φ एक समाकृतिकता हो जाएगा (जी, *) और (सी एन , * ') अगर हम परिभाषित *' द्वारा एक्स * 'y = φ (φ -1 (एक्स) * φ -1 (y))

इसका मतलब यह है कि यह C n में सभी समूह ऑपरेटरों का अध्ययन करने के लिए पर्याप्त है जैसे कि 0 तटस्थ तत्व है।

हम एक समूह ऑपरेटर का प्रतिनिधित्व करेंगी * में आयामों के एक आयताकार सरणी T द्वारा C n n × n जैसे कि T [x] [y] = xY।

इस तरह की एक सरणी उत्पन्न करने के लिए, हम इसकी प्रत्येक n पंक्तियों के लिए C n का क्रमचय चुनकर शुरू कर सकते हैं।

इस तरह, सभी पंक्तियों (लेकिन जरूरी नहीं कि सभी कॉलम ) में मौजूद होगा, जिसका अर्थ है कि तीसरी स्थिति (एक व्युत्क्रम का अस्तित्व) पूरी हो जाएगी , जो कुछ भी हो सकती है।

हम ठीक कर सकते हैं ई = 0 की आवश्यकता होती है कि पहले से स्तंभ के टी के बराबर है सी एन । विशेष रूप से, दूसरी स्थिति (एक तटस्थ तत्व का अस्तित्व) धारण करेगी।

सत्यापित करने के लिए कि टी एक समूह ऑपरेटर से मेल खाती है, जो करने के लिए शेष है वह यह सत्यापित करना है कि पहली शर्त (संघात्मकता) रखती है। इसे T [T [x] [y]] [z] == T [x] [T [y] [z]] सभी x, y, z के लिए C n में चेक करके समाप्त किया जा सकता है ।

गैर-आइसोमॉर्फिक समूहों की गिनती

समूहों को खोजने के लिए उपरोक्त विधि कुछ आइसोमॉर्फिक समूहों का उत्पादन करेगी। यह पहचानने के बजाय कि कौन से लोग आइसोमोर्फिक हैं, हम उनमें से हर एक के लिए सभी आइसोमॉर्फिक समूहों के परिवार को उत्पन्न करते हैं।

यह सभी पूर्वाग्रहों पर ध्यान देकर प्राप्त किया जा सकता है φ: C n -> C n , और संबंधित सरणी T by का निर्धारण , द्वारा परिभाषित Tφ [x] [y] = φ -1 (टी [φ (x)] [φ (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 तक पहुंचाना मुश्किल था, इसलिए मैंने गति के लिए बाइट्स का कारोबार किया।
एंड्रिया बियोन्डो

1

पायथन 2 , 515 507 बाइट्स

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)

इसे ऑनलाइन आज़माएं!


n Σnn

वर्बोज़ संस्करण से लिंक करें ।


के आदेश sऔर Gबात करते हैं? यदि नहीं, तो आप उपयोग कर सकते हैं def f(k,*s):...f(~-k,j,*s)...और def c(k,*G):...c(~-k,s,*G)....
डेनिस

@ डेनिस वे नहीं; धन्यवाद।
जोनाथन फ्रैच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.