Ticket #10976: trac_10976.5.patch

File trac_10976.5.patch, 3.8 KB (added by swenson, 9 years ago)
  • sage/groups/perm_gps/permgroup.py

    diff --git a/sage/groups/perm_gps/permgroup.py b/sage/groups/perm_gps/permgroup.py
    a b  
    9090
    9191- Nicolas Borie (2009): Added orbit, transversals, stabiliser and strong_generating_system methods
    9292
     93- Christopher Swenson (2012): Added a special case to compute the order efficiently.
     94  (This patch Copyright 2012 Google Inc. All Rights Reserved. )
     95
    9396REFERENCES:
    9497
    9598- Cameron, P., Permutation Groups. New York: Cambridge University
     
    132135from sage.misc.package import is_package_installed
    133136from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
    134137from sage.categories.all import FiniteEnumeratedSets
     138from sage.functions.other import factorial
    135139
    136140def load_hap():
    137141    """
     
    12891293        return '\\langle ' + \
    12901294               ', '.join([x._latex_() for x in self.gens()]) + ' \\rangle'
    12911295
     1296    def _order(self):
     1297        """
     1298        This handles a few special cases of computing the subgroup order much
     1299        faster than GAP.
     1300
     1301        This currently operates very quickly for stabilizer subgroups of
     1302        permutation groups, for one.
     1303
     1304        Will return None if the we could not easily compute it.
     1305
     1306        Author: Christopher Swenson
     1307
     1308        EXAMPLES::
     1309
     1310            sage: SymmetricGroup(10).stabilizer(4)._order()
     1311            362880
     1312            sage: SymmetricGroup(10).stabilizer(4).stabilizer(5)._order()
     1313            40320
     1314            sage: SymmetricGroup(200).stabilizer(100)._order() == factorial(199) # this should be very fast
     1315            True
     1316       
     1317        TESTS::
     1318
     1319            sage: [SymmetricGroup(n).stabilizer(1)._gap_().Size() for n in [4..10]]
     1320            [6, 24, 120, 720, 5040, 40320, 362880]
     1321            sage: [SymmetricGroup(n).stabilizer(1)._order() for n in [4..10]]
     1322            [6, 24, 120, 720, 5040, 40320, 362880]
     1323        """
     1324        gens = self.gens()
     1325        # This special case only works with more than 1 generator.
     1326        if not gens or len(gens) < 2:
     1327            return None
     1328        # Special case: certain subgroups of the symmetric group for which Gap reports
     1329        # generators of the form ((1, 2), (1, 3), ...)
     1330        # This means that this group is isomorphic to a smaller symmetric group
     1331        # S_n, where n is the number of generators supported.
     1332        #
     1333        # The code that follows checks that the following assumptions hold:
     1334        #     * All generators have order 2
     1335        #     * All generators share a common element
     1336        #
     1337        # We then know that this group is isomorphic to S_n,
     1338        # and therefore its order is n!.
     1339       
     1340        # Check that all generators are order 2.
     1341        for g in gens:
     1342            if g.order() != 2:
     1343                return None
     1344        # Find the common element.
     1345        g0 = gens[0].cycle_tuples()[0]
     1346        g1 = gens[1].cycle_tuples()[0]
     1347        a, b = g0
     1348        if a not in g1 and b not in g1:
     1349            return None
     1350        if a in g1:
     1351            elem = a
     1352        else:
     1353            elem = b
     1354        # Count the number of unique elements in the generators.
     1355        unique = set()
     1356        for g in gens:
     1357            a, b = g.cycle_tuples()[0]
     1358            if a != elem and b != elem:
     1359                return None
     1360            unique.add(a)
     1361            unique.add(b)
     1362        # Compute the order.
     1363        return factorial(len(unique))
     1364
    12921365    def order(self):
    12931366        """
    12941367        Return the number of elements of this group.
     
    13071380        """
    13081381        if not self.gens() or self.gens() == [self(1)]:
    13091382            return Integer(1)
     1383        subgroup_order = self._order()
     1384        if subgroup_order is not None:
     1385          return subgroup_order
    13101386        return Integer(self._gap_().Size())
    13111387
    13121388    def random_element(self):