Ticket #8549: trac_8549_cycle_enumerator-nb.patch

File trac_8549_cycle_enumerator-nb.patch, 7.2 KB (added by nborie, 12 years ago)
  • doc/en/reference/categories.rst

    # HG changeset patch
    # User Nicolas Borie <nicolas.borie at math.u-psud.fr>
    # Date 1275387488 -7200
    # Node ID e5f0f3e37a75719912125a99173878e5301413d5
    # Parent  b05c517e57a3f16b8fe0480eb57c104294cf58bb
    * * *
    #8549: Implements cycle index for permutation groups, toward Polya enumeration
    
    Reviewer's patch to the previous
    Adds FinitePermutationGroups to the manual, and fix header
    
    diff --git a/doc/en/reference/categories.rst b/doc/en/reference/categories.rst
    a b  
    6262   sage/categories/finite_enumerated_sets
    6363   sage/categories/finite_fields
    6464   sage/categories/finite_monoids
     65   sage/categories/finite_permutation_groups
    6566   sage/categories/finite_semigroups
    6667   sage/categories/finite_weyl_groups
    6768   sage/categories/gcd_domains
  • sage/categories/finite_permutation_groups.py

    diff --git a/sage/categories/finite_permutation_groups.py b/sage/categories/finite_permutation_groups.py
    a b  
    11r"""
    2 FinitePermutationGroups
     2Finite Permutation Groups
    33"""
    44#*****************************************************************************
    55#  Copyright (C) 2010 Nicolas M. Thiery <nthiery at users.sf.net>
     6#                     Nicolas Borie <Nicolas.Borie at u-pusd.fr>
    67#
    78#  Distributed under the terms of the GNU General Public License (GPL)
    89#                  http://www.gnu.org/licenses/
     
    8687        return DihedralGroup(3)
    8788
    8889    class ParentMethods:
    89         # TODO (Cf MuPAD-Combinat, lib/DOMAINS/CATEGORIES/PermutationGroup.mu)
    90         #  - cycle_indicator
    91         #  - strong_generating_set
    92         #  - ...
    93         pass
     90        # TODO
     91        #  - Port features from MuPAD-Combinat, lib/DOMAINS/CATEGORIES/PermutationGroup.mu
     92        #  - Move here generic code from sage/groups/perm_gps/permgroup.py
     93
     94        def cycle_index(self, parent = None):
     95            r"""
     96            INPUT:
     97
     98             - ``self`` - a permutation group `G`
     99             - ``parent`` -- a free module with basis indexed by partitions,
     100               or behave as such, with a ``term`` and ``sum`` method
     101               (default: the symmetric functions over the rational field in the p basis)
     102
     103            Returns the *cycle index* of `G`, which is a gadget counting
     104            the elements of `G` by cycle type, averaged over the group:
     105
     106            .. math::
     107
     108                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }
     109
     110            EXAMPLES:
     111
     112            Among the permutations of the symmetric group `S_4`, there is
     113            the identity, 6 cycles of length 2, 3 products of two cycles
     114            of length 2, 8 cycles of length 3, and 6 cycles of length 4::
     115
     116                sage: S4 = SymmetricGroup(4)
     117                sage: P = S4.cycle_index()
     118                sage: 24 * P
     119                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]
     120
     121            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
     122            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::
     123
     124                sage: 24 * P[ Partition([3,1]) ]
     125                8
     126
     127            The cycle index plays an important role in the enumeration of
     128            objects modulo the action of a group (Polya enumeration), via
     129            the use of symmetric functions and plethysms. It is therefore
     130            encoded as a symmetric function, expressed in the powersum
     131            basis::
     132
     133                sage: P.parent()
     134                Symmetric Function Algebra over Rational Field, Power symmetric functions as basis
     135
     136            This symmetric function can have some nice properties; for
     137            example, for the symmetric group `S_n`, we get the complete
     138            symmetric function `h_n`::
     139
     140                sage: S = SymmetricFunctions(QQ); h = S.h()
     141                sage: h( P )
     142                h[4]
     143
     144            TODO: add some simple examples of Polya enumeration, once it
     145            will be easy to expand symmetric functions on any alphabet.
     146
     147            Here are the cycle indices of some permutation groups::
     148
     149                sage: 6 * CyclicPermutationGroup(6).cycle_index()
     150                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]
     151
     152                sage: 60 * AlternatingGroup(5).cycle_index()
     153                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
     154
     155                sage: for G in TransitiveGroups(5):               # requires optional database_gap # long time
     156                ...       G.cardinality() * G.cycle_index()
     157                p[1, 1, 1, 1, 1] + 4*p[5]
     158                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
     159                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
     160                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
     161                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]
     162
     163            One may specify another parent for the result::
     164
     165                sage: F = CombinatorialFreeModule(QQ, Partitions())
     166                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
     167                sage: 6 * P
     168                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
     169                sage: P.parent() is F
     170                True
     171
     172            This parent should have a ``term`` and ``sum`` method::
     173
     174                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
     175                Traceback (most recent call last):
     176                  ...
     177                AssertionError: `parent` should be (or behave as) a free module with basis indexed by partitions
     178
     179            REFERENCES:
     180
     181             .. [Ker1991] A. Kerber. Algebraic combinatorics via finite group actions, 2.2 p. 70.
     182               BI-Wissenschaftsverlag, Mannheim, 1991.
     183
     184            AUTHORS:
     185
     186             - Nicolas Borie and Nicolas M. Thiery
     187
     188            TESTS::
     189
     190                sage: P = PermutationGroup([]); P
     191                Permutation Group with generators [()]
     192                sage: P.cycle_index()
     193                p[1]
     194                sage: P = PermutationGroup([[(1)]]); P
     195                Permutation Group with generators [()]
     196                sage: P.cycle_index()
     197                p[1]
     198            """
     199            from sage.combinat.permutation import Permutation
     200            if parent is None:
     201                 from sage.rings.rational_field import QQ
     202                 from sage.combinat.sf.sf import SymmetricFunctions
     203                 parent = SymmetricFunctions(QQ).powersum()
     204            else:
     205                assert hasattr(parent, "term") and hasattr(parent, "sum"), \
     206                    "`parent` should be (or behave as) a free module with basis indexed by partitions"
     207            base_ring = parent.base_ring()
     208            # TODO: use self.conjugacy_classes() once available
     209            from sage.interfaces.gap import gap
     210            CC = ([Permutation(self(C.Representative())).cycle_type(), base_ring(C.Size())] for C in gap(self).ConjugacyClasses())
     211            return parent.sum( parent.term( partition, coeff ) for (partition, coeff) in CC)/self.cardinality()
     212
    94213
    95214    class ElementMethods:
    96215        # TODO: put abstract_methods for