Ticket #10976: trac_10976.2.patch

File trac_10976.2.patch, 3.5 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 (2011): 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        gens = self.gens()
     1318        # This special case only works with more than 1 generator.
     1319        if not gens or len(gens) < 2:
     1320            return None
     1321        # Special case: certain subgroups of the symmetric group that Gap reports
     1322        # generators of the form ((1, 2), (1, 3), ..., (1, m))
     1323        # This means that this graph is isomorphic to a smaller symmetric group
     1324        # S_n, where n is the number of generators supported.
     1325        #
     1326        # The code that follows checks that the following assumptions hold:
     1327        #     * All generators have order 2
     1328        #     * All generators share a common element
     1329        #
     1330        # We then know that the order of this group is isomorphic to S_n,
     1331        # and therefore its order is n!.
     1332       
     1333        # Check that all generators are order 2.
     1334        for g in gens:
     1335            if g.order() != 2:
     1336                return None
     1337        # Find the common element.
     1338        g0 = gens[0].cycle_tuples()[0]
     1339        g1 = gens[1].cycle_tuples()[0]
     1340        a, b = g0
     1341        if a not in g1 and b not in g1:
     1342            return None
     1343        if a in g1:
     1344            elem = a
     1345        else:
     1346            elem = b
     1347        # Count the number of unique elements in the generators.
     1348        unique = set()
     1349        for g in gens:
     1350            a, b = g.cycle_tuples()[0]
     1351            if a != elem and b != elem:
     1352                return None
     1353            unique.add(a)
     1354            unique.add(b)
     1355        # Compute the order.
     1356        return factorial(len(unique))
     1357
    12921358    def order(self):
    12931359        """
    12941360        Return the number of elements of this group.
     
    13071373        """
    13081374        if not self.gens() or self.gens() == [self(1)]:
    13091375            return Integer(1)
     1376        subgroup_order = self._order()
     1377        if subgroup_order is not None:
     1378          return subgroup_order
    13101379        return Integer(self._gap_().Size())
    13111380
    13121381    def random_element(self):