Ticket #8500: trac_8500_number_transitive_group-review-nt.patch

File trac_8500_number_transitive_group-review-nt.patch, 19.2 KB (added by nthiery, 12 years ago)
  • doc/en/reference/groups.rst

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1271620682 -7200
    # Node ID e5b6f9e216992b1c359b343a6338eb405f2bf5ca
    # Parent  cdea1400fc2897a06c5f1cbaa8f7caa8db2b919b
    #8500: Add the set of TransitiveGroups; reviewer's patch
    
    diff --git a/doc/en/reference/groups.rst b/doc/en/reference/groups.rst
    a b Groups 
    1313   sage/groups/abelian_gps/abelian_group_morphism
    1414   sage/groups/abelian_gps/dual_abelian_group
    1515   sage/groups/perm_gps/permgroup
     16   sage/groups/perm_gps/permgroup_named
    1617   sage/groups/perm_gps/permgroup_element
    1718   sage/groups/perm_gps/permgroup_morphism
    1819   sage/groups/perm_gps/cubegroup
  • sage/groups/perm_gps/permgroup_named.py

    diff --git a/sage/groups/perm_gps/permgroup_named.py b/sage/groups/perm_gps/permgroup_named.py
    a b You can construct the following permutat 
    1616
    1717-- DiCyclicGroup, nonabelian groups of order `4m` with a unique element of order 2
    1818
    19 -- TransitiveGroup, $i^{th}$ transitive group of degree $n$
     19-- TransitiveGroup, $n^{th}$ transitive group of degree $d$
    2020                      from the GAP tables of transitive groups (requires
    2121                      the "optional" package database_gap)
    2222
     23-- TransitiveGroups(d), TransitiveGroups(), set of all of the above
     24
    2325-- MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24.
    2426
    2527-- KleinFourGroup, subgroup of $S_4$ of order $4$ which is not $C_2 \times C_2$
    from sage.rings.all import Integer 
    7274from sage.interfaces.all import gap
    7375from sage.rings.finite_field import FiniteField as GF
    7476from sage.rings.arith import factor
     77from sage.rings.integer_ring import ZZ
    7578from sage.groups.abelian_gps.abelian_group import AbelianGroup
    7679from sage.misc.functional import is_even
    7780from sage.misc.cachefunc import cached_method
    from sage.structure.parent import Parent 
    8285from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    8386from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
    8487from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
     88from sage.categories.enumerated_sets import EnumeratedSets
    8589from sage.sets.non_negative_integers import NonNegativeIntegers
    8690from sage.sets.family import Family
    8791
    class MathieuGroup(PermutationGroup_uniq 
    859863            Mathieu group of degree 12 and order 95040 as a permutation group
    860864        """
    861865        return "Mathieu group of degree %s and order %s as a permutation group"%(self._n,self.order())
    862    
     866
    863867class TransitiveGroup(PermutationGroup_unique):
    864868    def __init__(self, d, n):
    865869        """
    866870        The transitive group from the GAP tables of transitive groups.
    867        
     871
    868872        INPUT:
    869873            d -- positive integer; the degree
    870874            n -- positive integer; the number
    class TransitiveGroup(PermutationGroup_u 
    874878
    875879        EXAMPLES::
    876880
    877             sage: G = TransitiveGroup(1,1); G
     881            sage: TransitiveGroup(0,1)
     882            Transitive group number 1 of degree 0
     883            sage: TransitiveGroup(1,1)
    878884            Transitive group number 1 of degree 1
    879             sage: G = TransitiveGroup(5, 2); G         # requires optional database_gap 
     885            sage: G = TransitiveGroup(5, 2); G         # requires optional database_gap
    880886            Transitive group number 2 of degree 5
    881             sage: G.gens()                             # requires optional database_gap 
     887            sage: G.gens()                             # requires optional database_gap
    882888            [(1,2,3,4,5), (1,4)(2,3)]
    883889
    884             sage: G.category()
     890            sage: G.category()                         # requires optional database_gap
    885891            Category of finite permutation groups
    886             sage: TestSuite(G).run()
     892
     893        .. warning:: this follows GAP's naming convention of indexing
     894          the transitive groups starting from ``1``::
     895
     896            sage: TransitiveGroup(5,0)                 # requires optional database_gap
     897            Traceback (most recent call last):
     898            ...
     899            AssertionError: n should be in {1,..,5}
     900
     901        .. warning:: only transitive groups of "small" degree are
     902          available in GAP's database::
     903
     904            sage: TransitiveGroup(31,1)                # requires optional database_gap
     905            Traceback (most recent call last):
     906            ...
     907            NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
     908
     909        TESTS::
     910
     911            sage: TestSuite(TransitiveGroup(0,1)).run()
     912            sage: TestSuite(TransitiveGroup(1,1)).run()
     913            sage: TestSuite(TransitiveGroup(5,2)).run()# requires optional database_gap
     914
     915            sage: TransitiveGroup(1,5)
     916            Traceback (most recent call last):
     917            ...
     918            AssertionError: n should be in {1,..,1}
    887919        """
    888         id = 'Group([()])' if d in [0,1] else 'TransitiveGroup(%s,%s)'%(d,n)
     920        d = ZZ(d)
     921        n = ZZ(n)
     922        assert d >= 0
     923        assert n > 0
     924        max_n = TransitiveGroups(d).cardinality()
     925        assert n <= max_n, "n should be in {1,..,%s}"%max_n
     926        gap_group = 'Group([()])' if d in [0,1] else 'TransitiveGroup(%s,%s)'%(d,n)
    889927        try:
    890             PermutationGroup_generic.__init__(self, gap_group=id)
     928            PermutationGroup_generic.__init__(self, gap_group=gap_group)
    891929        except RuntimeError:
    892930            from sage.misc.misc import verbose
    893931            verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0)
    894        
     932
    895933        self._d = d
    896934        self._n = n
    897        
     935
    898936    def _repr_(self):
    899937        """
    900938        EXAMPLES:
    class TransitiveGroup(PermutationGroup_u 
    903941        """
    904942        return "Transitive group number %s of degree %s"%(self._n, self._d)
    905943
    906 def number_of_transitive_groups(degree):
     944def TransitiveGroups(d=None):
    907945    """
    908     Returns the number of transitive groups of a given ``degree``.
    909     As in Gap, transitive groups of degree `n` are indexed from 1 to
    910     number_of_transitive_groups(n).
     946    INPUT:
    911947
    912     The database_gap contains all transitive groups up to degree 30.
     948     - ``d`` -- an integer (optional)
     949
     950    Returns the set of all transitive groups of a given degree
     951    ``d``. If ``d`` is not specified, it returns the set of all
     952    transitive groups.
     953
     954    Warning: TransitiveGroups requires the optional GAP database
     955    package. Please install it with ``sage -i database_gap``.
    913956
    914957    EXAMPLES::
    915958
    916         sage: from sage.groups.perm_gps.permgroup_named import number_of_transitive_groups
    917         sage: k = number_of_transitive_groups(12); k                # requires optional database_gap
    918         301
    919         sage: type(k)                                               # requires optional database_gap
    920         <type 'sage.rings.integer.Integer'>
    921         sage: [number_of_transitive_groups(Integer(i)) for i in range(11)] # requires optional database_gap
    922         [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]
    923         sage: for i in range(number_of_transitive_groups(5)):       # requires optional database_gap
    924         ...       print TransitiveGroup(6,i+1).cardinality()
    925         6
    926         6
    927         12
    928         12
    929         18
     959        sage: TransitiveGroups(3)
     960        Transitive Groups of degree 3
     961        sage: TransitiveGroups(7)
     962        Transitive Groups of degree 7
     963        sage: TransitiveGroups(8)
     964        Transitive Groups of degree 8
     965
     966        sage: TransitiveGroups()
     967        Transitive Groups
     968
     969    .. warning:: in practice, the database currently only contains
     970      transitive groups up to degree 30::
     971
     972        sage: TransitiveGroups(31).cardinality() # requires optional database_gap
     973        Traceback (most recent call last):
     974        ...
     975        NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
     976
    930977    """
    931     if (not isinstance(degree, Integer)) or degree < 0:
    932         raise ValueError("A transitive group acts on a non negative integer number of positions")
    933     if degree == 0: # gap.NrTransitiveGroups(0) --> fail : This ligne can't be removed.
    934         return 1
    935     if degree > 30:
    936         raise NotImplementedError
    937     else:
    938         try:
    939             G = PermutationGroup_generic(gap_group='TransitiveGroup(2,1)')
    940             return Integer(gap.NrTransitiveGroups(gap(degree)))
    941         except RuntimeError:
    942             from sage.misc.misc import verbose
    943             verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0)
    944 
    945 def TransitiveGroups(n=None):
    946     """
    947     Returns the set of transitive groups of a given degree ``n`` if
    948     specified, it returns the set of all transitive groups up to
    949     degree 30 otherwise.
    950 
    951     Warning: Computing with TransitiveGroups requires the optional
    952     database_gap package. Please install it.
    953 
    954     EXAMPLES::
    955    
    956         sage: from sage.groups.perm_gps.permgroup_named import number_of_transitive_groups
    957         sage: TransitiveGroups(3) # requires optional database_gap
    958         Transitive Groups of degree 3
    959         sage: TransitiveGroups(7) # requires optional database_gap
    960         Transitive Groups of degree 7
    961         sage: TransitiveGroups(8) # requires optional database_gap
    962         Transitive Groups of degree 8
    963        
    964     If no degree is specified, it Returns the complete database which
    965     contains all transitive groups up to degree 30::
    966 
    967         sage: TransitiveGroups() # requires optional database_gap
    968         Transitive Groups
    969     """
    970 #    tests of the file takes [234.0 s] on a macbook(2009) with the following check
    971 #    if any(['database_gap' == p.split("-")[0] for p in optional_packages()[0]]):
    972 #    instead of [59.8 s] for the hard coded following check over an optional
    973 #    object
    974     try:
    975         G = PermutationGroup_generic(gap_group='TransitiveGroup(2,1)')
    976     except RuntimeError:
    977         from sage.misc.misc import verbose
    978         verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0)       
    979 
    980     if n == None:
     978    if d == None:
    981979        return TransitiveGroupsAll()
    982980    else:
    983         if (not isinstance(n, Integer)) or n < 0:
    984             raise ValueError("A transitive group acts on a non negative integer number of positions")
    985         if n < 31:
    986             return TransitiveGroupsOfDegree(n)
    987         else:
    988             raise NotImplementedError
    989 
     981        d == Integer(d)
     982        assert d >= 0, "A transitive group acts on a non negative integer number of positions"
     983        return TransitiveGroupsOfDegree(d)
    990984
    991985class TransitiveGroupsAll(DisjointUnionEnumeratedSets):
    992986    """
    class TransitiveGroupsAll(DisjointUnionE 
    994988
    995989    EXAMPLES::
    996990
    997         sage: L = TransitiveGroups(); L # requires optional database_gap
     991        sage: L = TransitiveGroups(); L
    998992        Transitive Groups
    999         sage: L.cardinality() # requires optional database_gap
     993        sage: L.category()
     994        Category of infinite enumerated sets
     995        sage: L.cardinality()
    1000996        +Infinity
    1001         sage: p = L.__iter__() # requires optional database_gap
     997
     998        sage: p = L.__iter__()            # requires optional database_gap
    1002999        sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) # requires optional database_gap
    10031000        (Transitive group number 1 of degree 0, Transitive group number 1 of degree 1, Transitive group number 1 of degree 2, Transitive group number 1 of degree 3, Transitive group number 2 of degree 3, Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4)
    10041001
    class TransitiveGroupsAll(DisjointUnionE 
    10161013        """
    10171014        DisjointUnionEnumeratedSets.__init__(self, Family(NonNegativeIntegers(), lambda i: TransitiveGroups(i)) )
    10181015
    1019     def __repr__(self):
     1016    def _repr_(self):
    10201017        """
    10211018        TESTS::
    10221019
    1023             sage: TransitiveGroups() # requires optional database_gap
     1020            sage: TransitiveGroups() # requires optional database_gap # indirect doctest
    10241021            Transitive Groups
    10251022        """
    10261023        return "Transitive Groups"
    class TransitiveGroupsAll(DisjointUnionE 
    10331030            True
    10341031            sage: TransitiveGroup(6,5) in TransitiveGroups() # requires optional database_gap
    10351032            True
     1033            sage: 1 in TransitiveGroups() # requires optional database_gap
     1034            False
    10361035        """
    10371036        return isinstance(G,TransitiveGroup)
    10381037
    class TransitiveGroupsAll(DisjointUnionE 
    10421041
    10431042        EXAMPLES::
    10441043
    1045             sage: TransitiveGroups(5)._an_element_() # requires optional database_gap
     1044            sage: TransitiveGroups(5).an_element() # requires optional database_gap # indirect doctest
    10461045            Transitive group number 1 of degree 5
    10471046        """
    10481047        return TransitiveGroup(7,3)
    10491048
    10501049class TransitiveGroupsOfDegree(UniqueRepresentation, Parent):
    10511050    """
    1052     The Set of Transitive Groups of a given small degree.
     1051    The set of all transitive groups of a given (small) degree.
    10531052
    10541053    EXAMPLES::
    10551054
    1056         sage: S = TransitiveGroups(4); S # requires optional database_gap
     1055        sage: S = TransitiveGroups(4); S       # requires optional database_gap
    10571056        Transitive Groups of degree 4
    1058         sage: list(S) # requires optional database_gap
     1057        sage: list(S)                          # requires optional database_gap
    10591058        [Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4, Transitive group number 4 of degree 4, Transitive group number 5 of degree 4]
    10601059
    1061     TEST::
    1062    
    1063         sage: TestSuite(TransitiveGroups(6)).run() # requires optional database_gap # long time
     1060        sage: TransitiveGroups(5).an_element() # requires optional database_gap
     1061        Transitive group number 1 of degree 5
     1062
     1063    We write the cardinality of all transitive groups of degree 5::
     1064
     1065        sage: for G in TransitiveGroups(5):    # requires optional database_gap
     1066        ...       print G.cardinality()
     1067        5
     1068        10
     1069        20
     1070        60
     1071        120
     1072
     1073    TESTS::
     1074
     1075        sage: TestSuite(TransitiveGroups(3)).run() # requires optional database_gap
     1076
     1077
    10641078    """
    10651079    def __init__(self, n):
    10661080        """
    class TransitiveGroupsOfDegree(UniqueRep 
    10731087        self._degree = n
    10741088        Parent.__init__(self, category = FiniteEnumeratedSets())
    10751089
    1076     def __repr__(self):
     1090    def _repr_(self):
    10771091        """
    10781092        TESTS::
    10791093
    class TransitiveGroupsOfDegree(UniqueRep 
    10901104            False
    10911105            sage: TransitiveGroup(4,3) in TransitiveGroups(4) # requires optional database_gap
    10921106            True
     1107            sage: 1 in TransitiveGroups(4) # requires optional database_gap
     1108            False
    10931109        """
    10941110        if isinstance(G,TransitiveGroup):
    10951111            return G._d == self._degree
    10961112        else:
    10971113            False
    10981114
    1099     def _an_element_(self):
    1100         """
    1101         Returns an element of ``self``.
     1115    def __getitem__(self, n):
     1116        r"""
     1117        INPUT:
     1118
     1119         - ``n`` -- a positive integer
     1120
     1121        Returns the `n`-th transitive group of a given degree.
    11021122
    11031123        EXAMPLES::
    11041124
    1105             sage: TransitiveGroups(5)._an_element_() # requires optional database_gap
    1106             Transitive group number 1 of degree 5
     1125            sage: TransitiveGroups(5)[3]          # requires optional database_gap#
     1126            Transitive group number 3 of degree 5
     1127
     1128        .. warning:: this follows GAP's naming convention of indexing
     1129        the transitive groups starting from ``1``::
     1130
     1131            sage: TransitiveGroups(5)[0]
     1132            Traceback (most recent call last):
     1133            ...
     1134                assert n > 0
     1135            AssertionError
    11071136        """
    1108         return TransitiveGroup(self._degree,1)
     1137        return TransitiveGroup(self._degree, n)
    11091138
    11101139    def __iter__(self):
    11111140        """
    class TransitiveGroupsOfDegree(UniqueRep 
    11141143            sage: list(TransitiveGroups(5)) # indirect doctest # requires optional database_gap
    11151144            [Transitive group number 1 of degree 5, Transitive group number 2 of degree 5, Transitive group number 3 of degree 5, Transitive group number 4 of degree 5, Transitive group number 5 of degree 5]
    11161145        """
    1117         for i in range(1,number_of_transitive_groups(self._degree)+1):
    1118             yield TransitiveGroup(self._degree,i)
     1146        for n in xrange(1, self.cardinality() + 1):
     1147            yield self[n]
    11191148
     1149    _an_element_ = EnumeratedSets.ParentMethods._an_element_
     1150
     1151    @cached_method
    11201152    def cardinality(self):
    1121         """
    1122         Returns the cardinality of ``self``.
     1153        r"""
     1154        Returns the cardinality of ``self``, that is the number of
     1155        transitive groups of a given degree.
    11231156
    11241157        EXAMPLES::
    1125        
    1126             sage: TransitiveGroups(2).cardinality() # requires optional database_gap
     1158
     1159            sage: TransitiveGroups(0).cardinality()                      # requires optional database_gap
    11271160            1
    1128             sage: TransitiveGroups(7).cardinality() # requires optional database_gap
     1161            sage: TransitiveGroups(2).cardinality()                      # requires optional database_gap
     1162            1
     1163            sage: TransitiveGroups(7).cardinality()                      # requires optional database_gap
    11291164            7
    1130             sage: TransitiveGroups(12).cardinality() # requires optional database_gap
     1165            sage: TransitiveGroups(12).cardinality()                     # requires optional database_gap
    11311166            301
     1167            sage: [TransitiveGroups(i).cardinality() for i in range(11)] # requires optional database_gap
     1168            [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]
     1169
     1170        .. warning:: The database_gap contains all transitive groups
     1171          up to degree 30::
     1172
     1173            sage: TransitiveGroups(31).cardinality()                     # requires optional database_gap
     1174            Traceback (most recent call last):
     1175            ...
     1176            NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
     1177
     1178        TESTS::
     1179
     1180            sage: type(TransitiveGroups(12).cardinality())               # requires optional database_gap
     1181            <type 'sage.rings.integer.Integer'>
     1182            sage: type(TransitiveGroups(0).cardinality())
     1183            <type 'sage.rings.integer.Integer'>
    11321184        """
    1133         return number_of_transitive_groups(self._degree)
     1185        # gap.NrTransitiveGroups(0) fails, so Sage needs to handle this
     1186
     1187        # While we are at it, and since Sage also handles the
     1188        # transitive group of degree 1, we may as well handle 1
     1189        if self._degree <= 1:
     1190            return ZZ(1)
     1191        else:
     1192            try:
     1193                return Integer(gap.NrTransitiveGroups(gap(self._degree)))
     1194            except RuntimeError:
     1195                from sage.misc.misc import verbose
     1196                verbose("Warning: TransitiveGroups requires the GAP database package. Please install it with ``sage -i database_gap``.", level=0)
     1197            except TypeError:
     1198                raise NotImplementedError, "Only the transitive groups of order less than 30 are available in GAP's database"
    11341199
    11351200class PermutationGroup_plg(PermutationGroup_unique):
    11361201    def base_ring(self):