Ticket #14347: group_cycle_index_series-agd.patch

File group_cycle_index_series-agd.patch, 9.4 KB (added by agd, 7 years ago)

Re-implement using CombinatorialFreeModule?

  • doc/en/reference/combinat/species.rst

    # HG changeset patch
    # Parent 7205e6ab78648704102c7f8a84f6754063ad1b5c
    Implement group cycle index series
    
    diff --git a/doc/en/reference/combinat/species.rst b/doc/en/reference/combinat/species.rst
    a b Power Series 
    1212   ../sage/combinat/species/series_order
    1313   ../sage/combinat/species/series
    1414   ../sage/combinat/species/generating_series
     15   ../sage/combinat/species/group_cycle_index_series
    1516
    1617Basic Species
    1718-------------
  • new file sage/combinat/species/group_cycle_index_series.py

    diff --git a/sage/combinat/species/group_cycle_index_series.py b/sage/combinat/species/group_cycle_index_series.py
    new file mode 100644
    - +  
     1"""
     2Group Cycle Indices
     3
     4This file implements the group cycle indices of Henderson and Gainer-Dewar.
     5
     6For a group `\Gamma` and a ring `R`, a `\Gamma`-cycle index over `R` is a
     7function from `\Gamma` to the ring `R [p_{1}, p_{2}, p_{3}, \dots]` of `R`-cycle indices
     8(i.e. formal power series in the countably infinite family of variables `p_{i}` with
     9coefficients in `R`).
     10
     11These objects are of interest because they can be used to enumerate `\Gamma`-species;
     12they serve the same role in that theory as ordinary cycle indices do for classical
     13species.
     14
     15AUTHORS:
     16
     17- Andrew Gainer-Dewar (2013): initial version
     18
     19EXAMPLES::
     20
     21    sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     22    sage: GCISR = GroupCycleIndexSeriesRing(SymmetricGroup(4))
     23    sage: loads(dumps(GCISR))
     24    Ring of (Symmetric group of order 4! as a permutation group)-Cycle Index Series over Rational Field
     25"""
     26#*****************************************************************************
     27#       Copyright (C) 2013 Andrew Gainer-Dewar <andrew.gainer.dewar@gmail.com>
     28#
     29#  Distributed under the terms of the GNU General Public License (GPL)
     30#  as published by the Free Software Foundation; either version 2 of
     31#  the License, or (at your option) any later version.
     32#                  http://www.gnu.org/licenses/
     33#*****************************************************************************
     34from sage.rings.rational_field import RationalField
     35from sage.misc.cachefunc import cached_function
     36from sage.combinat.free_module import CombinatorialFreeModule,CombinatorialFreeModuleElement
     37
     38@cached_function
     39def GroupCycleIndexSeriesRing(G, R = RationalField()):
     40    """
     41    Returns the ring of group cycle index series.
     42
     43    EXAMPLES::
     44
     45        sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     46        sage: GCISR = GroupCycleIndexSeriesRing(SymmetricGroup(4)); GCISR
     47        Ring of (Symmetric group of order 4! as a permutation group)-Cycle Index Series over Rational Field
     48
     49    TESTS: We test to make sure that caching works. ::
     50
     51        sage: GCISR is GroupCycleIndexSeriesRing(SymmetricGroup(4))
     52        True
     53    """
     54    return GroupCycleIndexSeriesRing_class(G, R)
     55
     56class GroupCycleIndexSeriesRing_class(CombinatorialFreeModule):
     57    def __init__(self, G, R = RationalField()):
     58        """
     59        EXAMPLES::
     60
     61            sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     62            sage: GCISR = GroupCycleIndexSeriesRing(SymmetricGroup(4)); GCISR
     63            Ring of (Symmetric group of order 4! as a permutation group)-Cycle Index Series over Rational Field
     64            sage: GCISR == loads(dumps(GCISR))
     65            True
     66        """
     67        from sage.combinat.species.generating_series import CycleIndexSeriesRing
     68        from sage.categories.algebras_with_basis import AlgebrasWithBasis
     69       
     70        self._coeff_ring = R
     71        CISR = CycleIndexSeriesRing(R)
     72        self._cisr = CISR
     73        self._group = G
     74
     75        CombinatorialFreeModule.__init__(self, CISR, G, element_class = GroupCycleIndexSeries, category = AlgebrasWithBasis(CISR), prefix = 'G')
     76   
     77    def product_on_basis(self, left, right):
     78        if left == right:
     79            return self.monomial(left)
     80        else:
     81            return self.zero()
     82   
     83    def one_basis(self):
     84        return self._group.identity()
     85   
     86    def algebra_generators(self):
     87        return Family( [self.monomial( self._group.identity() )])
     88       
     89    def _repr_(self):
     90        """
     91        EXAMPLES::
     92
     93            sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     94            sage: GCISR = GroupCycleIndexSeriesRing(SymmetricGroup(4)); GCISR
     95            Ring of (Symmetric group of order 4! as a permutation group)-Cycle Index Series over Rational Field
     96        """
     97        return "Ring of (%s)-Cycle Index Series over %s" %(self._group, self._coeff_ring)
     98
     99class GroupCycleIndexSeries(CombinatorialFreeModuleElement):
     100    def quotient(self):
     101        """
     102        Returns the quotient of this group cycle index.
     103
     104        This is defined to be the ordinary cycle index `F / \Gamma` obtained from a
     105        `\Gamma`-cycle index `F` by:
     106
     107        .. MATH::
     108            F / \Gamma = 1 / \lvert \Gamma \\rvert \sum_{\gamma \in \Gamma} F [\gamma].
     109
     110        By [AGdiss]_, if `F` is the `\Gamma`-cycle index of a `\Gamma`-species, `F / \Gamma` is the ordinary
     111        cycle index of orbits of structures under the action of `\Gamma`.
     112
     113        EXAMPLES::
     114
     115            sage: S4 = SymmetricGroup(4)
     116            sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     117            sage: GCISR = GroupCycleIndexSeriesRing(S4)
     118            sage: GCISR.an_element()
     119            p[]*G[()] + 2*p[]*G[(3,4)] + 3*p[]*G[(2,3)] + p[]*G[(1,2,3,4)]
     120            sage: GCISR.an_element().quotient().coefficients(4)
     121            [7/24*p[], 0, 0, 0]
     122
     123        REFERENCES:
     124
     125        .. [AGdiss] Andrew Gainer. "`\Gamma`-species, quotients, and graph enumeration". Ph.D. diss. Brandeis University, 2012.
     126        """
     127        return 1/self.parent()._group.cardinality() * sum(self.coefficients())
     128
     129    def composition(self, y):
     130        """
     131        Plethysm of group cycle index series is defined by a sort of `mixing' operation in [Hend]_:
     132
     133        .. MATH::
     134            (F \circ G) [\gamma] (p_{1}, p_{2}, p_{3}, \dots) =
     135            F [\gamma] \left( G [\gamma] (p_{1}, p_{2}, p_{3}, \dots),
     136            G [\gamma^{2}] (p_{2}, p_{4}, p_{6}, \dots), \dots \\right).
     137
     138        It is shown in [Hend]_ that this operation on $\Gamma$-cycle indices corresponds to the
     139        'composition' operation on $\Gamma$-species.
     140
     141        EXAMPLES::
     142
     143            sage: S2 = SymmetricGroup(2)
     144            sage: Eplus = sage.combinat.species.set_species.SetSpecies(min=1).cycle_index_series()
     145            sage: E = sage.combinat.species.set_species.SetSpecies().cycle_index_series()
     146            sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     147            sage: GCISR = GroupCycleIndexSeriesRing(S2)
     148            sage: e = S2.identity()
     149            sage: t = S2.gen()
     150            sage: GCIS = GCISR(e)*Eplus*E + GCISR(t)*Eplus
     151            sage: example = GCIS(GCIS)
     152            sage: example[e].coefficients(4)
     153            [0, p[1], 3*p[1, 1] + p[2], 41/6*p[1, 1, 1] + 9/2*p[2, 1] + 2/3*p[3]]
     154            sage: example[t].coefficients(4)
     155            [0, p[1], p[1, 1] + p[2], 5/6*p[1, 1, 1] + 3/2*p[2, 1] + 2/3*p[3]]
     156
     157        REFERENCES:
     158
     159        .. [Hend] Anthony Henderson. "Species over a finite field". J. Algebraic Combin., 21(2):147-161, 2005.
     160        """
     161        from sage.combinat.species.stream import Stream, _integers_from
     162        from sage.misc.misc_c import prod
     163
     164        assert self.parent() == y.parent()
     165
     166        parent = self.parent()
     167        cisr = parent._cisr
     168        group = parent._group
     169
     170        for ycis in y.coefficients():
     171            assert ycis.coefficient(0) == 0
     172
     173        def monomial_composer (part, g):
     174            res = prod(y[g**l].stretch(l) for l in part)
     175            return res
     176       
     177        def term_map (term, g):
     178            if term == 0:
     179                return cisr(0)
     180            else:
     181                res = sum(coeff*monomial_composer(part, g) for part,coeff in term)
     182                return res
     183
     184        def component_builder (g):
     185            if self[g] == 0:
     186                res = cisr(0)
     187            elif g == group.identity():
     188                res = self[g](y[g])
     189            else:
     190                res = cisr.sum_generator(term_map(self[g].coefficient(i), g) for i in _integers_from(0))
     191            return res
     192
     193        components_generator = ( (g, component_builder(g)) for g in group)
     194        res = parent.sum_of_terms(components_generator, distinct = True)
     195        return res
     196
     197    __call__ = composition
     198
     199    def derivative(self):
     200        """
     201        Differentiation of group cycle index series is defined termwise:
     202
     203        .. MATH::
     204            (F')[\gamma] = (F [\gamma])'
     205
     206        EXAMPLES::
     207
     208            sage: S4 = SymmetricGroup(4)
     209            sage: from sage.combinat.species.group_cycle_index_series import GroupCycleIndexSeriesRing
     210            sage: GCISR = GroupCycleIndexSeriesRing(S4)
     211            sage: G = GCISR(SymmetricGroup(4).an_element())*sage.combinat.species.library.SimpleGraphSpecies().cycle_index_series()
     212            sage: G.derivative()[SymmetricGroup(4).an_element()].coefficients(4)
     213            [p[1], 2*p[1, 1] + 2*p[2], 4*p[1, 1, 1] + 6*p[2, 1] + 2*p[3], 32/3*p[1, 1, 1, 1] + 16*p[2, 1, 1] + 8*p[2, 2] + 16/3*p[3, 1] + 4*p[4]]
     214
     215        """
     216        return self.map_coefficients(lambda x: x.derivative())