Groups
Release 10.4

The Sage Development TeamJul 23, 2024

CONTENTS

1

Examples of Groups

1

2

Base class for groups

33Group homomorphisms for groups with a GAP backend

94

LibGAP-based Groups

19

5

Generic LibGAP-based Group33

6

Mix-in Class for GAP-based Groups

35

7

PARI Groups

59

8

Miscellaneous generic functions

63

9Free Groups

91

10 Finitely Presented Groups

101

11 Named Finitely Presented Groups

137

12 Braid groups

145

13 Cubic Braid Groups

193

14 Indexed Free Groups

215

15 Artin Groups

221

16 Right-Angled Artin Groups

233

17 Cactus Groups

241

18 Functor that converts a commutative additive group into a multiplicative group.

253

19 Semidirect product of groups259

20 Miscellaneous Groups

267

21 Semimonomial transformation group269

22 Elements of a semimonomial transformation group273i

23 Kernel Subgroups

277

24 Class functions of groups.

281

25 Conjugacy classes of groups299

26 Abelian Groups

307

27 Permutation Groups

407

28 Matrix and Affine Groups

597

29 Lie Groups

717

30 Partition Refinement

737

31 Internals

757

32 Indices and Tables

761

Bibliography

763

Python Module Index

765

Index

767

ii

CHAPTERONE

EXAMPLES OF GROUPS

The groups object may be used to access examples of various groups. Using tab-completion on this object is an easy
way to discover and quickly create the groups that are available (as listed here).
Let <tab> indicate pressing the Tab key. So begin by typing groups.<tab> to the see primary divisions, followedby (for example) groups.matrix.<tab> to access various groups implemented as sets of matrices.
• Permutation Groups (groups.permutation.<tab>)– groups.permutation.Symmetric– groups.permutation.Alternating– groups.permutation.KleinFour– groups.permutation.Quaternion– groups.permutation.Cyclic– groups.permutation.ComplexReflection– groups.permutation.Dihedral– groups.permutation.DiCyclic– groups.permutation.Mathieu– groups.permutation.Suzuki– groups.permutation.PGL– groups.permutation.PSL– groups.permutation.PSp– groups.permutation.PSU– groups.permutation.PGU– groups.permutation.Transitive– groups.permutation.RubiksCube• Matrix Groups (groups.matrix.<tab>)– groups.matrix.QuaternionGF3– groups.matrix.GL– groups.matrix.SL– groups.matrix.Sp– groups.matrix.GU

1

Groups, Release 10.4

– groups.matrix.SU– groups.matrix.GO– groups.matrix.SO• Finitely Presented Groups (groups.presentation.<tab>)– groups.presentation.Alternating– groups.presentation.Cactus– groups.presentation.Cyclic– groups.presentation.Dihedral– groups.presentation.DiCyclic– groups.presentation.FGAbelian– groups.presentation.KleinFour– groups.presentation.Quaternion– groups.presentation.Symmetric• Affine Groups (groups.affine.<tab>)– groups.affine.Affine– groups.affine.Euclidean• Lie Groups (groups.lie.<tab>)– groups.lie.Nilpotent• Miscellaneous Groups (groups.misc.<tab>)– Coxeter, reflection and related groups∗ groups.misc.Braid∗ groups.misc.Cactus∗ groups.misc.CoxeterGroup∗ groups.misc.PureCactus∗ groups.misc.ReflectionGroup∗ groups.misc.RightAngledArtin∗ groups.misc.WeylGroup– other miscellaneous groups∗ groups.misc.AdditiveAbelian∗ groups.misc.AdditiveCyclic∗ groups.misc.Free∗ groups.misc.SemimonomialTransformation

2

Chapter 1. Examples of Groups

CHAPTERTWOBASE CLASS FOR GROUPS

class sage.groups.group.AbelianGroupBases: Group
Generic abelian group.
is_abelian()
Return True.
EXAMPLES:
sage: from sage.groups.group import AbelianGroupsage: G = AbelianGroup()
sage: G.is_abelian()True>>> from sage.all import *>>> from sage.groups.group import AbelianGroup>>> G = AbelianGroup()>>> G.is_abelian()
Trueclass sage.groups.group.AlgebraicGroupBases: Group
class sage.groups.group.FiniteGroupBases: Group
Generic finite group.
is_finite()
Return True.
EXAMPLES:
sage: from sage.groups.group import FiniteGroupsage: G = FiniteGroup()
sage: G.is_finite()True>>> from sage.all import *>>> from sage.groups.group import FiniteGroup>>> G = FiniteGroup()>>> G.is_finite()
True

3Groups, Release 10.4class sage.groups.group.GroupBases: Parent
Base class for all groups.
is_abelian()
Test whether this group is abelian.
EXAMPLES:
sage: from sage.groups.group import Groupsage: G = Group()
sage: G.is_abelian()Traceback (most recent call last):...
NotImplementedError>>> from sage.all import *>>> from sage.groups.group import Group>>> G = Group()>>> G.is_abelian()Traceback (most recent call last):...
NotImplementedError

is_commutative()
Test whether this group is commutative.
This is an alias for is_abelian, largely to make groups work well with the Factorization class.
(Note for developers: Derived classes should override is_abelian, not is_commutative.)
EXAMPLES:
sage: SL(2, 7).is_commutative()
˓→needs sage.libs.gap sage.modules sage.rings.finite_rings
False

#␣

>>> from sage.all import *>>> SL(Integer(2), Integer(7)).is_commutative()˓→# needs sage.libs.gap sage.modules sage.rings.finite_rings
False

␣

is_finite()
Return True if this group is finite.
EXAMPLES:
sage: from sage.groups.group import Groupsage: G = Group()
sage: G.is_finite()
Traceback (most recent call last):...
NotImplementedError>>> from sage.all import *>>> from sage.groups.group import Group>>> G = Group()(continues on next page)

4

Chapter 2. Base class for groups

Groups, Release 10.4

(continued from previous page)>>> G.is_finite()
Traceback (most recent call last):...
NotImplementedError

is_multiplicative()
Return True if the group operation is given by * (rather than +).
Override for additive groups.
EXAMPLES:
sage: from sage.groups.group import Groupsage: G = Group()
sage: G.is_multiplicative()
True>>> from sage.all import *>>> from sage.groups.group import Group>>> G = Group()>>> G.is_multiplicative()
True

is_trivial()
Return True if this group is the trivial group.
A group is trivial, if it consists only of the identity element.
Warning: It is in principle undecidable whether a group is trivial, for example, if the group is given bya finite presentation. Thus, this method may not terminate.
EXAMPLES:
sage: groups.presentation.Cyclic(1).is_trivial()
True
sage: G.<a,b> = FreeGroup( a, b )sage: H = G / (a^2, b^3, a*b*~a*~b)sage: H.is_trivial()
False>>> from sage.all import *>>> groups.presentation.Cyclic(Integer(1)).is_trivial()
True>>> G = FreeGroup( a, b , names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (a**Integer(2), b**Integer(3), a*b*~a*~b)>>> H.is_trivial()
False

A non-trivial presentation of the trivial group:sage: F.<a,b> = FreeGroup()
sage: J = F / ((~a)*b*a*(~b)^2, (~b)*a*b*(~a)^2)(continues on next page)5

Groups, Release 10.4

(continued from previous page)

sage: J.is_trivial()
True>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> J = F / ((~a)*b*a*(~b)**Integer(2), (~b)*a*b*(~a)**Integer(2))>>> J.is_trivial()
Trueorder()
Return the number of elements of this group.
This is either a positive integer or infinity.
EXAMPLES:
sage: from sage.groups.group import Groupsage: G = Group()
sage: G.order()Traceback (most recent call last):...
NotImplementedError>>> from sage.all import *>>> from sage.groups.group import Group>>> G = Group()>>> G.order()Traceback (most recent call last):...
NotImplementedError

quotient(H, **kwds)
Return the quotient of this group by the normal subgroup 𝐻.
EXAMPLES:
sage: from sage.groups.group import Groupsage: G = Group()
sage: G.quotient(G)Traceback (most recent call last):...
NotImplementedError>>> from sage.all import *>>> from sage.groups.group import Group>>> G = Group()>>> G.quotient(G)Traceback (most recent call last):...
NotImplementedError

sage.groups.group.is_Group(x)Return whether x is a group object.
INPUT:• x – anything
6

Chapter 2. Base class for groups

Groups, Release 10.4

OUTPUT: boolean
EXAMPLES:
sage: F.<a,b> = FreeGroup()
˓→needs sage.groups
sage: from sage.groups.group import is_Groupsage: is_Group(F)˓→needs sage.groups
doctest:warning...DeprecationWarning: use instead G in Groups()
See https://github.com/sagemath/sage/issues/37449 for details.
Truesage: is_Group("a string")
False

#␣

#␣

>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)# needs sage.
˓→groups>>> from sage.groups.group import is_Group>>> is_Group(F)#␣˓→needs sage.groups
doctest:warning...DeprecationWarning: use instead G in Groups()
See https://github.com/sagemath/sage/issues/37449 for details.
True>>> is_Group("a string")
False

7

Groups, Release 10.4

8Chapter 2. Base class for groups

CHAPTERTHREE

GROUP HOMOMORPHISMS FOR GROUPS WITH A GAP BACKEND

EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2, 4])
sage: F.<a,b> = FreeGroup()
sage: f = F.hom([g for g in A.gens()])
sage: K = f.kernel()sage: KGroup(<free, no generators known>)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2), Integer(4)])>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> f = F.hom([g for g in A.gens()])>>> K = f.kernel()>>> K
Group(<free, no generators known>)

AUTHORS:• Simon Brandhorst (2018-02-08): initial version• Sebastian Oehms (2018-11-15): have this functionality work for permutation groups (Issue #26750) and implement
section() and natural_map()
class sage.groups.libgap_morphism.GroupHomset_libgap(G, H, category=None, check=True)
Bases: HomsetWithBase
Homsets of groups with a libgap backend.
Do not call this directly instead use Hom().
INPUT:• G – a libgap group• H – a libgap group• category – a category
OUTPUT: the homset of two libgap groups
EXAMPLES:

9

Groups, Release 10.4

sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2,4])
sage: H = A.Hom(A)sage: HSet of Morphisms from Abelian group with gap, generator orders (2, 4)
to Abelian group with gap, generator orders (2, 4)
in Category of finite enumerated commutative groups>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2),Integer(4)])>>> H = A.Hom(A)>>> H
Set of Morphisms from Abelian group with gap, generator orders (2, 4)
to Abelian group with gap, generator orders (2, 4)
in Category of finite enumerated commutative groups

Element
alias of GroupMorphism_libgap
natural_map()
This method from HomsetWithBase is overloaded here for cases in which both groups have corresponding
lists of generators.
OUTPUT:
An instance of the element class of self if there exists a group homomorphism mapping the generators ofthe domain of self to the according generators of the codomain. Otherwise, the method falls back to thedefault.
EXAMPLES:
sage: G = GL(3,2)
sage: P = PGL(3,2)
sage: nat = Hom(G, P).natural_map()
sage: type(nat)<class sage.groups.libgap_morphism.GroupHomset_libgap_with_category.element_
˓→class >sage: g1, g2 = G.gens()
sage: nat(g1*g2)(1,2,4,5,7,3,6)>>> from sage.all import *>>> G = GL(Integer(3),Integer(2))>>> P = PGL(Integer(3),Integer(2))>>> nat = Hom(G, P).natural_map()>>> type(nat)<class sage.groups.libgap_morphism.GroupHomset_libgap_with_category.element_
˓→class >>>> g1, g2 = G.gens()>>> nat(g1*g2)(1,2,4,5,7,3,6)

class sage.groups.libgap_morphism.GroupMorphism_libgap(homset, gap_hom, check=True)
Bases: Morphism
This wraps GAP group homomorphisms.

10

Chapter 3. Group homomorphisms for groups with a GAP backend

Groups, Release 10.4

Checking if the input defines a group homomorphism can be expensive if the group is large.
INPUT:• homset – the parent• gap_hom – a sage.libs.gap.element.GapElement consisting of a group homomorphism• check – (default: True) check if the gap_hom is a group homomorphism; this can be expensive
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2, 4])
sage: A.hom([g^2 for g in A.gens()])
Group endomorphism of Abelian group with gap, generator orders (2, 4)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2), Integer(4)])>>> A.hom([g**Integer(2) for g in A.gens()])
Group endomorphism of Abelian group with gap, generator orders (2, 4)

Homomorphisms can be defined between different kinds of GAP groups:
sage: G = MatrixGroup([Matrix(ZZ, 2, [0,1,1,0])])sage: f = A.hom([G.0, G(1)])
sage: fGroup morphism:
From: Abelian group with gap, generator orders (2, 4)
To:
Matrix group over Integer Ring with 1 generators (
[0 1]
[1 0]
)
sage: G.<a,b> = FreeGroup()
sage: H = G / (G([1]), G([2])^3)
sage: f = G.hom(H.gens())
sage: fGroup morphism:
From: Free Group on generators {a, b}
To:
Finitely presented group < a, b | a, b^3 >>>> from sage.all import *>>> G = MatrixGroup([Matrix(ZZ, Integer(2), [Integer(0),Integer(1),Integer(1),˓→Integer(0)])])>>> f = A.hom([G.gen(0), G(Integer(1))])>>> f
Group morphism:
From: Abelian group with gap, generator orders (2, 4)
To:
Matrix group over Integer Ring with 1 generators (
[0 1]
[1 0]
)
>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (G([Integer(1)]), G([Integer(2)])**Integer(3))>>> f = G.hom(H.gens())>>> f
Group morphism:(continues on next page)11

Groups, Release 10.4

(continued from previous page)

From: Free Group on generators {a, b}
To:
Finitely presented group < a, b | a, b^3 >Homomorphisms can be defined between GAP groups and permutation groups:
sage: S = Sp(4,3)
sage: P = PSp(4,3)
sage: pr = S.hom(P.gens())
sage: E = copy(S.one().matrix())
sage: E[3,0] = 2; e = S(E)sage: pr(e)(1,16,15)(3,22,18)(4,19,21)(6,34,24)(7,25,33)(9,40,27)(10,28,39)(12,37,30)(13,31,
˓→36)>>> from sage.all import *>>> S = Sp(Integer(4),Integer(3))>>> P = PSp(Integer(4),Integer(3))>>> pr = S.hom(P.gens())>>> E = copy(S.one().matrix())>>> E[Integer(3),Integer(0)] = Integer(2); e = S(E)>>> pr(e)(1,16,15)(3,22,18)(4,19,21)(6,34,24)(7,25,33)(9,40,27)(10,28,39)(12,37,30)(13,31,
˓→36)

gap()
Return the underlying LibGAP group homomorphism.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2,4])
sage: f = A.hom([g^2 for g in A.gens()])
sage: f.gap()[ f1, f2 ] -> [ <identity> of ..., f3 ]>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2),Integer(4)])>>> f = A.hom([g**Integer(2) for g in A.gens()])>>> f.gap()[ f1, f2 ] -> [ <identity> of ..., f3 ]image(J, *args, **kwds)
The image of an element or a subgroup.
INPUT:• J – a subgroup or an element of the domain of self
OUTPUT: the image of J under self
Note: pushforward is the method that is used when a map is called on anything that is not an elementof its domain. For historical reasons, we keep the alias image() for this method.
EXAMPLES:

12

Chapter 3. Group homomorphisms for groups with a GAP backend

Groups, Release 10.4

sage: G.<a,b> = FreeGroup()
sage: H = G / (G([1]), G([2])^3)
sage: f = G.hom(H.gens())
sage: S = G.subgroup([a.gap()])
sage: f.pushforward(S)Group([ a ])sage: x = f.image(a)sage: xasage: x.parent()
Finitely presented group < a, b | a, b^3 >sage: # needs sage.rings.finite_rings
sage: G = GU(3,2)
sage: P = PGU(3,2)
sage: pr = Hom(G, P).natural_map()
sage: GS = G.subgroup([G.gen(0)])
sage: pr.pushforward(GS)Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of(The projective general unitary group of degree 3 over Finite Field of size 2)>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (G([Integer(1)]), G([Integer(2)])**Integer(3))>>> f = G.hom(H.gens())>>> S = G.subgroup([a.gap()])>>> f.pushforward(S)Group([ a ])>>> x = f.image(a)>>> xa>>> x.parent()
Finitely presented group < a, b | a, b^3 >>>> # needs sage.rings.finite_rings>>> G = GU(Integer(3),Integer(2))>>> P = PGU(Integer(3),Integer(2))>>> pr = Hom(G, P).natural_map()>>> GS = G.subgroup([G.gen(Integer(0))])>>> pr.pushforward(GS)Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of(The projective general unitary group of degree 3 over Finite Field of size 2)

kernel()Return the kernel of self.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A1 = AbelianGroupGap([6, 6])
sage: A2 = AbelianGroupGap([3, 3])
sage: f = A1.hom(A2.gens())
sage: f.kernel()
Subgroup of Abelian group with gap, generator orders (6, 6)
generated by (f1*f2, f3*f4)
sage: f.kernel().order()4(continues on next page)13

Groups, Release 10.4

(continued from previous page)

sage: S = Sp(6,3)
sage: P = PSp(6,3)
sage: pr = Hom(S, P).natural_map()
sage: pr.kernel()
Subgroup with 1 generators ([2 0 0 0 0 0]
[0 2 0 0 0 0]
[0 0 2 0 0 0]
[0 0 0 2 0 0]
[0 0 0 0 2 0]
[0 0 0 0 0 2]
) of Symplectic Group of degree 6 over Finite Field of size 3>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A1 = AbelianGroupGap([Integer(6), Integer(6)])>>> A2 = AbelianGroupGap([Integer(3), Integer(3)])>>> f = A1.hom(A2.gens())>>> f.kernel()
Subgroup of Abelian group with gap, generator orders (6, 6)
generated by (f1*f2, f3*f4)>>> f.kernel().order()4>>> S = Sp(Integer(6),Integer(3))>>> P = PSp(Integer(6),Integer(3))>>> pr = Hom(S, P).natural_map()>>> pr.kernel()
Subgroup with 1 generators ([2 0 0 0 0 0]
[0 2 0 0 0 0]
[0 0 2 0 0 0]
[0 0 0 2 0 0]
[0 0 0 0 2 0]
[0 0 0 0 0 2]
) of Symplectic Group of degree 6 over Finite Field of size 3lift(h)Return an element of the domain that maps to h.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2,4])
sage: f = A.hom([g^2 for g in A.gens()])
sage: a = A.gens()[1]sage: f.lift(a^2)
f2>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2),Integer(4)])>>> f = A.hom([g**Integer(2) for g in A.gens()])>>> a = A.gens()[Integer(1)]>>> f.lift(a**Integer(2))
f2

If the element is not in the image, we raise an error:
14

Chapter 3. Group homomorphisms for groups with a GAP backend

Groups, Release 10.4

sage: f.lift(a)Traceback (most recent call last):...
ValueError: f2 is not an element of the image of Group endomorphismof Abelian group with gap, generator orders (2, 4)>>> from sage.all import *>>> f.lift(a)Traceback (most recent call last):...
ValueError: f2 is not an element of the image of Group endomorphismof Abelian group with gap, generator orders (2, 4)

preimage(S)Return the preimage of the subgroup S.
INPUT:• S – a subgroup of this group
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2,4])
sage: B = AbelianGroupGap([4])
sage: f = A.hom([B.one(), B.gen(0)^2])
sage: S = B.subgroup([B.one()])
sage: f.preimage(S) == f.kernel()True
sage: S = Sp(4,3)
sage: P = PSp(4,3)
sage: pr = Hom(S, P).natural_map()
sage: PS = P.subgroup([P.gen(0)])
sage: pr.preimage(PS)Subgroup with 2 generators ([2 0 0 0] [1 0 0 0]
[0 2 0 0] [0 2 0 0]
[0 0 2 0] [0 0 2 0]
[0 0 0 2], [0 0 0 1]
) of Symplectic Group of degree 4 over Finite Field of size 3>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2),Integer(4)])>>> B = AbelianGroupGap([Integer(4)])>>> f = A.hom([B.one(), B.gen(Integer(0))**Integer(2)])>>> S = B.subgroup([B.one()])>>> f.preimage(S) == f.kernel()True>>> S = Sp(Integer(4),Integer(3))>>> P = PSp(Integer(4),Integer(3))>>> pr = Hom(S, P).natural_map()>>> PS = P.subgroup([P.gen(Integer(0))])>>> pr.preimage(PS)Subgroup with 2 generators ([2 0 0 0] [1 0 0 0]
[0 2 0 0] [0 2 0 0](continues on next page)15

Groups, Release 10.4

(continued from previous page)[0 0 2 0] [0 0 2 0]
[0 0 0 2], [0 0 0 1]
) of Symplectic Group of degree 4 over Finite Field of size 3

pushforward(J, *args, **kwds)
The image of an element or a subgroup.
INPUT:• J – a subgroup or an element of the domain of self
OUTPUT: the image of J under self
Note: pushforward is the method that is used when a map is called on anything that is not an elementof its domain. For historical reasons, we keep the alias image() for this method.
EXAMPLES:
sage: G.<a,b> = FreeGroup()
sage: H = G / (G([1]), G([2])^3)
sage: f = G.hom(H.gens())
sage: S = G.subgroup([a.gap()])
sage: f.pushforward(S)Group([ a ])sage: x = f.image(a)sage: xasage: x.parent()
Finitely presented group < a, b | a, b^3 >sage: # needs sage.rings.finite_rings
sage: G = GU(3,2)
sage: P = PGU(3,2)
sage: pr = Hom(G, P).natural_map()
sage: GS = G.subgroup([G.gen(0)])
sage: pr.pushforward(GS)Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of(The projective general unitary group of degree 3 over Finite Field of size 2)>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (G([Integer(1)]), G([Integer(2)])**Integer(3))>>> f = G.hom(H.gens())>>> S = G.subgroup([a.gap()])>>> f.pushforward(S)Group([ a ])>>> x = f.image(a)>>> xa>>> x.parent()
Finitely presented group < a, b | a, b^3 >>>> # needs sage.rings.finite_rings>>> G = GU(Integer(3),Integer(2))>>> P = PGU(Integer(3),Integer(2))(continues on next page)

16

Chapter 3. Group homomorphisms for groups with a GAP backend

Groups, Release 10.4

(continued from previous page)>>> pr = Hom(G, P).natural_map()>>> GS = G.subgroup([G.gen(Integer(0))])>>> pr.pushforward(GS)Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of(The projective general unitary group of degree 3 over Finite Field of size 2)

section()Return a section map of self by use of lift().
See section() of sage.categories.map.Map, as well.
OUTPUT: an instance of sage.categories.morphism.SetMorphism mapping an element of thecodomain of self to one of its preimages
EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: G = GU(3,2)
sage: P = PGU(3,2)
sage: pr = Hom(G, P).natural_map()
sage: sect = pr.section()sage: sect(P.an_element())[a + 1
a
a]
[
1
1
0]
[
a
0
0]
>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> G = GU(Integer(3),Integer(2))>>> P = PGU(Integer(3),Integer(2))>>> pr = Hom(G, P).natural_map()>>> sect = pr.section()>>> sect(P.an_element())[a + 1
a
a]
[
1
1
0]
[
a
0
0]

17

Groups, Release 10.4

18

Chapter 3. Group homomorphisms for groups with a GAP backend

CHAPTERFOURLIBGAP-BASED GROUPS

This module provides helper class for wrapping GAP groups via libgap. See free_group for an example how they
are used.
The parent class keeps track of the GAP element object, to use it in your Python parent you have to derive both from thesuitable group parent and ParentLibGAP
sage: from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP
sage: from sage.groups.group import Groupsage: class FooElement(ElementLibGAP):
....:
pass
sage: class FooGroup(Group, ParentLibGAP):....:
Element = FooElement....:
def __init__(self):....:
lg = libgap(libgap.CyclicGroup(3))# dummy....:ParentLibGAP.__init__(self, lg)....:
Group.__init__(self)>>> from sage.all import *>>> from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP>>> from sage.groups.group import Group>>> class FooElement(ElementLibGAP):...
pass>>> class FooGroup(Group, ParentLibGAP):...
Element = FooElement...
def __init__(self):...
lg = libgap(libgap.CyclicGroup(Integer(3)))# dummy...
ParentLibGAP.__init__(self, lg)...
Group.__init__(self)

Note how we call the constructor of both superclasses to initialize Group and ParentLibGAP separately. The parent
class implements its output via LibGAP:
sage: FooGroup()<pc group of size 3 with 1 generator>
sage: type(FooGroup().gap())<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> FooGroup()<pc group of size 3 with 1 generator>>>> type(FooGroup().gap())<class sage.libs.gap.element.GapElement >19

Groups, Release 10.4

The element class is a subclass of MultiplicativeGroupElement. To use it, you just inherit from ElementLibGAP
sage: element = FooGroup().an_element()
sage: element
f1>>> from sage.all import *>>> element = FooGroup().an_element()>>> element
f1

The element class implements group operations and printing via LibGAP:
sage: element._repr_()f1
sage: element * element
f1^2>>> from sage.all import *>>> element._repr_()f1>>> element * element
f1^2

AUTHORS:• Volker Braunclass sage.groups.libgap_wrapper.ElementLibGAP
Bases: MultiplicativeGroupElement
A class for LibGAP-based Sage group elements.
INPUT:• parent – the Sage parent• libgap_element – the libgap element that is being wrapped
EXAMPLES:
sage: from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP
sage: from sage.groups.group import Groupsage: class FooElement(ElementLibGAP):
....:
pass
sage: class FooGroup(Group, ParentLibGAP):....:
Element = FooElement....:
def __init__(self):....:
lg = libgap(libgap.CyclicGroup(3))# dummy....:ParentLibGAP.__init__(self, lg)....:
Group.__init__(self)
sage: FooGroup()<pc group of size 3 with 1 generator>
sage: FooGroup().gens()(f1,)>>> from sage.all import *>>> from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP(continues on next page)

20

Chapter 4. LibGAP-based Groups

Groups, Release 10.4

(continued from previous page)>>> from sage.groups.group import Group>>> class FooElement(ElementLibGAP):...
pass>>> class FooGroup(Group, ParentLibGAP):...
Element = FooElement...
def __init__(self):...
lg = libgap(libgap.CyclicGroup(Integer(3)))...
ParentLibGAP.__init__(self, lg)...
Group.__init__(self)>>> FooGroup()<pc group of size 3 with 1 generator>>>> FooGroup().gens()(f1,)# dummygap()
Return a LibGAP representation of the element.
OUTPUT: a GapElement
EXAMPLES:
sage: G.<a,b> = FreeGroup( a, b )sage: x = G([1, 2, -1, -2])
sage: xa*b*a^-1*b^-1
sage: xg = x.gap()
sage: xg
a*b*a^-1*b^-1
sage: type(xg)<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> G = FreeGroup( a, b , names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> x = G([Integer(1), Integer(2), -Integer(1), -Integer(2)])>>> x
a*b*a^-1*b^-1>>> xg = x.gap()>>> xga*b*a^-1*b^-1>>> type(xg)<class sage.libs.gap.element.GapElement >inverse()Return the inverse of self.
is_conjugate(other)
Return whether the elements self and other are conjugate.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(libgap.GL(2, 3))
sage: a,b = G.gens()
sage: a.is_conjugate(b)False
sage: a.is_conjugate((a*b^2) * a * ~(a*b^2))
True

21

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(libgap.GL(Integer(2), Integer(3)))>>> a,b = G.gens()>>> a.is_conjugate(b)False>>> a.is_conjugate((a*b**Integer(2)) * a * ~(a*b**Integer(2)))
True

is_one()Test whether the group element is the trivial element.
OUTPUT: boolean
EXAMPLES:
sage: G.<a,b> = FreeGroup( a, b )sage: x = G([1, 2, -1, -2])
sage: x.is_one()False
sage: (x * ~x).is_one()True>>> from sage.all import *>>> G = FreeGroup( a, b , names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> x = G([Integer(1), Integer(2), -Integer(1), -Integer(2)])>>> x.is_one()
False>>> (x * ~x).is_one()
True

multiplicative_order()Return the multiplicative order.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(libgap.GL(2, 3))
sage: a,b = G.gens()
sage: print(a.order())
2
sage: print(a.multiplicative_order())
2
sage: z = Mod(0, 3)
sage: o = Mod(1, 3)
sage: G(libgap([[o,o],[z,o]])).order()3>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(libgap.GL(Integer(2), Integer(3)))>>> a,b = G.gens()>>> print(a.order())
2>>> print(a.multiplicative_order())
2(continues on next page)

22

Chapter 4. LibGAP-based Groups

Groups, Release 10.4

(continued from previous page)>>> z = Mod(Integer(0), Integer(3))>>> o = Mod(Integer(1), Integer(3))>>> G(libgap([[o,o],[z,o]])).order()3normalizer()
Return the normalizer of the cyclic group generated by this element.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(libgap.GL(3,3))
sage: a,b = G.gens()
sage: H = a.normalizer()
sage: H<group of 3x3 matrices over GF(3)>sage: H.cardinality()96
sage: all(g*a == a*g for g in H)
True>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(libgap.GL(Integer(3),Integer(3)))>>> a,b = G.gens()>>> H = a.normalizer()>>> H<group of 3x3 matrices over GF(3)>>>> H.cardinality()96>>> all(g*a == a*g for g in H)
True

nth_roots(n)Return the set of n-th roots of this group element.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(libgap.GL(3,3))
sage: a,b = G.gens()
sage: g = a*b**2*a*~b
sage: r = g.nth_roots(4)sage: r[[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3)^0, Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3)␣
˓→] ],[ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3)␣
˓→] ]]
sage: r[0]**4 == r[1]**4 == g
True>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(libgap.GL(Integer(3),Integer(3)))>>> a,b = G.gens()(continues on next page)

23

Groups, Release 10.4

(continued from previous page)>>> g = a*b**Integer(2)*a*~b>>> r = g.nth_roots(Integer(4))>>> r[[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3)^0, Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3)␣
˓→] ],[ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3)␣
˓→] ]]>>> r[Integer(0)]**Integer(4) == r[Integer(1)]**Integer(4) == g
Trueorder()
Return the multiplicative order.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(libgap.GL(2, 3))
sage: a,b = G.gens()
sage: print(a.order())
2
sage: print(a.multiplicative_order())
2
sage: z = Mod(0, 3)
sage: o = Mod(1, 3)
sage: G(libgap([[o,o],[z,o]])).order()3>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(libgap.GL(Integer(2), Integer(3)))>>> a,b = G.gens()>>> print(a.order())
2>>> print(a.multiplicative_order())
2>>> z = Mod(Integer(0), Integer(3))>>> o = Mod(Integer(1), Integer(3))>>> G(libgap([[o,o],[z,o]])).order()3class sage.groups.libgap_wrapper.ParentLibGAP(libgap_parent, ambient=None)
Bases: SageObject
A class for parents to keep track of the GAP parent.
This is not a complete group in Sage, this class is only a base class that you can use to implement your own groups
with LibGAP. See libgap_group for a minimal example of a group that is actually usable.
Your implementation definitely needs to supply• __reduce__(): serialize the LibGAP group. Since GAP does not support Python pickles natively, youneed to figure out yourself how you can recreate the group from a pickle.
INPUT:• libgap_parent – the libgap element that is the parent in GAP

24

Chapter 4. LibGAP-based Groups

Groups, Release 10.4

• ambient – A derived class of ParentLibGAP or None (default); the ambient class if libgap_parent
has been defined as a subgroup
EXAMPLES:
sage: from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP
sage: from sage.groups.group import Groupsage: class FooElement(ElementLibGAP):
....:
pass
sage: class FooGroup(Group, ParentLibGAP):....:
Element = FooElement....:
def __init__(self):....:
lg = libgap(libgap.CyclicGroup(3))# dummy....:ParentLibGAP.__init__(self, lg)....:
Group.__init__(self)
sage: FooGroup()<pc group of size 3 with 1 generator>>>> from sage.all import *>>> from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP>>> from sage.groups.group import Group>>> class FooElement(ElementLibGAP):...
pass>>> class FooGroup(Group, ParentLibGAP):...
Element = FooElement...
def __init__(self):...
lg = libgap(libgap.CyclicGroup(Integer(3)))# dummy...
ParentLibGAP.__init__(self, lg)...
Group.__init__(self)>>> FooGroup()<pc group of size 3 with 1 generator>

ambient()
Return the ambient group of a subgroup.
OUTPUT:
A group containing self. If self has not been defined as a subgroup, we just return self.
EXAMPLES:
sage: G = FreeGroup(3)sage: G.ambient() is G
True>>> from sage.all import *>>> G = FreeGroup(Integer(3))>>> G.ambient() is G
True

gap()
Return the GAP representation of self.
OUTPUT: a GapElement
EXAMPLES:
sage: G = FreeGroup(3); GFree Group on generators {x0, x1, x2}(continues on next page)25

Groups, Release 10.4

(continued from previous page)

sage: G.gap()<free group on the generators [ x0, x1, x2 ]>sage: G.gap().parent()
C library interface to GAP
sage: type(G.gap())<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> G = FreeGroup(Integer(3)); GFree Group on generators {x0, x1, x2}>>> G.gap()<free group on the generators [ x0, x1, x2 ]>>>> G.gap().parent()
C library interface to GAP>>> type(G.gap())<class sage.libs.gap.element.GapElement >This can be useful, for example, to call GAP functions that are not wrapped in Sage:sage: G = FreeGroup(3)sage: H = G.gap()
sage: H.DirectProduct(H)<fp group on the generators [ f1, f2, f3, f4, f5, f6 ]>sage: H.DirectProduct(H).RelatorsOfFpGroup()[ f1^-1*f4^-1*f1*f4, f1^-1*f5^-1*f1*f5, f1^-1*f6^-1*f1*f6, f2^-1*f4^-1*f2*f4,
f2^-1*f5^-1*f2*f5, f2^-1*f6^-1*f2*f6, f3^-1*f4^-1*f3*f4, f3^-1*f5^-1*f3*f5,
f3^-1*f6^-1*f3*f6 ]>>> from sage.all import *>>> G = FreeGroup(Integer(3))>>> H = G.gap()>>> H.DirectProduct(H)<fp group on the generators [ f1, f2, f3, f4, f5, f6 ]>>>> H.DirectProduct(H).RelatorsOfFpGroup()[ f1^-1*f4^-1*f1*f4, f1^-1*f5^-1*f1*f5, f1^-1*f6^-1*f1*f6, f2^-1*f4^-1*f2*f4,
f2^-1*f5^-1*f2*f5, f2^-1*f6^-1*f2*f6, f3^-1*f4^-1*f3*f4, f3^-1*f5^-1*f3*f5,
f3^-1*f6^-1*f3*f6 ]We can also convert directly to libgap:
sage: libgap(GL(2, ZZ))
GL(2,Integers)>>> from sage.all import *>>> libgap(GL(Integer(2), ZZ))
GL(2,Integers)

gen(i)
Return the 𝑖-th generator of self.
Warning: Indexing starts at 0 as usual in Sage/Python. Not as in GAP, where indexing starts at 1.
INPUT:

26

Chapter 4. LibGAP-based Groups

Groups, Release 10.4

• i – integer between 0 (inclusive) and ngens() (exclusive); the index of the generator
OUTPUT: the 𝑖-th generator of the group
EXAMPLES:
sage: G = FreeGroup( a, b )sage: G.gen(0)asage: G.gen(1)b>>> from sage.all import *>>> G = FreeGroup( a, b )>>> G.gen(Integer(0))
a>>> G.gen(Integer(1))
bgenerators()
Return the generators of the group.
EXAMPLES:
sage: G = FreeGroup(2)sage: G.gens()(x0, x1)
sage: H = FreeGroup( a, b, c )sage: H.gens()(a, b, c)>>> from sage.all import *>>> G = FreeGroup(Integer(2))>>> G.gens()(x0, x1)>>> H = FreeGroup( a, b, c )>>> H.gens()(a, b, c)generators() is an alias for gens()
sage: G = FreeGroup( a, b )sage: G.generators()(a, b)
sage: H = FreeGroup(3, x )sage: H.generators()(x0, x1, x2)>>> from sage.all import *>>> G = FreeGroup( a, b )>>> G.generators()(a, b)>>> H = FreeGroup(Integer(3),>>> H.generators()(x0, x1, x2)

x )gens()
Return the generators of the group.
27

Groups, Release 10.4

EXAMPLES:
sage: G = FreeGroup(2)sage: G.gens()(x0, x1)
sage: H = FreeGroup( a, b, c )sage: H.gens()(a, b, c)>>> from sage.all import *>>> G = FreeGroup(Integer(2))>>> G.gens()(x0, x1)>>> H = FreeGroup( a, b, c )>>> H.gens()(a, b, c)generators() is an alias for gens()
sage: G = FreeGroup( a, b )sage: G.generators()(a, b)
sage: H = FreeGroup(3, x )sage: H.generators()(x0, x1, x2)>>> from sage.all import *>>> G = FreeGroup( a, b )>>> G.generators()(a, b)>>> H = FreeGroup(Integer(3),>>> H.generators()(x0, x1, x2)

x )is_subgroup()
Return whether the group was defined as a subgroup of a bigger group.
You can access the containing group with ambient().
OUTPUT: boolean
EXAMPLES:
sage: G = FreeGroup(3)sage: G.is_subgroup()
False>>> from sage.all import *>>> G = FreeGroup(Integer(3))>>> G.is_subgroup()
False

maximal_normal_subgroups()
Return the maximal proper normal subgroups of self.
This raises an error if 𝐺/[𝐺, 𝐺] is infinite, yielding infinitely many maximal normal subgroups.
EXAMPLES:

28

Chapter 4. LibGAP-based Groups

Groups, Release 10.4

sage: SL(2,GF(49)).minimal_normal_subgroups()[Subgroup with 1 generators (
[6 0]
[0 6]
) of Special Linear Group of degree 2 over Finite Field in z2 of size 7^2]>>> from sage.all import *>>> SL(Integer(2),GF(Integer(49))).minimal_normal_subgroups()[Subgroup with 1 generators (
[6 0]
[0 6]
) of Special Linear Group of degree 2 over Finite Field in z2 of size 7^2]

minimal_normal_subgroups()
Return the nontrivial minimal normal subgroups of self.
EXAMPLES:
sage: SL(2,GF(49)).minimal_normal_subgroups()[Subgroup with 1 generators (
[6 0]
[0 6]
) of Special Linear Group of degree 2 over Finite Field in z2 of size 7^2]>>> from sage.all import *>>> SL(Integer(2),GF(Integer(49))).minimal_normal_subgroups()[Subgroup with 1 generators (
[6 0]
[0 6]
) of Special Linear Group of degree 2 over Finite Field in z2 of size 7^2]

ngens()
Return the number of generators of self.
OUTPUT: integer
EXAMPLES:
sage: G = FreeGroup(2)sage: G.ngens()2>>> from sage.all import *>>> G = FreeGroup(Integer(2))>>> G.ngens()2

one()
Return the identity element of self.
EXAMPLES:
sage: G = FreeGroup(3)sage: G.one()1
sage: G.one() == G([])(continues on next page)

29

Groups, Release 10.4

(continued from previous page)True
sage: G.one().Tietze()()>>> from sage.all import *>>> G = FreeGroup(Integer(3))>>> G.one()1>>> G.one() == G([])
True>>> G.one().Tietze()()

subgroup(generators)
Return the subgroup generated.
INPUT:• generators – a list/tuple/iterable of group elements.
OUTPUT: the subgroup generated by generators
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F.subgroup([a^2*b]);
Group([ a^2*b ])sage: G.gens()(a^2*b,)G>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F.subgroup([a**Integer(2)*b]); GGroup([ a^2*b ])>>> G.gens()(a^2*b,)

We check that coercions between the subgroup and its ambient group work:
sage: F.0 * G.0a^3*b>>> from sage.all import *>>> F.gen(0) * G.gen(0)a^3*bChecking that Issue #19270 is fixed:
sage: gens = [w.matrix() for w in WeylGroup([ B , 3])]sage: G = MatrixGroup(gens)sage: import itertools
sage: diagonals = itertools.product((1,-1), repeat=3)
sage: subgroup_gens = [diagonal_matrix(L) for L in diagonals]
sage: G.subgroup(subgroup_gens)
Subgroup with 8 generators of Matrix group over Rational Field with 48␣
˓→generators

30

Chapter 4. LibGAP-based Groups

Groups, Release 10.4>>> from sage.all import *>>> gens = [w.matrix() for w in WeylGroup([ B , Integer(3)])]>>> G = MatrixGroup(gens)>>> import itertools>>> diagonals = itertools.product((Integer(1),-Integer(1)), repeat=Integer(3))>>> subgroup_gens = [diagonal_matrix(L) for L in diagonals]>>> G.subgroup(subgroup_gens)
Subgroup with 8 generators of Matrix group over Rational Field with 48␣
˓→generators

31

Groups, Release 10.4

32

Chapter 4. LibGAP-based Groups

CHAPTER

FIVE

GENERIC LIBGAP-BASED GROUP

This is useful if you need to use a GAP group implementation in Sage that does not have a dedicated Sage interface.
If you want to implement your own group class, you should not derive from this but directly from ParentLibGAP.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G_gap = libgap.Group([ (a*b^2).gap() ])sage: from sage.groups.libgap_group import GroupLibGAP
sage: G = GroupLibGAP(G_gap); GGroup([ a*b^2 ])sage: type(G)<class sage.groups.libgap_group.GroupLibGAP_with_category >sage: G.gens()(a*b^2,)>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G_gap = libgap.Group([ (a*b**Integer(2)).gap() ])>>> from sage.groups.libgap_group import GroupLibGAP>>> G = GroupLibGAP(G_gap); GGroup([ a*b^2 ])>>> type(G)<class sage.groups.libgap_group.GroupLibGAP_with_category >>>> G.gens()(a*b^2,)class sage.groups.libgap_group.GroupLibGAP(*args, **kwds)
Bases: GroupMixinLibGAP, Group, ParentLibGAP
Group interface for LibGAP-based groups.
INPUT:
Same as ParentLibGAP.
Element
alias of ElementLibGAP

33

Groups, Release 10.4

34

Chapter 5. Generic LibGAP-based GroupCHAPTERSIX

MIX-IN CLASS FOR GAP-BASED GROUPS

This class adds access to GAP functionality to groups such that parent and element have a gap() method that returns a
GAP object for the parent/element.
If your group implementation uses libgap, then you should add GroupMixinLibGAP as the first class that you are
deriving from. This ensures that it properly overrides any default methods that just raise NotImplementedError.
class sage.groups.libgap_mixin.GroupMixinLibGAP
Bases: object
cardinality()
Implement EnumeratedSets.ParentMethods.cardinality().
EXAMPLES:
sage: G = Sp(4,GF(3))
sage: G.cardinality()
51840
sage: G = SL(4,GF(3))
sage: G.cardinality()
12130560
sage: F = GF(5); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: G.cardinality()480
sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
sage: G.cardinality()+Infinity
sage: G = Sp(4,GF(3))
sage: G.cardinality()
51840
sage: G = SL(4,GF(3))
sage: G.cardinality()
12130560
sage: F = GF(5); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: G.cardinality()
480(continues on next page)

35

Groups, Release 10.4

(continued from previous page)

sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
sage: G.cardinality()+Infinity>>> from sage.all import *>>> G = Sp(Integer(4),GF(Integer(3)))>>> G.cardinality()
51840>>> G = SL(Integer(4),GF(Integer(3)))>>> G.cardinality()
12130560>>> F = GF(Integer(5)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(2)],[-Integer(1),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> G.cardinality()480>>> G = MatrixGroup([matrix(ZZ,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)])])>>> G.cardinality()+Infinity>>> G = Sp(Integer(4),GF(Integer(3)))>>> G.cardinality()
51840>>> G = SL(Integer(4),GF(Integer(3)))>>> G.cardinality()
12130560>>> F = GF(Integer(5)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(2)],[-Integer(1),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> G.cardinality()480>>> G = MatrixGroup([matrix(ZZ,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)])])>>> G.cardinality()+Infinity

center()Return the center of this group as a subgroup.
OUTPUT: the center as a subgroup
EXAMPLES:
sage: G = SU(3, GF(2))˓→needs sage.rings.finite_rings
sage: G.center()˓→needs sage.rings.finite_rings#␣#␣(continues on next page)

36

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)

Subgroup with 1 generators ([a 0 0][0 a 0][0 0 a]) of Special Unitary Group of degree 3 over Finite Field in a of size 2^2
sage: GL(2, GF(3)).center()
Subgroup with 1 generators (
[2 0]
[0 2]
) of General Linear Group of degree 2 over Finite Field of size 3
sage: GL(3, GF(3)).center()
Subgroup with 1 generators ([2 0 0][0 2 0][0 0 2]) of General Linear Group of degree 3 over Finite Field of size 3
sage: GU(3, GF(2)).center()˓→needs sage.rings.finite_rings
Subgroup with 1 generators ([a + 100][
0 a + 10][0
0 a + 1]) of General Unitary Group of degree 3 over Finite Field in a of size 2^2#␣

sage: A = Matrix(FiniteField(5), [[2,0,0], [0,3,0], [0,0,1]])
sage: B = Matrix(FiniteField(5), [[1,0,0], [0,1,0], [0,1,1]])
sage: MatrixGroup([A,B]).center()
Subgroup with 1 generators ([1 0 0][0 1 0][0 0 1]) of Matrix group over Finite Field of size 5 with 2 generators ([2 0 0] [1 0 0]
[0 3 0] [0 1 0]
[0 0 1], [0 1 1])
sage: GL = groups.matrix.GL(3, ZZ)
sage: GL.center()Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> G = SU(Integer(3), GF(Integer(2)))␣˓→# needs sage.rings.finite_rings>>> G.center()#␣˓→needs sage.rings.finite_rings
Subgroup with 1 generators ([a 0 0][0 a 0][0 0 a]) of Special Unitary Group of degree 3 over Finite Field in a of size 2^2>>> GL(Integer(2), GF(Integer(3))).center()
Subgroup with 1 generators ([2 0](continues on next page)

37

Groups, Release 10.4

(continued from previous page)[0 2]) of General Linear Group of degree 2 over Finite Field of size 3>>> GL(Integer(3), GF(Integer(3))).center()
Subgroup with 1 generators ([2 0 0][0 2 0][0 0 2]) of General Linear Group of degree 3 over Finite Field of size 3>>> GU(Integer(3), GF(Integer(2))).center()˓→# needs sage.rings.finite_rings
Subgroup with 1 generators ([a + 100][
0 a + 10][0
0 a + 1]) of General Unitary Group of degree 3 over Finite Field in a of size 2^2␣>>> A = Matrix(FiniteField(Integer(5)), [[Integer(2),Integer(0),Integer(0)],␣
˓→[Integer(0),Integer(3),Integer(0)], [Integer(0),Integer(0),Integer(1)]])>>> B = Matrix(FiniteField(Integer(5)), [[Integer(1),Integer(0),Integer(0)],␣
˓→[Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(1),Integer(1)]])>>> MatrixGroup([A,B]).center()
Subgroup with 1 generators ([1 0 0][0 1 0][0 0 1]) of Matrix group over Finite Field of size 5 with 2 generators ([2 0 0] [1 0 0]
[0 3 0] [0 1 0]
[0 0 1], [0 1 1])>>> GL = groups.matrix.GL(Integer(3), ZZ)>>> GL.center()Traceback (most recent call last):...
NotImplementedError: group must be finite

centralizer(g)Return the centralizer of g in self.
EXAMPLES:
sage: G = groups.matrix.GL(2, 3)
sage: g = G([[1,1], [1,0]])
sage: C = G.centralizer(g); C
Subgroup with 3 generators ([1 1] [2 0] [2 1][1 0], [0 2], [1 1]) of General Linear Group of degree 2 over Finite Field of size 3
sage: C.order()8sage: S = G.subgroup([G([[2,0],[0,2]]), G([[0,1],[2,0]])]); S
Subgroup with 2 generators ([2 0] [0 1][0 2], [2 0]) of General Linear Group of degree 2 over Finite Field of size 3(continues on next page)

38

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)

sage: G.centralizer(S)Subgroup with 3 generators ([2 0] [0 1] [2 2][0 2], [2 0], [1 2]) of General Linear Group of degree 2 over Finite Field of size 3
sage: G = GL(3,2)
sage: all(G.order() == G.centralizer(x).order() * G.conjugacy_class(x).
˓→cardinality()....:
for x in G)
True
sage: H = groups.matrix.Heisenberg(2)sage: H.centralizer(H.an_element())
Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> G = groups.matrix.GL(Integer(2), Integer(3))>>> g = G([[Integer(1),Integer(1)], [Integer(1),Integer(0)]])>>> C = G.centralizer(g); C
Subgroup with 3 generators ([1 1] [2 0] [2 1][1 0], [0 2], [1 1]) of General Linear Group of degree 2 over Finite Field of size 3>>> C.order()8>>> S = G.subgroup([G([[Integer(2),Integer(0)],[Integer(0),Integer(2)]]),␣
˓→G([[Integer(0),Integer(1)],[Integer(2),Integer(0)]])]); S
Subgroup with 2 generators ([2 0] [0 1][0 2], [2 0]) of General Linear Group of degree 2 over Finite Field of size 3>>> G.centralizer(S)Subgroup with 3 generators ([2 0] [0 1] [2 2][0 2], [2 0], [1 2]) of General Linear Group of degree 2 over Finite Field of size 3>>> G = GL(Integer(3),Integer(2))>>> all(G.order() == G.centralizer(x).order() * G.conjugacy_class(x).
˓→cardinality()...
for x in G)
True>>> H = groups.matrix.Heisenberg(Integer(2))>>> H.centralizer(H.an_element())
Traceback (most recent call last):...
NotImplementedError: group must be finite

character(values)
Return a group character from values, where values is a list of the values of the character evaluated on
the conjugacy classes.
INPUT:• values – a list of values of the character
OUTPUT: a group character
39

Groups, Release 10.4

EXAMPLES:
sage: G = MatrixGroup(AlternatingGroup(4))
sage: G.character([1]*len(G.conjugacy_classes_representatives()))˓→needs sage.rings.number_field
Character of Matrix group over Integer Ring with 12 generators>>> from sage.all import *>>> G = MatrixGroup(AlternatingGroup(Integer(4)))>>> G.character([Integer(1)]*len(G.conjugacy_classes_representatives()))˓→# needs sage.rings.number_field
Character of Matrix group over Integer Ring with 12 generators#␣␣

sage: G = GL(2,ZZ)
sage: G.character([1,1,1,1])
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> from sage.all import *>>> G = GL(Integer(2),ZZ)>>> G.character([Integer(1),Integer(1),Integer(1),Integer(1)])
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups

character_table()
Return the matrix of values of the irreducible characters of this group 𝐺 at its conjugacy classes.
The columns represent the conjugacy classes of 𝐺 and the rows represent the different irreducible charactersin the ordering given by GAP.
OUTPUT: a matrix defined over a cyclotomic field
EXAMPLES:
sage: MatrixGroup(SymmetricGroup(2)).character_table()
˓→needs sage.rings.number_field[ 1 -1][ 1 1]
sage: MatrixGroup(SymmetricGroup(3)).character_table()
˓→needs sage.rings.number_field[ 1 1 -1]
[ 2 -1 0][ 1 1 1]
sage: MatrixGroup(SymmetricGroup(5)).character_table()[ 1 -1 -1 1 -1 1 1]
[ 4 0 1 -1 -2 1 0]
[ 5 1 -1 0 -1 -1 1][ 6 0 0 1 0 0 -2][ 5 -1 1 0 1 -1 1][ 4 0 -1 -1 2 1 0]
[ 1 1 1 1 1 1 1]#␣#␣# long time>>> from sage.all import *>>> MatrixGroup(SymmetricGroup(Integer(2))).character_table()˓→# needs sage.rings.number_field␣(continues on next page)

40

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)[ 1 -1][ 1 1]>>> MatrixGroup(SymmetricGroup(Integer(3))).character_table()˓→# needs sage.rings.number_field[ 1 1 -1]
[ 2 -1 0][ 1 1 1]>>> MatrixGroup(SymmetricGroup(Integer(5))).character_table()[ 1 -1 -1 1 -1 1 1]
[ 4 0 1 -1 -2 1 0]
[ 5 1 -1 0 -1 -1 1][ 6 0 0 1 0 0 -2][ 5 -1 1 0 1 -1 1][ 4 0 -1 -1 2 1 0]
[ 1 1 1 1 1 1 1]␣# long timeclass_function(values)
Return the class function with given values.
INPUT:• values – list/tuple/iterable of numbers; the values of the class function on the conjugacy classes, inthat order
EXAMPLES:
sage: G = GL(2,GF(3))
sage: chi = G.class_function(range(8))˓→needs sage.rings.number_fieldsage: list(chi)˓→needs sage.rings.number_field[0, 1, 2, 3, 4, 5, 6, 7]>>> from sage.all import *>>> G = GL(Integer(2),GF(Integer(3)))>>> chi = G.class_function(range(Integer(8)))˓→# needs sage.rings.number_field>>> list(chi)˓→needs sage.rings.number_field[0, 1, 2, 3, 4, 5, 6, 7]

#␣
#␣

␣
#␣

conjugacy_class(g)Return the conjugacy class of g.
OUTPUT:The conjugacy class of g in the group self. If self is the group denoted by 𝐺, this method computes theset {𝑥−1 𝑔𝑥 | 𝑥 ∈ 𝐺}.
EXAMPLES:
sage: G = SL(2, QQ)
sage: g = G([[1,1],[0,1]])
sage: G.conjugacy_class(g)Conjugacy class of [1 1][0 1] in Special Linear Group of degree 2 over Rational Field

41

Groups, Release 10.4>>> from sage.all import *>>> G = SL(Integer(2), QQ)>>> g = G([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])>>> G.conjugacy_class(g)Conjugacy class of [1 1][0 1] in Special Linear Group of degree 2 over Rational Field

conjugacy_classes()
Return a list with all the conjugacy classes of self.
EXAMPLES:
sage: G = SL(2, GF(2))
sage: G.conjugacy_classes()(Conjugacy class of [1 0][0 1] in Special Linear Group of degree 2 over Finite Field of size 2,
Conjugacy class of [0 1][1 0] in Special Linear Group of degree 2 over Finite Field of size 2,
Conjugacy class of [0 1][1 1] in Special Linear Group of degree 2 over Finite Field of size 2)>>> from sage.all import *>>> G = SL(Integer(2), GF(Integer(2)))>>> G.conjugacy_classes()(Conjugacy class of [1 0][0 1] in Special Linear Group of degree 2 over Finite Field of size 2,
Conjugacy class of [0 1][1 0] in Special Linear Group of degree 2 over Finite Field of size 2,
Conjugacy class of [0 1][1 1] in Special Linear Group of degree 2 over Finite Field of size 2)
sage: GL(2,ZZ).conjugacy_classes()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> from sage.all import *>>> GL(Integer(2),ZZ).conjugacy_classes()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups

conjugacy_classes_representatives()
Return a set of representatives for each of the conjugacy classes of the group.
EXAMPLES:
sage: G = SU(3,GF(2))˓→needs sage.rings.finite_rings
sage: len(G.conjugacy_classes_representatives())
˓→needs sage.rings.finite_rings
16

#␣
#␣

sage: G = GL(2,GF(3))
sage: G.conjugacy_classes_representatives()((continues on next page)

42

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)[1 0] [0 2] [2 0] [0 2] [0 2] [0 1] [0 1] [2 0][0 1], [1 1], [0 2], [1 2], [1 0], [1 2], [1 1], [0 1])sage: len(GU(2,GF(5)).conjugacy_classes_representatives())
˓→needs sage.rings.finite_rings36#␣>>> from sage.all import *>>> G = SU(Integer(3),GF(Integer(2)))˓→# needs sage.rings.finite_rings>>> len(G.conjugacy_classes_representatives())
˓→needs sage.rings.finite_rings
16

␣
#␣

>>> G = GL(Integer(2),GF(Integer(3)))>>> G.conjugacy_classes_representatives()([1 0] [0 2] [2 0] [0 2] [0 2] [0 1] [0 1] [2 0][0 1], [1 1], [0 2], [1 2], [1 0], [1 2], [1 1], [0 1])>>> len(GU(Integer(2),GF(Integer(5))).conjugacy_classes_representatives())˓→# needs sage.rings.finite_rings36␣

sage: GL(2,ZZ).conjugacy_classes_representatives()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> from sage.all import *>>> GL(Integer(2),ZZ).conjugacy_classes_representatives()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups

conjugacy_classes_subgroups()
Return a complete list of representatives of conjugacy classes of subgroups in self.
The ordering is that given by GAP.
EXAMPLES:
sage: G = groups.matrix.GL(2,2)
sage: G.conjugacy_classes_subgroups()[Subgroup with 0 generators ()of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 1]
[0 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,(continues on next page)

43

Groups, Release 10.4

(continued from previous page)

Subgroup with 2 generators ([0 1] [1 1][1 1], [0 1]) of General Linear Group of degree 2 over Finite Field of size 2]
sage: H = groups.matrix.Heisenberg(2)sage: H.conjugacy_classes_subgroups()
Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> G = groups.matrix.GL(Integer(2),Integer(2))>>> G.conjugacy_classes_subgroups()[Subgroup with 0 generators ()of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 1]
[0 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 2 generators ([0 1] [1 1][1 1], [0 1]) of General Linear Group of degree 2 over Finite Field of size 2]>>> H = groups.matrix.Heisenberg(Integer(2))>>> H.conjugacy_classes_subgroups()
Traceback (most recent call last):...
NotImplementedError: group must be finite

exponent()
Computes the exponent of the group.
The exponent 𝑒 of a group 𝐺 is the LCM of the orders of its elements, that is, 𝑒 is the smallest integer suchthat 𝑔 𝑒 = 1 for all 𝑔 ∈ 𝐺.
EXAMPLES:
sage: G = groups.matrix.GL(2, 3)
sage: G.exponent()24
sage: H = groups.matrix.Heisenberg(2)sage: H.exponent()
Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> G = groups.matrix.GL(Integer(2), Integer(3))>>> G.exponent()(continues on next page)

44

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)24>>> H = groups.matrix.Heisenberg(Integer(2))>>> H.exponent()
Traceback (most recent call last):...
NotImplementedError: group must be finitegroup_id()
Return the ID code of self, which is a list of two integers.
It is a unique identified assigned by GAP for groups in the SmallGroup library.
EXAMPLES:
sage: PGL(2,3).group_id()[24, 12]sage: SymmetricGroup(4).group_id()[24, 12]sage: G = groups.matrix.GL(2, 2)
sage: G.group_id()[6, 1]
sage: G = groups.matrix.GL(2, 3)
sage: G.id()[48, 29]
sage: G = groups.matrix.GL(2, ZZ)
sage: G.group_id()
Traceback (most recent call last):...
GAPError: Error, the group identification for groups of size infinity is not␣
˓→available>>> from sage.all import *>>> PGL(Integer(2),Integer(3)).group_id()[24, 12]>>> SymmetricGroup(Integer(4)).group_id()[24, 12]>>> G = groups.matrix.GL(Integer(2), Integer(2))>>> G.group_id()[6, 1]>>> G = groups.matrix.GL(Integer(2), Integer(3))>>> G.id()[48, 29]>>> G = groups.matrix.GL(Integer(2), ZZ)>>> G.group_id()
Traceback (most recent call last):...
GAPError: Error, the group identification for groups of size infinity is not␣
˓→available

id()
Return the ID code of self, which is a list of two integers.
It is a unique identified assigned by GAP for groups in the SmallGroup library.
45

Groups, Release 10.4

EXAMPLES:
sage: PGL(2,3).group_id()[24, 12]sage: SymmetricGroup(4).group_id()[24, 12]sage: G = groups.matrix.GL(2, 2)
sage: G.group_id()[6, 1]
sage: G = groups.matrix.GL(2, 3)
sage: G.id()[48, 29]
sage: G = groups.matrix.GL(2, ZZ)
sage: G.group_id()
Traceback (most recent call last):...
GAPError: Error, the group identification for groups of size infinity is not␣
˓→available>>> from sage.all import *>>> PGL(Integer(2),Integer(3)).group_id()[24, 12]>>> SymmetricGroup(Integer(4)).group_id()[24, 12]>>> G = groups.matrix.GL(Integer(2), Integer(2))>>> G.group_id()[6, 1]>>> G = groups.matrix.GL(Integer(2), Integer(3))>>> G.id()[48, 29]>>> G = groups.matrix.GL(Integer(2), ZZ)>>> G.group_id()
Traceback (most recent call last):...
GAPError: Error, the group identification for groups of size infinity is not␣
˓→available

intersection(other)
Return the intersection of two groups (if it makes sense) as a subgroup of the first group.
EXAMPLES:
sage: A = Matrix([(0, 1/2, 0), (2, 0, 0), (0, 0, 1)])
sage: B = Matrix([(0, 1/2, 0), (-2, -1, 2), (0, 0, 1)])
sage: G = MatrixGroup([A,B])
sage: len(G) # isomorphic to S_3
6sage: G.intersection(GL(3,ZZ))
Subgroup with 1 generators ([ 1 0 0][-2 -1 2][ 0 0 1]) of Matrix group over Rational Field with 2 generators ([ 0 1/20] [ 0 1/2
0](continues on next page)46

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)[ 200] [ -2 -1
2][ 0
01], [ 00
1])
sage: GL(3,ZZ).intersection(G)Subgroup with 1 generators ([ 1 0 0][-2 -1 2][ 0 0 1]) of General Linear Group of degree 3 over Integer Ringsage: G.intersection(SL(3,ZZ))
Subgroup with 0 generators ()of Matrix group over Rational Field with 2 generators ([ 0 1/20] [ 0 1/20][ 2
00] [ -2 -1
2][ 0
01], [ 00
1])>>> from sage.all import *>>> A = Matrix([(Integer(0), Integer(1)/Integer(2), Integer(0)), (Integer(2),␣
˓→Integer(0), Integer(0)), (Integer(0), Integer(0), Integer(1))])>>> B = Matrix([(Integer(0), Integer(1)/Integer(2), Integer(0)), (-Integer(2),˓→ -Integer(1), Integer(2)), (Integer(0), Integer(0), Integer(1))])>>> G = MatrixGroup([A,B])>>> len(G) # isomorphic to S_3
6>>> G.intersection(GL(Integer(3),ZZ))
Subgroup with 1 generators ([ 1 0 0][-2 -1 2][ 0 0 1]) of Matrix group over Rational Field with 2 generators ([ 0 1/20] [ 0 1/20][ 2
00] [ -2 -1
2][ 0
01], [ 00
1])>>> GL(Integer(3),ZZ).intersection(G)Subgroup with 1 generators ([ 1 0 0][-2 -1 2][ 0 0 1]) of General Linear Group of degree 3 over Integer Ring>>> G.intersection(SL(Integer(3),ZZ))
Subgroup with 0 generators ()of Matrix group over Rational Field with 2 generators ([ 0 1/20] [ 0 1/20][ 2
00] [ -2 -1
2][ 0
01], [ 001])

irreducible_characters()
Return the irreducible characters of the group.
OUTPUT: tuple containing all irreducible characters
EXAMPLES:

47

Groups, Release 10.4

sage: G = GL(2,2)
sage: G.irreducible_characters()#␣˓→needs sage.rings.number_field(Character of General Linear Group of degree 2 over Finite Field of size 2,
Character of General Linear Group of degree 2 over Finite Field of size 2,
Character of General Linear Group of degree 2 over Finite Field of size 2)>>> from sage.all import *>>> G = GL(Integer(2),Integer(2))>>> G.irreducible_characters()#␣˓→needs sage.rings.number_field(Character of General Linear Group of degree 2 over Finite Field of size 2,
Character of General Linear Group of degree 2 over Finite Field of size 2,
Character of General Linear Group of degree 2 over Finite Field of size 2)
sage: GL(2,ZZ).irreducible_characters()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> from sage.all import *>>> GL(Integer(2),ZZ).irreducible_characters()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups

is_abelian()
Return whether the group is Abelian.
OUTPUT: boolean; True if this group is an Abelian group and False otherwise
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.CyclicGroup(12)).is_abelian()True
sage: GroupLibGAP(libgap.SymmetricGroup(12)).is_abelian()False
sage: SL(1, 17).is_abelian()True
sage: SL(2, 17).is_abelian()False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.CyclicGroup(Integer(12))).is_abelian()
True>>> GroupLibGAP(libgap.SymmetricGroup(Integer(12))).is_abelian()
False>>> SL(Integer(1), Integer(17)).is_abelian()
True>>> SL(Integer(2), Integer(17)).is_abelian()
False

48

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

is_finite()
Test whether the matrix group is finite.
OUTPUT: boolean
EXAMPLES:
sage: G = GL(2,GF(3))
sage: G.is_finite()True
sage: SL(2,ZZ).is_finite()
False>>> from sage.all import *>>> G = GL(Integer(2),GF(Integer(3)))>>> G.is_finite()
True>>> SL(Integer(2),ZZ).is_finite()False

is_isomorphic(H)Test whether self and H are isomorphic groups.
INPUT:• H – a group
OUTPUT: boolean
EXAMPLES:
sage: m1 = matrix(GF(3), [[1,1],[0,1]])
sage: m2 = matrix(GF(3), [[1,2],[0,1]])
sage: F = MatrixGroup(m1)sage: G = MatrixGroup(m1, m2)
sage: H = MatrixGroup(m2)sage: F.is_isomorphic(G)Truesage: G.is_isomorphic(H)Truesage: F.is_isomorphic(H)Truesage: F == G, G == H, F == H
(False, False, False)>>> from sage.all import *>>> m1 = matrix(GF(Integer(3)), [[Integer(1),Integer(1)],[Integer(0),˓→Integer(1)]])>>> m2 = matrix(GF(Integer(3)), [[Integer(1),Integer(2)],[Integer(0),˓→Integer(1)]])>>> F = MatrixGroup(m1)>>> G = MatrixGroup(m1, m2)>>> H = MatrixGroup(m2)>>> F.is_isomorphic(G)
True>>> G.is_isomorphic(H)
True>>> F.is_isomorphic(H)
True(continues on next page)49

Groups, Release 10.4

(continued from previous page)>>> F == G, G == H, F == H
(False, False, False)

is_nilpotent()
Return whether this group is nilpotent.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.AlternatingGroup(3)).is_nilpotent()
True
sage: GroupLibGAP(libgap.SymmetricGroup(3)).is_nilpotent()
False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.AlternatingGroup(Integer(3))).is_nilpotent()
True>>> GroupLibGAP(libgap.SymmetricGroup(Integer(3))).is_nilpotent()
False

is_p_group()
Return whether this group is a p-group.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.CyclicGroup(9)).is_p_group()
True
sage: GroupLibGAP(libgap.CyclicGroup(10)).is_p_group()
False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.CyclicGroup(Integer(9))).is_p_group()
True>>> GroupLibGAP(libgap.CyclicGroup(Integer(10))).is_p_group()
False

is_perfect()
Return whether this group is perfect.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.SymmetricGroup(5)).is_perfect()
False
sage: GroupLibGAP(libgap.AlternatingGroup(5)).is_perfect()True
sage: SL(3,3).is_perfect()True>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP(continues on next page)

50

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)>>> GroupLibGAP(libgap.SymmetricGroup(Integer(5))).is_perfect()False>>> GroupLibGAP(libgap.AlternatingGroup(Integer(5))).is_perfect()
True>>> SL(Integer(3),Integer(3)).is_perfect()True

is_polycyclic()
Return whether this group is polycyclic.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.AlternatingGroup(4)).is_polycyclic()Truesage: GroupLibGAP(libgap.AlternatingGroup(5)).is_solvable()
False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.AlternatingGroup(Integer(4))).is_polycyclic()
True>>> GroupLibGAP(libgap.AlternatingGroup(Integer(5))).is_solvable()False

is_simple()
Return whether this group is simple.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.SL(2,3)).is_simple()False
sage: GroupLibGAP(libgap.SL(3,3)).is_simple()True
sage: SL(3,3).is_simple()True>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.SL(Integer(2),Integer(3))).is_simple()
False>>> GroupLibGAP(libgap.SL(Integer(3),Integer(3))).is_simple()
True>>> SL(Integer(3),Integer(3)).is_simple()True

is_solvable()
Return whether this group is solvable.
EXAMPLES:

51

Groups, Release 10.4

sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.SymmetricGroup(4)).is_solvable()True
sage: GroupLibGAP(libgap.SymmetricGroup(5)).is_solvable()
False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.SymmetricGroup(Integer(4))).is_solvable()
True>>> GroupLibGAP(libgap.SymmetricGroup(Integer(5))).is_solvable()False

is_supersolvable()
Return whether this group is supersolvable.
EXAMPLES:
sage: from sage.groups.libgap_group import GroupLibGAP
sage: GroupLibGAP(libgap.SymmetricGroup(3)).is_supersolvable()True
sage: GroupLibGAP(libgap.SymmetricGroup(4)).is_supersolvable()
False>>> from sage.all import *>>> from sage.groups.libgap_group import GroupLibGAP>>> GroupLibGAP(libgap.SymmetricGroup(Integer(3))).is_supersolvable()
True>>> GroupLibGAP(libgap.SymmetricGroup(Integer(4))).is_supersolvable()
False

list()
List all elements of this group.
OUTPUT: tuple containing all group elements in a random but fixed order
EXAMPLES:
sage: F = GF(3)sage: gens = [matrix(F,2, [1,0,-1,1]), matrix(F, 2, [1,1,0,1])]
sage: G = MatrixGroup(gens)sage: G.cardinality()24
sage: v = G.list()
sage: len(v)24sage: v[:5]([1 0] [2 0] [0 1] [0 2] [1 2][0 1], [0 2], [2 0], [1 0], [2 2])sage: all(g in G for g in G.list())
True>>> from sage.all import *>>> F = GF(Integer(3))(continues on next page)

52

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)>>> gens = [matrix(F,Integer(2), [Integer(1),Integer(0),-Integer(1),˓→Integer(1)]), matrix(F, Integer(2), [Integer(1),Integer(1),Integer(0),˓→Integer(1)])]>>> G = MatrixGroup(gens)>>> G.cardinality()
24>>> v = G.list()>>> len(v)24>>> v[:Integer(5)]([1 0] [2 0] [0 1] [0 2] [1 2][0 1], [0 2], [2 0], [1 0], [2 2])>>> all(g in G for g in G.list())
True

An example over a ring (see Issue #5241):
sage: M1 = matrix(ZZ,2,[[-1,0],[0,1]])
sage: M2 = matrix(ZZ,2,[[1,0],[0,-1]])
sage: M3 = matrix(ZZ,2,[[-1,0],[0,-1]])
sage: MG = MatrixGroup([M1, M2, M3])
sage: MG.list()([1 0] [ 1 0] [-1 0] [-1 0][0 1], [ 0 -1], [ 0 1], [ 0 -1])
sage: MG.list()[1][ 1 0][ 0 -1]
sage: MG.list()[1].parent()
Matrix group over Integer Ring with 3 generators ([-1 0] [ 1 0] [-1 0][ 0 1], [ 0 -1], [ 0 -1])>>> from sage.all import *>>> M1 = matrix(ZZ,Integer(2),[[-Integer(1),Integer(0)],[Integer(0),˓→Integer(1)]])>>> M2 = matrix(ZZ,Integer(2),[[Integer(1),Integer(0)],[Integer(0),˓→Integer(1)]])>>> M3 = matrix(ZZ,Integer(2),[[-Integer(1),Integer(0)],[Integer(0),˓→Integer(1)]])>>> MG = MatrixGroup([M1, M2, M3])>>> MG.list()([1 0] [ 1 0] [-1 0] [-1 0][0 1], [ 0 -1], [ 0 1], [ 0 -1])>>> MG.list()[Integer(1)][ 1 0][ 0 -1]>>> MG.list()[Integer(1)].parent()
Matrix group over Integer Ring with 3 generators ((continues on next page)53

Groups, Release 10.4

(continued from previous page)

[-1
[ 0
)

0] [ 1 0] [-1 0]
1], [ 0 -1], [ 0 -1]

An example over a field (see Issue #10515):
sage: gens = [matrix(QQ,2,[1,0,0,1])]
sage: MatrixGroup(gens).list()
(
[1 0]
[0 1]
)
>>> from sage.all import *>>> gens = [matrix(QQ,Integer(2),[Integer(1),Integer(0),Integer(0),˓→Integer(1)])]>>> MatrixGroup(gens).list()
(
[1 0]
[0 1]
)

Another example over a ring (see Issue #9437):
sage: len(SL(2, Zmod(4)).list())
48>>> from sage.all import *>>> len(SL(Integer(2), Zmod(Integer(4))).list())
48

An error is raised if the group is not finite:sage: GL(2,ZZ).list()
Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> GL(Integer(2),ZZ).list()
Traceback (most recent call last):...
NotImplementedError: group must be finite

order()
Implement EnumeratedSets.ParentMethods.cardinality().
EXAMPLES:
sage: G = Sp(4,GF(3))
sage: G.cardinality()
51840
sage: G = SL(4,GF(3))
sage: G.cardinality()(continues on next page)

54

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)12130560
sage: F = GF(5); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: G.cardinality()480
sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
sage: G.cardinality()+Infinity
sage: G = Sp(4,GF(3))
sage: G.cardinality()
51840
sage: G = SL(4,GF(3))
sage: G.cardinality()
12130560
sage: F = GF(5); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: G.cardinality()480
sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
sage: G.cardinality()+Infinity>>> from sage.all import *>>> G = Sp(Integer(4),GF(Integer(3)))>>> G.cardinality()
51840>>> G = SL(Integer(4),GF(Integer(3)))>>> G.cardinality()
12130560>>> F = GF(Integer(5)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(2)],[-Integer(1),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> G.cardinality()480>>> G = MatrixGroup([matrix(ZZ,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)])])>>> G.cardinality()+Infinity>>> G = Sp(Integer(4),GF(Integer(3)))>>> G.cardinality()
51840>>> G = SL(Integer(4),GF(Integer(3)))(continues on next page)

55

Groups, Release 10.4

(continued from previous page)>>> G.cardinality()
12130560>>> F = GF(Integer(5)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(2)],[-Integer(1),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> G.cardinality()480>>> G = MatrixGroup([matrix(ZZ,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)])])>>> G.cardinality()+Infinity

random_element()
Return a random element of this group.
OUTPUT: a group element
EXAMPLES:
sage: G = Sp(4,GF(3))
sage: G.random_element() # random[2 1 1 1][1 0 2 1][0 1 1 0][1 0 0 1]
sage: G.random_element() in G
True
sage: F = GF(5); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,2],[-1,1]]), MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: G.random_element() # random
[1 3]
[0 3]
sage: G.random_element() in G
True>>> from sage.all import *>>> G = Sp(Integer(4),GF(Integer(3)))>>> G.random_element() # random[2 1 1 1][1 0 2 1][0 1 1 0][1 0 0 1]>>> G.random_element() in G
True>>> F = GF(Integer(5)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(2)],[-Integer(1),Integer(1)]]),␣
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> G.random_element() # random
[1 3]
[0 3]
(continues on next page)

56

Chapter 6. Mix-in Class for GAP-based Groups

Groups, Release 10.4

(continued from previous page)>>> G.random_element() in G
True

subgroups()
Return a list of all the subgroups of self.
OUTPUT:
Each possible subgroup of self is contained once in the returned list. The list is in order, according to thesize of the subgroups, from the trivial subgroup with one element on through up to the whole group. Conjugacy
classes of subgroups are contiguous in the list.
Warning: For even relatively small groups this method can take a very long time to execute, or create
vast amounts of output. Likely both. Its purpose is instructional, as it can be useful for studying small
groups.
For faster results, which still exhibit the structure of the possible subgroups, use conjugacy_classes_subgroups().
EXAMPLES:
sage: G = groups.matrix.GL(2, 2)
sage: G.subgroups()[Subgroup with 0 generators ()of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 0]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 0]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 1]
[0 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 2 generators ([0 1] [1 1][1 1], [0 1]) of General Linear Group of degree 2 over Finite Field of size 2]
sage: H = groups.matrix.Heisenberg(2)sage: H.subgroups()
Traceback (most recent call last):...
NotImplementedError: group must be finite>>> from sage.all import *>>> G = groups.matrix.GL(Integer(2), Integer(2))>>> G.subgroups()(continues on next page)

57

Groups, Release 10.4

(continued from previous page)[Subgroup with 0 generators ()of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 0]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 0]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[1 1]
[0 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 1 generators (
[0 1]
[1 1]
) of General Linear Group of degree 2 over Finite Field of size 2,
Subgroup with 2 generators ([0 1] [1 1][1 1], [0 1]) of General Linear Group of degree 2 over Finite Field of size 2]>>> H = groups.matrix.Heisenberg(Integer(2))>>> H.subgroups()
Traceback (most recent call last):...
NotImplementedError: group must be finite

trivial_character()
Return the trivial character of this group.
OUTPUT: a group character
EXAMPLES:
sage: MatrixGroup(SymmetricGroup(3)).trivial_character()˓→needs sage.rings.number_field
Character of Matrix group over Integer Ring with 6 generators>>> from sage.all import *>>> MatrixGroup(SymmetricGroup(Integer(3))).trivial_character()˓→# needs sage.rings.number_field
Character of Matrix group over Integer Ring with 6 generators#␣␣

sage: GL(2,ZZ).trivial_character()Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> from sage.all import *>>> GL(Integer(2),ZZ).trivial_character()Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups

58

Chapter 6. Mix-in Class for GAP-based Groups

CHAPTERSEVENPARI GROUPS

See pari:polgalois for the PARI documentation of these objects.
class sage.groups.pari_group.PariGroup(x, degree)
Bases: object
EXAMPLES:
sage: PariGroup([6, -1, 2, "S3"], 3)
PARI group [6, -1, 2, S3] of degree 3
sage: R.<x> = PolynomialRing(QQ)
sage: f = x^4 - 17*x^3 - 2*x + 1
sage: G = f.galois_group(pari_group=True); G
PARI group [24, -1, 5, "S4"] of degree 4>>> from sage.all import *>>> PariGroup([Integer(6), -Integer(1), Integer(2), "S3"], Integer(3))
PARI group [6, -1, 2, S3] of degree 3>>> R = PolynomialRing(QQ, names=( x ,)); (x,) = R._first_ngens(1)>>> f = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G = f.galois_group(pari_group=True); G
PARI group [24, -1, 5, "S4"] of degree 4

cardinality()
Return the order of self.
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ)
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.order()24>>> from sage.all import *>>> R = PolynomialRing(QQ, names=( x ,)); (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.order()24degree()Return the degree of this group.
EXAMPLES:
59

Groups, Release 10.4

sage: R.<x> = PolynomialRing(QQ)
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.degree()4>>> from sage.all import *>>> R = PolynomialRing(QQ, names=( x ,)); (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.degree()4label()
Return the human readable description for this group generated by Pari.
EXAMPLES:
sage: R.<x> = QQ[]
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.label()
S4>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.label()
S4order()
Return the order of self.
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ)
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.order()24>>> from sage.all import *>>> R = PolynomialRing(QQ, names=( x ,)); (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.order()24

permutation_group()
Return the corresponding GAP transitive group.
EXAMPLES:
sage: R.<x> = QQ[]
sage: f = x^8 - x^5 + x^4 - x^3 + 1(continues on next page)

60

Chapter 7. PARI Groups

Groups, Release 10.4

(continued from previous page)

sage: G = f.galois_group(pari_group=True)
sage: G.permutation_group()
Transitive group number 44 of degree 8>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> f = x**Integer(8) - x**Integer(5) + x**Integer(4) - x**Integer(3) +␣˓→Integer(1)>>> G = f.galois_group(pari_group=True)>>> G.permutation_group()
Transitive group number 44 of degree 8

signature()
Return 1 if contained in the alternating group, -1 otherwise.
EXAMPLES:
sage: R.<x> = QQ[]
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.signature()-1>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.signature()-1

transitive_number()If the transitive label is nTk, return 𝑘.
EXAMPLES:
sage: R.<x> = QQ[]
sage: f1 = x^4 - 17*x^3 - 2*x + 1
sage: G1 = f1.galois_group(pari_group=True)
sage: G1.transitive_number()5>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> f1 = x**Integer(4) - Integer(17)*x**Integer(3) - Integer(2)*x + Integer(1)>>> G1 = f1.galois_group(pari_group=True)>>> G1.transitive_number()
561

Groups, Release 10.4

62

Chapter 7. PARI Groups

CHAPTEREIGHTMISCELLANEOUS GENERIC FUNCTIONS

A collection of functions implementing generic algorithms in arbitrary groups, including additive and multiplicative
groups.
In all cases the group operation is specified by a parameter operation, which is a string either one of the set of multiplication_names or addition_names specified below, or other. In the latter case, the caller must provide
an identity, inverse() and op() functions.
multiplication_names = ( multiplication , times ,addition_names= ( addition , plus , sum ,product ,+ )* )Also included are a generic function for computing multiples (or powers), and an iterator for general multiples and powers.
EXAMPLES:
Some examples in the multiplicative group of a finite field:• Discrete logs:
sage: # needs sage.rings.finite_rings
sage: K = GF(3^6, b )sage: b = K.gen()sage: a = b^210
sage: discrete_log(a, b, K.order() - 1)
210>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(6), b )>>> b = K.gen()>>> a = b**Integer(210)>>> discrete_log(a, b, K.order() - Integer(1))
210• Linear relation finder:
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(3^6, a )sage: a.multiplicative_order().factor()
2^3 * 7 * 13
sage: b = a^7
sage: c = a^13
sage: linear_relation(b,c, * )(13, 7)sage: b^13 == c^7
True

63

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = GF(Integer(3)**Integer(6), a , names=( a ,)); (a,) = F._first_ngens(1)>>> a.multiplicative_order().factor()
2^3 * 7 * 13>>> b = a**Integer(7)>>> c = a**Integer(13)>>> linear_relation(b,c, * )(13, 7)>>> b**Integer(13) == c**Integer(7)True• Orders of elements:
sage: # needs sage.rings.finite_rings
sage: from sage.groups.generic import order_from_multiple, order_from_bounds
sage: k.<a> = GF(5^5)
sage: b = a^4
sage: order_from_multiple(b, 5^5 - 1, operation= * )781
sage: order_from_bounds(b, (5^4, 5^5), operation= * )781>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> from sage.groups.generic import order_from_multiple, order_from_bounds>>> k = GF(Integer(5)**Integer(5), names=( a ,)); (a,) = k._first_ngens(1)>>> b = a**Integer(4)>>> order_from_multiple(b, Integer(5)**Integer(5) - Integer(1), operation= * )781>>> order_from_bounds(b, (Integer(5)**Integer(4), Integer(5)**Integer(5)),␣
˓→operation= * )781

Some examples in the group of points of an elliptic curve over a finite field:• Discrete logs:
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: F = GF(37^2, a )sage: E = EllipticCurve(F,[1,1])
sage: F.<a> = GF(37^2, a )sage: E = EllipticCurve(F,[1,1])
sage: P = E(25*a + 16 , 15*a + 7 )sage: P.order()672
sage: Q = 39*P; Q(36*a + 32 : 5*a + 12 : 1)sage: discrete_log(Q, P, P.order(), operation= + )39>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(2), a )>>> E = EllipticCurve(F,[Integer(1),Integer(1)])>>> F = GF(Integer(37)**Integer(2), a , names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F,[Integer(1),Integer(1)])(continues on next page)

64

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)>>> P = E(Integer(25)*a + Integer(16) , Integer(15)*a + Integer(7) )>>> P.order()672>>> Q = Integer(39)*P; Q(36*a + 32 : 5*a + 12 : 1)>>> discrete_log(Q, P, P.order(), operation= + )39• Linear relation finder:
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: F.<a> = GF(3^6, a )sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2 , 0)
sage: Q = E(2*a^3 + 2*a^2 + 2*a , a^3 + 2*a^2 + 1)
sage: linear_relation(P,Q, + )(1, 2)
sage: P == 2*Q
True>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> F = GF(Integer(3)**Integer(6), a , names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve([a**Integer(5) + Integer(2)*a**Integer(3) +␣˓→Integer(2)*a**Integer(2) + Integer(2)*a, a**Integer(4) + a**Integer(3) +␣˓→Integer(2)*a + Integer(1)])>>> P = E(a**Integer(5) + a**Integer(4) + a**Integer(3) + a**Integer(2) + a +␣˓→Integer(2) , Integer(0))>>> Q = E(Integer(2)*a**Integer(3) + Integer(2)*a**Integer(2) + Integer(2)*a ,␣
˓→a**Integer(3) + Integer(2)*a**Integer(2) + Integer(1))>>> linear_relation(P,Q, + )(1, 2)>>> P == Integer(2)*Q
True• Orders of elements:
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: from sage.groups.generic import order_from_multiple, order_from_bounds
sage: k.<a> = GF(5^5)
sage: E = EllipticCurve(k,[2,4])
sage: P = E(3*a^4 + 3*a, 2*a + 1)
sage: M = E.cardinality(); M3227
sage: plist = M.prime_factors()
sage: order_from_multiple(P, M, plist, operation= + )3227
sage: Q = E(0,2)
sage: order_from_multiple(Q, M, plist, operation= + )7
sage: order_from_bounds(Q, Hasse_bounds(5^5), operation= + )7>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> from sage.groups.generic import order_from_multiple, order_from_bounds(continues on next page)

65

Groups, Release 10.4

(continued from previous page)>>> k = GF(Integer(5)**Integer(5), names=( a ,)); (a,) = k._first_ngens(1)>>> E = EllipticCurve(k,[Integer(2),Integer(4)])>>> P = E(Integer(3)*a**Integer(4) + Integer(3)*a, Integer(2)*a + Integer(1))>>> M = E.cardinality(); M3227>>> plist = M.prime_factors()>>> order_from_multiple(P, M, plist, operation= + )3227>>> Q = E(Integer(0),Integer(2))>>> order_from_multiple(Q, M, plist, operation= + )7>>> order_from_bounds(Q, Hasse_bounds(Integer(5)**Integer(5)), operation= + )7sage.groups.generic.bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None)
Totally generic discrete baby-step giant-step function.
Solves 𝑛𝑎 = 𝑏 (or 𝑎𝑛 = 𝑏) with 𝑙𝑏 ≤ 𝑛 ≤ 𝑢𝑏 where bounds==(lb,ub), raising an error if no such 𝑛 exists.
𝑎 and 𝑏 must be elements of some group with given identity, inverse of x given by inverse(x), and group
operation on x, y by op(x,y).
If operation is ‘*’ or ‘+’ then the other arguments are provided automatically; otherwise they must be provided by
the caller.
INPUT:• a – group element• b – group element• bounds – a 2-tuple of integers (lower,upper) with 0<=lower<=upper• operation – string: * , + , other• identity – the identity element of the group• inverse() – function of 1 argument x, returning inverse of x
• op() – function of 2 arguments x, y returning x*y in the group
OUTPUT:
An integer 𝑛 such that 𝑎𝑛 = 𝑏 (or 𝑛𝑎 = 𝑏). If no such 𝑛 exists, this function raises a ValueError exception.
Note: This is a generalization of discrete logarithm. One situation where this version is useful is to find the orderof an element in a group where we only have bounds on the group order (see the elliptic curve example below).
√
ALGORITHM: Baby step giant step. Time and space are soft 𝑂( 𝑛) where 𝑛 is the difference between upper andlower bounds.
EXAMPLES:
sage: from sage.groups.generic import bsgs
sage: b = Mod(2,37); a = b^20
sage: bsgs(b, a, (0, 36))
20
sage: p = next_prime(10^20)#␣(continues on next page)

66

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)needs sage.libs.pari
sage: a = Mod(2,p); b = a^(10^25)
˓→needs sage.libs.pari
sage: bsgs(a, b, (10^25 - 10^6, 10^25 + 10^6)) == 10^25
˓→needs sage.libs.pari
True
˓→

#␣
#␣

sage: # needs sage.rings.finite_rings
sage: K = GF(3^6, b )sage: a = K.gen()sage: b = a^210
sage: bsgs(a, b, (0, K.order() - 1))
210
sage: K.<z> = CyclotomicField(230)
˓→needs sage.rings.number_fieldsage: w = z^500
˓→needs sage.rings.number_fieldsage: bsgs(z, w, (0, 229))
˓→needs sage.rings.number_field
40

#␣
#␣
#␣

>>> from sage.all import *>>> from sage.groups.generic import bsgs>>> b = Mod(Integer(2),Integer(37)); a = b**Integer(20)>>> bsgs(b, a, (Integer(0), Integer(36)))20>>> p = next_prime(Integer(10)**Integer(20))˓→# needs sage.libs.pari>>> a = Mod(Integer(2),p); b = a**(Integer(10)**Integer(25))˓→# needs sage.libs.pari>>> bsgs(a, b, (Integer(10)**Integer(25) - Integer(10)**Integer(6),␣
˓→Integer(10)**Integer(25) + Integer(10)**Integer(6))) ==␣
˓→Integer(10)**Integer(25)# needs sage.libs.pari
True

␣
␣

>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(6), b )>>> a = K.gen()>>> b = a**Integer(210)>>> bsgs(a, b, (Integer(0), K.order() - Integer(1)))
210>>> K = CyclotomicField(Integer(230), names=( z ,)); (z,) = K._first_ngens(1)#␣
˓→needs sage.rings.number_field>>> w = z**Integer(500)˓→# needs sage.rings.number_field>>> bsgs(z, w, (Integer(0), Integer(229)))˓→# needs sage.rings.number_field40

␣␣

An additive example in an elliptic curve group:sage: # needs sage.rings.finite_rings sage.schemes
sage: F.<a> = GF(37^5)(continues on next page)67

Groups, Release 10.4

(continued from previous page)

sage: E = EllipticCurve(F, [1,1])
sage: P = E.lift_x(a); P(a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)>>> from sage.all import *>>> # needs sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(5), names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> P = E.lift_x(a); P(a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)

This will return a multiple of the order of P:
sage: bsgs(P, P.parent().zero(), Hasse_bounds(F.order()), operation= + )˓→# needs sage.rings.finite_rings sage.schemes
69327408␣>>> from sage.all import *>>> bsgs(P, P.parent().zero(), Hasse_bounds(F.order()), operation= + )˓→# needs sage.rings.finite_rings sage.schemes
69327408

AUTHOR:• John Cremona (2008-03-15)
sage.groups.generic.discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None,
inverse=None, op=None, algorithm='bsgs')
Totally generic discrete log function.
INPUT:• a – group element• base – group element (the base)• ord – integer (multiple of order of base, or None)• bounds – a priori bounds on the log• operation – string: * , + , other• identity – the group’s identity• inverse – function of 1 argument x, returning inverse of x
• op – function of 2 arguments x, y, returning x*y in the group• algorithm – string denoting what algorithm to use for prime-order logarithms:
lambdabsgs ,rho ,a and base must be elements of some group with identity given by identity, inverse of x by inverse(x),and group operation on x, y by op(x,y).
If operation is * or + , then the other arguments are provided automatically; otherwise they must be provided
by the caller.
OUTPUT:
This returns an integer 𝑛 such that 𝑏𝑛 = 𝑎 (or 𝑛𝑏 = 𝑎), assuming that ord is a multiple of the order of the base𝑏. If ord is not specified, an attempt is made to compute it.

68

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

If no such 𝑛 exists, this function raises a ValueError exception.
Warning: If x has a log method, it is likely to be vastly faster than using this function. E.g., if x is an integer
modulo 𝑛, use its log method instead!
ALGORITHM: Pohlig-Hellman, Baby step giant step, Pollard’s lambda/kangaroo, and Pollard’s rho.
EXAMPLES:
sage: b = Mod(2,37); a = b^20
sage: discrete_log(a, b)
20
sage: b = Mod(3,2017); a = b^20
sage: discrete_log(a, b, bounds=(10, 100))
20
sage: # needs sage.rings.finite_rings
sage: K = GF(3^6, b )sage: b = K.gen()sage: a = b^210
sage: discrete_log(a, b, K.order() - 1)
210
sage: b = Mod(1,37); x = Mod(2,37)
sage: discrete_log(x, b)
Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1
sage: b = Mod(1,997); x = Mod(2,997)
sage: discrete_log(x, b)
Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1>>> from sage.all import *>>> b = Mod(Integer(2),Integer(37)); a = b**Integer(20)>>> discrete_log(a, b)
20>>> b = Mod(Integer(3),Integer(2017)); a = b**Integer(20)>>> discrete_log(a, b, bounds=(Integer(10), Integer(100)))
20>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(6), b )>>> b = K.gen()>>> a = b**Integer(210)>>> discrete_log(a, b, K.order() - Integer(1))
210>>> b = Mod(Integer(1),Integer(37)); x = Mod(Integer(2),Integer(37))>>> discrete_log(x, b)
Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1>>> b = Mod(Integer(1),Integer(997)); x = Mod(Integer(2),Integer(997))>>> discrete_log(x, b)(continues on next page)69

Groups, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1

See Issue #2356:
sage: F.<w> = GF(121)˓→needs sage.rings.finite_rings
sage: v = w^120
˓→needs sage.rings.finite_rings
sage: v.log(w)˓→needs sage.rings.finite_rings0#␣

sage: K.<z> = CyclotomicField(230)
˓→needs sage.rings.number_fieldsage: w = z^50
˓→needs sage.rings.number_fieldsage: discrete_log(w, z)
˓→needs sage.rings.number_field
50

#␣

#␣
#␣

#␣
#␣

>>> from sage.all import *>>> F = GF(Integer(121), names=( w ,)); (w,) = F._first_ngens(1)# needs sage.
˓→rings.finite_rings>>> v = w**Integer(120)␣˓→# needs sage.rings.finite_rings>>> v.log(w)#␣˓→needs sage.rings.finite_rings
0>>> K = CyclotomicField(Integer(230), names=( z ,)); (z,) = K._first_ngens(1)#␣
˓→needs sage.rings.number_field>>> w = z**Integer(50)␣˓→# needs sage.rings.number_field>>> discrete_log(w, z)#␣˓→needs sage.rings.number_field50

An example where the order is infinite: note that we must give an upper bound here:
sage: # needs sage.rings.number_fieldsage: K.<a> = QuadraticField(23)sage: eps = 5*a - 24
# a fundamental unit
sage: eps.multiplicative_order()+Infinity
sage: eta = eps^100
sage: discrete_log(eta, eps, bounds=(0,1000))
100>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = QuadraticField(Integer(23), names=( a ,)); (a,) = K._first_ngens(1)>>> eps = Integer(5)*a - Integer(24)# a fundamental unit>>> eps.multiplicative_order()+Infinity(continues on next page)

70

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)>>> eta = eps**Integer(100)>>> discrete_log(eta, eps, bounds=(Integer(0),Integer(1000)))
100

In this case we cannot detect negative powers:
sage: eta = eps^(-3)
˓→needs sage.rings.number_fieldsage: discrete_log(eta,eps,bounds=(0,100))
˓→needs sage.rings.number_field
Traceback (most recent call last):...
ValueError: no discrete log of -11515*a - 55224 found to base 5*a - 24>>> from sage.all import *>>> eta = eps**(-Integer(3))˓→# needs sage.rings.number_field>>> discrete_log(eta,eps,bounds=(Integer(0),Integer(100)))˓→# needs sage.rings.number_field
Traceback (most recent call last):...
ValueError: no discrete log of -11515*a - 55224 found to base 5*a - 24

#␣
#␣

␣
␣

But we can invert the base (and negate the result) instead:sage: -discrete_log(eta^-1, eps, bounds=(0,100))
˓→needs sage.rings.number_field-3#␣>>> from sage.all import *>>> -discrete_log(eta**-Integer(1), eps, bounds=(Integer(0),Integer(100)))˓→# needs sage.rings.number_field-3

␣An additive example: elliptic curve DLOG:
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: F = GF(37^2, a )sage: E = EllipticCurve(F, [1,1])
sage: F.<a> = GF(37^2, a )sage: E = EllipticCurve(F, [1,1])
sage: P = E(25*a + 16, 15*a + 7)
sage: P.order()672
sage: Q = 39*P; Q(36*a + 32 : 5*a + 12 : 1)sage: discrete_log(Q, P, P.order(), operation= + )39>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(2), a )>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> F = GF(Integer(37)**Integer(2), a , names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F, [Integer(1),Integer(1)])(continues on next page)

71

Groups, Release 10.4

(continued from previous page)>>> P = E(Integer(25)*a + Integer(16), Integer(15)*a + Integer(7))>>> P.order()672>>> Q = Integer(39)*P; Q(36*a + 32 : 5*a + 12 : 1)>>> discrete_log(Q, P, P.order(), operation= + )39

An example of big smooth group:sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(2^63)
sage: g = F.gen()sage: u = g**123456789
sage: discrete_log(u,g)
123456789>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = GF(Integer(2)**Integer(63), names=( a ,)); (a,) = F._first_ngens(1)>>> g = F.gen()>>> u = g**Integer(123456789)>>> discrete_log(u,g)
123456789

The above examples also work when the rho and lambda algorithms are used:
sage: b = Mod(2,37); a = b^20
sage: discrete_log(a, b, algorithm= rho )20
sage: b = Mod(3,2017); a = b^20
sage: discrete_log(a, b, algorithm= lambda , bounds=(10, 100))
20
sage: # needs sage.rings.finite_rings
sage: K = GF(3^6, b )sage: b = K.gen()sage: a = b^210
sage: discrete_log(a, b, K.order()-1, algorithm= rho )210
sage: b = Mod(1,37); x = Mod(2,37)
sage: discrete_log(x, b, algorithm= lambda )Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1
sage: b = Mod(1,997); x = Mod(2,997)
sage: discrete_log(x, b, algorithm= rho )Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: F = GF(37^2, a )sage: E = EllipticCurve(F, [1,1])
sage: F.<a> = GF(37^2, a )(continues on next page)

72

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)

sage: E = EllipticCurve(F, [1,1])
sage: P = E(25*a + 16, 15*a + 7)
sage: P.order()672
sage: Q = 39*P; Q(36*a + 32 : 5*a + 12 : 1)sage: discrete_log(Q, P, P.order(), operation= + , algorithm= lambda )39
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(2^63)
sage: g = F.gen()sage: u = g**123456789
sage: discrete_log(u, g, algorithm= rho )123456789>>> from sage.all import *>>> b = Mod(Integer(2),Integer(37)); a = b**Integer(20)>>> discrete_log(a, b, algorithm= rho )20>>> b = Mod(Integer(3),Integer(2017)); a = b**Integer(20)>>> discrete_log(a, b, algorithm= lambda , bounds=(Integer(10), Integer(100)))
20>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(6), b )>>> b = K.gen()>>> a = b**Integer(210)>>> discrete_log(a, b, K.order()-Integer(1), algorithm= rho )210>>> b = Mod(Integer(1),Integer(37)); x = Mod(Integer(2),Integer(37))>>> discrete_log(x, b, algorithm= lambda )Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1>>> b = Mod(Integer(1),Integer(997)); x = Mod(Integer(2),Integer(997))>>> discrete_log(x, b, algorithm= rho )Traceback (most recent call last):...
ValueError: no discrete log of 2 found to base 1>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(2), a )>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> F = GF(Integer(37)**Integer(2), a , names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> P = E(Integer(25)*a + Integer(16), Integer(15)*a + Integer(7))>>> P.order()672>>> Q = Integer(39)*P; Q(36*a + 32 : 5*a + 12 : 1)>>> discrete_log(Q, P, P.order(), operation= + , algorithm= lambda )39>>> # needs sage.rings.finite_rings(continues on next page)73

Groups, Release 10.4

(continued from previous page)>>> F = GF(Integer(2)**Integer(63), names=( a ,)); (a,) = F._first_ngens(1)>>> g = F.gen()>>> u = g**Integer(123456789)>>> discrete_log(u, g, algorithm= rho )123456789

AUTHORS:• William Stein and David Joyner (2005-01-05)• John Cremona (2008-02-29) rewrite using dict() and make generic• Julien Grijalva (2022-08-09) rewrite to make more generic, more algorithm options, and more effective useof bounds
sage.groups.generic.discrete_log_generic(a, base, ord=None, bounds=None, operation='*',
identity=None, inverse=None, op=None,algorithm='bsgs')
Alias for discrete_log.
sage.groups.generic.discrete_log_lambda(a, base, bounds, operation='*', identity=None,
inverse=None, op=None, hash_function=<built-in functionhash>)
Pollard Lambda algorithm for computing discrete logarithms. It uses only a logarithmic amount of memory. It’s
useful if you have bounds on the logarithm. If you are computing logarithms in a whole finite group, you should
use Pollard Rho algorithm.
INPUT:• a – a group element• base – a group element• bounds – a couple (lb,ub) representing the range where we look for a logarithm• operation – string: ‘+’, ‘*’ or ‘other’• identity – the identity element of the group• inverse() – function of 1 argument x returning inverse of x
• op() – function of 2 arguments x, y returning x*y in the group• hash_function – having an efficient hash function is critical for this algorithm
OUTPUT: integer 𝑛 such that 𝑎 = 𝑏𝑎𝑠𝑒𝑛 (or 𝑎 = 𝑛 * 𝑏𝑎𝑠𝑒)
ALGORITHM: Pollard Lambda, if bounds are (lb,ub) it has time complexity
O(sqrt(ub-lb)) and space complexity O(log(ub-lb))
EXAMPLES:
sage: F.<a> = GF(2^63)
˓→needs sage.rings.finite_rings
sage: discrete_log_lambda(a^1234567, a, (1200000,1250000))
˓→needs sage.rings.finite_rings
1234567#␣#␣

sage: # needs sage.rings.finite_rings sage.schemes
sage: F.<a> = GF(37^5)
sage: E = EllipticCurve(F, [1,1])(continues on next page)

74

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)

sage: P = E.lift_x(a); P(a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)>>> from sage.all import *>>> F = GF(Integer(2)**Integer(63), names=( a ,)); (a,) = F._first_ngens(1)#␣
˓→needs sage.rings.finite_rings>>> discrete_log_lambda(a**Integer(1234567), a, (Integer(1200000),
˓→Integer(1250000)))# needs sage.rings.finite_rings
1234567>>> # needs sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(5), names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> P = E.lift_x(a); P(a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)

This will return a multiple of the order of P:
sage: discrete_log_lambda(P.parent().zero(), P, Hasse_bounds(F.order()),˓→# needs sage.rings.finite_rings sage.schemes....:
operation= + )69327408␣sage: K.<a> = GF(89**5)#␣
˓→needs sage.rings.finite_rings
sage: hs = lambda x: hash(x) + 15
sage: discrete_log_lambda(a**(89**3 - 3),# long time (10s on sage.math,␣
˓→2011), needs sage.rings.finite_rings....:a, (89**2, 89**4), operation= * , hash_function=hs)
704966>>> from sage.all import *>>> discrete_log_lambda(P.parent().zero(), P, Hasse_bounds(F.order()),˓→# needs sage.rings.finite_rings sage.schemes...
operation= + )69327408>>> K = GF(Integer(89)**Integer(5), names=( a ,)); (a,) = K._first_ngens(1)#␣
˓→needs sage.rings.finite_rings>>> hs = lambda x: hash(x) + Integer(15)>>> discrete_log_lambda(a**(Integer(89)**Integer(3) - Integer(3)),# long␣˓→time (10s on sage.math, 2011), needs sage.rings.finite_rings...
a, (Integer(89)**Integer(2), Integer(89)**Integer(4)),␣
˓→operation= * , hash_function=hs)
704966AUTHOR:– Yann Laigle-Chapuy (2009-01-25)
sage.groups.generic.discrete_log_rho(a, base, ord=None, operation='*', identity=None,
inverse=None, op=None, hash_function=<built-in functionhash>)
Pollard Rho algorithm for computing discrete logarithm in cyclic group of prime order. If the group order is verysmall it falls back to the baby step giant step algorithm.
INPUT:
75

Groups, Release 10.4

• a – a group element• base – a group element• ord – the order of base or None, in this case we try to compute it• operation – a string (default: * ) denoting whether we are in an additive group or a multiplicative one• identity – the group’s identity• inverse() – function of 1 argument x, returning inverse of x
• op() – function of 2 arguments x, y, returning x*y in the group• hash_function – having an efficient hash function is critical for this algorithm (see examples)
OUTPUT: integer 𝑛 such that 𝑎 = 𝑏𝑎𝑠𝑒𝑛 (or 𝑎 = 𝑛 * 𝑏𝑎𝑠𝑒)
ALGORITHM: Pollard rho for discrete logarithm, adapted from the article of Edlyn Teske, ‘A space efficientalgorithm for group structure computation’.
EXAMPLES:
sage: F.<a> = GF(2^13)
˓→needs sage.rings.finite_rings
sage: g = F.gen()˓→needs sage.rings.finite_rings
sage: discrete_log_rho(g^1234, g)
˓→needs sage.rings.finite_rings
1234

#␣
#␣
#␣

sage: # needs sage.rings.finite_rings sage.schemes
sage: F.<a> = GF(37^5)
sage: E = EllipticCurve(F, [1,1])
sage: G = (3*31*2^4)*E.lift_x(a)sage: discrete_log_rho(12345*G, G, ord=46591, operation= + )12345>>> from sage.all import *>>> F = GF(Integer(2)**Integer(13), names=( a ,)); (a,) = F._first_ngens(1)#␣
˓→needs sage.rings.finite_rings>>> g = F.gen()#␣˓→needs sage.rings.finite_rings>>> discrete_log_rho(g**Integer(1234), g)␣˓→# needs sage.rings.finite_rings
1234>>> # needs sage.rings.finite_rings sage.schemes>>> F = GF(Integer(37)**Integer(5), names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve(F, [Integer(1),Integer(1)])>>> G = (Integer(3)*Integer(31)*Integer(2)**Integer(4))*E.lift_x(a)>>> discrete_log_rho(Integer(12345)*G, G, ord=Integer(46591), operation= + )12345

It also works with matrices:sage: A = matrix(GF(50021), [[10577, 23999, 28893],
˓→needs sage.modules sage.rings.finite_rings....:[14601, 41019, 30188],....:[3081, 736, 27092]])
sage: discrete_log_rho(A^1234567, A)#␣#␣(continues on next page)

76

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)needs sage.modules sage.rings.finite_rings
1234567˓→>>> from sage.all import *>>> A = matrix(GF(Integer(50021)), [[Integer(10577), Integer(23999),␣
˓→Integer(28893)],# needs sage.modules sage.rings.
˓→finite_rings...
[Integer(14601), Integer(41019), Integer(30188)],...
[Integer(3081), Integer(736), Integer(27092)]])>>> discrete_log_rho(A**Integer(1234567), A)˓→# needs sage.modules sage.rings.finite_rings
1234567

␣

Beware, the order must be prime:
sage: I = IntegerModRing(171980)
sage: discrete_log_rho(I(2), I(3))˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: for Pollard rho algorithm the order of the group must be prime>>> from sage.all import *>>> I = IntegerModRing(Integer(171980))>>> discrete_log_rho(I(Integer(2)), I(Integer(3)))˓→# needs sage.libs.pari
Traceback (most recent call last):...
ValueError: for Pollard rho algorithm the order of the group must be prime#␣␣

If it fails to find a suitable logarithm, it raises a ValueError:
sage: I = IntegerModRing(171980)
sage: discrete_log_rho(I(31002), I(15501))
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: Pollard rho algorithm failed to find a logarithm>>> from sage.all import *>>> I = IntegerModRing(Integer(171980))>>> discrete_log_rho(I(Integer(31002)), I(Integer(15501)))˓→# needs sage.libs.pari
Traceback (most recent call last):...
ValueError: Pollard rho algorithm failed to find a logarithm#␣␣

The main limitation on the hash function is that we don’t want to have hash(x*y) == hash(x) + hash(y):sage: # needs sage.libs.pari
sage: I = IntegerModRing(next_prime(2^23))
sage: def test():
....:
try:
....:
discrete_log_rho(I(123456), I(1), operation= + )....:except Exception:(continues on next page)

77

Groups, Release 10.4

(continued from previous page)....:
sage: test()
FAILURE

print("FAILURE")# random failure>>> from sage.all import *>>> # needs sage.libs.pari>>> I = IntegerModRing(next_prime(Integer(2)**Integer(23)))>>> def test():
...
try:
...
discrete_log_rho(I(Integer(123456)), I(Integer(1)), operation= + )...
except Exception:...
print("FAILURE")>>> test() # random failure
FAILURE

If this happens, we can provide a better hash function:
sage: discrete_log_rho(I(123456), I(1), operation= + ,˓→needs sage.libs.pari....:
hash_function=lambda x: hash(x*x))123456#␣>>> from sage.all import *>>> discrete_log_rho(I(Integer(123456)), I(Integer(1)), operation= + ,˓→# needs sage.libs.pari...
hash_function=lambda x: hash(x*x))123456␣

AUTHOR:• Yann Laigle-Chapuy (2009-09-05)
sage.groups.generic.has_order(P, n, operation='+')
Generic function to test if a group element 𝑃 has order exactly equal to a given positive integer 𝑛.
INPUT:• P – group element with respect to the specified operation• n – positive integer, or its Factorization• operation – string, either + (default) or *EXAMPLES:
sage: from sage.groups.generic import has_ordersage: E.<P> = EllipticCurve(GF(71), [5,5])
sage: P.order()57
sage: has_order(P, 57)
True
sage: has_order(P, factor(57))
True
sage: has_order(P, 19)
False
sage: has_order(3*P, 19)
True(continues on next page)

78

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)

sage: has_order(3*P, 57)
False>>> from sage.all import *>>> from sage.groups.generic import has_order>>> E = EllipticCurve(GF(Integer(71)), [Integer(5),Integer(5)], names=( P ,)); (P,˓→) = E._first_ngens(1)>>> P.order()57>>> has_order(P, Integer(57))
True>>> has_order(P, factor(Integer(57)))
True>>> has_order(P, Integer(19))
False>>> has_order(Integer(3)*P, Integer(19))
True>>> has_order(Integer(3)*P, Integer(57))
False
sage: R = Zmod(14981)
sage: g = R(321)sage: g.multiplicative_order()42sage: has_order(g, 42, operation= * )Truesage: has_order(g, factor(42), operation= * )Truesage: has_order(g, 70, operation= * )False>>> from sage.all import *>>> R = Zmod(Integer(14981))>>> g = R(Integer(321))>>> g.multiplicative_order()42>>> has_order(g, Integer(42), operation= * )True>>> has_order(g, factor(Integer(42)), operation= * )True>>> has_order(g, Integer(70), operation= * )False

Note: In some cases, order testing can be much faster than computing the order using order_from_multiple().
sage.groups.generic.linear_relation(P, Q, operation='+', identity=None, inverse=None, op=None)
Function which solves the equation a*P=m*Q or P^a=Q^m.
Additive version: returns (𝑎, 𝑚) with minimal 𝑚 > 0 such that 𝑎𝑃 = 𝑚𝑄. Special case: if ⟨𝑃 ⟩ and ⟨𝑄⟩ intersect
only in {0} then (𝑎, 𝑚) = (0, 𝑛) where 𝑛 is Q.additive_order().
Multiplicative version: returns (𝑎, 𝑚) with minimal 𝑚 > 0 such that 𝑃 𝑎 = 𝑄𝑚 . Special case: if ⟨𝑃 ⟩ and ⟨𝑄⟩intersect only in {1} then (𝑎, 𝑚) = (0, 𝑛) where 𝑛 is Q.multiplicative_order().

79Groups, Release 10.4

ALGORITHM:
Uses the generic bsgs() function, and so works in general finite abelian groups.
EXAMPLES:
An additive example (in an elliptic curve group):
sage: # needs sage.rings.finite_rings sage.schemes
sage: F.<a> = GF(3^6, a )sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2, 0)
sage: Q = E(2*a^3 + 2*a^2 + 2*a, a^3 + 2*a^2 + 1)
sage: linear_relation(P, Q, + )(1, 2)
sage: P == 2*Q
True>>> from sage.all import *>>> # needs sage.rings.finite_rings sage.schemes>>> F = GF(Integer(3)**Integer(6), a , names=( a ,)); (a,) = F._first_ngens(1)>>> E = EllipticCurve([a**Integer(5) + Integer(2)*a**Integer(3) +␣˓→Integer(2)*a**Integer(2) + Integer(2)*a, a**Integer(4) + a**Integer(3) +␣˓→Integer(2)*a + Integer(1)])>>> P = E(a**Integer(5) + a**Integer(4) + a**Integer(3) + a**Integer(2) + a +␣˓→Integer(2), Integer(0))>>> Q = E(Integer(2)*a**Integer(3) + Integer(2)*a**Integer(2) + Integer(2)*a,␣
˓→a**Integer(3) + Integer(2)*a**Integer(2) + Integer(1))>>> linear_relation(P, Q, + )(1, 2)>>> P == Integer(2)*Q
True

A multiplicative example (in a finite field’s multiplicative group):
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(3^6, a )sage: a.multiplicative_order().factor()
2^3 * 7 * 13
sage: b = a^7
sage: c = a^13
sage: linear_relation(b, c, * )(13, 7)sage: b^13 == c^7
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = GF(Integer(3)**Integer(6), a , names=( a ,)); (a,) = F._first_ngens(1)>>> a.multiplicative_order().factor()
2^3 * 7 * 13>>> b = a**Integer(7)>>> c = a**Integer(13)>>> linear_relation(b, c, * )(13, 7)>>> b**Integer(13) == c**Integer(7)Truesage.groups.generic.merge_points(P1, P2, operation='+', identity=None, inverse=None, op=None,check=True)
80

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

Return a group element whose order is the lcm of the given elements.
INPUT:• P1 – a pair (𝑔1 , 𝑛1 ) where 𝑔1 is a group element of order 𝑛1• P2 – a pair (𝑔2 , 𝑛2 ) where 𝑔2 is a group element of order 𝑛2• operation – string: + (default) or * or other. If other, the following must be supplied:– identity – the identity element for the group;– inverse() – a function of one argument giving the inverse of a group element;– op() – a function of 2 arguments defining the group binary operation.
OUTPUT: a pair (𝑔3 , 𝑛3 ) where 𝑔3 has order 𝑛3 = lcm(𝑛1 , 𝑛2 )EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: from sage.groups.generic import merge_points
sage: F.<a> = GF(3^6, a )sage: b = a^7
sage: c = a^13
sage: ob = (3^6-1)//7
sage: oc = (3^6-1)//13
sage: merge_points((b,ob), (c,oc), operation= * )(a^4 + 2*a^3 + 2*a^2, 728)
sage: d, od = merge_points((b,ob), (c,oc), operation= * )sage: od == d.multiplicative_order()True
sage: od == lcm(ob, oc)
True
sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
sage: P = E(2*a^5 + 2*a^4 + a^3 + 2, a^4 + a^3 + a^2 + 2*a + 2)
sage: P.order()7
sage: Q = E(2*a^5 + 2*a^4 + 1, a^5 + 2*a^3 + 2*a + 2)
sage: Q.order()4
sage: R, m = merge_points((P,7), (Q,4), operation= + )sage: R.order() == mTrue
sage: m == lcm(7,4)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> from sage.groups.generic import merge_points>>> F = GF(Integer(3)**Integer(6), a , names=( a ,)); (a,) = F._first_ngens(1)>>> b = a**Integer(7)>>> c = a**Integer(13)>>> ob = (Integer(3)**Integer(6)-Integer(1))//Integer(7)>>> oc = (Integer(3)**Integer(6)-Integer(1))//Integer(13)>>> merge_points((b,ob), (c,oc), operation= * )(a^4 + 2*a^3 + 2*a^2, 728)>>> d, od = merge_points((b,ob), (c,oc), operation= * )(continues on next page)81

Groups, Release 10.4

(continued from previous page)>>> od == d.multiplicative_order()True>>> od == lcm(ob, oc)
True>>> # needs sage.libs.gap sage.rings.finite_rings sage.schemes>>> E = EllipticCurve([a**Integer(5) + Integer(2)*a**Integer(3) +␣˓→Integer(2)*a**Integer(2) + Integer(2)*a, a**Integer(4) + a**Integer(3) +␣˓→Integer(2)*a + Integer(1)])>>> P = E(Integer(2)*a**Integer(5) + Integer(2)*a**Integer(4) + a**Integer(3) +␣˓→Integer(2), a**Integer(4) + a**Integer(3) + a**Integer(2) + Integer(2)*a +␣˓→Integer(2))>>> P.order()7>>> Q = E(Integer(2)*a**Integer(5) + Integer(2)*a**Integer(4) + Integer(1),␣
˓→a**Integer(5) + Integer(2)*a**Integer(3) + Integer(2)*a + Integer(2))>>> Q.order()4>>> R, m = merge_points((P,Integer(7)), (Q,Integer(4)), operation= + )>>> R.order() == m
True>>> m == lcm(Integer(7),Integer(4))
Truesage.groups.generic.multiple(a, n, operation='*', identity=None, inverse=None, op=None)
Return either 𝑛𝑎 or 𝑎𝑛 , where 𝑛 is any integer and 𝑎 is a Python object on which a group operation such as additionor multiplication is defined. Uses the standard binary algorithm.
INPUT: See the documentation for discrete_logarithm().
EXAMPLES:
sage: multiple(2, 5)32
sage: multiple(RealField()( 2.5 ), 4)
˓→needs sage.rings.real_mpfr
39.0625000000000
sage: multiple(2, -3)
1/8
sage: multiple(2, 100, + ) == 100*2
True
sage: multiple(2, 100) == 2**100
Truesage: multiple(2, -100,) == 2**-100
True
sage: R.<x> = ZZ[]
sage: multiple(x, 100)x^100
sage: multiple(x, 100, + )100*x
sage: multiple(x, -10)
1/x^10#␣>>> from sage.all import *>>> multiple(Integer(2), Integer(5))
32>>> multiple(RealField()( 2.5 ), Integer(4))␣(continues on next page)

82

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)# needs sage.rings.real_mpfr
39.0625000000000>>> multiple(Integer(2), -Integer(3))
1/8>>> multiple(Integer(2), Integer(100), + ) == Integer(100)*Integer(2)True>>> multiple(Integer(2), Integer(100)) == Integer(2)**Integer(100)True>>> multiple(Integer(2), -Integer(100),) == Integer(2)**-Integer(100)True>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)>>> multiple(x, Integer(100))x^100>>> multiple(x, Integer(100), + )100*x>>> multiple(x, -Integer(10))
1/x^10˓→

Idempotence is detected, making the following fast:sage: multiple(1, 10^1000)
1
sage: # needs sage.schemes
sage: E = EllipticCurve( 389a1 )sage: P = E(-1,1)
sage: multiple(P, 10, + )(645656132358737542773209599489/22817025904944891235367494656 :
525532176124281192881231818644174845702936831/
˓→3446581505217248068297884384990762467229696 : 1)sage: multiple(P, -10, + )(645656132358737542773209599489/22817025904944891235367494656 :-528978757629498440949529703029165608170166527/
˓→3446581505217248068297884384990762467229696 : 1)>>> from sage.all import *>>> multiple(Integer(1), Integer(10)**Integer(1000))
1>>> # needs sage.schemes>>> E = EllipticCurve( 389a1 )>>> P = E(-Integer(1),Integer(1))>>> multiple(P, Integer(10), + )(645656132358737542773209599489/22817025904944891235367494656 :
525532176124281192881231818644174845702936831/
˓→3446581505217248068297884384990762467229696 : 1)>>> multiple(P, -Integer(10), + )(645656132358737542773209599489/22817025904944891235367494656 :-528978757629498440949529703029165608170166527/
˓→3446581505217248068297884384990762467229696 : 1)class sage.groups.generic.multiples(P, n, P0=None, indexed=False, operation='+', op=None)
Bases: object
Return an iterator which runs through P0+i*P for i in range(n).
P and P0 must be Sage objects in some group; if the operation is multiplication then the returned values are instead

83

Groups, Release 10.4

P0*P**i.
EXAMPLES:
sage: list(multiples(1, 10))[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sage: list(multiples(1, 10, 100))[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
sage: E = EllipticCurve( 389a1 )˓→needs sage.schemes
sage: P = E(-1,1)
˓→needs sage.schemes
sage: for Q in multiples(P, 5): print((Q, Q.height()/P.height()))˓→needs sage.schemes((0 : 1 : 0), 0.000000000000000)((-1 : 1 : 1), 1.00000000000000)((10/9 : -35/27 : 1), 4.00000000000000)((26/361 : -5720/6859 : 1), 9.00000000000000)((47503/16641 : 9862190/2146689 : 1), 16.0000000000000)
sage: R.<x> = ZZ[]
sage: list(multiples(x, 5))[0, x, 2*x, 3*x, 4*x]
sage: list(multiples(x, 5, operation= * ))[1, x, x^2, x^3, x^4]
sage: list(multiples(x, 5, indexed=True))[(0, 0), (1, x), (2, 2*x), (3, 3*x), (4, 4*x)]
sage: list(multiples(x, 5, indexed=True, operation= * ))[(0, 1), (1, x), (2, x^2), (3, x^3), (4, x^4)]
sage: for i,y in multiples(x, 5, indexed=True): print("%s0 times x = 0
1 times x = x
2 times x = 2*x
3 times x = 3*x
4 times x = 4*x

#␣
#␣
#␣

times %s = %s"%(i,x,y))

sage: for i,n in multiples(3, 5, indexed=True, operation= * ):....:print("3 to the power %s = %s" % (i,n))
3 to the power 0 = 1
3 to the power 1 = 3
3 to the power 2 = 9
3 to the power 3 = 27
3 to the power 4 = 81>>> from sage.all import *>>> list(multiples(Integer(1), Integer(10)))[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> list(multiples(Integer(1), Integer(10), Integer(100)))[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]>>> E = EllipticCurve( 389a1 )˓→needs sage.schemes>>> P = E(-Integer(1),Integer(1))˓→# needs sage.schemes>>> for Q in multiples(P, Integer(5)): print((Q, Q.height()/P.height()))˓→# needs sage.schemes((0 : 1 : 0), 0.000000000000000)#␣␣␣(continues on next page)

84

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

(continued from previous page)((-1 : 1 : 1), 1.00000000000000)((10/9 : -35/27 : 1), 4.00000000000000)((26/361 : -5720/6859 : 1), 9.00000000000000)((47503/16641 : 9862190/2146689 : 1), 16.0000000000000)>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)>>> list(multiples(x, Integer(5)))[0, x, 2*x, 3*x, 4*x]>>> list(multiples(x, Integer(5), operation= * ))[1, x, x^2, x^3, x^4]>>> list(multiples(x, Integer(5), indexed=True))[(0, 0), (1, x), (2, 2*x), (3, 3*x), (4, 4*x)]>>> list(multiples(x, Integer(5), indexed=True, operation= * ))[(0, 1), (1, x), (2, x^2), (3, x^3), (4, x^4)]>>> for i,y in multiples(x, Integer(5), indexed=True): print("%s˓→%(i,x,y))0 times x = 0
1 times x = x
2 times x = 2*x
3 times x = 3*x
4 times x = 4*xtimes %s = %s">>> for i,n in multiples(Integer(3), Integer(5), indexed=True, operation= * ):...
print("3 to the power %s = %s" % (i,n))
3 to the power 0 = 1
3 to the power 1 = 3
3 to the power 2 = 9
3 to the power 3 = 27
3 to the power 4 = 81

next()
Return the next item in this multiples iterator.
sage.groups.generic.order_from_bounds(P, bounds, d=None, operation='+', identity=None,
inverse=None, op=None)
Generic function to find order of a group element, given only upper and lower bounds for a multiple of the order(e.g. bounds on the order of the group of which it is an element)
INPUT:• P – a Sage object which is a group element• bounds – a 2-tuple (lb,ub) such that m*P=0 (or P**m=1) for some m with lb<=m<=ub• d – (optional) a positive integer; only m which are multiples of this will be considered• operation – string: + (default ) or * or other. If other, the following must be supplied:– identity – the identity element for the group;– inverse() – a function of one argument giving the inverse of a group element;– op() – a function of 2 arguments defining the group binary operation.
Note: Typically lb and ub will be bounds on the group order, and from previous calculation we know that thegroup order is divisible by d.
EXAMPLES:85

Groups, Release 10.4

sage: from sage.groups.generic import order_from_bounds
sage: # needs sage.rings.finite_rings
sage: k.<a> = GF(5^5)
sage: b = a^4
sage: order_from_bounds(b, (5^4, 5^5), operation= * )781
sage: # needs sage.rings.finite_rings sage.schemes
sage: E = EllipticCurve(k, [2,4])
sage: P = E(3*a^4 + 3*a, 2*a + 1)
sage: bounds = Hasse_bounds(5^5)
sage: Q = E(0,2)
sage: order_from_bounds(Q, bounds, operation= + )7
sage: order_from_bounds(P, bounds, 7, operation= + )3227
sage: # needs sage.rings.number_fieldsage: K.<z> = CyclotomicField(230)
sage: w = z^50
sage: order_from_bounds(w, (200, 250), operation= * )23>>> from sage.all import *>>> from sage.groups.generic import order_from_bounds>>> # needs sage.rings.finite_rings>>> k = GF(Integer(5)**Integer(5), names=( a ,)); (a,) = k._first_ngens(1)>>> b = a**Integer(4)>>> order_from_bounds(b, (Integer(5)**Integer(4), Integer(5)**Integer(5)),␣
˓→operation= * )781>>> # needs sage.rings.finite_rings sage.schemes>>> E = EllipticCurve(k, [Integer(2),Integer(4)])>>> P = E(Integer(3)*a**Integer(4) + Integer(3)*a, Integer(2)*a + Integer(1))>>> bounds = Hasse_bounds(Integer(5)**Integer(5))>>> Q = E(Integer(0),Integer(2))>>> order_from_bounds(Q, bounds, operation= + )7>>> order_from_bounds(P, bounds, Integer(7), operation= + )3227>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(230), names=( z ,)); (z,) = K._first_ngens(1)>>> w = z**Integer(50)>>> order_from_bounds(w, (Integer(200), Integer(250)), operation= * )23sage.groups.generic.order_from_multiple(P, m, plist=None, factorization=None, check=True,
operation='+', identity=None, inverse=None, op=None)
Generic function to find order of a group element given a multiple of its order.
See bsgs() for full explanation of the inputs.
INPUT:

86

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

• P – a Sage object which is a group element• m – a Sage integer which is a multiple of the order of P, i.e. we require that m*P=0 (or P**m=1)• check – a Boolean (default: True), indicating whether we check if m really is a multiple of the order• factorization – the factorization of m, or None in which case this function will need to factor m• plist – a list of the prime factors of m, or None. Kept for compatibility only, prefer the use of factorization• operation – string: + (default), * or None
• identity – the identity element of the group• inverse – function of 1 argument x, returning inverse of x
• op – function of 2 arguments x, y returning x*y in the group
Note: It is more efficient for the caller to factor m and cache the factors for subsequent calls.
EXAMPLES:
sage: from sage.groups.generic import order_from_multiple
sage: # needs sage.rings.finite_rings
sage: k.<a> = GF(5^5)
sage: b = a^4
sage: order_from_multiple(b, 5^5 - 1, operation= * )781
sage: # needs sage.rings.finite_rings sage.schemes
sage: E = EllipticCurve(k, [2,4])
sage: P = E(3*a^4 + 3*a, 2*a + 1)
sage: M = E.cardinality(); M3227
sage: F = M.factor()sage: order_from_multiple(P, M, factorization=F, operation= + )3227
sage: Q = E(0,2)
sage: order_from_multiple(Q, M, factorization=F, operation= + )7
sage: # needs sage.rings.number_fieldsage: K.<z> = CyclotomicField(230)
sage: w = z^50
sage: order_from_multiple(w, 230, operation= * )23
sage: # needs sage.modules sage.rings.finite_rings
sage: F = GF(2^1279, a )sage: n = F.cardinality() - 1 # Mersenne prime
sage: order_from_multiple(F.random_element(), n,....:
factorization=[(n,1)], operation= * ) == nTruesage: # needs sage.rings.finite_rings
sage: K.<a> = GF(3^60)
sage: order_from_multiple(a, 3^60 - 1, operation= * , check=False)
42391158275216203514294433200

87

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.generic import order_from_multiple>>> # needs sage.rings.finite_rings>>> k = GF(Integer(5)**Integer(5), names=( a ,)); (a,) = k._first_ngens(1)>>> b = a**Integer(4)>>> order_from_multiple(b, Integer(5)**Integer(5) - Integer(1), operation= * )781>>> # needs sage.rings.finite_rings sage.schemes>>> E = EllipticCurve(k, [Integer(2),Integer(4)])>>> P = E(Integer(3)*a**Integer(4) + Integer(3)*a, Integer(2)*a + Integer(1))>>> M = E.cardinality(); M
3227>>> F = M.factor()>>> order_from_multiple(P, M, factorization=F, operation= + )3227>>> Q = E(Integer(0),Integer(2))>>> order_from_multiple(Q, M, factorization=F, operation= + )7>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(230), names=( z ,)); (z,) = K._first_ngens(1)>>> w = z**Integer(50)>>> order_from_multiple(w, Integer(230), operation= * )23>>> # needs sage.modules sage.rings.finite_rings>>> F = GF(Integer(2)**Integer(1279), a )>>> n = F.cardinality() - Integer(1) # Mersenne prime>>> order_from_multiple(F.random_element(), n,...
factorization=[(n,Integer(1))], operation= * ) == nTrue>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(60), names=( a ,)); (a,) = K._first_ngens(1)>>> order_from_multiple(a, Integer(3)**Integer(60) - Integer(1), operation= * ,␣˓→check=False)
42391158275216203514294433200

sage.groups.generic.structure_description(G, latex=False)
Return a string that tries to describe the structure of G.
This methods wraps GAP’s StructureDescription method.
For full details, including the form of the returned string and the algorithm to build it, see GAP’s documentation.
INPUT:• latex – a boolean (default: False); if True, return a LaTeX formatted string
OUTPUT: string
Warning: From GAP’s documentation: The string returned by StructureDescription is not an isomorphism invariant: non-isomorphic groups can have the same string value, and two isomorphic groups indifferent representations can produce different strings.
EXAMPLES:
88

Chapter 8. Miscellaneous generic functions

Groups, Release 10.4

sage: # needs sage.groups
sage: G = CyclicPermutationGroup(6)sage: G.structure_description()C6
sage: G.structure_description(latex=True)
C_{6}sage: G2 = G.direct_product(G, maps=False)
sage: LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}>>> from sage.all import *>>> # needs sage.groups>>> G = CyclicPermutationGroup(Integer(6))>>> G.structure_description()
C6>>> G.structure_description(latex=True)
C_{6}>>> G2 = G.direct_product(G, maps=False)>>> LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}This method is mainly intended for small groups or groups with few normal subgroups. Even then there are somesurprises:
sage: D3 = DihedralGroup(3)˓→needs sage.groups
sage: D3.structure_description()
˓→needs sage.groups
S3>>> from sage.all import *>>> D3 = DihedralGroup(Integer(3))˓→# needs sage.groups>>> D3.structure_description()
˓→needs sage.groups
S3

#␣
#␣

␣
#␣

We use the Sage notation for the degree of dihedral groups:
sage: D4 = DihedralGroup(4)˓→needs sage.groups
sage: D4.structure_description()
˓→needs sage.groups
D4>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))˓→# needs sage.groups>>> D4.structure_description()
˓→needs sage.groups
D4

#␣
#␣

␣
#␣

Works for finitely presented groups (Issue #17573):
sage: F.<x, y> = FreeGroup()
˓→needs sage.groups#␣(continues on next page)

89

Groups, Release 10.4

(continued from previous page)

sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]
˓→needs sage.groups
sage: G.structure_description()
˓→needs sage.groups
C7

#␣
#␣

>>> from sage.all import *>>> F = FreeGroup(names=( x , y ,)); (x, y,) = F._first_ngens(2)# needs sage.
˓→groups>>> G = F / [x**Integer(2)*y**-Integer(1), x**Integer(3)*y**Integer(2), x*y*x**˓→Integer(1)*y**-Integer(1)]# needs sage.groups>>> G.structure_description()#␣˓→needs sage.groups
C7

And matrix groups (Issue #17573):
sage: groups.matrix.GL(4,2).structure_description()
˓→needs sage.libs.gap sage.modules
A8>>> from sage.all import *>>> groups.matrix.GL(Integer(4),Integer(2)).structure_description()˓→# needs sage.libs.gap sage.modules
A8

90

#␣

␣

Chapter 8. Miscellaneous generic functions

CHAPTER

NINE

FREE GROUPS

Free groups and finitely presented groups are implemented as a wrapper over the corresponding GAP objects.
A free group can be created by giving the number of generators, or their names. It is also possible to create indexed
generators:
sage: G.<x,y,z> = FreeGroup(); GFree Group on generators {x, y, z}
sage: FreeGroup(3)Free Group on generators {x0, x1, x2}
sage: FreeGroup( a,b,c )Free Group on generators {a, b, c}
sage: FreeGroup(3, t )Free Group on generators {t0, t1, t2}>>> from sage.all import *>>> G = FreeGroup(names=( x , y , z ,)); (x, y, z,) = G._first_ngens(3);Free Group on generators {x, y, z}>>> FreeGroup(Integer(3))
Free Group on generators {x0, x1, x2}>>> FreeGroup( a,b,c )Free Group on generators {a, b, c}>>> FreeGroup(Integer(3), t )Free Group on generators {t0, t1, t2}

G

The elements can be created by operating with the generators, or by passing a list with the indices of the letters to thegroup:
EXAMPLES:
sage: G.<a,b,c> = FreeGroup()
sage: a*b*c*a
a*b*c*asage: G([1,2,3,1])
a*b*c*asage: a * b / c * b^2
a*b*c^-1*b^2
sage: G([1,1,2,-1,-3,2])a^2*b*a^-1*c^-1*b>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c ,)); (a, b, c,) = G._first_ngens(3)>>> a*b*c*a
a*b*c*a>>> G([Integer(1),Integer(2),Integer(3),Integer(1)])(continues on next page)91

Groups, Release 10.4

(continued from previous page)

a*b*c*a>>> a * b / c * b**Integer(2)a*b*c^-1*b^2>>> G([Integer(1),Integer(1),Integer(2),-Integer(1),-Integer(3),Integer(2)])
a^2*b*a^-1*c^-1*b

You can use call syntax to replace the generators with a set of arbitrary ring elements:
sage: g = a * b / c * b^2
sage: g(1,2,3)
8/3
sage: M1 = identity_matrix(2)sage: M2 = matrix([[1,1],[0,1]])
sage: M3 = matrix([[0,1],[1,0]])
sage: g([M1, M2, M3])
[1 3]
[1 2]
>>> from sage.all import *>>> g = a * b / c * b**Integer(2)>>> g(Integer(1),Integer(2),Integer(3))
8/3>>> M1 = identity_matrix(Integer(2))>>> M2 = matrix([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])>>> M3 = matrix([[Integer(0),Integer(1)],[Integer(1),Integer(0)]])>>> g([M1, M2, M3])
[1 3]
[1 2]

AUTHORS:• Miguel Angel Marco Buzunariz• Volker Braunsage.groups.free_group.FreeGroup(n=None, names='x', index_set=None, abelian=False, **kwds)
Construct a Free Group.
INPUT:• n – integer (default: None); the number of generators (if not specified the names are counted)• names – string or list/tuple/iterable of strings (default: x ); the generator names or name prefix• index_set – (optional) an index set for the generators; if specified then the optional keyword abelian
can be used
• abelian – (default: False) whether to construct a free abelian group or a free group
Note: If you want to create a free group, it is currently preferential to use Groups().free(...) as that does
not load GAP.
EXAMPLES:
sage: G.<a,b> = FreeGroup(); GFree Group on generators {a, b}
sage: H = FreeGroup( a, b )(continues on next page)

92

Chapter 9. Free Groups

Groups, Release 10.4

(continued from previous page)

sage: G is H
True
sage: FreeGroup(0)Free Group on generators {}>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2);Free Group on generators {a, b}>>> H = FreeGroup( a, b )>>> G is H
True>>> FreeGroup(Integer(0))
Free Group on generators {}G

The entry can be either a string with the names of the generators, or the number of generators and the prefix of thenames to be given. The default prefix is x
sage: FreeGroup(3)Free Group on generators {x0, x1, x2}
sage: FreeGroup(3, g )Free Group on generators {g0, g1, g2}
sage: FreeGroup()Free Group on generators {x}>>> from sage.all import *>>> FreeGroup(Integer(3))
Free Group on generators {x0, x1, x2}>>> FreeGroup(Integer(3), g )Free Group on generators {g0, g1, g2}>>> FreeGroup()Free Group on generators {x}We give two examples using the index_set option:
sage: FreeGroup(index_set=ZZ)
˓→needs sage.combinat
Free group indexed by Integer Ringsage: FreeGroup(index_set=ZZ, abelian=True)
˓→needs sage.combinat
Free abelian group indexed by Integer Ring>>> from sage.all import *>>> FreeGroup(index_set=ZZ)
˓→needs sage.combinat
Free group indexed by Integer Ring>>> FreeGroup(index_set=ZZ, abelian=True)
˓→needs sage.combinat
Free abelian group indexed by Integer Ring

#␣

#␣

#␣

#␣

class sage.groups.free_group.FreeGroupElement(parent, x)
Bases: ElementLibGAP
A wrapper of GAP’s Free Group elements.
INPUT:

93

Groups, Release 10.4

• x – something that determines the group element; either a GapElement or the Tietze list (see Tietze())
of the group element• parent – the parent FreeGroup
EXAMPLES:
sage: G = FreeGroup( a, b )sage: x = G([1, 2, -1, -2])
sage: xa*b*a^-1*b^-1
sage: y = G([2, 2, 2, 1, -2, -2, -2])
sage: yb^3*a*b^-3
sage: x*ya*b*a^-1*b^2*a*b^-3
sage: y*xb^3*a*b^-3*a*b*a^-1*b^-1
sage: x^(-1)
b*a*b^-1*a^-1
sage: x == x*y*y^(-1)
True>>> from sage.all import *>>> G = FreeGroup( a, b )>>> x = G([Integer(1), Integer(2), -Integer(1), -Integer(2)])>>> x
a*b*a^-1*b^-1>>> y = G([Integer(2), Integer(2), Integer(2), Integer(1), -Integer(2), ˓→Integer(2), -Integer(2)])>>> yb^3*a*b^-3>>> x*ya*b*a^-1*b^2*a*b^-3>>> y*xb^3*a*b^-3*a*b*a^-1*b^-1>>> x**(-Integer(1))
b*a*b^-1*a^-1>>> x == x*y*y**(-Integer(1))
True

Tietze()Return the Tietze list of the element.
The Tietze list of a word is a list of integers that represent the letters in the word. A positive integer 𝑖represents the letter corresponding to the 𝑖-th generator of the group. Negative integers represent the inversesof generators.
OUTPUT: tuple of integers
EXAMPLES:
sage: G.<a,b> = FreeGroup()
sage: a.Tietze()(1,)
sage: x = a^2 * b^(-3) * a^(-2)
sage: x.Tietze()(1, 1, -2, -2, -2, -1, -1)

94

Chapter 9. Free Groups

Groups, Release 10.4>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> a.Tietze()(1,)>>> x = a**Integer(2) * b**(-Integer(3)) * a**(-Integer(2))>>> x.Tietze()(1, 1, -2, -2, -2, -1, -1)

fox_derivative(gen, im_gens=None, ring=None)
Return the Fox derivative of self with respect to a given generator gen of the free group.
Let 𝐹 be a free group with free generators 𝑥1 , 𝑥2 , . . . , 𝑥𝑛 . Let 𝑗 ∈ {1, 2, . . . , 𝑛}. Let 𝑎1 , 𝑎2 , . . . , 𝑎𝑛 be 𝑛
invertible elements of a ring 𝐴. Let 𝑎 : 𝐹 → 𝐴× be the (unique) homomorphism from 𝐹 to the multiplicative
group of invertible elements of 𝐴 which sends each 𝑥𝑖 to 𝑎𝑖 . Then, we can define a map 𝜕𝑗 : 𝐹 → 𝐴 by therequirements that𝜕𝑗 (𝑥𝑖 ) = 𝛿𝑖,𝑗

for all indices 𝑖 and 𝑗and𝜕𝑗 (𝑢𝑣) = 𝜕𝑗 (𝑢) + 𝑎(𝑢)𝜕𝑗 (𝑣)for all 𝑢, 𝑣 ∈ 𝐹.

This map 𝜕𝑗 is called the 𝑗-th Fox derivative on 𝐹 induced by (𝑎1 , 𝑎2 , . . . , 𝑎𝑛 ).
The most well-known case is when 𝐴 is the group ring [𝐹 ] of 𝐹 over , and when 𝑎𝑖 = 𝑥𝑖 ∈ 𝐴. In thiscase, 𝜕𝑗 is simply called the 𝑗-th Fox derivative on 𝐹 .
INPUT:• gen – the generator with respect to which the derivative will be computed. If this is 𝑥𝑗 , then the method
will return 𝜕𝑗 .
• im_gens (optional) – the images of the generators (given as a list or iterable). This is the list
(𝑎1 , 𝑎2 , . . . , 𝑎𝑛 ). If not provided, it defaults to (𝑥1 , 𝑥2 , . . . , 𝑥𝑛 ) in the group ring [𝐹 ].
• ring (optional) – the ring in which the elements of the list (𝑎1 , 𝑎2 , . . . , 𝑎𝑛 ) lie. If not provided, thisring is inferred from these elements.
OUTPUT:
The fox derivative of self with respect to gen (induced by im_gens). By default, it is an element of
the group algebra with integer coefficients. If im_gens are provided, the result lives in the algebra where
im_gens live.
EXAMPLES:
sage: G = FreeGroup(5)sage: G.inject_variables()Defining x0, x1, x2, x3, x4
sage: (~x0*x1*x0*x2*~x0).fox_derivative(x0)-x0^-1 + x0^-1*x1 - x0^-1*x1*x0*x2*x0^-1
sage: (~x0*x1*x0*x2*~x0).fox_derivative(x1)x0^-1sage: (~x0*x1*x0*x2*~x0).fox_derivative(x2)x0^-1*x1*x0
sage: (~x0*x1*x0*x2*~x0).fox_derivative(x3)095Groups, Release 10.4>>> from sage.all import *>>> G = FreeGroup(Integer(5))>>> G.inject_variables()Defining x0, x1, x2, x3, x4>>> (~x0*x1*x0*x2*~x0).fox_derivative(x0)-x0^-1 + x0^-1*x1 - x0^-1*x1*x0*x2*x0^-1>>> (~x0*x1*x0*x2*~x0).fox_derivative(x1)x0^-1>>> (~x0*x1*x0*x2*~x0).fox_derivative(x2)x0^-1*x1*x0>>> (~x0*x1*x0*x2*~x0).fox_derivative(x3)0

If im_gens is given, the images of the generators are mapped to them:sage: F = FreeGroup(3)sage: a = F([2,1,3,-1,2])
sage: a.fox_derivative(F([1]))x1 - x1*x0*x2*x0^-1
sage: R.<t> = LaurentPolynomialRing(ZZ)
sage: a.fox_derivative(F([1]),[t,t,t])
t - t^2sage: S.<t1,t2,t3> = LaurentPolynomialRing(ZZ)
sage: a.fox_derivative(F([1]),[t1,t2,t3])-t2*t3 + t2
sage: R.<x,y,z> = QQ[]
sage: a.fox_derivative(F([1]),[x,y,z])-y*z + ysage: a.inverse().fox_derivative(F([1]),[x,y,z])(z - 1)/(y*z)>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> a = F([Integer(2),Integer(1),Integer(3),-Integer(1),Integer(2)])>>> a.fox_derivative(F([Integer(1)]))x1 - x1*x0*x2*x0^-1>>> R = LaurentPolynomialRing(ZZ, names=( t ,)); (t,) = R._first_ngens(1)>>> a.fox_derivative(F([Integer(1)]),[t,t,t])
t - t^2>>> S = LaurentPolynomialRing(ZZ, names=( t1 , t2 , t3 ,)); (t1, t2, t3,) =␣
˓→S._first_ngens(3)>>> a.fox_derivative(F([Integer(1)]),[t1,t2,t3])-t2*t3 + t2>>> R = QQ[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> a.fox_derivative(F([Integer(1)]),[x,y,z])-y*z + y>>> a.inverse().fox_derivative(F([Integer(1)]),[x,y,z])(z - 1)/(y*z)

The optional parameter ring determines the ring 𝐴:
sage: u = a.fox_derivative(F([1]), [1,2,3], ring=QQ)
sage: u-4
sage: parent(u)Rational Field
sage: u = a.fox_derivative(F([1]), [1,2,3], ring=R)(continues on next page)

96

Chapter 9. Free Groups

Groups, Release 10.4

(continued from previous page)

sage: u-4
sage: parent(u)Multivariate Polynomial Ring in x, y, z over Rational Field>>> from sage.all import *>>> u = a.fox_derivative(F([Integer(1)]), [Integer(1),Integer(2),Integer(3)],␣
˓→ring=QQ)>>> u-4>>> parent(u)Rational Field>>> u = a.fox_derivative(F([Integer(1)]), [Integer(1),Integer(2),Integer(3)],␣
˓→ring=R)>>> u-4>>> parent(u)Multivariate Polynomial Ring in x, y, z over Rational Fieldsyllables()Return the syllables of the word.
Consider a free group element 𝑔 = 𝑥𝑛1 1 𝑥𝑛2 2 · · · 𝑥𝑛𝑘 𝑘 . The uniquely-determined subwords 𝑥𝑒𝑖 𝑖 consisting onlyof powers of a single generator are called the syllables of 𝑔.
OUTPUT:
The tuple of syllables. Each syllable is given as a pair (𝑥𝑖 , 𝑒𝑖 ) consisting of a generator and a non-zero integer.
EXAMPLES:
sage: G.<a,b> = FreeGroup()
sage: w = a^2 * b^-1 * a^3sage: w.syllables()((a, 2), (b, -1), (a, 3))>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> w = a**Integer(2) * b**-Integer(1) * a**Integer(3)>>> w.syllables()((a, 2), (b, -1), (a, 3))class sage.groups.free_group.FreeGroup_class(generator_names, libgap_free_group=None)
Bases: UniqueRepresentation, Group, ParentLibGAP
A class that wraps GAP’s FreeGroup
See FreeGroup() for details.
Element
alias of FreeGroupElement
abelian_invariants()
Return the Abelian invariants of self.
The Abelian invariants are given by a list of integers 𝑖1 . . . 𝑖𝑗 , such that the abelianization of the group isisomorphic to/(𝑖1 ) × · · · × /(𝑖𝑗 )97

Groups, Release 10.4

EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: F.abelian_invariants()(0, 0)>>> from sage.all import *>>> F = FreeGroup(names=( a ,>>> F.abelian_invariants()(0, 0)b ,)); (a, b,) = F._first_ngens(2)quotient(relations, **kwds)
Return the quotient of self by the normal subgroup generated by the given elements.
This quotient is a finitely presented groups with the same generators as self, and relations given by theelements of relations.
INPUT:• relations – a list/tuple/iterable with the elements of the free group• further named arguments, that are passed to the constructor of a finitely presented group
OUTPUT:
A finitely presented group, with generators corresponding to the generators of the free group, and relations
corresponding to the elements in relations.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: F.quotient([a*b^2*a, b^3])
Finitely presented group < a, b | a*b^2*a, b^3 >>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> F.quotient([a*b**Integer(2)*a, b**Integer(3)])
Finitely presented group < a, b | a*b^2*a, b^3 >Division is shorthand for quotient()
sage: F / [a*b^2*a, b^3]
Finitely presented group < a, b | a*b^2*a, b^3 >>>> from sage.all import *>>> F / [a*b**Integer(2)*a, b**Integer(3)]Finitely presented group < a, b | a*b^2*a, b^3 >Relations are converted to the free group, even if they are not elements of it (if possible)
sage: F1.<a,b,c,d> = FreeGroup()
sage: F2.<a,b> = FreeGroup()
sage: r = a*b/a
sage: r.parent()
Free Group on generators {a, b}
sage: F1/[r]Finitely presented group < a, b, c, d | a*b*a^-1 >98

Chapter 9. Free Groups

Groups, Release 10.4>>> from sage.all import *>>> F1 = FreeGroup(names=( a , b , c , d ,)); (a, b, c, d,) = F1._first_
˓→ngens(4)>>> F2 = FreeGroup(names=( a , b ,)); (a, b,) = F2._first_ngens(2)>>> r = a*b/a>>> r.parent()
Free Group on generators {a, b}>>> F1/[r]Finitely presented group < a, b, c, d | a*b*a^-1 >rank()
Return the number of generators of self.
Alias for ngens().
OUTPUT: integer
EXAMPLES:
sage: G = FreeGroup( a, b ); GFree Group on generators {a, b}
sage: G.rank()
2sage: H = FreeGroup(3, x )sage: HFree Group on generators {x0, x1, x2}
sage: H.rank()
3>>> from sage.all import *>>> G = FreeGroup( a, b ); GFree Group on generators {a, b}>>> G.rank()
2>>> H = FreeGroup(Integer(3), x )>>> HFree Group on generators {x0, x1, x2}>>> H.rank()
3sage.groups.free_group.is_FreeGroup(x)Test whether x is a FreeGroup_class.
INPUT:• x – anything
OUTPUT: boolean
EXAMPLES:
sage: from sage.groups.free_group import is_FreeGroupsage: is_FreeGroup( a string )˓→needs sage.combinat
False
sage: is_FreeGroup(FreeGroup(0))
Truesage: is_FreeGroup(FreeGroup(index_set=ZZ))#␣#␣(continues on next page)99

Groups, Release 10.4

(continued from previous page)needs sage.combinat
True˓→>>> from sage.all import *>>> from sage.groups.free_group import is_FreeGroup>>> is_FreeGroup( a string )˓→needs sage.combinat
False>>> is_FreeGroup(FreeGroup(Integer(0)))
True>>> is_FreeGroup(FreeGroup(index_set=ZZ))
˓→needs sage.combinat
True

#␣

#␣

sage.groups.free_group.wrap_FreeGroup(libgap_free_group)
Wrap a LibGAP free group.
This function changes the comparison method of libgap_free_group to comparison by Python id. If you
want to put the LibGAP free group into a container (set, dict) then you should understand the implications of_set_compare_by_id(). To be safe, it is recommended that you just work with the resulting Sage FreeGroup_class.
INPUT:• libgap_free_group – a LibGAP free group
OUTPUT: a Sage FreeGroup_class
EXAMPLES:First construct a LibGAP free group:sage: F = libgap.FreeGroup([ a , b ])sage: type(F)<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> F = libgap.FreeGroup([ a , b ])>>> type(F)<class sage.libs.gap.element.GapElement >Now wrap it:
sage: from sage.groups.free_group import wrap_FreeGroupsage: wrap_FreeGroup(F)Free Group on generators {a, b}>>> from sage.all import *>>> from sage.groups.free_group import wrap_FreeGroup>>> wrap_FreeGroup(F)Free Group on generators {a, b}

100

Chapter 9. Free Groups

CHAPTERTENFINITELY PRESENTED GROUPS

Finitely presented groups are constructed as quotients of free_group:sage: F.<a,b,c> = FreeGroup()
sage: G = F / [a^2, b^2, c^2, a*b*c*a*b*c]
sage: G
Finitely presented group < a, b, c | a^2, b^2, c^2, (a*b*c)^2 >>>> from sage.all import *>>> F = FreeGroup(names=( a , b , c ,)); (a, b, c,) = F._first_ngens(3)>>> G = F / [a**Integer(2), b**Integer(2), c**Integer(2), a*b*c*a*b*c]>>> G
Finitely presented group < a, b, c | a^2, b^2, c^2, (a*b*c)^2 >One can create their elements by multiplying the generators or by specifying a Tietze list (see Tietze()) as in the caseof free groups:
sage: G.gen(0) * G.gen(1)a*bsage: G([1,2,-1])
a*b*a^-1sage: a.parent()
Free Group on generators {a, b, c}
sage: G.inject_variables()Defining a, b, c
sage: a.parent()
Finitely presented group < a, b, c | a^2, b^2, c^2, (a*b*c)^2 >>>> from sage.all import *>>> G.gen(Integer(0)) * G.gen(Integer(1))
a*b>>> G([Integer(1),Integer(2),-Integer(1)])
a*b*a^-1>>> a.parent()
Free Group on generators {a, b, c}>>> G.inject_variables()Defining a, b, c>>> a.parent()
Finitely presented group < a, b, c | a^2, b^2, c^2, (a*b*c)^2 >Notice that, even if they are represented in the same way, the elements of a finitely presented group and the elements ofthe corresponding free group are not the same thing. However, they can be converted from one parent to the other:101

Groups, Release 10.4

sage: F.<a,b,c> = FreeGroup()
sage: G = F / [a^2,b^2,c^2,a*b*c*a*b*c]
sage: F([1])
asage: G([1])
asage: F([1]) is G([1])
Falsesage: F([1]) == G([1])
Falsesage: G(a*b/c)
a*b*c^-1sage: F(G(a*b/c))
a*b*c^-1>>> from sage.all import *>>> F = FreeGroup(names=( a , b , c ,)); (a, b, c,) = F._first_ngens(3)>>> G = F / [a**Integer(2),b**Integer(2),c**Integer(2),a*b*c*a*b*c]>>> F([Integer(1)])
a>>> G([Integer(1)])
a>>> F([Integer(1)]) is G([Integer(1)])
False>>> F([Integer(1)]) == G([Integer(1)])
False>>> G(a*b/c)
a*b*c^-1>>> F(G(a*b/c))
a*b*c^-1Finitely presented groups are implemented via GAP. You can use the gap() method to access the underlying LibGAP
object:sage: G = FreeGroup(2)sage: G.inject_variables()Defining x0, x1
sage: H = G / (x0^2, (x0*x1)^2, x1^2)
sage: H.gap()<fp group on the generators [ x0, x1 ]>>>> from sage.all import *>>> G = FreeGroup(Integer(2))>>> G.inject_variables()Defining x0, x1>>> H = G / (x0**Integer(2), (x0*x1)**Integer(2), x1**Integer(2))>>> H.gap()<fp group on the generators [ x0, x1 ]>This can be useful, for example, to use GAP functions that are not yet wrapped in Sage:sage: H.gap().LowerCentralSeries()[ Group(<fp, no generators known>), Group(<fp, no generators known>) ]>>> from sage.all import *>>> H.gap().LowerCentralSeries()(continues on next page)

102

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)[ Group(<fp, no generators known>), Group(<fp, no generators known>) ]The same holds for the group elements:
sage: G = FreeGroup(2)sage: H = G / (G([1, 1]), G([2, 2, 2]), G([1, 2, -1, -2])); H
Finitely presented group < x0, x1 | x0^2, x1^3, x0*x1*x0^-1*x1^-1 >sage: a = H([1])
sage: ax0
sage: a.gap()x0
sage: a.gap().Order()2sage: type(_)# note that the above output is not a Sage integer<class sage.libs.gap.element.GapElement_Integer >>>> from sage.all import *>>> G = FreeGroup(Integer(2))>>> H = G / (G([Integer(1), Integer(1)]), G([Integer(2), Integer(2), Integer(2)]),␣
˓→G([Integer(1), Integer(2), -Integer(1), -Integer(2)]));
H
Finitely presented group < x0, x1 | x0^2, x1^3, x0*x1*x0^-1*x1^-1 >>>> a = H([Integer(1)])>>> ax0>>> a.gap()x0>>> a.gap().Order()2>>> type(_)# note that the above output is not a Sage integer<class sage.libs.gap.element.GapElement_Integer >You can use call syntax to replace the generators with a set of arbitrary ring elements. For example, take the free abeliangroup obtained by modding out the commutator subgroup of the free group:sage: G = FreeGroup(2)sage: G_ab = G / [G([1, 2, -1, -2])]; G_ab
Finitely presented group < x0, x1 | x0*x1*x0^-1*x1^-1 >sage: a,b = G_ab.gens()
sage: g = a * b
sage: M1 = matrix([[1,0],[0,2]])
sage: M2 = matrix([[0,1],[1,0]])
sage: g(3, 5)
15
sage: g(M1, M1)
[1 0]
[0 4]
sage: M1*M2 == M2*M1# matrices do not commute
False
sage: g(M1, M2)
Traceback (most recent call last):...
ValueError: the values do not satisfy all relations of the group>>> from sage.all import *>>> G = FreeGroup(Integer(2))(continues on next page)103

Groups, Release 10.4

(continued from previous page)>>> G_ab = G / [G([Integer(1), Integer(2), -Integer(1), -Integer(2)])];
Finitely presented group < x0, x1 | x0*x1*x0^-1*x1^-1 >>>> a,b = G_ab.gens()>>> g = a * b>>> M1 = matrix([[Integer(1),Integer(0)],[Integer(0),Integer(2)]])>>> M2 = matrix([[Integer(0),Integer(1)],[Integer(1),Integer(0)]])>>> g(Integer(3), Integer(5))
15>>> g(M1, M1)
[1 0]
[0 4]
>>> M1*M2 == M2*M1# matrices do not commute
False>>> g(M1, M2)
Traceback (most recent call last):...
ValueError: the values do not satisfy all relations of the group

G_ab

Warning: Some methods are not guaranteed to finish since the word problem for finitely presented groups is, ingeneral, undecidable. In those cases the process may run until the available memory is exhausted.
REFERENCES:• Wikipedia article Presentation_of_a_group• Wikipedia article Word_problem_for_groups
AUTHOR:• Miguel Angel Marco Buzunariz
class sage.groups.finitely_presented.FinitelyPresentedGroup(free_group, relations,
category=None)
Bases: GroupMixinLibGAP, UniqueRepresentation, Group, ParentLibGAP
A class that wraps GAP’s Finitely Presented Groups.
Warning: You should use quotient() to construct finitely presented groups as quotients of free groups.
EXAMPLES:
sage: G.<a,b> = FreeGroup()
sage: H = G / [a, b^3]
sage: H
Finitely presented group < a, b | a, b^3 >sage: H.gens()(a, b)
sage: F.<a,b> = FreeGroup( a, b )sage: J = F / (F([1]), F([2, 2, 2]))sage: J is H
True
sage: G = FreeGroup(2)(continues on next page)

104

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

sage: H = G / (G([1, 1]), G([2, 2, 2]))sage: H.gens()(x0, x1)
sage: H.gen(0)x0sage: H.ngens()2
sage: H.gap()<fp group on the generators [ x0, x1 ]>sage: type(_)<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / [a, b**Integer(3)]>>> H
Finitely presented group < a, b | a, b^3 >>>> H.gens()(a, b)>>> F = FreeGroup( a, b , names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> J = F / (F([Integer(1)]), F([Integer(2), Integer(2), Integer(2)]))>>> J is H
True>>> G = FreeGroup(Integer(2))>>> H = G / (G([Integer(1), Integer(1)]), G([Integer(2), Integer(2), Integer(2)]))>>> H.gens()(x0, x1)>>> H.gen(Integer(0))
x0>>> H.ngens()2>>> H.gap()<fp group on the generators [ x0, x1 ]>>>> type(_)<class sage.libs.gap.element.GapElement >Element
alias of FinitelyPresentedGroupElement
abelian_alexander_matrix(ring=Rational Field, simplified=True)
Return the Alexander matrix of the group with values in the group algebra of the abelianized.
INPUT:• ring – (default: QQ) the base ring of the group algebra• simplified – boolean (default: False); if set to True use Gauss elimination and erase rows andcolumns
OUTPUT:• A – a matrix with coefficients in R
• ideal – an list of generators of an ideal I of R = A.base_ring() such that R/I is the groupalgebra of the abelianization of self
EXAMPLES:105

Groups, Release 10.4

sage: G.<a,b,c> = FreeGroup()
sage: H = G.quotient([a*b/a/b, a*c/a/c, c*b/c/b])
sage: A, ideal = H.abelian_alexander_matrix()
sage: A[-f2 + 1 f1 - 1
0][-f3 + 1
0 f1 - 1][
0 f3 - 1 -f2 + 1]
sage: A.base_ring()
Multivariate Laurent Polynomial Ring in f1, f2, f3 over Rational Field
sage: ideal[]
sage: G = FreeGroup(3)/[(2, 1, 1), (1, 2, 2, 3, 3)]
sage: A, ideal = G.abelian_alexander_matrix(simplified=True); A[-f3^2 - f3^4 - f3^6
f3^3 + f3^6]
sage: g = FreeGroup(1) / []sage: g.abelian_alexander_matrix()([], [])
sage: g.abelian_alexander_matrix()[0].base_ring()
Univariate Laurent Polynomial Ring in f1 over Rational Field
sage: g = FreeGroup(0) / []sage: A, ideal = g.abelian_alexander_matrix(); A[]
sage: A.base_ring()
Rational Field>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c ,)); (a, b, c,) = G._first_ngens(3)>>> H = G.quotient([a*b/a/b, a*c/a/c, c*b/c/b])>>> A, ideal = H.abelian_alexander_matrix()>>> A[-f2 + 1 f1 - 1
0][-f3 + 1
0 f1 - 1][
0 f3 - 1 -f2 + 1]>>> A.base_ring()
Multivariate Laurent Polynomial Ring in f1, f2, f3 over Rational Field>>> ideal[]>>> G = FreeGroup(Integer(3))/[(Integer(2), Integer(1), Integer(1)),␣
˓→(Integer(1), Integer(2), Integer(2), Integer(3), Integer(3))]>>> A, ideal = G.abelian_alexander_matrix(simplified=True); A[-f3^2 - f3^4 - f3^6
f3^3 + f3^6]>>> g = FreeGroup(Integer(1)) / []>>> g.abelian_alexander_matrix()([], [])>>> g.abelian_alexander_matrix()[Integer(0)].base_ring()
Univariate Laurent Polynomial Ring in f1 over Rational Field>>> g = FreeGroup(Integer(0)) / []>>> A, ideal = g.abelian_alexander_matrix(); A[]>>> A.base_ring()
Rational Field

abelian_invariants()
Return the abelian invariants of self.
The abelian invariants are given by a list of integers (𝑖1 , . . . , 𝑖𝑗 ), such that the abelianization of the group isisomorphic to /(𝑖1 ) × · · · × /(𝑖𝑗 ).

106

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

EXAMPLES:
sage: G = FreeGroup(4, g )sage: G.inject_variables()Defining g0, g1, g2, g3
sage: H = G.quotient([g1^2, g2*g1*g2^(-1)*g1^(-1), g1*g3^(-2), g0^4])
sage: H.abelian_invariants()(0, 4, 4)>>> from sage.all import *>>> G = FreeGroup(Integer(4), g )>>> G.inject_variables()Defining g0, g1, g2, g3>>> H = G.quotient([g1**Integer(2), g2*g1*g2**(-Integer(1))*g1**(-Integer(1)),˓→ g1*g3**(-Integer(2)), g0**Integer(4)])>>> H.abelian_invariants()(0, 4, 4)

ALGORITHM:
Uses GAP.
abelianization_map()
Return the abelianization map of self.
OUTPUT: the abelianization map of self as a homomorphism of finitely presented groups
EXAMPLES:
sage: G = FreeGroup(4, g )sage: G.inject_variables(verbose=False)
sage: H = G.quotient([g1^2, g2*g1*g2^(-1)*g1^(-1), g1*g3^(-2), g0^4])
sage: H.abelianization_map()
Group morphism:
From: Finitely presented group < g0, g1, g2, g3 | g1^2, g2*g1*g2^-1*g1^˓→1, g1*g3^-2, g0^4 >To:
Finitely presented group < f2, f3, f4 | f2^-1*f3^-1*f2*f3, f2^˓→1*f4^-1*f2*f4, f3^-1*f4^-1*f3*f4, f2^4, f3^4 >sage: g = FreeGroup(0) / []sage: g.abelianization_map()
Group endomorphism of Finitely presented group < | >>>> from sage.all import *>>> G = FreeGroup(Integer(4), g )>>> G.inject_variables(verbose=False)>>> H = G.quotient([g1**Integer(2), g2*g1*g2**(-Integer(1))*g1**(-Integer(1)),˓→ g1*g3**(-Integer(2)), g0**Integer(4)])>>> H.abelianization_map()
Group morphism:
From: Finitely presented group < g0, g1, g2, g3 | g1^2, g2*g1*g2^-1*g1^˓→1, g1*g3^-2, g0^4 >To:
Finitely presented group < f2, f3, f4 | f2^-1*f3^-1*f2*f3, f2^˓→1*f4^-1*f2*f4, f3^-1*f4^-1*f3*f4, f2^4, f3^4 >>>> g = FreeGroup(Integer(0)) / []>>> g.abelianization_map()
Group endomorphism of Finitely presented group < | >abelianization_to_algebra(ring=Rational Field)

107

Groups, Release 10.4

Return the group algebra of the abelianization of self together with the monomials representing the generators of self.
INPUT:• ring – (default: QQ); the base ring for the group algebra of self
OUTPUT:• ab – the abelianization of self as a finitely presented group with a minimal number 𝑛 of generators.
• R – a Laurent polynomial ring with 𝑛 variables with base ring ring.
• ideal – a list of generators of an ideal I in R such that R/I is the group algebra of the abelianization
over ring• image – a list with the images of the generators of self in R/I
EXAMPLES:
sage: G = FreeGroup(4, g )sage: G.inject_variables()Defining g0, g1, g2, g3
sage: H = G.quotient([g1^2, g2*g1*g2^(-1)*g1^(-1), g1*g3^(-2), g0^4])
sage: H.abelianization_to_algebra()(Finitely presented group < f2, f3, f4 | f2^-1*f3^-1*f2*f3, f2^-1*f4^˓→1*f2*f4,
f3^-1*f4^-1*f3*f4, f2^4, f3^4 >,Multivariate Laurent Polynomial Ring in f2, f3, f4 over Rational Field,[f2^4 - 1, f3^4 - 1], [f2^-1*f3^-2, f3^-2, f4, f3])
sage: g=FreeGroup(0) / []sage: g.abelianization_to_algebra()(Finitely presented group < | >, Rational Field, [], [])>>> from sage.all import *>>> G = FreeGroup(Integer(4), g )>>> G.inject_variables()Defining g0, g1, g2, g3>>> H = G.quotient([g1**Integer(2), g2*g1*g2**(-Integer(1))*g1**(-Integer(1)),˓→ g1*g3**(-Integer(2)), g0**Integer(4)])>>> H.abelianization_to_algebra()(Finitely presented group < f2, f3, f4 | f2^-1*f3^-1*f2*f3, f2^-1*f4^˓→1*f2*f4,
f3^-1*f4^-1*f3*f4, f2^4, f3^4 >,Multivariate Laurent Polynomial Ring in f2, f3, f4 over Rational Field,[f2^4 - 1, f3^4 - 1], [f2^-1*f3^-2, f3^-2, f4, f3])>>> g=FreeGroup(Integer(0)) / []>>> g.abelianization_to_algebra()(Finitely presented group < | >, Rational Field, [], [])alexander_matrix(im_gens=None)
Return the Alexander matrix of the group.
This matrix is given by the fox derivatives of the relations with respect to the generators.
• im_gens – (optional) the images of the generators
OUTPUT:
A matrix with coefficients in the group algebra. If im_gens is given, the coefficients will live in the same
algebra as the given values. The result depends on the (fixed) choice of presentation.
EXAMPLES:
108

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

sage: G.<a,b,c> = FreeGroup()
sage: H = G.quotient([a*b/a/b, a*c/a/c, c*b/c/b])
sage: H.alexander_matrix()[
1 - a*b*a^-1 a - a*b*a^-1*b^-10][
1 - a*c*a^-1
0 a - a*c*a^-1*c^-1][0 c - c*b*c^-1*b^-1
1 - c*b*c^-1]>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c ,)); (a, b, c,) = G._first_ngens(3)>>> H = G.quotient([a*b/a/b, a*c/a/c, c*b/c/b])>>> H.alexander_matrix()[
1 - a*b*a^-1 a - a*b*a^-1*b^-10][
1 - a*c*a^-1
0 a - a*c*a^-1*c^-1][0 c - c*b*c^-1*b^-1
1 - c*b*c^-1]

If we introduce the images of the generators, we obtain the result in the corresponding algebra.
sage: G.<a,b,c,d,e> = FreeGroup()
sage: H = G.quotient([a*b/a/b, a*c/a/c, a*d/a/d, b*c*d/(c*d*b), b*c*d/˓→(d*b*c)])sage: H.alexander_matrix()[
1 - a*b*a^-1a - a*b*a^-1*b^-1
˓→
0
0
0]
[
1 - a*c*a^-10a - a*c*a^˓→1*c^-100][
1 - a*d*a^-10
˓→0a - a*d*a^-1*d^-10][0
1 - b*c*d*b^-1b - b*c*d*b^-1*d^˓→1*c^-1
b*c - b*c*d*b^-1*d^-10][0
1 - b*c*d*c^-1*b^-1b -␣
˓→b*c*d*c^-1 b*c - b*c*d*c^-1*b^-1*d^-10]
sage: R.<t1,t2,t3,t4> = LaurentPolynomialRing(ZZ)
sage: H.alexander_matrix([t1,t2,t3,t4])[-t2 + 1
t1 - 10
00][-t3 + 10
t1 - 100][-t4 + 100
t1 - 1
0][
0 -t3*t4 + 1
t2 - 1 t2*t3 - t3
0][0
-t4 + 1 -t2*t4 + t2
t2*t3 - 10]

␣␣>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c , d , e ,)); (a, b, c, d, e,) = G._˓→first_ngens(5)>>> H = G.quotient([a*b/a/b, a*c/a/c, a*d/a/d, b*c*d/(c*d*b), b*c*d/(d*b*c)])>>> H.alexander_matrix()[
1 - a*b*a^-1a - a*b*a^-1*b^-1
␣
˓→
0
0
0]
[
1 - a*c*a^-10a - a*c*a^˓→1*c^-100][
1 - a*d*a^-10␣˓→0a - a*d*a^-1*d^-10][0
1 - b*c*d*b^-1b - b*c*d*b^-1*d^˓→1*c^-1
b*c - b*c*d*b^-1*d^-10][0
1 - b*c*d*c^-1*b^-1b -␣
˓→b*c*d*c^-1 b*c - b*c*d*c^-1*b^-1*d^-10]>>> R = LaurentPolynomialRing(ZZ, names=( t1 , t2 , t3 , t4 ,)); (t1, t2,␣
˓→t3, t4,) = R._first_ngens(4)>>> H.alexander_matrix([t1,t2,t3,t4])(continues on next page)

109

Groups, Release 10.4

(continued from previous page)

[
[
[
[
[

-t2 + 1
-t3 + 1
-t4 + 100

t1 - 100
t1 - 100-t3*t4 + 1
t2 - 1-t4 + 1 -t2*t4 + t2

0
0
t1 - 1t2*t3 - t3
t2*t3 - 1

0]
0]
0]
0]
0]

as_permutation_group(limit=4096000)
Return an isomorphic permutation group.
The generators of the resulting group correspond to the images by the isomorphism of the generators of thegiven group.
INPUT:• limit – integer (default: 4096000); the maximal number of cosets before the computation is aborted
OUTPUT:A Sage PermutationGroup(). If the number of cosets exceeds the given limit, a ValueError isreturned.
EXAMPLES:
sage: G.<a,b> = FreeGroup()
sage: H = G / (a^2, b^3, a*b*~a*~b)sage: H.as_permutation_group()
Permutation Group with generators [(1,2)(3,5)(4,6), (1,3,4)(2,5,6)]
sage: G.<a,b> = FreeGroup()
sage: H = G / [a^3*b]
sage: H.as_permutation_group(limit=1000)
Traceback (most recent call last):...
ValueError: Coset enumeration exceeded limit, is the group finite?
>>> from sage.all import *>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (a**Integer(2), b**Integer(3), a*b*~a*~b)>>> H.as_permutation_group()
Permutation Group with generators [(1,2)(3,5)(4,6), (1,3,4)(2,5,6)]>>> G = FreeGroup(names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / [a**Integer(3)*b]>>> H.as_permutation_group(limit=Integer(1000))
Traceback (most recent call last):...
ValueError: Coset enumeration exceeded limit, is the group finite?

ALGORITHM:
Uses GAP’s coset enumeration on the trivial subgroup.
Warning: This is in general not a decidable problem (in fact, it is not even possible to check if the groupis finite or not). If the group is infinite, or too big, you should be prepared for a long computation that
consumes all the memory without finishing if you do not set a sensible limit.

110

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

cardinality(limit=4096000)
Compute the cardinality of self.
INPUT:• limit – integer (default: 4096000); the maximal number of cosets before the computation is aborted
OUTPUT: integer or Infinity; the number of elements in the group
EXAMPLES:
sage: G.<a,b> = FreeGroup( a, b )sage: H = G / (a^2, b^3, a*b*~a*~b)sage: H.cardinality()
6
sage: F.<a,b,c> = FreeGroup()
sage: J = F / (F([1]), F([2, 2, 2]))sage: J.cardinality()+Infinity>>> from sage.all import *>>> G = FreeGroup( a, b , names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (a**Integer(2), b**Integer(3), a*b*~a*~b)>>> H.cardinality()6>>> F = FreeGroup(names=( a , b , c ,)); (a, b, c,) = F._first_ngens(3)>>> J = F / (F([Integer(1)]), F([Integer(2), Integer(2), Integer(2)]))>>> J.cardinality()+Infinity

ALGORITHM:
Uses GAP.
Warning: This is in general not a decidable problem, so it is not guaranteed to give an answer. If thegroup is infinite, or too big, you should be prepared for a long computation that consumes all the memory
without finishing if you do not set a sensible limit.
characteristic_varieties(ring=Rational Field, matrix_ideal=None, groebner=False)
Return the characteristic varieties of the group self.
There are several definitions of the characteristic varieties of a group 𝐺, see e.g. [CS1999a]. Let Λ be thegroup algebra of 𝐺/𝐺′ and T its associated algebraic variety (a torus). Each element 𝜉 ∈ T defines a local
system of coefficients and the 𝑘-th characteristic variety is
𝑉𝑘 (𝐺) = {𝜉 ∈ T | dim 𝐻 1 (𝐺; 𝜉) ≥ 𝑘}.
These varieties are defined by ideals in Λ.
INPUT:• ring – (default: QQ) the base ring of the group algebra• groebner – boolean (default: False); If set to True the minimal associated primes of the ideals
and their groebner bases are computed; ignored if the base ring is not a field

111

Groups, Release 10.4

OUTPUT:
A dictionary with keys the indices of the varieties. If groebner is False the values are the ideals defining
the characteristic varieties. If it is True, lists for Gröbner bases for the ideal of each irreducible component,
stopping when the first time a characteristic variety is empty.
EXAMPLES:
sage: L = [2*(i, j) + 2* (-i, -j) for i, j in ((1, 2), (2, 3), (3, 1))]
sage: G = FreeGroup(3) / L
sage: G.characteristic_varieties(groebner=True){0: [(0,)],
1: [(f1 - 1, f2 - 1, f3 - 1), (f1*f3 + 1, f2 - 1), (f1*f2 + 1, f3 - 1),␣
˓→(f2*f3 + 1, f1 - 1),(f2*f3 + 1, f1 - f2), (f2*f3 + 1, f1 - f3), (f1*f3 + 1, f2 - f3)],
2: [(f1 - 1, f2 - 1, f3 - 1), (f1 + 1, f2 - 1, f3 - 1), (f1 - 1, f2 - 1, f3␣
˓→+ 1),(f3^2 + 1, f1 - f3, f2 - f3), (f1 - 1, f2 + 1, f3 - 1)],
3: [(f1 - 1, f2 - 1, f3 - 1)],
4: []}
sage: G = FreeGroup(2)/[2*(1,2,-1,-2)]
sage: G.characteristic_varieties(){0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational␣
˓→Field,
1: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Rational Field,
2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Rational Field,
3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational␣
˓→Field}
sage: G.characteristic_varieties(ring=ZZ){0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer␣
˓→Ring,1: Ideal (2*f2 - 2, 2*f1 - 2) of Multivariate Laurent Polynomial Ring in f1,␣˓→f2 over Integer Ring,
2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Integer Ring,
3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer␣
˓→Ring}sage: G = FreeGroup(2)/[(1,2,1,-2,-1,-2)]
sage: G.characteristic_varieties(){0: Ideal (0) of Univariate Laurent Polynomial Ring in f2 over Rational Field,
1: Ideal (-1 + 2*f2 - 2*f2^2 + f2^3) of Univariate Laurent Polynomial Ring␣˓→in f2 over Rational Field,
2: Ideal (1) of Univariate Laurent Polynomial Ring in f2 over Rational Field}
sage: G.characteristic_varieties(groebner=True){0: [0], 1: [-1 + f2, 1 - f2 + f2^2], 2: []}sage: G = FreeGroup(2)/[3 * (1, ), 2 * (2, )]sage: G.characteristic_varieties(groebner=True){0: [-1 + F1, 1 + F1, 1 - F1 + F1^2, 1 + F1 + F1^2], 1: [1 - F1 + F1^2], 2:␣
˓→[]}
sage: G = FreeGroup(2)/[2 * (2, )]sage: G.characteristic_varieties(groebner=True){0: [(f1 + 1,), (f1 - 1,)], 1: [(f1 + 1,), (f1 - 1, f2 - 1)], 2: []}sage: G = (FreeGroup(0) / [])sage: G.characteristic_varieties(){0: Principal ideal (0) of Rational Field,
1: Principal ideal (1) of Rational Field}
sage: G.characteristic_varieties(groebner=True)(continues on next page)

112

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page){0: [(0,)], 1: [(1,)]}>>> from sage.all import *>>> L = [Integer(2)*(i, j) + Integer(2)* (-i, -j) for i, j in ((Integer(1),␣
˓→Integer(2)), (Integer(2), Integer(3)), (Integer(3), Integer(1)))]>>> G = FreeGroup(Integer(3)) / L>>> G.characteristic_varieties(groebner=True){0: [(0,)],
1: [(f1 - 1, f2 - 1, f3 - 1), (f1*f3 + 1, f2 - 1), (f1*f2 + 1, f3 - 1),␣
˓→(f2*f3 + 1, f1 - 1),(f2*f3 + 1, f1 - f2), (f2*f3 + 1, f1 - f3), (f1*f3 + 1, f2 - f3)],
2: [(f1 - 1, f2 - 1, f3 - 1), (f1 + 1, f2 - 1, f3 - 1), (f1 - 1, f2 - 1, f3␣
˓→+ 1),(f3^2 + 1, f1 - f3, f2 - f3), (f1 - 1, f2 + 1, f3 - 1)],
3: [(f1 - 1, f2 - 1, f3 - 1)],
4: []}>>> G = FreeGroup(Integer(2))/[Integer(2)*(Integer(1),Integer(2),-Integer(1),˓→Integer(2))]>>> G.characteristic_varieties(){0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational␣
˓→Field,
1: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Rational Field,
2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Rational Field,
3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational␣
˓→Field}>>> G.characteristic_varieties(ring=ZZ){0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer␣
˓→Ring,1: Ideal (2*f2 - 2, 2*f1 - 2) of Multivariate Laurent Polynomial Ring in f1,␣˓→f2 over Integer Ring,
2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2␣
˓→over Integer Ring,
3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer␣
˓→Ring}>>> G = FreeGroup(Integer(2))/[(Integer(1),Integer(2),Integer(1),-Integer(2),˓→Integer(1),-Integer(2))]>>> G.characteristic_varieties(){0: Ideal (0) of Univariate Laurent Polynomial Ring in f2 over Rational Field,
1: Ideal (-1 + 2*f2 - 2*f2^2 + f2^3) of Univariate Laurent Polynomial Ring␣˓→in f2 over Rational Field,
2: Ideal (1) of Univariate Laurent Polynomial Ring in f2 over Rational Field}>>> G.characteristic_varieties(groebner=True){0: [0], 1: [-1 + f2, 1 - f2 + f2^2], 2: []}>>> G = FreeGroup(Integer(2))/[Integer(3) * (Integer(1), ), Integer(2) *␣˓→(Integer(2), )]>>> G.characteristic_varieties(groebner=True){0: [-1 + F1, 1 + F1, 1 - F1 + F1^2, 1 + F1 + F1^2], 1: [1 - F1 + F1^2], 2:␣
˓→[]}>>> G = FreeGroup(Integer(2))/[Integer(2) * (Integer(2), )]>>> G.characteristic_varieties(groebner=True){0: [(f1 + 1,), (f1 - 1,)], 1: [(f1 + 1,), (f1 - 1, f2 - 1)], 2: []}>>> G = (FreeGroup(Integer(0)) / [])>>> G.characteristic_varieties(){0: Principal ideal (0) of Rational Field,(continues on next page)

113

Groups, Release 10.4

(continued from previous page)1: Principal ideal (1) of Rational Field}>>> G.characteristic_varieties(groebner=True){0: [(0,)], 1: [(1,)]}

direct_product(H, reduced=False, new_names=True)
Return the direct product of self with finitely presented group H.
Calls GAP function DirectProduct, which returns the direct product of a list of groups of any representation.
From [Joh1990] (p. 45, proposition 4): If 𝐺, 𝐻 are groups presented by ⟨𝑋 | 𝑅⟩ and ⟨𝑌 | 𝑆⟩ respectively, then their direct product has the presentation ⟨𝑋, 𝑌 | 𝑅, 𝑆, [𝑋, 𝑌 ]⟩ where [𝑋, 𝑌 ] denotes the set ofcommutators {𝑥−1 𝑦 −1 𝑥𝑦 | 𝑥 ∈ 𝑋, 𝑦 ∈ 𝑌 }.
INPUT:• H – a finitely presented group• reduced – (default: False) boolean; if True, then attempt to reduce the presentation of the productgroup• new_names – (default: True) boolean; If True, then lexicographical variable names are assigned
to the generators of the group to be returned. If False, the group to be returned keeps the generator
names of the two groups forming the direct product. Note that one cannot ask to reduce the output andask to keep the old variable names, as they may change meaning in the output group if its presentationis reduced.
OUTPUT: the direct product of self with H as a finitely presented group
EXAMPLES:
sage: G = FreeGroup()
sage: C12 = ( G / [G([1,1,1,1])] ).direct_product( G / [G([1,1,1])]); C12
Finitely presented group < a, b | a^4, b^3, a^-1*b^-1*a*b >sage: C12.order(), C12.as_permutation_group().is_cyclic()(12, True)
sage: klein = ( G / [G([1,1])] ).direct_product( G / [G([1,1])]); klein
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >sage: klein.order(), klein.as_permutation_group().is_cyclic()(4, False)>>> from sage.all import *>>> G = FreeGroup()>>> C12 = ( G / [G([Integer(1),Integer(1),Integer(1),Integer(1)])] ).direct_
˓→product( G / [G([Integer(1),Integer(1),Integer(1)])]); C12
Finitely presented group < a, b | a^4, b^3, a^-1*b^-1*a*b >>>> C12.order(), C12.as_permutation_group().is_cyclic()(12, True)>>> klein = ( G / [G([Integer(1),Integer(1)])] ).direct_product( G /␣˓→[G([Integer(1),Integer(1)])]); klein
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >>>> klein.order(), klein.as_permutation_group().is_cyclic()(4, False)

We can keep the variable names from self and H to examine how new relations are formed:
sage: F = FreeGroup("a"); G = FreeGroup("g")
sage: X = G / [G.0^12]; A = F / [F.0^6](continues on next page)

114

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

sage: X.direct_product(A, new_names=False)
Finitely presented group < g, a | g^12, a^6, g^-1*a^-1*g*a >sage: A.direct_product(X, new_names=False)
Finitely presented group < a, g | a^6, g^12, a^-1*g^-1*a*g >>>> from sage.all import *>>> F = FreeGroup("a"); G = FreeGroup("g")>>> X = G / [G.gen(0)**Integer(12)]; A = F / [F.gen(0)**Integer(6)]>>> X.direct_product(A, new_names=False)
Finitely presented group < g, a | g^12, a^6, g^-1*a^-1*g*a >>>> A.direct_product(X, new_names=False)
Finitely presented group < a, g | a^6, g^12, a^-1*g^-1*a*g >Or we can attempt to reduce the output group presentation:
sage: F = FreeGroup("a"); G = FreeGroup("g")
sage: X = G / [G.0]; A = F / [F.0]sage: X.direct_product(A, new_names=True)
Finitely presented group < a, b | a, b, a^-1*b^-1*a*b >sage: X.direct_product(A, reduced=True, new_names=True)
Finitely presented group < | >>>> from sage.all import *>>> F = FreeGroup("a"); G = FreeGroup("g")>>> X = G / [G.gen(0)]; A = F / [F.gen(0)]>>> X.direct_product(A, new_names=True)
Finitely presented group < a, b | a, b, a^-1*b^-1*a*b >>>> X.direct_product(A, reduced=True, new_names=True)
Finitely presented group < | >But we cannot do both:
sage: K = FreeGroup([ a , b ])sage: D = K / [K.0^5, K.1^8]
sage: D.direct_product(D, reduced=True, new_names=False)
Traceback (most recent call last):...
ValueError: cannot reduce output and keep old variable names>>> from sage.all import *>>> K = FreeGroup([ a , b ])>>> D = K / [K.gen(0)**Integer(5), K.gen(1)**Integer(8)]>>> D.direct_product(D, reduced=True, new_names=False)
Traceback (most recent call last):...
ValueError: cannot reduce output and keep old variable names

AUTHORS:• Davis Shurbert (2013-07-20): initial version
epimorphisms(H)Return the epimorphisms from self to 𝐻, up to automorphism of 𝐻.
INPUT:• H – another group115

Groups, Release 10.4

EXAMPLES:
sage: F = FreeGroup(3)sage: G = F / [F([1, 2, 3, 1, 2, 3]), F([1, 1, 1])]
sage: H = AlternatingGroup(3)sage: G.epimorphisms(H)[Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> ()x1 |--> (1,3,2)
x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> ()x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> (1,2,3)
x2 |--> (),Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,2,3)
x1 |--> (1,2,3)
x2 |--> (1,2,3)]>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> G = F / [F([Integer(1), Integer(2), Integer(3), Integer(1), Integer(2),␣
˓→Integer(3)]), F([Integer(1), Integer(1), Integer(1)])]>>> H = AlternatingGroup(Integer(3))>>> G.epimorphisms(H)[Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> ()x1 |--> (1,3,2)
x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> ()x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> (1,2,3)
x2 |--> (),Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group(continues on next page)

116

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

Defn: x0 |--> (1,2,3)
x1 |--> (1,2,3)
x2 |--> (1,2,3)]

ALGORITHM:
Uses libgap’s GQuotients function.
free_group()
Return the free group (without relations).
OUTPUT: a FreeGroup()
EXAMPLES:
sage: G.<a,b,c> = FreeGroup()
sage: H = G / (a^2, b^3, a*b*~a*~b)sage: H.free_group()Free Group on generators {a, b, c}
sage: H.free_group() is G
True>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c ,)); (a, b, c,) = G._first_ngens(3)>>> H = G / (a**Integer(2), b**Integer(3), a*b*~a*~b)>>> H.free_group()Free Group on generators {a, b, c}>>> H.free_group() is G
Trueorder(limit=4096000)
Compute the cardinality of self.
INPUT:• limit – integer (default: 4096000); the maximal number of cosets before the computation is aborted
OUTPUT: integer or Infinity; the number of elements in the group
EXAMPLES:
sage: G.<a,b> = FreeGroup( a, b )sage: H = G / (a^2, b^3, a*b*~a*~b)sage: H.cardinality()
6
sage: F.<a,b,c> = FreeGroup()
sage: J = F / (F([1]), F([2, 2, 2]))sage: J.cardinality()+Infinity>>> from sage.all import *>>> G = FreeGroup( a, b , names=( a , b ,)); (a, b,) = G._first_ngens(2)>>> H = G / (a**Integer(2), b**Integer(3), a*b*~a*~b)>>> H.cardinality()6>>> F = FreeGroup(names=( a ,b ,c ,)); (a, b, c,) = F._first_ngens(3)(continues on next page)

117

Groups, Release 10.4

(continued from previous page)>>> J = F / (F([Integer(1)]), F([Integer(2), Integer(2), Integer(2)]))>>> J.cardinality()+Infinity

ALGORITHM:
Uses GAP.
Warning: This is in general not a decidable problem, so it is not guaranteed to give an answer. If thegroup is infinite, or too big, you should be prepared for a long computation that consumes all the memory
without finishing if you do not set a sensible limit.
relations()
Return the relations of the group.
OUTPUT: the relations as a tuple of elements of free_group()
EXAMPLES:
sage: F = FreeGroup(5, x )sage: F.inject_variables()Defining x0, x1, x2, x3, x4
sage: G = F.quotient([x0*x2, x3*x1*x3, x2*x1*x2])
sage: G.relations()(x0*x2, x3*x1*x3, x2*x1*x2)
sage: all(rel in F for rel in G.relations())
True>>> from sage.all import *>>> F = FreeGroup(Integer(5), x )>>> F.inject_variables()Defining x0, x1, x2, x3, x4>>> G = F.quotient([x0*x2, x3*x1*x3, x2*x1*x2])>>> G.relations()(x0*x2, x3*x1*x3, x2*x1*x2)>>> all(rel in F for rel in G.relations())
Truerewriting_system()
Return the rewriting system corresponding to the finitely presented group. This rewriting system can be used
to reduce words with respect to the relations.
If the rewriting system is transformed into a confluent one, the reduction process will give as a result the(unique) reduced form of an element.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F / [a^2,b^3,(a*b/a)^3,b*a*b*a]
sage: k = G.rewriting_system()sage: kRewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→b*a*b*a >with rules:
a^2
--->
1
(continues on next page)

118

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

b^3
--->
1
b*a*b*a--->1
a*b^3*a^-1--->

1

sage: G([1,1,2,2,2])a^2*b^3sage: k.reduce(G([1,1,2,2,2]))
1
sage: k.reduce(G([2,2,1]))b^2*a
sage: k.make_confluent()
sage: k.reduce(G([2,2,1]))
a*b>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F / [a**Integer(2),b**Integer(3),(a*b/a)**Integer(3),b*a*b*a]>>> k = G.rewriting_system()>>> k
Rewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→b*a*b*a >with rules:
a^2
--->
1
b^3
--->
1
b*a*b*a--->1
a*b^3*a^-1--->
1>>> G([Integer(1),Integer(1),Integer(2),Integer(2),Integer(2)])
a^2*b^3>>> k.reduce(G([Integer(1),Integer(1),Integer(2),Integer(2),Integer(2)]))
1>>> k.reduce(G([Integer(2),Integer(2),Integer(1)]))b^2*a>>> k.make_confluent()>>> k.reduce(G([Integer(2),Integer(2),Integer(1)]))a*b

semidirect_product(H, hom, check=True, reduced=False)
The semidirect product of self with H via hom.
If there exists a homomorphism 𝜑 from a group 𝐺 to the automorphism group of a group 𝐻, then we candefine the semidirect product of 𝐺 with 𝐻 via 𝜑 as the Cartesian product of 𝐺 and 𝐻 with the operation(𝑔1 , ℎ1 )(𝑔2 , ℎ2 ) = (𝑔1 𝑔2 , 𝜑(𝑔2 )(ℎ1 )ℎ2 ).
INPUT:• H – Finitely presented group which is implicitly acted on by self and can be naturally embedded as anormal subgroup of the semidirect product.
• hom – Homomorphism from self to the automorphism group of H. Given as a pair, with generators ofself in the first slot and the images of the corresponding generators in the second. These images must
be automorphisms of H, given again as a pair of generators and images.
• check – Boolean (default True). If False the defining homomorphism and automorphism images
are not tested for validity. This test can be costly with large groups, so it can be bypassed if the user isconfident that his morphisms are valid.

119Groups, Release 10.4

• reduced – Boolean (default False). If True then the method attempts to reduce the presentationof the output group.
OUTPUT:
The semidirect product of self with H via hom as a finitely presented group.
See
PermutationGroup_generic.semidirect_product for a more in depth explanation of asemidirect product.
AUTHORS:• Davis Shurbert (8-1-2013)
EXAMPLES:
Group of order 12 as two isomorphic semidirect products:
sage: D4 = groups.presentation.Dihedral(4)sage: C3 = groups.presentation.Cyclic(3)sage: alpha1 = ([C3.gen(0)],[C3.gen(0)])
sage: alpha2 = ([C3.gen(0)],[C3([1,1])])
sage: S1 = D4.semidirect_product(C3, ([D4.gen(1), D4.gen(0)],[alpha1,alpha2]))
sage: C2 = groups.presentation.Cyclic(2)sage: Q = groups.presentation.DiCyclic(3)sage: a = Q([1]); b = Q([-2])sage: alpha = (Q.gens(), [a,b])
sage: S2 = C2.semidirect_product(Q, ([C2.0],[alpha]))sage: S1.is_isomorphic(S2)#I Forcing finiteness test
True>>> from sage.all import *>>> D4 = groups.presentation.Dihedral(Integer(4))>>> C3 = groups.presentation.Cyclic(Integer(3))>>> alpha1 = ([C3.gen(Integer(0))],[C3.gen(Integer(0))])>>> alpha2 = ([C3.gen(Integer(0))],[C3([Integer(1),Integer(1)])])>>> S1 = D4.semidirect_product(C3, ([D4.gen(Integer(1)), D4.gen(Integer(0))],˓→[alpha1,alpha2]))>>> C2 = groups.presentation.Cyclic(Integer(2))>>> Q = groups.presentation.DiCyclic(Integer(3))>>> a = Q([Integer(1)]); b = Q([-Integer(2)])>>> alpha = (Q.gens(), [a,b])>>> S2 = C2.semidirect_product(Q, ([C2.gen(0)],[alpha]))>>> S1.is_isomorphic(S2)#I Forcing finiteness test
True

Dihedral groups can be constructed as semidirect products of cyclic groups:
sage: C2 = groups.presentation.Cyclic(2)sage: C8 = groups.presentation.Cyclic(8)sage: hom = (C2.gens(), [ ([C8([1])], [C8([-1])]) ])sage: D = C2.semidirect_product(C8, hom)sage: D.as_permutation_group().is_isomorphic(DihedralGroup(8))
True>>> from sage.all import *>>> C2 = groups.presentation.Cyclic(Integer(2))>>> C8 = groups.presentation.Cyclic(Integer(8))(continues on next page)

120

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)>>> hom = (C2.gens(), [ ([C8([Integer(1)])], [C8([-Integer(1)])]) ])>>> D = C2.semidirect_product(C8, hom)>>> D.as_permutation_group().is_isomorphic(DihedralGroup(Integer(8)))
True

You can attempt to reduce the presentation of the output group:sage: D = C2.semidirect_product(C8, hom); D
Finitely presented group < a, b | a^2, b^8, a^-1*b*a*b >sage: D = C2.semidirect_product(C8, hom, reduced=True); D
Finitely presented group < a, b | a^2, a*b*a*b, b^8 >sage: C3 = groups.presentation.Cyclic(3)sage: C4 = groups.presentation.Cyclic(4)sage: hom = (C3.gens(), [(C4.gens(), C4.gens())])
sage: C3.semidirect_product(C4, hom)Finitely presented group < a, b | a^3, b^4, a^-1*b*a*b^-1 >sage: D = C3.semidirect_product(C4, hom, reduced=True); D
Finitely presented group < a, b | a^3, b^4, a^-1*b*a*b^-1 >sage: D.as_permutation_group().is_cyclic()True>>> from sage.all import *>>> D = C2.semidirect_product(C8, hom); D
Finitely presented group < a, b | a^2, b^8, a^-1*b*a*b >>>> D = C2.semidirect_product(C8, hom, reduced=True); D
Finitely presented group < a, b | a^2, a*b*a*b, b^8 >>>> C3 = groups.presentation.Cyclic(Integer(3))>>> C4 = groups.presentation.Cyclic(Integer(4))>>> hom = (C3.gens(), [(C4.gens(), C4.gens())])>>> C3.semidirect_product(C4, hom)Finitely presented group < a, b | a^3, b^4, a^-1*b*a*b^-1 >>>> D = C3.semidirect_product(C4, hom, reduced=True); D
Finitely presented group < a, b | a^3, b^4, a^-1*b*a*b^-1 >>>> D.as_permutation_group().is_cyclic()
True

You can turn off the checks for the validity of the input morphisms. This check is expensive but behavior isunpredictable if inputs are invalid and are not caught by these tests:
sage: C5 = groups.presentation.Cyclic(5)sage: C12 = groups.presentation.Cyclic(12)sage: hom = (C5.gens(), [(C12.gens(), C12.gens())])
sage: sp = C5.semidirect_product(C12, hom, check=False); sp
Finitely presented group < a, b | a^5, b^12, a^-1*b*a*b^-1 >sage: sp.as_permutation_group().is_cyclic(), sp.order()(True, 60)>>> from sage.all import *>>> C5 = groups.presentation.Cyclic(Integer(5))>>> C12 = groups.presentation.Cyclic(Integer(12))>>> hom = (C5.gens(), [(C12.gens(), C12.gens())])>>> sp = C5.semidirect_product(C12, hom, check=False); sp
Finitely presented group < a, b | a^5, b^12, a^-1*b*a*b^-1 >>>> sp.as_permutation_group().is_cyclic(), sp.order()(continues on next page)

121

Groups, Release 10.4

(continued from previous page)(True, 60)

simplification_isomorphism()
Return an isomorphism from self to a finitely presented group with a (hopefully) simpler presentation.
EXAMPLES:
sage: G.<a,b,c> = FreeGroup()
sage: H = G / [a*b*c, a*b^2, c*b/c^2]
sage: I = H.simplification_isomorphism()
sage: I
Generic morphism:
From: Finitely presented group < a, b, c | a*b*c, a*b^2, c*b*c^-2 >To:
Finitely presented group < b | >Defn: a |--> b^-2
b |--> bc |--> b
sage: I(a)b^-2
sage: I(b)bsage: I(c)b>>> from sage.all import *>>> G = FreeGroup(names=( a , b , c ,)); (a, b, c,) = G._first_ngens(3)>>> H = G / [a*b*c, a*b**Integer(2), c*b/c**Integer(2)]>>> I = H.simplification_isomorphism()>>> I
Generic morphism:
From: Finitely presented group < a, b, c | a*b*c, a*b^2, c*b*c^-2 >To:
Finitely presented group < b | >Defn: a |--> b^-2
b |--> bc |--> b>>> I(a)b^-2>>> I(b)b>>> I(c)b

ALGORITHM:
Uses GAP.
simplified()
Return an isomorphic group with a (hopefully) simpler presentation.
OUTPUT:
A new finitely presented group. Use simplification_isomorphism() if you want to know theisomorphism.
EXAMPLES:
sage: G.<x,y> = FreeGroup()
sage: H = G / [x ^5, y ^4, y*x*y^3*x ^3](continues on next page)

122

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

sage: H
Finitely presented group < x, y | x^5, y^4, y*x*y^3*x^3 >sage: H.simplified()
Finitely presented group < x, y | y^4, y*x*y^-1*x^-2, x^5 >>>> from sage.all import *>>> G = FreeGroup(names=( x , y ,)); (x, y,) = G._first_ngens(2)>>> H = G / [x **Integer(5), y **Integer(4), y*x*y**Integer(3)*x␣
˓→**Integer(3)]>>> H
Finitely presented group < x, y | x^5, y^4, y*x*y^3*x^3 >>>> H.simplified()
Finitely presented group < x, y | y^4, y*x*y^-1*x^-2, x^5 >A more complicate example:
sage: G.<e0, e1, e2, e3, e4, e5, e6, e7, e8, e9> = FreeGroup()
sage: rels = [e6, e5, e3, e9, e4*e7^-1*e6, e9*e7^-1*e0,....:
e0*e1^-1*e2, e5*e1^-1*e8, e4*e3^-1*e8, e2]
sage: H = G.quotient(rels); H
Finitely presented group < e0, e1, e2, e3, e4, e5, e6, e7, e8, e9 |e6, e5, e3, e9, e4*e7^-1*e6, e9*e7^-1*e0, e0*e1^-1*e2, e5*e1^-1*e8, e4*e3^˓→1*e8, e2 >sage: H.simplified()
Finitely presented group < e0 | e0^2 >>>> from sage.all import *>>> G = FreeGroup(names=( e0 , e1 , e2 , e3 , e4 , e5 , e6 , e7 , e8 ,˓→e9 ,)); (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,) = G._first_ngens(10)>>> rels = [e6, e5, e3, e9, e4*e7**-Integer(1)*e6, e9*e7**-Integer(1)*e0,...
e0*e1**-Integer(1)*e2, e5*e1**-Integer(1)*e8, e4*e3**˓→Integer(1)*e8, e2]>>> H = G.quotient(rels); H
Finitely presented group < e0, e1, e2, e3, e4, e5, e6, e7, e8, e9 |e6, e5, e3, e9, e4*e7^-1*e6, e9*e7^-1*e0, e0*e1^-1*e2, e5*e1^-1*e8, e4*e3^˓→1*e8, e2 >>>> H.simplified()
Finitely presented group < e0 | e0^2 >sorted_presentation()
Return the same presentation with the relations sorted to ensure equality.
OUTPUT: a new finitely presented group with the relations sorted
EXAMPLES:
sage: G = FreeGroup(2) / [(1, 2, -1, -2), ()]; G
Finitely presented group < x0, x1 | x0*x1*x0^-1*x1^-1, 1 >sage: G.sorted_presentation()
Finitely presented group < x0, x1 | 1, x1^-1*x0^-1*x1*x0 >>>> from sage.all import *>>> G = FreeGroup(Integer(2)) / [(Integer(1), Integer(2), -Integer(1), ˓→Integer(2)), ()]; G
Finitely presented group < x0, x1 | x0*x1*x0^-1*x1^-1, 1 >(continues on next page)123

Groups, Release 10.4

(continued from previous page)>>> G.sorted_presentation()
Finitely presented group < x0, x1 | 1, x1^-1*x0^-1*x1*x0 >structure_description(G, latex=False)
Return a string that tries to describe the structure of G.
This methods wraps GAP’s StructureDescription method.
For full details, including the form of the returned string and the algorithm to build it, see GAP’s documentation.
INPUT:• latex – a boolean (default: False); if True, return a LaTeX formatted string
OUTPUT: string
Warning: From GAP’s documentation: The string returned by StructureDescription is not
an isomorphism invariant: non-isomorphic groups can have the same string value, and two isomorphic
groups in different representations can produce different strings.
EXAMPLES:
sage: # needs sage.groups
sage: G = CyclicPermutationGroup(6)sage: G.structure_description()C6
sage: G.structure_description(latex=True)
C_{6}sage: G2 = G.direct_product(G, maps=False)
sage: LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}>>> from sage.all import *>>> # needs sage.groups>>> G = CyclicPermutationGroup(Integer(6))>>> G.structure_description()
C6>>> G.structure_description(latex=True)
C_{6}>>> G2 = G.direct_product(G, maps=False)>>> LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}This method is mainly intended for small groups or groups with few normal subgroups. Even then there aresome surprises:
sage: D3 = DihedralGroup(3)˓→# needs sage.groups
sage: D3.structure_description()˓→# needs sage.groups
S3>>> from sage.all import *>>> D3 = DihedralGroup(Integer(3))␣␣␣(continues on next page)

124

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)# needs sage.groups>>> D3.structure_description()
˓→# needs sage.groups
S3˓→

We use the Sage notation for the degree of dihedral groups:
sage: D4 = DihedralGroup(4)˓→# needs sage.groups
sage: D4.structure_description()˓→# needs sage.groups
D4␣␣>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))˓→# needs sage.groups>>> D4.structure_description()
˓→# needs sage.groups
D4

␣

Works for finitely presented groups (Issue #17573):
sage: F.<x, y> = FreeGroup()˓→# needs sage.groups
sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]˓→# needs sage.groups
sage: G.structure_description()˓→# needs sage.groups
C7

␣
␣
␣

>>> from sage.all import *>>> F = FreeGroup(names=( x , y ,)); (x, y,) = F._first_ngens(2)# needs sage.
˓→groups>>> G = F / [x**Integer(2)*y**-Integer(1), x**Integer(3)*y**Integer(2),␣
˓→x*y*x**-Integer(1)*y**-Integer(1)]# needs␣
˓→sage.groups>>> G.structure_description()
˓→# needs sage.groups
C7

And matrix groups (Issue #17573):
sage: groups.matrix.GL(4,2).structure_description()˓→# needs sage.libs.gap sage.modules
A8␣>>> from sage.all import *>>> groups.matrix.GL(Integer(4),Integer(2)).structure_description()˓→# needs sage.libs.gap sage.modules
A8␣

class sage.groups.finitely_presented.FinitelyPresentedGroupElement(parent, x,
check=True)
Bases: FreeGroupElement
A wrapper of GAP’s Finitely Presented Group elements.
125

Groups, Release 10.4

The elements are created by passing the Tietze list that determines them.
EXAMPLES:
sage: G = FreeGroup( a, b )sage: H = G / [G([1]), G([2, 2, 2])]sage: H([1, 2, 1, -1])
a*b
sage: H([1, 2, 1, -2])
a*b*a*b^-1
sage: x = H([1, 2, -1, -2])
sage: xa*b*a^-1*b^-1
sage: y = H([2, 2, 2, 1, -2, -2, -2])
sage: yb^3*a*b^-3
sage: x*ya*b*a^-1*b^2*a*b^-3
sage: x^(-1)
b*a*b^-1*a^-1>>> from sage.all import *>>> G = FreeGroup( a, b )>>> H = G / [G([Integer(1)]), G([Integer(2), Integer(2), Integer(2)])]>>> H([Integer(1), Integer(2), Integer(1), -Integer(1)])
a*b>>> H([Integer(1), Integer(2), Integer(1), -Integer(2)])
a*b*a*b^-1>>> x = H([Integer(1), Integer(2), -Integer(1), -Integer(2)])>>> x
a*b*a^-1*b^-1>>> y = H([Integer(2), Integer(2), Integer(2), Integer(1), -Integer(2), ˓→Integer(2), -Integer(2)])>>> yb^3*a*b^-3>>> x*ya*b*a^-1*b^2*a*b^-3>>> x**(-Integer(1))
b*a*b^-1*a^-1

Tietze()Return the Tietze list of the element.
The Tietze list of a word is a list of integers that represent the letters in the word. A positive integer 𝑖represents the letter corresponding to the 𝑖-th generator of the group. Negative integers represent the inversesof generators.
OUTPUT: tuple of integers
EXAMPLES:
sage: G = FreeGroup( a, b )sage: H = G / (G([1]), G([2, 2, 2]))sage: H.inject_variables()Defining a, b
sage: a.Tietze()(1,)
sage: x = a^2*b^(-3)*a^(-2)(continues on next page)

126

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

sage: x.Tietze()(1, 1, -2, -2, -2, -1, -1)>>> from sage.all import *>>> G = FreeGroup( a, b )>>> H = G / (G([Integer(1)]), G([Integer(2), Integer(2), Integer(2)]))>>> H.inject_variables()Defining a, b>>> a.Tietze()(1,)>>> x = a**Integer(2)*b**(-Integer(3))*a**(-Integer(2))>>> x.Tietze()(1, 1, -2, -2, -2, -1, -1)class sage.groups.finitely_presented.GroupMorphismWithGensImages
Bases: SetMorphism
Class used for morphisms from finitely presented groups to other groups. It just adds the images of the generators
at the end of the representation.
EXAMPLES:
sage: F = FreeGroup(3)sage: G = F / [F([1, 2, 3, 1, 2, 3]), F([1, 1, 1])]
sage: H = AlternatingGroup(3)sage: HS = G.Hom(H)sage: from sage.groups.finitely_presented import GroupMorphismWithGensImages
sage: GroupMorphismWithGensImages(HS, lambda a: H.one())
Generic morphism:
From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> ()x1 |--> ()x2 |--> ()>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> G = F / [F([Integer(1), Integer(2), Integer(3), Integer(1), Integer(2),␣
˓→Integer(3)]), F([Integer(1), Integer(1), Integer(1)])]>>> H = AlternatingGroup(Integer(3))>>> HS = G.Hom(H)>>> from sage.groups.finitely_presented import GroupMorphismWithGensImages>>> GroupMorphismWithGensImages(HS, lambda a: H.one())
Generic morphism:
From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 >To:
Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> ()x1 |--> ()x2 |--> ()class sage.groups.finitely_presented.RewritingSystem(G)Bases: object
A class that wraps GAP’s rewriting systems.
A rewriting system is a set of rules that allow to transform one word in the group to an equivalent one.

127

Groups, Release 10.4

If the rewriting system is confluent, then the transformed word is a unique reduced form of the element of thegroup.
Warning: Note that the process of making a rewriting system confluent might not end.
INPUT:• G – a group
REFERENCES:• Wikipedia article Knuth-Bendix_completion_algorithm
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F / [a*b/a/b]
sage: k = G.rewriting_system()sage: kRewriting system of Finitely presented group < a, b | a*b*a^-1*b^-1 >with rules:
a*b*a^-1*b^-1--->
1
sage: k.reduce(a*b*a*b)(a*b)^2sage: k.make_confluent()
sage: kRewriting system of Finitely presented group < a, b | a*b*a^-1*b^-1 >with rules:b^-1*a^-1--->a^-1*b^-1b^-1*a--->a*b^-1b*a^-1--->a^-1*bb*a--->
a*b
sage: k.reduce(a*b*a*b)
a^2*b^2>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F / [a*b/a/b]>>> k = G.rewriting_system()>>> k
Rewriting system of Finitely presented group < a, b | a*b*a^-1*b^-1 >with rules:
a*b*a^-1*b^-1--->
1>>> k.reduce(a*b*a*b)(a*b)^2>>> k.make_confluent()>>> k
Rewriting system of Finitely presented group < a, b | a*b*a^-1*b^-1 >with rules:b^-1*a^-1--->a^-1*b^-1b^-1*a--->a*b^-1b*a^-1--->a^-1*bb*a--->a*b(continues on next page)

128

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)>>> k.reduce(a*b*a*b)
a^2*b^2

Todo:• Include support for different orderings (currently only shortlex is used).
• Include the GAP package kbmag for more functionalities, including automatic structures and faster compiled
functions.
AUTHORS:• Miguel Angel Marco Buzunariz (2013-12-16)
finitely_presented_group()
The finitely presented group where the rewriting system is defined.
EXAMPLES:
sage: F = FreeGroup(3)sage: G = F / [ [1,2,3], [-1,-2,-3], [1,1], [2,2] ]sage: k = G.rewriting_system()sage: k.make_confluent()
sage: kRewriting system of Finitely presented group < x0, x1, x2 | x0*x1*x2, x0^˓→1*x1^-1*x2^-1, x0^2, x1^2 >with rules:
x0^-1
--->
x0
x1^-1
--->
x1
x2^-1
--->
x2
x0^2
--->
1
x0*x1
--->
x2
x0*x2
--->
x1
x1*x0
--->
x2
x1^2
--->
1
x1*x2
--->
x0
x2*x0
--->
x1
x2*x1
--->
x0
x2^2
--->
1
sage: k.finitely_presented_group()
Finitely presented group < x0, x1, x2 | x0*x1*x2, x0^-1*x1^-1*x2^-1, x0^2, x1^
˓→2 >>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> G = F / [ [Integer(1),Integer(2),Integer(3)], [-Integer(1),-Integer(2),˓→Integer(3)], [Integer(1),Integer(1)], [Integer(2),Integer(2)] ]>>> k = G.rewriting_system()>>> k.make_confluent()>>> k
Rewriting system of Finitely presented group < x0, x1, x2 | x0*x1*x2, x0^˓→1*x1^-1*x2^-1, x0^2, x1^2 >with rules:
x0^-1
--->
x0
x1^-1
--->
x1
x2^-1
--->
x2
(continues on next page)

129

Groups, Release 10.4

(continued from previous page)

x0^2
--->
1
x0*x1
--->
x2
x0*x2
--->
x1
x1*x0
--->
x2
x1^2
--->
1
x1*x2
--->
x0
x2*x0
--->
x1
x2*x1
--->
x0
x2^2
--->
1
>>> k.finitely_presented_group()
Finitely presented group < x0, x1, x2 | x0*x1*x2, x0^-1*x1^-1*x2^-1, x0^2, x1^
˓→2 >free_group()
The free group after which the rewriting system is defined
EXAMPLES:
sage: F = FreeGroup(3)sage: G = F / [ [1,2,3], [-1,-2,-3] ]sage: k = G.rewriting_system()sage: k.free_group()Free Group on generators {x0, x1, x2}>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> G = F / [ [Integer(1),Integer(2),Integer(3)], [-Integer(1),-Integer(2),˓→Integer(3)] ]>>> k = G.rewriting_system()>>> k.free_group()Free Group on generators {x0, x1, x2}

gap()
The gap representation of the rewriting system.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F/[a*a,b*b]
sage: k = G.rewriting_system()sage: k.gap()
Knuth Bendix Rewriting System for Monoid( [ a, A, b, B ] ) with rules[ [ a*A, <identity ...> ], [ A*a, <identity ...> ],[ b*B, <identity ...> ], [ B*b, <identity ...> ],[ a^2, <identity ...> ], [ b^2, <identity ...> ] ]>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F/[a*a,b*b]>>> k = G.rewriting_system()>>> k.gap()
Knuth Bendix Rewriting System for Monoid( [ a, A, b, B ] ) with rules[ [ a*A, <identity ...> ], [ A*a, <identity ...> ],[ b*B, <identity ...> ], [ B*b, <identity ...> ],[ a^2, <identity ...> ], [ b^2, <identity ...> ] ]130

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

is_confluent()
Return True if the system is confluent and False otherwise.
EXAMPLES:
sage: F = FreeGroup(3)sage: G = F / [F([1,2,1,2,1,3,-1]),F([2,2,2,1,1,2]),F([1,2,3])]
sage: k = G.rewriting_system()sage: k.is_confluent()
False
sage: kRewriting system of Finitely presented group < x0, x1, x2 | (x0*x1)^
˓→2*x0*x2*x0^-1, x1^3*x0^2*x1, x0*x1*x2 >with rules:
x0*x1*x2--->1x1^3*x0^2*x1--->
1(x0*x1)^2*x0*x2*x0^-1--->
1
sage: k.make_confluent()
sage: k.is_confluent()
True
sage: kRewriting system of Finitely presented group < x0, x1, x2 | (x0*x1)^
˓→2*x0*x2*x0^-1, x1^3*x0^2*x1, x0*x1*x2 >with rules:
x0^-1
--->
x0
x1^-1
--->
x1
x0^2
--->
1
x0*x1
--->
x2^-1
x0*x2^-1
--->
x1
x1*x0
--->
x2
x1^2
--->
1
x1*x2^-1
--->
x0*x2
x1*x2
--->
x0
x2^-1*x0--->x0*x2x2^-1*x1
--->
x0
x2^-2
--->
x2
x2*x0
--->
x1
x2*x1
--->
x0*x2
x2^2
--->
x2^-1
>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> G = F / [F([Integer(1),Integer(2),Integer(1),Integer(2),Integer(1),˓→Integer(3),-Integer(1)]),F([Integer(2),Integer(2),Integer(2),Integer(1),˓→Integer(1),Integer(2)]),F([Integer(1),Integer(2),Integer(3)])]>>> k = G.rewriting_system()>>> k.is_confluent()
False
>>> k
Rewriting system of Finitely presented group < x0, x1, x2 | (x0*x1)^
˓→2*x0*x2*x0^-1, x1^3*x0^2*x1, x0*x1*x2 >with rules:
x0*x1*x2--->1x1^3*x0^2*x1--->
1(x0*x1)^2*x0*x2*x0^-1--->
1>>> k.make_confluent()(continues on next page)131

Groups, Release 10.4

(continued from previous page)>>> k.is_confluent()
True
>>> k
Rewriting system of Finitely presented group < x0, x1, x2 | (x0*x1)^
˓→2*x0*x2*x0^-1, x1^3*x0^2*x1, x0*x1*x2 >with rules:
x0^-1
--->
x0
x1^-1
--->
x1
x0^2
--->
1
x0*x1
--->
x2^-1
x0*x2^-1
--->
x1
x1*x0
--->
x2
x1^2
--->
1
x1*x2^-1
--->
x0*x2
x1*x2
--->
x0
x2^-1*x0--->x0*x2x2^-1*x1
--->
x0
x2^-2
--->
x2
x2*x0
--->
x1
x2*x1
--->
x0*x2
x2^2
--->
x2^-1

make_confluent()
Apply the Knuth-Bendix algorithm to try to transform the rewriting system into a confluent one.
Note that this method does not return any object, just changes the rewriting system internally.
Warning: This algorithm is not granted to finish. Although it may be useful in some occasions to run
it, interrupt it manually after some time and use then the transformed rewriting system. Even if it is notconfluent, it could be used to reduce some words.
ALGORITHM:
Uses GAP’s MakeConfluent.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F / [a^2,b^3,(a*b/a)^3,b*a*b*a]
sage: k = G.rewriting_system()sage: kRewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→(b*a)^2 >with rules:
a^2
--->
1
b^3
--->
1
(b*a)^2--->1
a*b^3*a^-1--->
1
sage: k.make_confluent()
sage: kRewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→(b*a)^2 >with rules:
a^-1
--->
a
(continues on next page)

132

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

a^2
--->
1
b^-1*a
--->
a*b
b^-2
--->
b
b*a
--->
a*b^-1
b^2
--->
b^-1
>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F / [a**Integer(2),b**Integer(3),(a*b/a)**Integer(3),b*a*b*a]>>> k = G.rewriting_system()>>> k
Rewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→(b*a)^2 >with rules:
a^2
--->
1
b^3
--->
1
(b*a)^2--->1
a*b^3*a^-1--->
1>>> k.make_confluent()>>> k
Rewriting system of Finitely presented group < a, b | a^2, b^3, a*b^3*a^-1,␣˓→(b*a)^2 >with rules:
a^-1
--->
a
a^2
--->
1
b^-1*a
--->
a*b
b^-2
--->
b
b*a
--->
a*b^-1
b^2
--->
b^-1

reduce(element)
Apply the rules in the rewriting system to the element, to obtain a reduced form.
If the rewriting system is confluent, this reduced form is unique for all words representing the same element.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F/[a^2, b^3, (a*b/a)^3, b*a*b*a]
sage: k = G.rewriting_system()sage: k.reduce(b^4)
bsage: k.reduce(a*b*a)
a*b*a>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F/[a**Integer(2), b**Integer(3), (a*b/a)**Integer(3), b*a*b*a]>>> k = G.rewriting_system()>>> k.reduce(b**Integer(4))
b>>> k.reduce(a*b*a)a*b*arules()
Return the rules that form the rewriting system.
133

Groups, Release 10.4

OUTPUT:
A dictionary containing the rules of the rewriting system. Each key is a word in the free group, and its
corresponding value is the word to which it is reduced.
EXAMPLES:
sage: F.<a,b> = FreeGroup()
sage: G = F / [a*a*a,b*b*a*a]
sage: k = G.rewriting_system()sage: kRewriting system of Finitely presented group < a, b | a^3, b^2*a^2 >with rules:
a^3
--->
1
b^2*a^2--->
1
sage: k.rules(){a^3: 1, b^2*a^2: 1}
sage: k.make_confluent()
sage: sorted(k.rules().items())[(a^-2, a), (a^-1*b^-1, a*b), (a^-1*b, b^-1), (a^2, a^-1),(a*b^-1, b), (b^-1*a^-1, a*b), (b^-1*a, b), (b^-2, a^-1),(b*a^-1, b^-1), (b*a, a*b), (b^2, a)]>>> from sage.all import *>>> F = FreeGroup(names=( a , b ,)); (a, b,) = F._first_ngens(2)>>> G = F / [a*a*a,b*b*a*a]>>> k = G.rewriting_system()>>> k
Rewriting system of Finitely presented group < a, b | a^3, b^2*a^2 >with rules:
a^3
--->
1
b^2*a^2--->
1>>> k.rules(){a^3: 1, b^2*a^2: 1}>>> k.make_confluent()>>> sorted(k.rules().items())[(a^-2, a), (a^-1*b^-1, a*b), (a^-1*b, b^-1), (a^2, a^-1),(a*b^-1, b), (b^-1*a^-1, a*b), (b^-1*a, b), (b^-2, a^-1),(b*a^-1, b^-1), (b*a, a*b), (b^2, a)]sage.groups.finitely_presented.wrap_FpGroup(libgap_fpgroup)
Wrap a GAP finitely presented group.
This function changes the comparison method of libgap_free_group to comparison by Python id. If you
want to put the LibGAP free group into a container (set, dict) then you should understand the implications of_set_compare_by_id(). To be safe, it is recommended that you just work with the resulting Sage FinitelyPresentedGroup.
INPUT:• libgap_fpgroup – a LibGAP finitely presented group
OUTPUT: a Sage FinitelyPresentedGroup
EXAMPLES:First construct a LibGAP finitely presented group:

134

Chapter 10. Finitely Presented Groups

Groups, Release 10.4

sage: F = libgap.FreeGroup([ a , b ])sage: a_cubed = F.GeneratorsOfGroup()[0] ^ 3sage: P = F / libgap([ a_cubed ]);P<fp group of size infinity on the generators [ a, b ]>sage: type(P)<class sage.libs.gap.element.GapElement >>>> from sage.all import *>>> F = libgap.FreeGroup([ a , b ])>>> a_cubed = F.GeneratorsOfGroup()[Integer(0)] ** Integer(3)>>> P = F / libgap([ a_cubed ]);P<fp group of size infinity on the generators [ a, b ]>>>> type(P)<class sage.libs.gap.element.GapElement >Now wrap it:
sage: from sage.groups.finitely_presented import wrap_FpGroupsage: wrap_FpGroup(P)Finitely presented group < a, b | a^3 >>>> from sage.all import *>>> from sage.groups.finitely_presented import wrap_FpGroup>>> wrap_FpGroup(P)Finitely presented group < a, b | a^3 >135

Groups, Release 10.4

136

Chapter 10. Finitely Presented Groups

CHAPTERELEVENNAMED FINITELY PRESENTED GROUPS

Construct groups of small order and “named” groups as quotients of free groups. These groups are available through tabcompletion by typing groups.presentation.<tab> or by importing the required methods. Tab completion ismade available through Sage’s group catalog. Some examples are engineered from entries in [TW1980].
Groups available as finite presentations:• Alternating group, 𝐴𝑛 of order 𝑛!/2 – groups.presentation.Alternating• the 𝑛-fruit Cactus group, a standard notation for which is 𝐽𝑛 – groups.presentation.Cactus• Cyclic group, 𝐶𝑛 of order 𝑛 – groups.presentation.Cyclic• Dicyclic group, nonabelian groups of order 4𝑛 with a unique element of order 2 – groups.presentation.
DiCyclic• Dihedral group, 𝐷𝑛 of order 2𝑛 – groups.presentation.Dihedral• Finitely generated abelian group,

𝑛1 ×

𝑛2 × · · · ×

𝑛𝑘 – groups.presentation.FGAbelian• Finitely generated Heisenberg group – groups.presentation.Heisenberg• Klein four group, 𝐶2 × 𝐶2 – groups.presentation.KleinFour• Quaternion group of order 8 – groups.presentation.Quaternion• Symmetric group, 𝑆𝑛 of order 𝑛! – groups.presentation.Symmetric
AUTHORS:• Davis Shurbert (2013-06-21): initial version
EXAMPLES:
sage: groups.presentation.Cyclic(4)Finitely presented group < a | a^4 >>>> from sage.all import *>>> groups.presentation.Cyclic(Integer(4))
Finitely presented group < a | a^4 >You can also import the desired functions:sage: from sage.groups.finitely_presented_named import CyclicPresentation
sage: CyclicPresentation(4)Finitely presented group < a | a^4 >137

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.finitely_presented_named import CyclicPresentation>>> CyclicPresentation(Integer(4))
Finitely presented group < a | a^4 >sage.groups.finitely_presented_named.AlternatingPresentation(n)Build the Alternating group of order 𝑛!/2 as a finitely presented group.
INPUT:• n – the size of the underlying set of arbitrary symbols being acted on by the Alternating group of order 𝑛!/2
OUTPUT:
Alternating group as a finite presentation, implementation uses GAP to find an isomorphism from a permutation
representation to a finitely presented group representation. Due to this fact, the exact output presentation may not
be the same for every method call on a constant n.
EXAMPLES:
sage: A6 = groups.presentation.Alternating(6)sage: A6.as_permutation_group().is_isomorphic(AlternatingGroup(6)), A6.order()(True, 360)>>> from sage.all import *>>> A6 = groups.presentation.Alternating(Integer(6))>>> A6.as_permutation_group().is_isomorphic(AlternatingGroup(Integer(6))), A6.
˓→order()(True, 360)

sage.groups.finitely_presented_named.BinaryDihedralPresentation(n)Build a binary dihedral group of order 4𝑛 as a finitely presented group.
The binary dihedral group 𝐵𝐷𝑛 has the following presentation (note that there is a typo in [Sun2010]):
𝐵𝐷𝑛 = ⟨𝑥, 𝑦, 𝑧|𝑥2 = 𝑦 2 = 𝑧 𝑛 = 𝑥𝑦𝑧⟩.
INPUT:• n – the value 𝑛
OUTPUT: the binary dihedral group of order 4𝑛 as finite presentation
EXAMPLES:
sage: groups.presentation.BinaryDihedral(9)Finitely presented group < x, y, z | x^-2*y^2, x^-2*z^9, x^-1*y*z >>>> from sage.all import *>>> groups.presentation.BinaryDihedral(Integer(9))
Finitely presented group < x, y, z | x^-2*y^2, x^-2*z^9, x^-1*y*z >sage.groups.finitely_presented_named.CactusPresentation(n)Build the 𝑛-fruit cactus group as a finitely presented group.
OUTPUT: Cactus group 𝐽𝑛 as a finitely presented group
EXAMPLES:

138

Chapter 11. Named Finitely Presented Groups

Groups, Release 10.4

sage: J3 = groups.presentation.Cactus(3); J3
˓→needs sage.graphs
Finitely presented group < s12, s13, s23 |s12^2, s13^2, s23^2, s13*s12*s13^-1*s23^-1, s13*s23*s13^-1*s12^-1 >>>> from sage.all import *>>> J3 = groups.presentation.Cactus(Integer(3)); J3
˓→# needs sage.graphs
Finitely presented group < s12, s13, s23 |s12^2, s13^2, s23^2, s13*s12*s13^-1*s23^-1, s13*s23*s13^-1*s12^-1 >#␣␣sage.groups.finitely_presented_named.CyclicPresentation(n)Build cyclic group of order 𝑛 as a finitely presented group.
INPUT:• n – the order of the cyclic presentation to be returned
OUTPUT: the cyclic group of order 𝑛 as finite presentation
EXAMPLES:
sage: groups.presentation.Cyclic(10)Finitely presented group < a | a^10 >sage: n = 8; C = groups.presentation.Cyclic(n)sage: C.as_permutation_group().is_isomorphic(CyclicPermutationGroup(n))
True>>> from sage.all import *>>> groups.presentation.Cyclic(Integer(10))
Finitely presented group < a | a^10 >>>> n = Integer(8); C = groups.presentation.Cyclic(n)>>> C.as_permutation_group().is_isomorphic(CyclicPermutationGroup(n))
Truesage.groups.finitely_presented_named.DiCyclicPresentation(n)Build the dicyclic group of order 4𝑛, for 𝑛 ≥ 2, as a finitely presented group.
INPUT:• n – positive integer, 2 or greater, determining the order of the group (4𝑛)OUTPUT: the dicyclic group of order 4𝑛 is defined by the presentation⟨𝑎, 𝑥 | 𝑎2𝑛 = 1, 𝑥2 = 𝑎𝑛 , 𝑥−1 𝑎𝑥 = 𝑎−1 ⟩Note: This group is also available as a permutation group via groups.permutation.DiCyclic.
EXAMPLES:
sage: D = groups.presentation.DiCyclic(9); D
Finitely presented group < a, b | a^18, b^2*a^-9, b^-1*a*b*a >sage: D.as_permutation_group().is_isomorphic(groups.permutation.DiCyclic(9))
True

139

Groups, Release 10.4>>> from sage.all import *>>> D = groups.presentation.DiCyclic(Integer(9)); D
Finitely presented group < a, b | a^18, b^2*a^-9, b^-1*a*b*a >>>> D.as_permutation_group().is_isomorphic(groups.permutation.
˓→DiCyclic(Integer(9)))
Truesage.groups.finitely_presented_named.DihedralPresentation(n)Build the Dihedral group of order 2𝑛 as a finitely presented group.
INPUT:• n – the size of the set that 𝐷𝑛 is acting on
OUTPUT: Dihedral group of order 2𝑛EXAMPLES:
sage: D = groups.presentation.Dihedral(7); D
Finitely presented group < a, b | a^7, b^2, (a*b)^2 >sage: D.as_permutation_group().is_isomorphic(DihedralGroup(7))
True>>> from sage.all import *>>> D = groups.presentation.Dihedral(Integer(7)); D
Finitely presented group < a, b | a^7, b^2, (a*b)^2 >>>> D.as_permutation_group().is_isomorphic(DihedralGroup(Integer(7)))
True

sage.groups.finitely_presented_named.FinitelyGeneratedAbelianPresentation(int_list)
Return canonical presentation of finitely generated abelian group.
INPUT:• int_list – list of integers defining the group to be returned, the defining list is reduced to the invariantsof the input list before generating the corresponding group
OUTPUT:
Finitely generated abelian group,
the input list.

𝑛1 ×

𝑛2 × · · · ×

𝑛𝑘 as a finite presentation, where 𝑛𝑖 forms the invariants of

EXAMPLES:
sage: groups.presentation.FGAbelian([2,2])
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >sage: groups.presentation.FGAbelian([2,3])
Finitely presented group < a | a^6 >sage: groups.presentation.FGAbelian([2,4])
Finitely presented group < a, b | a^2, b^4, a^-1*b^-1*a*b >>>> from sage.all import *>>> groups.presentation.FGAbelian([Integer(2),Integer(2)])
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >>>> groups.presentation.FGAbelian([Integer(2),Integer(3)])
Finitely presented group < a | a^6 >>>> groups.presentation.FGAbelian([Integer(2),Integer(4)])
Finitely presented group < a, b | a^2, b^4, a^-1*b^-1*a*b >You can create free abelian groups:
140

Chapter 11. Named Finitely Presented Groups

Groups, Release 10.4

sage: groups.presentation.FGAbelian([0])
Finitely presented group < a | >sage: groups.presentation.FGAbelian([0,0])
Finitely presented group < a, b | a^-1*b^-1*a*b >sage: groups.presentation.FGAbelian([0,0,0])
Finitely presented group < a, b, c | a^-1*b^-1*a*b, a^-1*c^-1*a*c, b^-1*c^-1*b*c >>>> from sage.all import *>>> groups.presentation.FGAbelian([Integer(0)])
Finitely presented group < a | >>>> groups.presentation.FGAbelian([Integer(0),Integer(0)])
Finitely presented group < a, b | a^-1*b^-1*a*b >>>> groups.presentation.FGAbelian([Integer(0),Integer(0),Integer(0)])
Finitely presented group < a, b, c | a^-1*b^-1*a*b, a^-1*c^-1*a*c, b^-1*c^-1*b*c >And various infinite abelian groups:
sage: groups.presentation.FGAbelian([0,2])
Finitely presented group < a, b | a^2, a^-1*b^-1*a*b >sage: groups.presentation.FGAbelian([0,2,2])
Finitely presented group < a, b, c | a^2, b^2, a^-1*b^-1*a*b, a^-1*c^-1*a*c, b^˓→1*c^-1*b*c >>>> from sage.all import *>>> groups.presentation.FGAbelian([Integer(0),Integer(2)])
Finitely presented group < a, b | a^2, a^-1*b^-1*a*b >>>> groups.presentation.FGAbelian([Integer(0),Integer(2),Integer(2)])
Finitely presented group < a, b, c | a^2, b^2, a^-1*b^-1*a*b, a^-1*c^-1*a*c, b^˓→1*c^-1*b*c >Outputs are reduced to minimal generators and relations:sage: groups.presentation.FGAbelian([3,5,2,7,3])
Finitely presented group < a, b | a^3, b^210, a^-1*b^-1*a*b >sage: groups.presentation.FGAbelian([3,210])
Finitely presented group < a, b | a^3, b^210, a^-1*b^-1*a*b >>>> from sage.all import *>>> groups.presentation.FGAbelian([Integer(3),Integer(5),Integer(2),Integer(7),˓→Integer(3)])
Finitely presented group < a, b | a^3, b^210, a^-1*b^-1*a*b >>>> groups.presentation.FGAbelian([Integer(3),Integer(210)])Finitely presented group < a, b | a^3, b^210, a^-1*b^-1*a*b >The trivial group is an acceptable output:
sage: groups.presentation.FGAbelian([])
Finitely presented group < | >sage: groups.presentation.FGAbelian([1])
Finitely presented group < | >sage: groups.presentation.FGAbelian([1,1,1,1,1,1,1,1,1,1])
Finitely presented group < | >>>> from sage.all import *>>> groups.presentation.FGAbelian([])
Finitely presented group < | >(continues on next page)141

Groups, Release 10.4

(continued from previous page)>>> groups.presentation.FGAbelian([Integer(1)])
Finitely presented group < | >>>> groups.presentation.FGAbelian([Integer(1),Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)])
Finitely presented group < | >Input list must consist of positive integers:
sage: groups.presentation.FGAbelian([2,6,3,9,-4])Traceback (most recent call last):...
ValueError: input list must contain nonnegative entries
sage: groups.presentation.FGAbelian([2, a ,4])Traceback (most recent call last):...
TypeError: unable to convert a to an integer>>> from sage.all import *>>> groups.presentation.FGAbelian([Integer(2),Integer(6),Integer(3),Integer(9),˓→Integer(4)])
Traceback (most recent call last):...
ValueError: input list must contain nonnegative entries>>> groups.presentation.FGAbelian([Integer(2), a ,Integer(4)])
Traceback (most recent call last):...
TypeError: unable to convert a to an integer

sage.groups.finitely_presented_named.FinitelyGeneratedHeisenbergPresentation(n=1,p=0)
Return a finite presentation of the Heisenberg group.
The Heisenberg group is the group of (𝑛 + 2) × (𝑛 + 2) matrices over a ring 𝑅 with diagonal elements equal to 1,
first row and last column possibly nonzero, and all the other entries equal to zero.
INPUT:• n – the degree of the Heisenberg group• p – (optional) a prime number, where we construct the Heisenberg group over the finite field /𝑝
OUTPUT: finitely generated Heisenberg group over the finite field of order p or over the integers
See also:
HeisenbergGroup
EXAMPLES:
sage: H = groups.presentation.Heisenberg(); H
Finitely presented group < x1, y1, z |x1*y1*x1^-1*y1^-1*z^-1, z*x1*z^-1*x1^-1, z*y1*z^-1*y1^-1 >sage: H.order()+Infinity
sage: r1, r2, r3 = H.relations()
sage: A = matrix([[1, 1, 0], [0, 1, 0], [0, 0, 1]])
sage: B = matrix([[1, 0, 0], [0, 1, 1], [0, 0, 1]])
sage: C = matrix([[1, 0, 1], [0, 1, 0], [0, 0, 1]])
(continues on next page)

142

Chapter 11. Named Finitely Presented Groups

Groups, Release 10.4

(continued from previous page)

sage: r1(A, B, C)[1 0 0][0 1 0][0 0 1]
sage: r2(A, B, C)[1 0 0][0 1 0][0 0 1]
sage: r3(A, B, C)[1 0 0][0 1 0][0 0 1]
sage: p = 3
sage: Hp = groups.presentation.Heisenberg(p=3)
sage: Hp.order() == p**3
True
sage: Hnp = groups.presentation.Heisenberg(n=2, p=3)
sage: len(Hnp.relations())
13>>> from sage.all import *>>> H = groups.presentation.Heisenberg(); H
Finitely presented group < x1, y1, z |x1*y1*x1^-1*y1^-1*z^-1, z*x1*z^-1*x1^-1, z*y1*z^-1*y1^-1 >>>> H.order()+Infinity>>> r1, r2, r3 = H.relations()>>> A = matrix([[Integer(1), Integer(1), Integer(0)], [Integer(0), Integer(1),␣
˓→Integer(0)], [Integer(0), Integer(0), Integer(1)]])>>> B = matrix([[Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(1),␣
˓→Integer(1)], [Integer(0), Integer(0), Integer(1)]])>>> C = matrix([[Integer(1), Integer(0), Integer(1)], [Integer(0), Integer(1),␣
˓→Integer(0)], [Integer(0), Integer(0), Integer(1)]])>>> r1(A, B, C)[1 0 0][0 1 0][0 0 1]>>> r2(A, B, C)[1 0 0][0 1 0][0 0 1]>>> r3(A, B, C)[1 0 0][0 1 0][0 0 1]>>> p = Integer(3)>>> Hp = groups.presentation.Heisenberg(p=Integer(3))>>> Hp.order() == p**Integer(3)True>>> Hnp = groups.presentation.Heisenberg(n=Integer(2), p=Integer(3))>>> len(Hnp.relations())
13

REFERENCES:• Wikipedia article Heisenberg_group
sage.groups.finitely_presented_named.KleinFourPresentation()143

Groups, Release 10.4

Build the Klein group of order 4 as a finitely presented group.
OUTPUT: Klein four group (𝐶2 × 𝐶2 ) as a finitely presented group
EXAMPLES:
sage: K = groups.presentation.KleinFour(); K
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >>>> from sage.all import *>>> K = groups.presentation.KleinFour(); K
Finitely presented group < a, b | a^2, b^2, a^-1*b^-1*a*b >sage.groups.finitely_presented_named.QuaternionPresentation()
Build the Quaternion group of order 8 as a finitely presented group.
OUTPUT: Quaternion group as a finite presentation
EXAMPLES:
sage: Q = groups.presentation.Quaternion(); Q
Finitely presented group < a, b | a^4, b^2*a^-2, a*b*a*b^-1 >sage: Q.as_permutation_group().is_isomorphic(QuaternionGroup())
True>>> from sage.all import *>>> Q = groups.presentation.Quaternion(); Q
Finitely presented group < a, b | a^4, b^2*a^-2, a*b*a*b^-1 >>>> Q.as_permutation_group().is_isomorphic(QuaternionGroup())
True

sage.groups.finitely_presented_named.SymmetricPresentation(n)Build the Symmetric group of order 𝑛! as a finitely presented group.
INPUT:• n – the size of the underlying set of arbitrary symbols being acted on by the Symmetric group of order 𝑛!
OUTPUT:
Symmetric group as a finite presentation, implementation uses GAP to find an isomorphism from a permutation
representation to a finitely presented group representation. Due to this fact, the exact output presentation may not
be the same for every method call on a constant n.
EXAMPLES:
sage: S4 = groups.presentation.Symmetric(4)sage: S4.as_permutation_group().is_isomorphic(SymmetricGroup(4))
True>>> from sage.all import *>>> S4 = groups.presentation.Symmetric(Integer(4))>>> S4.as_permutation_group().is_isomorphic(SymmetricGroup(Integer(4)))
True

144

Chapter 11. Named Finitely Presented Groups

CHAPTERTWELVEBRAID GROUPS

Braid groups are implemented as a particular case of finitely presented groups, but with a lot of specific methods for
braids.
A braid group can be created by giving the number of strands, and the name of the generators:
sage: BraidGroup(3)Braid group on 3 strands
sage: BraidGroup(3, a )Braid group on 3 strands
sage: BraidGroup(3, a ).gens()(a0, a1)
sage: BraidGroup(3, a,b ).gens()(a, b)>>> from sage.all import *>>> BraidGroup(Integer(3))
Braid group on 3 strands>>> BraidGroup(Integer(3), a )Braid group on 3 strands>>> BraidGroup(Integer(3), a ).gens()(a0, a1)>>> BraidGroup(Integer(3), a,b ).gens()(a, b)The elements can be created by operating with the generators, or by passing a list with the indices of the letters to thegroup:
sage: B.<s0,s1,s2> = BraidGroup(4)sage: s0*s1*s0
s0*s1*s0
sage: B([1,2,1])s0*s1*s0>>> from sage.all import *>>> B = BraidGroup(Integer(4), names=( s0 ,˓→ngens(3)>>> s0*s1*s0
s0*s1*s0>>> B([Integer(1),Integer(2),Integer(1)])
s0*s1*s0s1 ,s2 ,)); (s0, s1, s2,) = B._first_

The mapping class action of the braid group over the free group is also implemented, see MappingClassGroupAction for an explanation. This action is left multiplication of a free group element by a braid:145

Groups, Release 10.4

sage: B.<b0,b1,b2> = BraidGroup()
sage: F.<f0,f1,f2,f3> = FreeGroup()
sage: B.strands() == F.rank()# necessary for the action to be definedTrue
sage: f1 * b1
f1*f2*f1^-1
sage: f0 * b1f0
sage: f1 * b1
f1*f2*f1^-1
sage: f1^-1 * b1
f1*f2^-1*f1^-1>>> from sage.all import *>>> B = BraidGroup(names=( b0 , b1 , b2 ,)); (b0, b1, b2,) = B._first_ngens(3)>>> F = FreeGroup(names=( f0 , f1 , f2 , f3 ,)); (f0, f1, f2, f3,) = F._first_
˓→ngens(4)>>> B.strands() == F.rank()# necessary for the action to be definedTrue>>> f1 * b1
f1*f2*f1^-1>>> f0 * b1
f0>>> f1 * b1
f1*f2*f1^-1>>> f1**-Integer(1) * b1
f1*f2^-1*f1^-1

AUTHORS:• Miguel Angel Marco Buzunariz• Volker Braun• Søren Fuglede Jørgensen• Robert Lipshitz• Thierry Monteil: add a __hash__ method consistent with the word problem to ensure correct Cayley graphcomputations.
• Sebastian Oehms (July and Nov 2018): add other versions for burau_matrix (unitary + simple, see Issue #25760
and Issue #26657)• Moritz Firsching (Sept 2021): Colored Jones polynomial• Sebastian Oehms (May 2022): add links_gould_polynomial()
class sage.groups.braid.Braid(parent, x, check=True)
Bases: FiniteTypeArtinGroupElement
An element of a braid group.
It is a particular case of element of a finitely presented group.
EXAMPLES:
sage: B.<s0,s1,s2> = BraidGroup(4)sage: B
Braid group on 4 strands
sage: s0*s1/s2/s1(continues on next page)

146

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)s0*s1*s2^-1*s1^-1
sage: B((1, 2, -3, -2))s0*s1*s2^-1*s1^-1>>> from sage.all import *>>> B = BraidGroup(Integer(4), names=( s0 , s1 , s2 ,)); (s0, s1, s2,) = B._
˓→first_ngens(3)>>> B
Braid group on 4 strands>>> s0*s1/s2/s1
s0*s1*s2^-1*s1^-1>>> B((Integer(1), Integer(2), -Integer(3), -Integer(2)))
s0*s1*s2^-1*s1^-1

LKB_matrix(variables='x,y')
Return the Lawrence-Krammer-Bigelow representation matrix.
The matrix is expressed in the basis {𝑒𝑖,𝑗 | 1 ≤ 𝑖 < 𝑗 ≤ 𝑛}, where the indices are ordered lexicographically.
It is a matrix whose entries are in the ring of Laurent polynomials on the given variables. By default, thevariables are x and y .
INPUT:• variables – string (default: x,y ). A string containing the names of the variables, separated by acomma.
OUTPUT: the matrix corresponding to the Lawrence-Krammer-Bigelow representation of the braid
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1, 2, 1])
sage: b.LKB_matrix()[
0 -x^4*y + x^3*y[0-x^3*y[-x^2*y x^3*y - x^2*ysage: c = B([2, 1, 2])
sage: c.LKB_matrix()[
0 -x^4*y + x^3*y[0-x^3*y[-x^2*y x^3*y - x^2*y-x^4*y]0]0]-x^4*y]0]0]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), Integer(1)])>>> b.LKB_matrix()[
0 -x^4*y + x^3*y-x^4*y][0-x^3*y0][-x^2*y x^3*y - x^2*y0]>>> c = B([Integer(2), Integer(1), Integer(2)])>>> c.LKB_matrix()[
0 -x^4*y + x^3*y-x^4*y][0-x^3*y0][-x^2*y x^3*y - x^2*y0]

REFERENCES:• [Big2003]
147

Groups, Release 10.4

TL_matrix(drain_size, variab=None, sparse=True)
Return the matrix representation of the Temperley–Lieb–Jones representation of the braid in a certain basis.
The basis is given by non-intersecting pairings of (𝑛 + 𝑑) points, where 𝑛 is the number of strands, 𝑑 is given
by drain_size, and the pairings satisfy certain rules. See TL_basis_with_drain() for details.
We use the convention that the eigenvalues of the standard generators are 1 and −𝐴4 , where 𝐴 is a variableof a Laurent polynomial ring.
When 𝑑 = 𝑛 − 2 and the variables are picked appropriately, the resulting representation is equivalent to the
reduced Burau representation.
INPUT:• drain_size – integer between 0 and the number of strands (both inclusive)• variab – variable (default: None); the variable in the entries of the matrices; if None, then use adefault variable in [𝐴, 𝐴−1 ]• sparse – boolean (default: True); whether or not the result should be given as a sparse matrix
OUTPUT:
The matrix of the TL representation of the braid.
The parameter sparse can be set to False if it is expected that the resulting matrix will not be sparse.
We currently make no attempt at guessing this.
EXAMPLES:
Let us calculate a few examples for 𝐵4 with 𝑑 = 0:
sage: B = BraidGroup(4)sage: b = B([1, 2, -3])
sage: b.TL_matrix(0)[1 - A^4-A^-2][-A^6
0]
sage: R.<x> = LaurentPolynomialRing(GF(2))
sage: b.TL_matrix(0, variab=x)[1 + x^4
x^-2]
[
x^6
0]
sage: b = B([])
sage: b.TL_matrix(0)
[1 0]
[0 1]
>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), -Integer(3)])>>> b.TL_matrix(Integer(0))[1 - A^4-A^-2][-A^6
0]>>> R = LaurentPolynomialRing(GF(Integer(2)), names=( x ,)); (x,) = R._first_
˓→ngens(1)>>> b.TL_matrix(Integer(0), variab=x)[1 + x^4
x^-2]
[
x^6
0]
>>> b = B([])>>> b.TL_matrix(Integer(0))
[1 0]
[0 1]

148

Chapter 12. Braid groups

Groups, Release 10.4

Test of one of the relations in 𝐵8 :sage: B = BraidGroup(8)sage: d = 0
sage: B([4,5,4]).TL_matrix(d) == B([5,4,5]).TL_matrix(d)True>>> from sage.all import *>>> B = BraidGroup(Integer(8))>>> d = Integer(0)>>> B([Integer(4),Integer(5),Integer(4)]).TL_matrix(d) == B([Integer(5),˓→Integer(4),Integer(5)]).TL_matrix(d)TrueAn element of the kernel of the Burau representation, following [Big1999]:
sage: B = BraidGroup(6)sage: psi1 = B([4, -5, -2, 1])
sage: psi2 = B([-4, 5, 5, 2, -1, -1])
sage: w1 = psi1^(-1) * B([3]) * psi1
sage: w2 = psi2^(-1) * B([3]) * psi2
sage: (w1 * w2 * w1^(-1) * w2^(-1)).TL_matrix(4)[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]>>> from sage.all import *>>> B = BraidGroup(Integer(6))>>> psi1 = B([Integer(4), -Integer(5), -Integer(2), Integer(1)])>>> psi2 = B([-Integer(4), Integer(5), Integer(5), Integer(2), -Integer(1), ˓→Integer(1)])>>> w1 = psi1**(-Integer(1)) * B([Integer(3)]) * psi1>>> w2 = psi2**(-Integer(1)) * B([Integer(3)]) * psi2>>> (w1 * w2 * w1**(-Integer(1)) * w2**(-Integer(1))).TL_matrix(Integer(4))[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]

REFERENCES:• [Big1999]• [Jon2005]
alexander_polynomial(var='t', normalized=True)
Return the Alexander polynomial of the closure of the braid.
INPUT:• var – string (default: t ); the name of the variable in the entries of the matrix• normalized – boolean (default: True); whether to return the normalized Alexander polynomial
OUTPUT:
The Alexander polynomial of the braid closure of the braid.

149

Groups, Release 10.4

This is computed using the reduced Burau representation. The unnormalized Alexander polynomial is a
Laurent polynomial, which is only well-defined up to multiplication by plus or minus times a power of 𝑡.
We normalize the polynomial by dividing by the largest power of 𝑡 and then if the resulting constant coefficientis negative, we multiply by −1.
EXAMPLES:
We first construct the trefoil:
sage: B = BraidGroup(3)sage: b = B([1,2,1,2])
sage: b.alexander_polynomial(normalized=False)
1 - t + t^2
sage: b.alexander_polynomial()t^-2 - t^-1 + 1>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1),Integer(2),Integer(1),Integer(2)])>>> b.alexander_polynomial(normalized=False)
1 - t + t^2>>> b.alexander_polynomial()t^-2 - t^-1 + 1

Next we construct the figure 8 knot:
sage: b = B([-1,2,-1,2])
sage: b.alexander_polynomial(normalized=False)-t^-2 + 3*t^-1 - 1
sage: b.alexander_polynomial()t^-2 - 3*t^-1 + 1>>> from sage.all import *>>> b = B([-Integer(1),Integer(2),-Integer(1),Integer(2)])>>> b.alexander_polynomial(normalized=False)-t^-2 + 3*t^-1 - 1>>> b.alexander_polynomial()t^-2 - 3*t^-1 + 1

Our last example is the Kinoshita-Terasaka knot:
sage: B = BraidGroup(4)sage: b = B([1,1,1,3,3,2,-3,-1,-1,2,-1,-3,-2])
sage: b.alexander_polynomial(normalized=False)-t^-1
sage: b.alexander_polynomial()
1>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1),Integer(1),Integer(1),Integer(3),Integer(3),Integer(2),˓→Integer(3),-Integer(1),-Integer(1),Integer(2),-Integer(1),-Integer(3),˓→Integer(2)])>>> b.alexander_polynomial(normalized=False)-t^-1>>> b.alexander_polynomial()
1150

Chapter 12. Braid groups

Groups, Release 10.4

REFERENCES:• Wikipedia article Alexander_polynomial
annular_khovanov_complex(qagrad=None, ring=None)
Return the annular Khovanov complex of the closure of a braid, as defined in [BG2013]
INPUT:• qagrad – tuple of quantum and annular grading for which to compute the chain complex. If not
specified all gradings are computed.
• ring – (default: ZZ) the coefficient ring.
OUTPUT:
The annular Khovanov complex of the braid, given as a dictionary whose keys are tuples of quantum andannular grading. If qagrad is specified only return the chain complex of that grading.
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1,-2,1,-2])
sage: C = b.annular_khovanov_complex()
sage: C{(-5, -1): Chain complex with at most 1 nonzero terms over Integer Ring,(-3, -3): Chain complex with at most 1 nonzero terms over Integer Ring,(-3, -1): Chain complex with at most 2 nonzero terms over Integer Ring,(-3, 1): Chain complex with at most 1 nonzero terms over Integer Ring,(-1, -1): Chain complex with at most 5 nonzero terms over Integer Ring,(-1, 1): Chain complex with at most 2 nonzero terms over Integer Ring,(1, -1): Chain complex with at most 2 nonzero terms over Integer Ring,(1, 1): Chain complex with at most 5 nonzero terms over Integer Ring,(3, -1): Chain complex with at most 1 nonzero terms over Integer Ring,(3, 1): Chain complex with at most 2 nonzero terms over Integer Ring,(3, 3): Chain complex with at most 1 nonzero terms over Integer Ring,(5, 1): Chain complex with at most 1 nonzero terms over Integer Ring}sage: C[1,-1].homology(){1: Z x Z, 2: 0}>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1),-Integer(2),Integer(1),-Integer(2)])>>> C = b.annular_khovanov_complex()>>> C{(-5, -1): Chain complex with at most 1 nonzero terms over Integer Ring,(-3, -3): Chain complex with at most 1 nonzero terms over Integer Ring,(-3, -1): Chain complex with at most 2 nonzero terms over Integer Ring,(-3, 1): Chain complex with at most 1 nonzero terms over Integer Ring,(-1, -1): Chain complex with at most 5 nonzero terms over Integer Ring,(-1, 1): Chain complex with at most 2 nonzero terms over Integer Ring,(1, -1): Chain complex with at most 2 nonzero terms over Integer Ring,(1, 1): Chain complex with at most 5 nonzero terms over Integer Ring,(3, -1): Chain complex with at most 1 nonzero terms over Integer Ring,(3, 1): Chain complex with at most 2 nonzero terms over Integer Ring,(3, 3): Chain complex with at most 1 nonzero terms over Integer Ring,(5, 1): Chain complex with at most 1 nonzero terms over Integer Ring}>>> C[Integer(1),-Integer(1)].homology(){1: Z x Z, 2: 0}151

Groups, Release 10.4

annular_khovanov_homology(qagrad=None, ring=Integer Ring)
Return the annular Khovanov homology of a closure of a braid.
INPUT:• qagrad – (optional) tuple of quantum and annular grading for which to compute the homology• ring – (default: ZZ) the coefficient ring
OUTPUT:If qagrad is None, return a dictionary of homologies in all gradings indexed by grading. If qagrad is
specified, return the homology of that grading.
Note: This is a simple wrapper around annular_khovanov_complex() to compute homology fromit.
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([1,3,-2])
sage: b.annular_khovanov_homology(){(-3, -4): {0: Z},(-3, -2): {-1: Z},(-1, -2): {-1: 0, 0: Z x Z x Z, 1: 0},(-1, 0): {-1: Z x Z},(1, -2): {1: Z x Z},(1, 0): {-1: 0, 0: Z x Z x Z x Z, 1: 0, 2: 0},(1, 2): {-1: Z},(3, 0): {1: Z x Z x Z, 2: 0},(3, 2): {-1: 0, 0: Z x Z x Z, 1: 0},(5, 0): {2: Z},(5, 2): {1: Z x Z},(5, 4): {0: Z}}
sage: B = BraidGroup(2)sage: b = B([1,1,1])
sage: b.annular_khovanov_homology((7,0)){2: 0, 3: C2}>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1),Integer(3),-Integer(2)])>>> b.annular_khovanov_homology(){(-3, -4): {0: Z},(-3, -2): {-1: Z},(-1, -2): {-1: 0, 0: Z x Z x Z, 1: 0},(-1, 0): {-1: Z x Z},(1, -2): {1: Z x Z},(1, 0): {-1: 0, 0: Z x Z x Z x Z, 1: 0, 2: 0},(1, 2): {-1: Z},(3, 0): {1: Z x Z x Z, 2: 0},(3, 2): {-1: 0, 0: Z x Z x Z, 1: 0},(5, 0): {2: Z},(5, 2): {1: Z x Z},(5, 4): {0: Z}}(continues on next page)

152

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)>>> B = BraidGroup(Integer(2))>>> b = B([Integer(1),Integer(1),Integer(1)])>>> b.annular_khovanov_homology((Integer(7),Integer(0))){2: 0, 3: C2}

burau_matrix(var='t', reduced=False)
Return the Burau matrix of the braid.
INPUT:• var – string (default: t ); the name of the variable in the entries of the matrix• reduced – boolean (default: False); whether to return the reduced or unreduced Burau representation, can be one of the following:– True or increasing – returns the reduced form using the basis given by 𝑒1 −𝑒𝑖 for 2 ≤ 𝑖 ≤ 𝑛–unitary – the unitary form according to Squier [Squ1984]–

simple – returns the reduced form using the basis given by simple roots 𝑒𝑖 − 𝑒𝑖+1 , which yields
the matrices given on the Wikipedia page

OUTPUT:
The Burau matrix of the braid. It is a matrix whose entries are Laurent polynomials in the variable var. If
reduced is True, return the matrix for the reduced Burau representation instead in the format specified.
If reduced is unitary , a triple M, Madj, H is returned, where M is the Burau matrix in the unitaryform, Madj the adjoined to M and H the hermitian form.
EXAMPLES:
sage: B = BraidGroup(4)sage: B.inject_variables()Defining s0, s1, s2
sage: b = s0*s1/s2/s1
sage: b.burau_matrix()
[
1 - t
0
t - t^2
[
1
0
0
[
0
0
1
[
0
t^-2 -t^-2 + t^-1
sage: s2.burau_matrix( x )
[
1
0
0
0]
[
0
1
0
0]
[
0
0 1 - x
x]
[
0
0
1
0]
sage: s0.burau_matrix(reduced=True)[-t 0 0][-t 1 0][-t 0 1]>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> B.inject_variables()Defining s0, s1, s2>>> b = s0*s1/s2/s1>>> b.burau_matrix()
[
1 - t
0
[
1
0
[
0
0

t - t^2
0
1

t^2]
0]
0]
-t^-1 + 1]

t^2]
0]
0]
(continues on next page)

153

Groups, Release 10.4

(continued from previous page)[0
t^-2 -t^-2 + t^-1>>> s2.burau_matrix( x )
[
1
0
0
0]
[
0
1
0
0]
[
0
0 1 - x
x]
[
0
0
1
0]
>>> s0.burau_matrix(reduced=True)[-t 0 0][-t 1 0][-t 0 1]-t^-1 + 1]

Using the different reduced forms:
sage: b.burau_matrix(reduced= simple )[1 - t -t^-1 + 1-1][
1 -t^-1 + 1
-1]
[
1
-t^-1
0]
sage: M, Madj, H = b.burau_matrix(reduced= unitary )sage: M[-t^-2 + 1tt^2][ t^-1 - t
1 - t^2
-t^3]
[
-t^-2
-t^-1
0]
sage: Madj
[ 1 - t^2 -t^-1 + t-t^2][t^-1 -t^-2 + 1
-t]
[
t^-2
-t^-3
0]
sage: H[t^-1 + t
-1
0][
-1 t^-1 + t-1][
0-1 t^-1 + t]
sage: M * H * Madj == H
True>>> from sage.all import *>>> b.burau_matrix(reduced= simple )[1 - t -t^-1 + 1-1][
1 -t^-1 + 1
-1]
[
1
-t^-1
0]
>>> M, Madj, H = b.burau_matrix(reduced= unitary )>>> M[-t^-2 + 1tt^2][ t^-1 - t
1 - t^2
-t^3]
[
-t^-2
-t^-1
0]
>>> Madj[ 1 - t^2 -t^-1 + t-t^2][t^-1 -t^-2 + 1
-t]
[
t^-2
-t^-3
0]
>>> H
[t^-1 + t
-1
0][
-1 t^-1 + t-1][
0-1 t^-1 + t]>>> M * H * Madj == H
True

REFERENCES:
154

Chapter 12. Braid groups

Groups, Release 10.4

• Wikipedia article Burau_representation• [Squ1984]
centralizer()
Return a list of generators of the centralizer of the braid.
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([2, 1, 3, 2])
sage: b.centralizer()[s1*s0*s2*s1, s0*s2]>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(2), Integer(1), Integer(3), Integer(2)])>>> b.centralizer()[s1*s0*s2*s1, s0*s2]

colored_jones_polynomial(N, variab=None, try_inverse=True)
Return the colored Jones polynomial of the trace closure of the braid.
INPUT:• N – integer; the number of colors• variab – (default: 𝑞) the variable in the resulting Laurent polynomial• try_inverse – boolean (default: True); if True, attempt a faster calculation by using the inverseof the braid
ALGORITHM:
The algorithm used is described in [HL2018]. We follow their notation, but work in a suitable free algebra
over a Laurent polynomial ring in one variable to simplify bookkeeping.
EXAMPLES:
sage: trefoil = BraidGroup(2)([1,1,1])
sage: trefoil.colored_jones_polynomial(2)q + q^3 - q^4sage: trefoil.colored_jones_polynomial(4)q^3 + q^7 - q^10 + q^11 - q^13 - q^14 + q^15 - q^17
+ q^19 + q^20 - q^21
sage: trefoil.inverse().colored_jones_polynomial(4)-q^-21 + q^-20 + q^-19 - q^-17 + q^-15 - q^-14 - q^-13+ q^-11 - q^-10 + q^-7 + q^-3
sage: figure_eight = BraidGroup(3)([-1, 2, -1, 2])
sage: figure_eight.colored_jones_polynomial(2)q^-2 - q^-1 + 1 - q + q^2
sage: figure_eight.colored_jones_polynomial(3, Q )Q^-6 - Q^-5 - Q^-4 + 2*Q^-3 - Q^-2 - Q^-1 + 3 - Q - Q^2+ 2*Q^3 - Q^4 - Q^5 + Q^6>>> from sage.all import *>>> trefoil = BraidGroup(Integer(2))([Integer(1),Integer(1),Integer(1)])>>> trefoil.colored_jones_polynomial(Integer(2))
q + q^3 - q^4(continues on next page)

155

Groups, Release 10.4

(continued from previous page)>>> trefoil.colored_jones_polynomial(Integer(4))
q^3 + q^7 - q^10 + q^11 - q^13 - q^14 + q^15 - q^17
+ q^19 + q^20 - q^21>>> trefoil.inverse().colored_jones_polynomial(Integer(4))-q^-21 + q^-20 + q^-19 - q^-17 + q^-15 - q^-14 - q^-13+ q^-11 - q^-10 + q^-7 + q^-3>>> figure_eight = BraidGroup(Integer(3))([-Integer(1), Integer(2), ˓→Integer(1), Integer(2)])>>> figure_eight.colored_jones_polynomial(Integer(2))
q^-2 - q^-1 + 1 - q + q^2>>> figure_eight.colored_jones_polynomial(Integer(3), Q )Q^-6 - Q^-5 - Q^-4 + 2*Q^-3 - Q^-2 - Q^-1 + 3 - Q - Q^2+ 2*Q^3 - Q^4 - Q^5 + Q^6components_in_closure()
Return the number of components of the trace closure of the braid.
OUTPUT: a positive integer
EXAMPLES:
sage: B = BraidGroup(5)sage: b = B([1, -3]) # Three disjoint unknots
sage: b.components_in_closure()3
sage: b = B([1, 2, 3, 4]) # The unknot
sage: b.components_in_closure()
1
sage: B = BraidGroup(4)sage: K11n42 = B([1, -2, 3, -2, 3, -2, -2, -1, 2, -3, -3, 2, 2])
sage: K11n42.components_in_closure()1>>> from sage.all import *>>> B = BraidGroup(Integer(5))>>> b = B([Integer(1), -Integer(3)]) # Three disjoint unknots>>> b.components_in_closure()3>>> b = B([Integer(1), Integer(2), Integer(3), Integer(4)]) # The unknot>>> b.components_in_closure()
1>>> B = BraidGroup(Integer(4))>>> K11n42 = B([Integer(1), -Integer(2), Integer(3), -Integer(2), Integer(3),␣
˓→-Integer(2), -Integer(2), -Integer(1), Integer(2), -Integer(3), -Integer(3),˓→ Integer(2), Integer(2)])>>> K11n42.components_in_closure()
1

conjugating_braid(other)
Return a conjugating braid, if it exists.
INPUT:• other – a braid in the same braid group as self
OUTPUT:
A conjugating braid. More precisely, if the output is 𝑑, 𝑜 equals other, and 𝑠 equals self then 𝑜 = 𝑑−1 ·𝑠·𝑑.
156

Chapter 12. Braid groups

Groups, Release 10.4

EXAMPLES:
sage: B = BraidGroup(3)sage: B.one().conjugating_braid(B.one())
1
sage: B.one().conjugating_braid(B.gen(0)) is None
True
sage: B.gen(0).conjugating_braid(B.gen(1))
s1*s0sage: B.gen(0).conjugating_braid(B.gen(1).inverse()) is None
True
sage: a = B([2, 2, -1, -1])
sage: b = B([2, 1, 2, 1])
sage: c = b * a / b
sage: d1 = a.conjugating_braid(c)sage: d1s1*s0
sage: d1 * c / d1 == aTruesage: d1 * a / d1 == cFalse
sage: l = sage.groups.braid.conjugatingbraid(a,c)˓→needs sage.groups
sage: d1 == B._element_from_libbraiding(l)˓→needs sage.groupsTrue
sage: b = B([2, 2, 2, 2, 1])
sage: c = b * a / b
sage: d1 = a.conjugating_braid(c)sage: len(d1.Tietze())
7
sage: d1 * c / d1 == aTruesage: d1 * a / d1 == cFalse
sage: d1s1^2*s0^2*s1^2*s0
sage: l = sage.groups.braid.conjugatingbraid(a,c)˓→needs sage.groups
sage: d2 = B._element_from_libbraiding(l)˓→needs sage.groups
sage: len(d2.Tietze())
˓→needs sage.groups13
sage: c.conjugating_braid(b) is None
True

#␣
#␣

#␣
#␣
#␣

>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> B.one().conjugating_braid(B.one())
1>>> B.one().conjugating_braid(B.gen(Integer(0))) is None
True>>> B.gen(Integer(0)).conjugating_braid(B.gen(Integer(1)))
s1*s0>>> B.gen(Integer(0)).conjugating_braid(B.gen(Integer(1)).inverse()) is None
True>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1)])(continues on next page)

157

Groups, Release 10.4

(continued from previous page)>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> c = b * a / b>>> d1 = a.conjugating_braid(c)>>> d1s1*s0>>> d1 * c / d1 == aTrue>>> d1 * a / d1 == c
False>>> l = sage.groups.braid.conjugatingbraid(a,c)˓→needs sage.groups>>> d1 == B._element_from_libbraiding(l)˓→needs sage.groupsTrue>>> b = B([Integer(2), Integer(2), Integer(2), Integer(2), Integer(1)])>>> c = b * a / b>>> d1 = a.conjugating_braid(c)>>> len(d1.Tietze())
7>>> d1 * c / d1 == aTrue>>> d1 * a / d1 == c
False>>> d1s1^2*s0^2*s1^2*s0>>> l = sage.groups.braid.conjugatingbraid(a,c)˓→needs sage.groups>>> d2 = B._element_from_libbraiding(l)˓→needs sage.groups>>> len(d2.Tietze())
˓→needs sage.groups13>>> c.conjugating_braid(b) is None
True

#␣
#␣

#␣
#␣
#␣

deformed_burau_matrix(variab='q')
Return the deformed Burau matrix of the braid.
INPUT:• variab – variable (default: q); the variable in the resulting laurent polynomial, which is the base ringfor the free algebra constructed
OUTPUT: a matrix with elements in the free algebra self._algebra
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([1, 2, -3, -2, 3, 1])
sage: db = b.deformed_burau_matrix(); db[
ap_0*ap_5 ... bp_0*ap_1*cm_3*bp_4]...
[
bm_2*bm_3*cp_5 ...
bm_2*am_3*bp_4]>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), -Integer(3), -Integer(2), Integer(3),␣
(continues on next page)

158

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)

Integer(1)])>>> db = b.deformed_burau_matrix(); db[
ap_0*ap_5 ... bp_0*ap_1*cm_3*bp_4]...
[
bm_2*bm_3*cp_5 ...
bm_2*am_3*bp_4]
˓→

We check how this relates to the nondeformed Burau matrix:
sage: def subs_gen(gen, q):....:
gen_str = str(gen)....:v = q if p in gen_str else 1/q....:
if b in gen_str:....:
return v....:
elif a in gen_str:....:
return 1 - v
....:
else:
....:
return 1
sage: db_base = db.parent().base_ring()sage: q = db_base.base_ring().gen()sage: db_simp = db.subs({gen: subs_gen(gen, q)....:
for gen in db_base.gens()})
sage: db_simp[ (1-2*q+q^2)(q-q^2) (q-q^2+q^3)(q^2-q^3)]
[
(1-q)
q
0
0]
[
0
0
(1-q)
q]
[
(q^-2)
0 -(q^-2-q^-1)-(q^-1-1)]
sage: burau = b.burau_matrix(); burau[1 - 2*t + t^2t - t^2 t - t^2 + t^3t^2 - t^3]
[
1 - t
t
0
0]
[
0
0
1 - t
t]
[
t^-2
0 -t^-2 + t^-1
-t^-1 + 1]
sage: t = burau.parent().base_ring().gen()sage: burau.subs({t:q}).change_ring(db_base) == db_simp
True>>> from sage.all import *>>> def subs_gen(gen, q):...
gen_str = str(gen)...
v = q if p in gen_str else Integer(1)/q...
if b in gen_str:...
return v...
elif a in gen_str:...
return Integer(1) - v
...
else:
...
return Integer(1)>>> db_base = db.parent().base_ring()>>> q = db_base.base_ring().gen()>>> db_simp = db.subs({gen: subs_gen(gen, q)...
for gen in db_base.gens()})>>> db_simp[ (1-2*q+q^2)(q-q^2) (q-q^2+q^3)(q^2-q^3)]
[
(1-q)
q
0
0]
[
0
0
(1-q)
q]
[
(q^-2)
0 -(q^-2-q^-1)-(q^-1-1)]>>> burau = b.burau_matrix(); burau[1 - 2*t + t^2t - t^2 t - t^2 + t^3t^2 - t^3](continues on next page)

159

Groups, Release 10.4

(continued from previous page)

[
1 - t
t
0
0]
[
0
0
1 - t
t]
[
t^-2
0 -t^-2 + t^-1
-t^-1 + 1]>>> t = burau.parent().base_ring().gen()>>> burau.subs({t:q}).change_ring(db_base) == db_simp
True

gcd(other)
Return the greatest common divisor of the two braids.
INPUT:• other – the other braid with respect with the gcd is computed
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1, 2, -1, -2, -2, 1])
sage: c = B([1, 2, 1])
sage: b.gcd(c)s0^-1*s1^-1*s0^-2*s1^2*s0
sage: c.gcd(b)s0^-1*s1^-1*s0^-2*s1^2*s0>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), -Integer(1), -Integer(2), -Integer(2),␣
˓→Integer(1)])>>> c = B([Integer(1), Integer(2), Integer(1)])>>> b.gcd(c)s0^-1*s1^-1*s0^-2*s1^2*s0>>> c.gcd(b)s0^-1*s1^-1*s0^-2*s1^2*s0

is_conjugated(other)
Check if the two braids are conjugated.
INPUT:• other – the other braid to check for conjugacy
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1])
sage: b = B([2, 1, 2, 1])
sage: c = b * a / b
sage: c.is_conjugated(a)Truesage: c.is_conjugated(b)False>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1)])>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> c = b * a / b(continues on next page)

160

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)>>> c.is_conjugated(a)True>>> c.is_conjugated(b)False

is_periodic()
Check whether the braid is periodic.
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1, 2, 2])
sage: b = B([2, 1, 2, 1])
sage: a.is_periodic()
False
sage: b.is_periodic()True>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> a.is_periodic()
False>>> b.is_periodic()True

is_pseudoanosov()Check if the braid is pseudo-anosov.
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1, 2, 2])
sage: b = B([2, 1, 2, 1])
sage: a.is_pseudoanosov()True
sage: b.is_pseudoanosov()False>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> a.is_pseudoanosov()True>>> b.is_pseudoanosov()
False

is_reducible()
Check whether the braid is reducible.
EXAMPLES:

161

Groups, Release 10.4

sage: B = BraidGroup(3)sage: b = B([1, 2, -1])
sage: b.is_reducible()True
sage: a = B([2, 2, -1, -1, 2, 2])
sage: a.is_reducible()
False>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), -Integer(1)])>>> b.is_reducible()True>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> a.is_reducible()
False

jones_polynomial(variab=None, skein_normalization=False)
Return the Jones polynomial of the trace closure of the braid.
The normalization is so that the unknot has Jones polynomial 1. If skein_normalization is True, thevariable of the result is replaced by a itself to the power of 4, so that the result agrees with the conventionsof [Lic1997] (which in particular differs slightly from the conventions used otherwise in this class), had oneused the conventional Kauffman bracket variable notation directly.
If variab is None return a polynomial in the variable 𝐴 or 𝑡, depending on the value skein_normalization. In particular, if skein_normalization is False, return the result in terms of the variable𝑡, also used in [Lic1997].
INPUT:• variab – variable (default: None); the variable in the resulting polynomial; if unspecified, use either
a default variable in [𝐴, 𝐴−1 ] or the variable 𝑡 in the symbolic ring• skein_normalization – boolean (default: False); determines the variable of the resulting polynomial
OUTPUT:
If skein_normalization if False, this returns an element in the symbolic ring as the Jones polynomialof the closure might have fractional powers when the closure of the braid is not a knot. Otherwise the result
is a Laurent polynomial in variab.
EXAMPLES:
The unknot:
sage: B = BraidGroup(9)sage: b = B([1, 2, 3, 4, 5, 6, 7, 8])
sage: b.jones_polynomial()
˓→needs sage.symbolic1#␣>>> from sage.all import *>>> B = BraidGroup(Integer(9))>>> b = B([Integer(1), Integer(2), Integer(3), Integer(4), Integer(5),␣
˓→Integer(6), Integer(7), Integer(8)])>>> b.jones_polynomial()#␣(continues on next page)

162

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)needs sage.symbolic˓→1

Two unlinked unknots:
sage: B = BraidGroup(2)sage: b = B([])
sage: b.jones_polynomial()
˓→needs sage.symbolic-sqrt(t) - 1/sqrt(t)>>> from sage.all import *>>> B = BraidGroup(Integer(2))>>> b = B([])>>> b.jones_polynomial()
˓→needs sage.symbolic-sqrt(t) - 1/sqrt(t)#␣#␣The Hopf link:
sage: B = BraidGroup(2)sage: b = B([-1,-1])
sage: b.jones_polynomial()
˓→needs sage.symbolic-1/sqrt(t) - 1/t^(5/2)>>> from sage.all import *>>> B = BraidGroup(Integer(2))>>> b = B([-Integer(1),-Integer(1)])>>> b.jones_polynomial()
˓→needs sage.symbolic-1/sqrt(t) - 1/t^(5/2)#␣#␣

Different representations of the trefoil and one of its mirror:
sage: # needs sage.symbolic
sage: B = BraidGroup(2)sage: b = B([-1, -1, -1])
sage: b.jones_polynomial(skein_normalization=True)-A^-16 + A^-12 + A^-4
sage: b.jones_polynomial()
1/t + 1/t^3 - 1/t^4
sage: B = BraidGroup(3)sage: b = B([-1, -2, -1, -2])
sage: b.jones_polynomial(skein_normalization=True)-A^-16 + A^-12 + A^-4
sage: R.<x> = LaurentPolynomialRing(GF(2))
sage: b.jones_polynomial(skein_normalization=True, variab=x)x^-16 + x^-12 + x^-4
sage: B = BraidGroup(3)sage: b = B([1, 2, 1, 2])
sage: b.jones_polynomial(skein_normalization=True)
A^4 + A^12 - A^16>>> from sage.all import *>>> # needs sage.symbolic(continues on next page)163

Groups, Release 10.4

(continued from previous page)>>> B = BraidGroup(Integer(2))>>> b = B([-Integer(1), -Integer(1), -Integer(1)])>>> b.jones_polynomial(skein_normalization=True)-A^-16 + A^-12 + A^-4>>> b.jones_polynomial()
1/t + 1/t^3 - 1/t^4>>> B = BraidGroup(Integer(3))>>> b = B([-Integer(1), -Integer(2), -Integer(1), -Integer(2)])>>> b.jones_polynomial(skein_normalization=True)-A^-16 + A^-12 + A^-4>>> R = LaurentPolynomialRing(GF(Integer(2)), names=( x ,)); (x,) = R._first_
˓→ngens(1)>>> b.jones_polynomial(skein_normalization=True, variab=x)x^-16 + x^-12 + x^-4>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), Integer(1), Integer(2)])>>> b.jones_polynomial(skein_normalization=True)
A^4 + A^12 - A^16

K11n42 (the mirror of the “Kinoshita-Terasaka” knot) and K11n34 (the mirror of the “Conway” knot):sage: B = BraidGroup(4)sage: b11n42 = B([1, -2, 3, -2, 3, -2, -2, -1, 2, -3, -3, 2, 2])
sage: b11n34 = B([1, 1, 2, -3, 2, -3, 1, -2, -2, -3, -3])
sage: bool(b11n42.jones_polynomial() == b11n34.jones_polynomial())˓→needs sage.symbolic
True

#␣

>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b11n42 = B([Integer(1), -Integer(2), Integer(3), -Integer(2), Integer(3),␣
˓→-Integer(2), -Integer(2), -Integer(1), Integer(2), -Integer(3), -Integer(3),˓→ Integer(2), Integer(2)])>>> b11n34 = B([Integer(1), Integer(1), Integer(2), -Integer(3), Integer(2), ˓→Integer(3), Integer(1), -Integer(2), -Integer(2), -Integer(3), -Integer(3)])>>> bool(b11n42.jones_polynomial() == b11n34.jones_polynomial())#␣˓→needs sage.symbolicTruelcm(other)
Return the least common multiple of the two braids.
INPUT:• other – the other braid with respect with the lcm is computed
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1, 2, -1, -2, -2, 1])
sage: c = B([1, 2, 1])
sage: b.lcm(c)(s0*s1)^2*s0>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), -Integer(1), -Integer(2), -Integer(2),␣
(continues on next page)

164

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)

Integer(1)])>>> c = B([Integer(1), Integer(2), Integer(1)])>>> b.lcm(c)(s0*s1)^2*s0
˓→left_normal_form(algorithm='libbraiding')
Return the left normal form of the braid.
INPUT:• algorithm – string (default: artin ); must be one of the following:–artin – the general method for Artin groups is used–libbraiding – the algorithm from the libbraiding package

OUTPUT:
A tuple of simple generators in the left normal form. The first element is a power of Δ, and the rest areelements of the natural section lift from the corresponding symmetric group.
EXAMPLES:
sage: B = BraidGroup(6)sage: B.one().left_normal_form()(1,)
sage: b = B([-2, 2, -4, -4, 4, -5, -1, 4, -1, 1])
sage: L1 = b.left_normal_form(); L1(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^˓→1*s1^-1*s0^-1,
s0*s2*s1*s0*s3*s2*s1*s0*s4*s3*s2*s1,
s3)
sage: L1 == b.left_normal_form()True
sage: B([1]).left_normal_form(algorithm= artin )(1, s0)sage: B([-3]).left_normal_form(algorithm= artin )(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^˓→1*s1^-1*s0^-1,
s0*s1*s2*s3*s4*s0*s1*s2*s3*s1*s2*s0*s1*s0)
sage: B = BraidGroup(3)sage: B([1,2,-1]).left_normal_form()(s0^-1*s1^-1*s0^-1, s1*s0, s0*s1)
sage: B([1,2,1]).left_normal_form()(s0*s1*s0,)>>> from sage.all import *>>> B = BraidGroup(Integer(6))>>> B.one().left_normal_form()(1,)>>> b = B([-Integer(2), Integer(2), -Integer(4), -Integer(4), Integer(4), ˓→Integer(5), -Integer(1), Integer(4), -Integer(1), Integer(1)])>>> L1 = b.left_normal_form(); L1(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^˓→1*s1^-1*s0^-1,
s0*s2*s1*s0*s3*s2*s1*s0*s4*s3*s2*s1,
s3)>>> L1 == b.left_normal_form()(continues on next page)165

Groups, Release 10.4

(continued from previous page)

True>>> B([Integer(1)]).left_normal_form(algorithm= artin )(1, s0)>>> B([-Integer(3)]).left_normal_form(algorithm= artin )(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^˓→1*s1^-1*s0^-1,
s0*s1*s2*s3*s4*s0*s1*s2*s3*s1*s2*s0*s1*s0)>>> B = BraidGroup(Integer(3))>>> B([Integer(1),Integer(2),-Integer(1)]).left_normal_form()(s0^-1*s1^-1*s0^-1, s1*s0, s0*s1)>>> B([Integer(1),Integer(2),Integer(1)]).left_normal_form()(s0*s1*s0,)

links_gould_matrix(symbolics=False)
Return the representation matrix of self according to the R-matrix representation being attached to thequantum superalgebra sl𝑞 (2|1). See [MW2012], section 3 and references given there.
INPUT:• symbolics – boolean (default False). If set to True the coefficients will be contained in the symbolic ring. Per default they are elements of a quotient ring of a three variate Laurent polynomial ring.
OUTPUT: the representation matrix of self over the ring according to the choice of the keyword symbolics (see the corresponding explanation)
EXAMPLES:
sage: Hopf = BraidGroup(2)([-1, -1])
sage: HopfLG = Hopf.links_gould_matrix()
sage: HopfLG.dimensions()(16, 16)
sage: HopfLG.base_ring()
Univariate Quotient Polynomial Ring in Yrbar
over Multivariate Laurent Polynomial Ring in s0r, s1r
over Integer Ring with modulus Yr^2 + s0r^2*s1r^2 - s0r^2 - s1r^2 + 1
sage: HopfLGs = Hopf.links_gould_matrix(symbolics=True)
˓→needs sage.symbolic
sage: HopfLGs.base_ring()
˓→needs sage.symbolic
Symbolic Ring>>> from sage.all import *>>> Hopf = BraidGroup(Integer(2))([-Integer(1), -Integer(1)])>>> HopfLG = Hopf.links_gould_matrix()>>> HopfLG.dimensions()(16, 16)>>> HopfLG.base_ring()
Univariate Quotient Polynomial Ring in Yrbar
over Multivariate Laurent Polynomial Ring in s0r, s1r
over Integer Ring with modulus Yr^2 + s0r^2*s1r^2 - s0r^2 - s1r^2 + 1>>> HopfLGs = Hopf.links_gould_matrix(symbolics=True)
˓→needs sage.symbolic>>> HopfLGs.base_ring()
˓→needs sage.symbolic
Symbolic Ring

#␣
#␣

#␣
#␣

links_gould_polynomial(varnames=None, use_symbolics=False)

166

Chapter 12. Braid groups

Groups, Release 10.4

Return the Links-Gould polynomial of the closure of self. See [MW2012], section 3 and references given
there.
INPUT:• varnames – string (default t0, t1)
OUTPUT: a Laurent polynomial in the given variable names
EXAMPLES:
sage: Hopf = BraidGroup(2)([-1, -1])
sage: Hopf.links_gould_polynomial()-1 + t1^-1 + t0^-1 - t0^-1*t1^-1
sage: _ == Hopf.links_gould_polynomial(use_symbolics=True)
True
sage: Hopf.links_gould_polynomial(varnames= a, b )-1 + b^-1 + a^-1 - a^-1*b^-1
sage: _ == Hopf.links_gould_polynomial(varnames= a, b , use_symbolics=True)
True>>> from sage.all import *>>> Hopf = BraidGroup(Integer(2))([-Integer(1), -Integer(1)])>>> Hopf.links_gould_polynomial()-1 + t1^-1 + t0^-1 - t0^-1*t1^-1>>> _ == Hopf.links_gould_polynomial(use_symbolics=True)
True>>> Hopf.links_gould_polynomial(varnames= a, b )-1 + b^-1 + a^-1 - a^-1*b^-1>>> _ == Hopf.links_gould_polynomial(varnames= a, b , use_symbolics=True)
True

REFERENCES:• [MW2012]
markov_trace(variab=None, normalized=True)
Return the Markov trace of the braid.
The normalization is so that in the underlying braid group representation, the eigenvalues of the standard
generators of the braid group are 1 and −𝐴4 .
INPUT:• variab – variable (default: None); the variable in the resulting polynomial; if None, then use thevariable 𝐴 in [𝐴, 𝐴−1 ]• normalized – boolean (default: True); if specified to be False, return instead a rescaled Laurent
polynomial version of the Markov trace
OUTPUT:
If normalized is False, return instead the Markov trace of the braid, normalized by a factor of (𝐴2 +𝐴−2 )𝑛 . The result is then a Laurent polynomial in variab. Otherwise it is a quotient of Laurent polynomials
in variab.
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([1, 2, -3])
sage: mt = b.markov_trace(); mt(continues on next page)

167

Groups, Release 10.4

(continued from previous page)A^4/(A^12 + 3*A^8 + 3*A^4 + 1)
sage: mt.factor()
A^4 * (A^4 + 1)^-3>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), -Integer(3)])>>> mt = b.markov_trace(); mt
A^4/(A^12 + 3*A^8 + 3*A^4 + 1)>>> mt.factor()
A^4 * (A^4 + 1)^-3

We now give the non-normalized Markov trace:
sage: mt = b.markov_trace(normalized=False); mt
A^-4 + 1
sage: mt.parent()
Univariate Laurent Polynomial Ring in A over Integer Ring>>> from sage.all import *>>> mt = b.markov_trace(normalized=False); mt
A^-4 + 1>>> mt.parent()
Univariate Laurent Polynomial Ring in A over Integer Ring

mirror_image()
Return the image of self under the mirror involution (see BraidGroup_class.
mirror_involution()). The link closure of it is mirrored to the closure of self (see theexample below of a positive amphicheiral knot).
EXAMPLES:
sage: B5 = BraidGroup(5)sage: b = B5((-1, 2, -3, -1, -3, 4, 2, -3, 2, 4, 2, -3)) # closure K12a_427
sage: bm = b.mirror_image(); bm
s0*s1^-1*s2*s0*s2*s3^-1*s1^-1*s2*s1^-1*s3^-1*s1^-1*s2
sage: bm.is_conjugated(b)Truesage: bm.is_conjugated(~b)
False>>> from sage.all import *>>> B5 = BraidGroup(Integer(5))>>> b = B5((-Integer(1), Integer(2), -Integer(3), -Integer(1), -Integer(3),␣
˓→Integer(4), Integer(2), -Integer(3), Integer(2), Integer(4), Integer(2), ˓→Integer(3))) # closure K12a_427>>> bm = b.mirror_image(); bm
s0*s1^-1*s2*s0*s2*s3^-1*s1^-1*s2*s1^-1*s3^-1*s1^-1*s2>>> bm.is_conjugated(b)True>>> bm.is_conjugated(~b)
False

permutation(W=None)
Return the permutation induced by the braid in its strands.

168

Chapter 12. Braid groups

Groups, Release 10.4

INPUT:• W – (optional) the permutation group to project self to; the default is self.parent().
coxeter_group()
OUTPUT: the image of self under the natural projection map to W
EXAMPLES:
sage: B.<s0,s1,s2> = BraidGroup()
sage: S = SymmetricGroup(4)sage: b = s0*s1/s2/s1
sage: c0 = b.permutation(W=S); c0(1,4,2)sage: c1 = b.permutation(W=Permutations(4)); c1[4, 1, 3, 2]
sage: c1 == b.permutation()
True>>> from sage.all import *>>> B = BraidGroup(names=( s0 , s1 , s2 ,)); (s0, s1, s2,) = B._first_
˓→ngens(3)>>> S = SymmetricGroup(Integer(4))>>> b = s0*s1/s2/s1>>> c0 = b.permutation(W=S); c0(1,4,2)>>> c1 = b.permutation(W=Permutations(Integer(4))); c1[4, 1, 3, 2]>>> c1 == b.permutation()
True

The canonical section from the symmetric group to the braid group (sending a permutation to its associatedpermutation braid) can be recovered:
sage: B(c0)s0*s1*s2*s1
sage: B(c0) == B(c1)True>>> from sage.all import *>>> B(c0)s0*s1*s2*s1>>> B(c0) == B(c1)
True

plot(color='rainbow', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds)
Plot the braid
The following options are available:• color – (default: rainbow ) the color of the strands. Possible values are:–rainbow , uses rainbow() according to the number of strands.

– a valid color name for bezier_path() and line(). Used for all strands.
– a list or a tuple of colors for each individual strand.
• orientation – (default: bottom-top ) determines how the braid is printed. The possible values
are:

169

Groups, Release 10.4–

bottom-top , the braid is printed from bottom to top–

top-bottom , the braid is printed from top to bottom–

left-right , the braid is printed from left to right• gap – floating point number (default: 0.05). determines the size of the gap left when a strand goes underanother.
• aspect_ratio – floating point number (default: 1). The aspect ratio.
• **kwds – other keyword options that are passed to bezier_path() and line().
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1])
sage: b = B([2, 1, 2, 1])
sage: c = b * a / b
sage: d = a.conjugating_braid(c)sage: d * c / d == aTruesage: ds1*s0
sage: d * a / d == cFalse
sage: B = BraidGroup(4, s )sage: b = B([1, 2, 3, 1, 2, 1])
sage: b.plot()
˓→needs sage.plot
Graphics object consisting of 30 graphics primitives
sage: b.plot(color=["red", "blue", "red", "blue"])
˓→needs sage.plot
Graphics object consisting of 30 graphics primitives#␣#␣

sage: B.<s,t> = BraidGroup(3)sage: b = t^-1*s^2
sage: b.plot(orientation="left-right", color="red")
˓→needs sage.plot
Graphics object consisting of 12 graphics primitives#␣>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1)])>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> c = b * a / b>>> d = a.conjugating_braid(c)>>> d * c / d == a
True
>>> d
s1*s0
>>> d * a / d == c
False>>> B = BraidGroup(Integer(4), s )>>> b = B([Integer(1), Integer(2), Integer(3), Integer(1), Integer(2),␣
˓→Integer(1)])>>> b.plot()
˓→needs sage.plot
Graphics object consisting of 30 graphics primitives>>> b.plot(color=["red", "blue", "red", "blue"])#␣#␣(continues on next page)

170

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)needs sage.plot
Graphics object consisting of 30 graphics primitives
˓→>>> B = BraidGroup(Integer(3), names=( s , t ,)); (s, t,) = B._first_ngens(2)>>> b = t**-Integer(1)*s**Integer(2)>>> b.plot(orientation="left-right", color="red")#␣˓→needs sage.plot
Graphics object consisting of 12 graphics primitives

plot3d(color='rainbow')
Plots the braid in 3d.
The following option is available:• color – (default: rainbow ) the color of the strands. Possible values are:–rainbow , uses rainbow() according to the number of strands.

– a valid color name for bezier3d(). Used for all strands.
– a list or a tuple of colors for each individual strand.
EXAMPLES:
sage: B = BraidGroup(4, s )sage: b = B([1, 2, 3, 1, 2, 1])
sage: b.plot3d()
˓→needs sage.plot sage.symbolic
Graphics3d Object
sage: b.plot3d(color="red")
˓→needs sage.plot sage.symbolic
Graphics3d Object
sage: b.plot3d(color=["red", "blue", "red", "blue"])
˓→needs sage.plot sage.symbolic
Graphics3d Object>>> from sage.all import *>>> B = BraidGroup(Integer(4), s )>>> b = B([Integer(1), Integer(2), Integer(3), Integer(1), Integer(2),␣
˓→Integer(1)])>>> b.plot3d()
˓→needs sage.plot sage.symbolic
Graphics3d Object>>> b.plot3d(color="red")
˓→needs sage.plot sage.symbolic
Graphics3d Object>>> b.plot3d(color=["red", "blue", "red", "blue"])
˓→needs sage.plot sage.symbolic
Graphics3d Object

#␣

#␣

#␣

#␣

#␣

#␣

pure_conjugating_braid(other)
Return a pure conjugating braid, i.e. a conjugating braid whose associated permutation is the identity, if itexists.
INPUT:• other – a braid in the same braid group as self
OUTPUT:

171

Groups, Release 10.4

A pure conjugating braid. More precisely, if the output is 𝑑, 𝑜 equals other, and 𝑠 equals self then𝑜 = 𝑑−1 · 𝑠 · 𝑑.
EXAMPLES:
sage: B = BraidGroup(4)sage: B.one().pure_conjugating_braid(B.one())
1
sage: B.one().pure_conjugating_braid(B.gen(0)) is None
True
sage: B.gen(0).pure_conjugating_braid(B.gen(1)) is None
True
sage: B.gen(0).conjugating_braid(B.gen(2).inverse()) is None
True
sage: a = B([1, 2, 3])
sage: b = B([3, 2,])sage: c = b ^ 12 * a / b ^ 12
sage: d1 = a.conjugating_braid(c)sage: len(d1.Tietze())
30
sage: S = SymmetricGroup(4)sage: d1.permutation(W=S)(1,3)(2,4)
sage: d1 * c / d1 == aTruesage: d1 * a / d1 == cFalse
sage: d2 = a.pure_conjugating_braid(c)sage: len(d2.Tietze())
24
sage: d2.permutation(W=S)()
sage: d2 * c / d2 == aTruesage: d2(s0*s1*s2^2*s1*s0)^4
sage: a.conjugating_braid(b) is None
True
sage: a.pure_conjugating_braid(b) is None
True
sage: a1 = B([1])
sage: a2 = B([2])
sage: a1.conjugating_braid(a2)s1*s0sage: a1.permutation(W=S)(1,2)
sage: a2.permutation(W=S)(2,3)
sage: a1.pure_conjugating_braid(a2) is None
True
sage: (a1^2).conjugating_braid(a2^2)
s1*s0
sage: (a1^2).pure_conjugating_braid(a2^2) is None
True>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> B.one().pure_conjugating_braid(B.one())(continues on next page)

172

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)1>>> B.one().pure_conjugating_braid(B.gen(Integer(0))) is None
True>>> B.gen(Integer(0)).pure_conjugating_braid(B.gen(Integer(1))) is None
True>>> B.gen(Integer(0)).conjugating_braid(B.gen(Integer(2)).inverse()) is None
True>>> a = B([Integer(1), Integer(2), Integer(3)])>>> b = B([Integer(3), Integer(2),])>>> c = b ** Integer(12) * a / b ** Integer(12)>>> d1 = a.conjugating_braid(c)>>> len(d1.Tietze())
30>>> S = SymmetricGroup(Integer(4))>>> d1.permutation(W=S)(1,3)(2,4)>>> d1 * c / d1 == aTrue>>> d1 * a / d1 == c
False>>> d2 = a.pure_conjugating_braid(c)>>> len(d2.Tietze())
24>>> d2.permutation(W=S)()>>> d2 * c / d2 == aTrue>>> d2(s0*s1*s2^2*s1*s0)^4>>> a.conjugating_braid(b) is None
True>>> a.pure_conjugating_braid(b) is None
True>>> a1 = B([Integer(1)])>>> a2 = B([Integer(2)])>>> a1.conjugating_braid(a2)s1*s0>>> a1.permutation(W=S)(1,2)>>> a2.permutation(W=S)(2,3)>>> a1.pure_conjugating_braid(a2) is None
True>>> (a1**Integer(2)).conjugating_braid(a2**Integer(2))
s1*s0>>> (a1**Integer(2)).pure_conjugating_braid(a2**Integer(2)) is None
Truereverse()Return the reverse of self obtained by reversing the order of the generators in its word. This defines ananti-involution on the braid group. The link closure of it has the reversed orientation (see the example below
of a non reversible knot).
EXAMPLES:
sage: b = BraidGroup(3)((1, 1, -2, 1, -2, 1, -2, -2))
sage: br = b.reverse(); br# closure K8_17(continues on next page)

173

Groups, Release 10.4

(continued from previous page)s1^-1*(s1^-1*s0)^3*s0
sage: br.is_conjugated(b)False>>> from sage.all import *>>> b = BraidGroup(Integer(3))((Integer(1), Integer(1), -Integer(2),␣
˓→Integer(1), -Integer(2), Integer(1), -Integer(2), -Integer(2)))# closure␣
˓→K8_17>>> br = b.reverse(); br
s1^-1*(s1^-1*s0)^3*s0>>> br.is_conjugated(b)Falseright_normal_form()
Return the right normal form of the braid.
A tuple of simple generators in the right normal form. The last element is a power of Δ, and the rest areelements of the natural section lift from the corresponding symmetric group.
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([1, 2, 1, -2, 3, 1])
sage: b.right_normal_form()(s1*s0, s0*s2, 1)>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), Integer(1), -Integer(2), Integer(3),␣
˓→Integer(1)])>>> b.right_normal_form()(s1*s0, s0*s2, 1)

rigidity()
Return the rigidity of self.
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([2, 1, 2, 1])
sage: a = B([2, 2, -1, -1, 2, 2])
sage: a.rigidity()
6
sage: b.rigidity()0>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> a.rigidity()
6>>> b.rigidity()0174

Chapter 12. Braid groups

Groups, Release 10.4

sliding_circuits()
Return the sliding circuits of the braid.
OUTPUT: a list of sliding circuits. Each sliding circuit is itself a list of braids.
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1, 2, 2])
sage: a.sliding_circuits()[[(s0^-1*s1^-1*s0^-1)^2*s1^3*s0^2*s1^3],[s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3],[s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2],[(s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2],[(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4],[s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4],[(s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1],[s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0],[(s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5],[s0^-1*s1^-1*s0^-2*s1*s0^5],[(s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1],[s0^-1*s1^-1*s0^-2*s1^5*s0]]
sage: b = B([2, 1, 2, 1])
sage: b.sliding_circuits()[[s0*s1*s0^2, (s0*s1)^2]]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> a.sliding_circuits()[[(s0^-1*s1^-1*s0^-1)^2*s1^3*s0^2*s1^3],[s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3],[s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2],[(s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2],[(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4],[s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4],[(s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1],[s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0],[(s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5],[s0^-1*s1^-1*s0^-2*s1*s0^5],[(s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1],[s0^-1*s1^-1*s0^-2*s1^5*s0]]>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> b.sliding_circuits()[[s0*s1*s0^2, (s0*s1)^2]]

strands()
Return the number of strands in the braid.
EXAMPLES:
sage: B = BraidGroup(4)sage: b = B([1, 2, -1, 3, -2])
sage: b.strands()
4

175

Groups, Release 10.4>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), -Integer(1), Integer(3), -Integer(2)])>>> b.strands()
4

super_summit_set()
Return a list with the super summit set of the braid.
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1, 2, -1, -2, -2, 1])
sage: b.super_summit_set()[s0^-1*s1^-1*s0^-2*s1^2*s0^2,(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^3*s1,(s0^-1*s1^-1*s0^-1)^2*s1*s0^3*s1^2,
s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^3*s0]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), -Integer(1), -Integer(2), -Integer(2),␣
˓→Integer(1)])>>> b.super_summit_set()[s0^-1*s1^-1*s0^-2*s1^2*s0^2,(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^3*s1,(s0^-1*s1^-1*s0^-1)^2*s1*s0^3*s1^2,
s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^3*s0]

thurston_type()
Return the thurston_type of self.
OUTPUT: one of reducible , periodic or pseudo-anosov
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1, 2, -1])
sage: b.thurston_type()
reducible
sage: a = B([2, 2, -1, -1, 2, 2])
sage: a.thurston_type()
pseudo-anosov
sage: c = B([2, 1, 2, 1])
sage: c.thurston_type()
periodic>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1), Integer(2), -Integer(1)])>>> b.thurston_type()
reducible>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> a.thurston_type()
pseudo-anosov>>> c = B([Integer(2), Integer(1), Integer(2), Integer(1)])(continues on next page)

176

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)>>> c.thurston_type()
periodictropical_coordinates()
Return the tropical coordinates of self in the braid group 𝐵𝑛 .
OUTPUT: a list of 2𝑛 tropical integers
EXAMPLES:
sage: B = BraidGroup(3)sage: b = B([1])
sage: tc = b.tropical_coordinates(); tc[1, 0, 0, 2, 0, 1]
sage: tc[0].parent()
Tropical semiring over Integer Ringsage: b = B([-2, -2, -1, -1, 2, 2, 1, 1])
sage: b.tropical_coordinates()[1, -19, -12, 9, 0, 13]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1)])>>> tc = b.tropical_coordinates(); tc[1, 0, 0, 2, 0, 1]>>> tc[Integer(0)].parent()
Tropical semiring over Integer Ring>>> b = B([-Integer(2), -Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2), Integer(1), Integer(1)])>>> b.tropical_coordinates()[1, -19, -12, 9, 0, 13]

REFERENCES:• [DW2007]• [Deh2011]
ultra_summit_set()
Return a list with the orbits of the ultra summit set of self.
EXAMPLES:
sage: B = BraidGroup(3)sage: a = B([2, 2, -1, -1, 2, 2])
sage: b = B([2, 1, 2, 1])
sage: b.ultra_summit_set()[[s0*s1*s0^2, (s0*s1)^2]]
sage: a.ultra_summit_set()[[(s0^-1*s1^-1*s0^-1)^2*s1^3*s0^2*s1^3,(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4,(s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5,
s0^-1*s1^-1*s0^-2*s1^5*s0,(s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1,(s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2],[s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3,(continues on next page)

177

Groups, Release 10.4

(continued from previous page)s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4,
s0^-1*s1^-1*s0^-2*s1*s0^5,(s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1,
s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0,s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2]]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> a = B([Integer(2), Integer(2), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(2)])>>> b = B([Integer(2), Integer(1), Integer(2), Integer(1)])>>> b.ultra_summit_set()[[s0*s1*s0^2, (s0*s1)^2]]>>> a.ultra_summit_set()[[(s0^-1*s1^-1*s0^-1)^2*s1^3*s0^2*s1^3,(s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4,(s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5,
s0^-1*s1^-1*s0^-2*s1^5*s0,(s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1,(s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2],[s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3,
s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4,
s0^-1*s1^-1*s0^-2*s1*s0^5,(s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1,
s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0,s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2]]

sage.groups.braid.BraidGroup(n=None, names='s')Construct a Braid Group.
INPUT:• n – integer or None (default). The number of strands. If not specified the names are counted and the groupis assumed to have one more strand than generators.
• names – string or list/tuple/iterable of strings (default: x ). The generator names or name prefix.
EXAMPLES:
sage: B.<a,b> = BraidGroup();
Braid group on 3 strands
sage: H = BraidGroup( a, b )sage: B is H
True
sage: BraidGroup(3)Braid group on 3 strands>>> from sage.all import *>>> B = BraidGroup(names=( a ,Braid group on 3 strands>>> H = BraidGroup( a, b )>>> B is H
True>>> BraidGroup(Integer(3))
Braid group on 3 strands

Bb ,)); (a, b,) = B._first_ngens(2);B

The entry can be either a string with the names of the generators, or the number of generators and the prefix of thenames to be given. The default prefix is s
178

Chapter 12. Braid groups

Groups, Release 10.4

sage: B = BraidGroup(3); B.generators()(s0, s1)
sage: BraidGroup(3, g ).generators()(g0, g1)>>> from sage.all import *>>> B = BraidGroup(Integer(3)); B.generators()(s0, s1)>>> BraidGroup(Integer(3), g ).generators()(g0, g1)

Since the word problem for the braid groups is solvable, their Cayley graph can be locally obtained as follows (seeIssue #16059):
sage: def ball(group, radius):....:
ret = set()....:
ret.add(group.one())....:
for length in range(1, radius):....:
for w in Words(alphabet=group.gens(), length=length):....:
ret.add(prod(w))....:
return ret
sage: B = BraidGroup(4)sage: GB = B.cayley_graph(elements=ball(B, 4), generators=B.gens()); GB˓→needs sage.combinat sage.graphs
Digraph on 31 vertices>>> from sage.all import *>>> def ball(group, radius):...
ret = set()...
ret.add(group.one())...
for length in range(Integer(1), radius):...
for w in Words(alphabet=group.gens(), length=length):...
ret.add(prod(w))...
return ret>>> B = BraidGroup(Integer(4))>>> GB = B.cayley_graph(elements=ball(B, Integer(4)), generators=B.gens()); GB˓→# needs sage.combinat sage.graphs
Digraph on 31 vertices#␣␣Since the braid group has nontrivial relations, this graph contains less vertices than the one associated to the freegroup (which is a tree):sage: F = FreeGroup(3)sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF
˓→needs sage.combinat sage.graphs
Digraph on 40 vertices>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> GF = F.cayley_graph(elements=ball(F, Integer(4)), generators=F.gens()); GF˓→# needs sage.combinat sage.graphs
Digraph on 40 vertices#␣␣class sage.groups.braid.BraidGroup_class(names)
Bases: FiniteTypeArtinGroupThe braid group on 𝑛 strands.
179

Groups, Release 10.4

EXAMPLES:
sage: B1 = BraidGroup(5)sage: B1
Braid group on 5 strands
sage: B2 = BraidGroup(3)sage: B1==B2
False
sage: B2 is BraidGroup(3)True>>> from sage.all import *>>> B1 = BraidGroup(Integer(5))>>> B1
Braid group on 5 strands>>> B2 = BraidGroup(Integer(3))>>> B1==B2
False>>> B2 is BraidGroup(Integer(3))
True

Element
alias of Braid
TL_basis_with_drain(drain_size)
Return a basis of a summand of the Temperley–Lieb–Jones representation of self.
The basis elements are given by non-intersecting pairings of 𝑛 + 𝑑 points in a square with 𝑛 points marked‘on the top’ and 𝑑 points ‘on the bottom’ so that every bottom point is paired with a top point. Here, 𝑛 is thenumber of strands of the braid group, and 𝑑 is specified by drain_size.
A basis element is specified as a list of integers obtained by considering the pairings as obtained as the ‘highest
term’ of trivalent trees marked by Jones–Wenzl projectors (see e.g. [Wan2010]). In practice, this is a listof non-negative integers whose first element is drain_size, whose last element is 0, and satisfying thatconsecutive integers have difference 1. Moreover, the length of each basis element is 𝑛 + 1.
Given these rules, the list of lists is constructed recursively in the natural way.
INPUT:• drain_size – integer between 0 and the number of strands (both inclusive)
OUTPUT: a list of basis elements, each of which is a list of integers
EXAMPLES:
We calculate the basis for the appropriate vector space for 𝐵5 when 𝑑 = 3:
sage: B = BraidGroup(5)sage: B.TL_basis_with_drain(3)[[3, 4, 3, 2, 1, 0],[3, 2, 3, 2, 1, 0],[3, 2, 1, 2, 1, 0],[3, 2, 1, 0, 1, 0]]>>> from sage.all import *>>> B = BraidGroup(Integer(5))>>> B.TL_basis_with_drain(Integer(3))[[3, 4, 3, 2, 1, 0],(continues on next page)

180

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)[3, 2, 3, 2, 1, 0],[3, 2, 1, 2, 1, 0],[3, 2, 1, 0, 1, 0]]

The number of basis elements hopefully corresponds to the general formula for the dimension of the representation spaces:sage: B = BraidGroup(10)sage: d = 2
sage: B.dimension_of_TL_space(d) == len(B.TL_basis_with_drain(d))
True>>> from sage.all import *>>> B = BraidGroup(Integer(10))>>> d = Integer(2)>>> B.dimension_of_TL_space(d) == len(B.TL_basis_with_drain(d))
True

TL_representation(drain_size, variab=None)
Return representation matrices of the Temperley–Lieb–Jones representation of standard braid group generators and inverses of self.
The basis is given by non-intersecting pairings of (𝑛 + 𝑑) points, where 𝑛 is the number of strands, and 𝑑
is given by drain_size, and the pairings satisfy certain rules. See TL_basis_with_drain() for
details. This basis has the useful property that all resulting entries can be regarded as Laurent polynomials.
We use the convention that the eigenvalues of the standard generators are 1 and −𝐴4 , where 𝐴 is the generatorof the Laurent polynomial ring.
When 𝑑 = 𝑛 − 2 and the variables are picked appropriately, the resulting representation is equivalent to the
reduced Burau representation. When 𝑑 = 𝑛, the resulting representation is trivial and 1-dimensional.
INPUT:• drain_size – integer between 0 and the number of strands (both inclusive)• variab – variable (default: None); the variable in the entries of the matrices; if None, then use adefault variable in [𝐴, 𝐴−1 ]OUTPUT: a list of matrices corresponding to the representations of each of the standard generators and theirinverses
EXAMPLES:
sage: B = BraidGroup(4)sage: B.TL_representation(0)
[(
[
1
0] [
1
0]
[ A^2 -A^4], [ A^-2 -A^-4]),([-A^4 A^2] [-A^-4 A^-2]
[
0
1], [
0
1]
),
(
[
1
0] [
1
0]
[ A^2 -A^4], [ A^-2 -A^-4])](continues on next page)

181

Groups, Release 10.4

(continued from previous page)

sage: R.<A> = LaurentPolynomialRing(GF(2))
sage: B.TL_representation(0, variab=A)
[(
[ 1
0] [
1
0]
[A^2 A^4], [A^-2 A^-4]),([A^4 A^2] [A^-4 A^-2]
[ 0
1], [
0
1]
),
(
[ 1
0] [
1
0]
[A^2 A^4], [A^-2 A^-4])]
sage: B = BraidGroup(8)sage: B.TL_representation(8)[([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1])]>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> B.TL_representation(Integer(0))
[(
[
1
0] [
1
0]
[ A^2 -A^4], [ A^-2 -A^-4]),([-A^4 A^2] [-A^-4 A^-2]
[
0
1], [
0
1]
),
(
[
1
0] [
1
0]
[ A^2 -A^4], [ A^-2 -A^-4])]>>> R = LaurentPolynomialRing(GF(Integer(2)), names=( A ,)); (A,) = R._first_
˓→ngens(1)>>> B.TL_representation(Integer(0), variab=A)
[(
[ 1
0] [
1
0]
[A^2 A^4], [A^-2 A^-4]),([A^4 A^2] [A^-4 A^-2]
[ 0
1], [
0
1]
),
(
[ 1
0] [
1
0]
[A^2 A^4], [A^-2 A^-4])]>>> B = BraidGroup(Integer(8))>>> B.TL_representation(Integer(8))(continues on next page)

182

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)[([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1]),([1], [1])]an_element()
Return an element of the braid group.
This is used both for illustration and testing purposes.
EXAMPLES:
sage: B = BraidGroup(2)sage: B.an_element()s>>> from sage.all import *>>> B = BraidGroup(Integer(2))>>> B.an_element()s

as_permutation_group()
Return an isomorphic permutation group.
OUTPUT: this raises a ValueError error since braid groups are infinite
cardinality()
Return the number of group elements.
OUTPUT: Infinity
dimension_of_TL_space(drain_size)
Return the dimension of a particular Temperley–Lieb representation summand of self.
Following the notation of TL_basis_with_drain(), the summand is the one corresponding to thenumber of drains being fixed to be drain_size.
INPUT:• drain_size – integer between 0 and the number of strands (both inclusive)
EXAMPLES:
Calculation of the dimension of the representation of 𝐵8 corresponding to having 2 drains:
sage: B = BraidGroup(8)sage: B.dimension_of_TL_space(2)28>>> from sage.all import *>>> B = BraidGroup(Integer(8))>>> B.dimension_of_TL_space(Integer(2))
28

The direct sum of endomorphism spaces of these vector spaces make up the entire Temperley–Lieb algebra:

183

Groups, Release 10.4

sage: import sage.combinat.diagram_algebras as da#␣˓→needs sage.combinat
sage: B = BraidGroup(6)sage: dimensions = [B.dimension_of_TL_space(d)**2 for d in [0, 2, 4, 6]]
sage: total_dim = sum(dimensions)sage: total_dim == len(list(da.temperley_lieb_diagrams(6)))# long␣˓→time, needs sage.combinat
True>>> from sage.all import *>>> import sage.combinat.diagram_algebras as da#␣˓→needs sage.combinat>>> B = BraidGroup(Integer(6))>>> dimensions = [B.dimension_of_TL_space(d)**Integer(2) for d in [Integer(0),˓→ Integer(2), Integer(4), Integer(6)]]>>> total_dim = sum(dimensions)>>> total_dim == len(list(da.temperley_lieb_diagrams(Integer(6))))#␣˓→long time, needs sage.combinat
Trueepimorphisms(H)Return the epimorphisms from self to H, up to automorphism of 𝐻 passing through the two generator
presentation of self.
INPUT:• 𝐻 – another group
EXAMPLES:
sage: B = BraidGroup(5)sage: B.epimorphisms(SymmetricGroup(5))[Generic morphism:
From: Braid group on 5 strands
To:
Symmetric group of order 5! as a permutation group
Defn: s0 |--> (1,5)
s1 |--> (4,5)
s2 |--> (3,4)
s3 |--> (2,3)]>>> from sage.all import *>>> B = BraidGroup(Integer(5))>>> B.epimorphisms(SymmetricGroup(Integer(5)))[Generic morphism:
From: Braid group on 5 strands
To:
Symmetric group of order 5! as a permutation group
Defn: s0 |--> (1,5)
s1 |--> (4,5)
s2 |--> (3,4)
s3 |--> (2,3)]

ALGORITHM:
Uses libgap’s GQuotients function.
mapping_class_action(F)Return the action of self in the free group F as mapping class group.

184

Chapter 12. Braid groups

Groups, Release 10.4

This action corresponds to the action of the braid over the punctured disk, whose fundamental group is thefree group on as many generators as strands.
In Sage, this action is the result of multiplying a free group element with a braid. So you generally do nothave to construct this action yourself.
OUTPUT: a MappingClassGroupAction
EXAMPLES:
sage: B = BraidGroup(3)sage: B.inject_variables()Defining s0, s1
sage: F.<a,b,c> = FreeGroup(3)sage: A = B.mapping_class_action(F)sage: A(a,s0)
a*b*a^-1sage: a * s0
# simpler notation
a*b*a^-1>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> B.inject_variables()Defining s0, s1>>> F = FreeGroup(Integer(3), names=( a ,˓→ngens(3)>>> A = B.mapping_class_action(F)>>> A(a,s0)
a*b*a^-1>>> a * s0
# simpler notation
a*b*a^-1b ,c ,)); (a, b, c,) = F._first_

mirror_involution()
Return the mirror involution of self.
This automorphism maps a braid to another one by replacing each generator in its word by the inverse. In
general this is different from the inverse of the braid since the order of the generators in the word is notreversed.
EXAMPLES:
sage: B = BraidGroup(4)sage: mirr = B.mirror_involution()sage: b = B((1,-2,-1,3,2,1))
sage: bm = mirr(b); bm
s0^-1*s1*s0*s2^-1*s1^-1*s0^-1
sage: bm == ~b
False
sage: bm.is_conjugated(b)Falsesage: bm.is_conjugated(~b)
True>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> mirr = B.mirror_involution()>>> b = B((Integer(1),-Integer(2),-Integer(1),Integer(3),Integer(2),˓→Integer(1)))(continues on next page)

185

Groups, Release 10.4

(continued from previous page)>>> bm = mirr(b); bm
s0^-1*s1*s0*s2^-1*s1^-1*s0^-1>>> bm == ~b
False>>> bm.is_conjugated(b)False>>> bm.is_conjugated(~b)
Trueorder()
Return the number of group elements.
OUTPUT: Infinity
presentation_two_generators(isomorphisms=False)
Construct a finitely presented group isomorphic to self with only two generators.
INPUT:• isomorphism – boolean (default False); if True, then an isomorphism from self and the isomorphic group and its inverse is also returned
EXAMPLES:
sage: B = BraidGroup(3)sage: B.presentation_two_generators()
Finitely presented group < x0, x1 | x1^3*x0^-2 >sage: B = BraidGroup(4)sage: G, hom1, hom2 = B.presentation_two_generators(isomorphisms=True)
sage: G
Finitely presented group < x0, x1 | x1^4*x0^-3, x0*x1*x0*x1^-2*x0^-1*x1^3*x0^˓→1*x1^-2 >sage: hom1(B.gen(0))
x0*x1^-1sage: hom1(B.gen(1))
x1*x0*x1^-2
sage: hom1(B.gen(2))
x1^2*x0*x1^-3
sage: all(hom2(hom1(a)) == a for a in B.gens())
Truesage: all(hom2(a) == B.one() for a in G.relations())
True>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> B.presentation_two_generators()
Finitely presented group < x0, x1 | x1^3*x0^-2 >>>> B = BraidGroup(Integer(4))>>> G, hom1, hom2 = B.presentation_two_generators(isomorphisms=True)>>> G
Finitely presented group < x0, x1 | x1^4*x0^-3, x0*x1*x0*x1^-2*x0^-1*x1^3*x0^˓→1*x1^-2 >>>> hom1(B.gen(Integer(0)))
x0*x1^-1>>> hom1(B.gen(Integer(1)))
x1*x0*x1^-2>>> hom1(B.gen(Integer(2)))(continues on next page)

186

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)x1^2*x0*x1^-3>>> all(hom2(hom1(a)) == a for a in B.gens())
True>>> all(hom2(a) == B.one() for a in G.relations())
True

some_elements()
Return a list of some elements of the braid group.
This is used both for illustration and testing purposes.
EXAMPLES:
sage: B = BraidGroup(3)sage: B.some_elements()[s0, s0*s1, (s0*s1)^3]>>> from sage.all import *>>> B = BraidGroup(Integer(3))>>> B.some_elements()[s0, s0*s1, (s0*s1)^3]

strands()
Return the number of strands.
OUTPUT: integer
EXAMPLES:
sage: B = BraidGroup(4)sage: B.strands()
4>>> from sage.all import *>>> B = BraidGroup(Integer(4))>>> B.strands()
4

class sage.groups.braid.MappingClassGroupAction(G, M)
Bases: Action
The right action of the braid group the free group as the mapping class group of the punctured disk.
That is, this action is the action of the braid over the punctured disk, whose fundamental group is the free group on
as many generators as strands.
This action is defined as follows:⎧−1⎪⎨𝑥𝑗 · 𝑥𝑗+1 · 𝑥𝑗
𝑥𝑗 · 𝜎𝑖 = 𝑥𝑗−1⎪⎩
𝑥𝑗

if 𝑖 = 𝑗if 𝑖 = 𝑗 − 1 ,otherwise

where 𝜎𝑖 are the generators of the braid group on 𝑛 strands, and 𝑥𝑗 the generators of the free group of rank 𝑛.
You should left multiplication of the free group element by the braid to compute the action. Alternatively, use themapping_class_action() method of the braid group to construct this action.
EXAMPLES:187

Groups, Release 10.4

sage: B.<s0,s1,s2> = BraidGroup(4)sage: F.<x0,x1,x2,x3> = FreeGroup(4)sage: x0 * s1x0
sage: x1 * s1
x1*x2*x1^-1
sage: x1^-1 * s1
x1*x2^-1*x1^-1
sage: A = B.mapping_class_action(F)sage: A
Right action by Braid group on 4 strands on Free Group on generators {x0, x1, x2,␣˓→x3}
sage: A(x0, s1)x0
sage: A(x1, s1)
x1*x2*x1^-1
sage: A(x1^-1, s1)
x1*x2^-1*x1^-1>>> from sage.all import *>>> B = BraidGroup(Integer(4), names=( s0 , s1 , s2 ,)); (s0, s1, s2,) = B._
˓→first_ngens(3)>>> F = FreeGroup(Integer(4), names=( x0 , x1 , x2 , x3 ,)); (x0, x1, x2, x3,)␣
˓→= F._first_ngens(4)>>> x0 * s1x0>>> x1 * s1
x1*x2*x1^-1>>> x1**-Integer(1) * s1
x1*x2^-1*x1^-1>>> A = B.mapping_class_action(F)>>> A
Right action by Braid group on 4 strands on Free Group on generators {x0, x1, x2,␣˓→x3}>>> A(x0, s1)x0>>> A(x1, s1)
x1*x2*x1^-1>>> A(x1**-Integer(1), s1)
x1*x2^-1*x1^-1class sage.groups.braid.RightQuantumWord(words)
Bases: object
A right quantum word as in Definition 4.1 of [HL2018].
INPUT:• words – an element in a suitable free algebra over a Laurent polynomial ring in one variable; this input does
not need to be in reduced form, but the monomials for the input can come in any order
EXAMPLES:
sage: from sage.groups.braid import RightQuantumWord
sage: fig_8 = BraidGroup(3)([-1, 2, -1, 2])
sage: (
(continues on next page)

188

Chapter 12. Braid groups

Groups, Release 10.4

(continued from previous page)....: bp_1, cp_1, ap_1,....: bp_3, cp_3, ap_3,....: bm_0, cm_0, am_0,....: bm_2, cm_2, am_2....: ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()
sage: q = bp_1.base_ring().gen()sage: RightQuantumWord(ap_1*cp_1 + q**3*bm_2*bp_1*am_0*cm_0)
The right quantum word represented by
q*cp_1*ap_1 + q^2*bp_1*cm_0*am_0*bm_2
reduced from ap_1*cp_1 + q^3*bm_2*bp_1*am_0*cm_0>>> from sage.all import *>>> from sage.groups.braid import RightQuantumWord>>> fig_8 = BraidGroup(Integer(3))([-Integer(1), Integer(2), -Integer(1),␣
˓→Integer(2)])>>> (... bp_1, cp_1, ap_1,... bp_3, cp_3, ap_3,... bm_0, cm_0, am_0,... bm_2, cm_2, am_2... ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()>>> q = bp_1.base_ring().gen()>>> RightQuantumWord(ap_1*cp_1 + q**Integer(3)*bm_2*bp_1*am_0*cm_0)
The right quantum word represented by
q*cp_1*ap_1 + q^2*bp_1*cm_0*am_0*bm_2
reduced from ap_1*cp_1 + q^3*bm_2*bp_1*am_0*cm_0

eps(N)
Evaluate the map ℰ𝑁 for a braid.
INPUT:• N – integer; the number of colors
EXAMPLES:
sage: from sage.groups.braid import RightQuantumWord
sage: B = BraidGroup(3)sage: b = B([1,-2,1,2])
sage: db = b.deformed_burau_matrix()[:, :]sage: q = db.parent().base_ring().base_ring().gen()sage: (bp_0, cp_0, ap_0,....: bp_2, cp_2, ap_2,....: bp_3, cp_3, ap_3,....: bm_1, cm_1, am_1) = db.parent().base_ring().gens()
sage: rqw = RightQuantumWord(....:q^3*bp_2*bp_0*ap_0 + q*ap_3*bm_1*am_1*bp_0)
sage: rqw.eps(3)-q^-1 + 2*q - q^5sage: rqw.eps(2)-1 + 2*q - q^2 + q^3 - q^4>>> from sage.all import *>>> from sage.groups.braid import RightQuantumWord>>> B = BraidGroup(Integer(3))>>> b = B([Integer(1),-Integer(2),Integer(1),Integer(2)])>>> db = b.deformed_burau_matrix()[:, :](continues on next page)

189

Groups, Release 10.4

(continued from previous page)>>> q = db.parent().base_ring().base_ring().gen()>>> (bp_0, cp_0, ap_0,... bp_2, cp_2, ap_2,... bp_3, cp_3, ap_3,... bm_1, cm_1, am_1) = db.parent().base_ring().gens()>>> rqw = RightQuantumWord(...
q**Integer(3)*bp_2*bp_0*ap_0 + q*ap_3*bm_1*am_1*bp_0)>>> rqw.eps(Integer(3))-q^-1 + 2*q - q^5>>> rqw.eps(Integer(2))-1 + 2*q - q^2 + q^3 - q^4

Todo: Parallelize this function, calculating all summands in the sum in parallel.
reduced_word()
Return the (reduced) right quantum word.
OUTPUT: an element in the free algebra
EXAMPLES:
sage: from sage.groups.braid import RightQuantumWord
sage: fig_8 = BraidGroup(3)([-1, 2, -1, 2])
sage: (....: bp_1, cp_1, ap_1,....: bp_3, cp_3, ap_3,....: bm_0, cm_0, am_0,....: bm_2, cm_2, am_2....: ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()
sage: q = bp_1.base_ring().gen()sage: qw = RightQuantumWord(ap_1*cp_1 +....:q**3*bm_2*bp_1*am_0*cm_0)
sage: qw.reduced_word()
q*cp_1*ap_1 + q^2*bp_1*cm_0*am_0*bm_2>>> from sage.all import *>>> from sage.groups.braid import RightQuantumWord>>> fig_8 = BraidGroup(Integer(3))([-Integer(1), Integer(2), -Integer(1),␣
˓→Integer(2)])>>> (... bp_1, cp_1, ap_1,... bp_3, cp_3, ap_3,... bm_0, cm_0, am_0,... bm_2, cm_2, am_2... ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()>>> q = bp_1.base_ring().gen()>>> qw = RightQuantumWord(ap_1*cp_1 +...
q**Integer(3)*bm_2*bp_1*am_0*cm_0)>>> qw.reduced_word()
q*cp_1*ap_1 + q^2*bp_1*cm_0*am_0*bm_2

Todo: Parallelize this function, calculating all summands in the sum in parallel.

190

Chapter 12. Braid groups

Groups, Release 10.4

tuples()Get a representation of the right quantum word as a dict, with keys monomials in the free algebra represented
as tuples and values in elements the Laurent polynomial ring in one variable.
This is in the reduced form as outlined in Definition 4.1 of [HL2018].
OUTPUT: a dict of tuples of ints corresponding to the exponents in the generators with values in the algebra’s
base ring
EXAMPLES:
sage: from sage.groups.braid import RightQuantumWord
sage: fig_8 = BraidGroup(3)([-1, 2, -1, 2])
sage: (....: bp_1, cp_1, ap_1,....: bp_3, cp_3, ap_3,....: bm_0, cm_0, am_0,....: bm_2, cm_2, am_2....: ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()
sage: q = bp_1.base_ring().gen()sage: qw = RightQuantumWord(ap_1*cp_1 +....:q**3*bm_2*bp_1*am_0*cm_0)
sage: for key, value in qw.tuples.items():....:
print(key, value)....:(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) q
(1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0) q^2>>> from sage.all import *>>> from sage.groups.braid import RightQuantumWord>>> fig_8 = BraidGroup(Integer(3))([-Integer(1), Integer(2), -Integer(1),␣
˓→Integer(2)])>>> (... bp_1, cp_1, ap_1,... bp_3, cp_3, ap_3,... bm_0, cm_0, am_0,... bm_2, cm_2, am_2... ) = fig_8.deformed_burau_matrix().parent().base_ring().gens()>>> q = bp_1.base_ring().gen()>>> qw = RightQuantumWord(ap_1*cp_1 +...
q**Integer(3)*bm_2*bp_1*am_0*cm_0)>>> for key, value in qw.tuples.items():...
print(key, value)....:(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) q
(1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0) q^2

191

Groups, Release 10.4

192

Chapter 12. Braid groups

CHAPTERTHIRTEEN

CUBIC BRAID GROUPS

This module is devoted to factor groups of the Artin braid groups, such that the images 𝑠𝑖 of the braid generators haveorder three:𝑠3𝑖 = 1.
In general these groups have firstly been investigated by Coxeter, H.S.M. in: “Factor groups of the braid groups, Proceedings of the Fourth Canadian Mathematical Congress (Vancouver 1957), pp. 95-122”.
Coxeter showed, that these groups are finite as long as the number of strands is less than 6 and infinite else-wise. Moreexplicitly the factor group on three strand braids is isomorphic to 𝑆𝐿(2, 3), on four strand braids to 𝐺𝑈 (3, 2) and on fivestrand braids to 𝑆𝑝(4, 3) × 𝐶3 . Today, these finite groups are known as irreducible complex reflection groups enumerated
in the Shephard-Todd classification as 𝐺4 , 𝐺25 and 𝐺32 .
Coxeter realized these groups as subgroups of unitary groups with respect to a certain Hermitian form over the complex
numbers (in fact over adjoined with a primitive 12-th root of unity).
In “Einige endliche Faktorgruppen der Zopfgruppen” (Math. Z., 163 (1978), 291-302) J. Assion considered two series
𝑆(𝑚) and 𝑈 (𝑚) of finite factors of these groups. The additional relations on the braid group generators {𝑠1 , · · · , 𝑠𝑚−1 }
are
−1 −1
S: 𝑠3 𝑠1 𝑡2 𝑠1 𝑡−1
2 𝑡3 𝑡2 𝑠1 𝑡2 𝑡3 = 1
U: 𝑡1 𝑡3 = 1

for 𝑚 >= 5 in case 𝑆(𝑚)for 𝑚 >= 5 in case 𝑈 (𝑚)where 𝑡𝑖 = (𝑠𝑖 𝑠𝑖+1 )3 . He showed that each series of finite cubic braid group factors must be an epimorphic image of
one of his two series, as long as the groups with less than 5 strands are the full cubic braid groups, whereas the group on
5 strands is not. He realized the groups 𝑆(𝑚) as symplectic groups over 𝐺𝐹 (3) (resp. subgroups therein) and 𝑈 (𝑚) as
general unitary groups over 𝐺𝐹 (4) (resp. subgroups therein).
All the groups considered by Coxeter and Assion are considered as finitely presented groups together with the classicalrealizations. It also allows for the conversion maps between the two realizations. In addition, we can construct otherrealizations and maps to matrix groups with help of the Burau representation. In case gap3 and CHEVIE are installed,
the reflection groups (via the gap3 interface) are available, too. This can be done using the methods as_classical_group(), as_matrix_group(), as_permutation_group(), and as_reflection_group().
REFERENCES:• [Cox1957]• [Ass1978]
AUTHORS:• Sebastian Oehms 2019-02-16, initial version.

193

Groups, Release 10.4

sage.groups.cubic_braid.AssionGroupS(n=None, names='s')Construct cubic braid groups CubicBraidGroup which have been investigated by J.Assion using the notation
S(m). This function is a short hand cut for setting the construction arguments cbg_type=CubicBraidGroup.
type.AssionS and default names= s .
INPUT:• n – integer (optional); the number of strands• names – (default: s ) string or list/tuple/iterable of strings
See also:
CubicBraidGroup
EXAMPLES:
sage: S3 = AssionGroupS(3); S3
Assion group on 3 strands of type S
sage: S3x = CubicBraidGroup(3, names= s , cbg_type=CubicBraidGroup.type.AssionS);␣
˓→S3x
Assion group on 3 strands of type S
sage: S3 == S3x
True>>> from sage.all import *>>> S3 = AssionGroupS(Integer(3)); S3
Assion group on 3 strands of type S>>> S3x = CubicBraidGroup(Integer(3), names= s , cbg_type=CubicBraidGroup.type.
˓→AssionS); S3x
Assion group on 3 strands of type S>>> S3 == S3x
True

sage.groups.cubic_braid.AssionGroupU(n=None, names='u')Construct cubic braid groups as instance of CubicBraidGroup which have been investigated by J.Assion using the notation U(m). This function is a short hand cut for setting the construction arguments
cbg_type=CubicBraidGroup.type.AssionU and default names= u .
INPUT:• n – integer (optional); the number of strands• names – (default: s ) string or list/tuple/iterable of strings
See also:
CubicBraidGroup
EXAMPLES:
sage: U3 = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3x = CubicBraidGroup(3, names= u , cbg_type=CubicBraidGroup.type.AssionU);␣
˓→U3x
Assion group on 3 strands of type U
sage: U3 == U3x
True

194

Chapter 13. Cubic Braid Groups

Groups, Release 10.4>>> from sage.all import *>>> U3 = AssionGroupU(Integer(3)); U3
Assion group on 3 strands of type U>>> U3x = CubicBraidGroup(Integer(3), names= u , cbg_type=CubicBraidGroup.type.
˓→AssionU); U3x
Assion group on 3 strands of type U>>> U3 == U3x
Trueclass sage.groups.cubic_braid.CubicBraidElement(parent, x, check=True)
Bases: FinitelyPresentedGroupElement
Elements of cubic factor groups of the braid group.
For more information see CubicBraidGroup.
EXAMPLES:
sage: C4.<c1, c2, c3> = CubicBraidGroup(4); C4
Cubic Braid group on 4 strands
sage: ele1 = c1*c2*c3^-1*c2^-1
sage: ele2 = C4((1, 2, -3, -2))
sage: ele1 == ele2
True>>> from sage.all import *>>> C4 = CubicBraidGroup(Integer(4), names=( c1 , c2 , c3 ,)); (c1, c2, c3,) =␣
˓→C4._first_ngens(3); C4
Cubic Braid group on 4 strands>>> ele1 = c1*c2*c3**-Integer(1)*c2**-Integer(1)>>> ele2 = C4((Integer(1), Integer(2), -Integer(3), -Integer(2)))>>> ele1 == ele2
True

braid()
Return the canonical braid preimage of self as a Braid.
EXAMPLES:
sage: C3.<c1, c2> = CubicBraidGroup(3)sage: c1.parent()
Cubic Braid group on 3 strands
sage: c1.braid().parent()
Braid group on 3 strands>>> from sage.all import *>>> C3 = CubicBraidGroup(Integer(3), names=( c1 ,˓→first_ngens(2)>>> c1.parent()
Cubic Braid group on 3 strands>>> c1.braid().parent()
Braid group on 3 strands

c2 ,)); (c1, c2,) = C3._

burau_matrix(root_bur=None, domain=None, characteristic=None, var='t', reduced=False)
Return the Burau matrix of the cubic braid coset.
This method uses the same method belonging to Braid, but reduces the indeterminate to a primitive sixth(resp. twelfth in case reduced= unitary ) root of unity.
195

Groups, Release 10.4

INPUT (all arguments are optional keywords):• root_bur – six (resp. twelfth) root of unity in some field (default: root of unity over)• domain – (default: cyclotomic field of order 3 and degree 2, resp. the domain of 𝑟𝑜𝑜𝑡𝑏 𝑢𝑟 if given) basering for the Burau matrix• characteristic – integer giving the characteristic of the domain (default: 0 or the characteristicof domain if given)• var – string used for the indeterminate name in case root_bur must be constructed in a splitting field• reduced – boolean or string (default: False); for more information see the documentation of burau_matrix() of Braid
OUTPUT:
The Burau matrix of the cubic braid coset with entries in the domain given by the options. In case the option
reduced= unitary is given a triple consisting of the Burau matrix, its adjoined and the Hermitian form
is returned.
EXAMPLES:
sage: C3.<c1, c2> = CubicBraidGroup(3)sage: ele = c1*c2*c1
sage: # needs sage.rings.number_fieldsage: BuMa = ele.burau_matrix(); BuMa
[ -zeta3
1
zeta3][ -zeta3 zeta3 + 1
0]
[
1
0
0]
sage: BuMa.base_ring()
Cyclotomic Field of order 3 and degree 2
sage: BuMa == ele.burau_matrix(characteristic=0)
True
sage: BuMa = ele.burau_matrix(domain=QQ); BuMa[-t + 1
1 t - 1][-t + 1
t
0]
[
1
0
0]
sage: BuMa.base_ring()
Number Field in t with defining polynomial t^2 - t + 1
sage: BuMa = ele.burau_matrix(domain = QQ[I, sqrt(3)]); BuMa
˓→needs sage.symbolic[ 1/2*sqrt3*I + 1/2
1 -1/2*sqrt3*I - 1/2]
[ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2
0]
[
1
0
0]
sage: BuMa.base_ring()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 over its base field#␣#␣

sage: BuMa = ele.burau_matrix(characteristic=7); BuMa
[3 1 4][3 5 0][1 0 0]sage: BuMa.base_ring()
Finite Field of size 7
sage: # needs sage.rings.finite_rings
sage: BuMa = ele.burau_matrix(characteristic=2); BuMa[t + 1
1 t + 1]
(continues on next page)

196

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

(continued from previous page)[t + 1
t
0]
[
1
0
0]
sage: BuMa.base_ring()
Finite Field in t of size 2^2
sage: F4.<r64> = GF(4)sage: BuMa = ele.burau_matrix(root_bur=r64); BuMa
[r64 + 1
1 r64 + 1]
[r64 + 1
r64
0]
[
1
0
0]
sage: BuMa.base_ring()
Finite Field in r64 of size 2^2
sage: BuMa = ele.burau_matrix(domain=GF(5)); BuMa
[2*t + 2
1 3*t + 3]
[2*t + 2 3*t + 4
0]
[
1
0
0]
sage: BuMa.base_ring()
Finite Field in t of size 5^2sage: # needs sage.rings.number_fieldsage: BuMa, BuMaAd, H = ele.burau_matrix(reduced= unitary ); BuMa[
0 zeta12^3][zeta12^30]
sage: BuMa * H * BuMaAd == H
True
sage: BuMa.base_ring()
Cyclotomic Field of order 12 and degree 4
sage: BuMa, BuMaAd, H = ele.burau_matrix(domain=QQ[I, sqrt(3)],˓→needs sage.symbolic....:
reduced= unitary ); BuMa
[0 I]
[I 0]
sage: BuMa.base_ring()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 over its base field>>> from sage.all import *>>> C3 = CubicBraidGroup(Integer(3), names=( c1 ,˓→first_ngens(2)>>> ele = c1*c2*c1#␣#␣c2 ,)); (c1, c2,) = C3._>>> # needs sage.rings.number_field>>> BuMa = ele.burau_matrix(); BuMa
[ -zeta3
1
zeta3][ -zeta3 zeta3 + 1
0]
[
1
0
0]
>>> BuMa.base_ring()
Cyclotomic Field of order 3 and degree 2>>> BuMa == ele.burau_matrix(characteristic=Integer(0))
True>>> BuMa = ele.burau_matrix(domain=QQ); BuMa[-t + 1
1 t - 1][-t + 1
t
0]
[
1
0
0]
>>> BuMa.base_ring()
Number Field in t with defining polynomial t^2 - t + 1>>> BuMa = ele.burau_matrix(domain = QQ[I, sqrt(Integer(3))]); BuMa␣(continues on next page)

197

Groups, Release 10.4

(continued from previous page)# needs sage.symbolic[ 1/2*sqrt3*I + 1/2
1 -1/2*sqrt3*I - 1/2]
[ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2
0]
[
1
0
0]
>>> BuMa.base_ring()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 over its base field˓→#␣>>> BuMa = ele.burau_matrix(characteristic=Integer(7)); BuMa
[3 1 4][3 5 0][1 0 0]>>> BuMa.base_ring()
Finite Field of size 7>>> # needs sage.rings.finite_rings>>> BuMa = ele.burau_matrix(characteristic=Integer(2)); BuMa[t + 1
1 t + 1][t + 1
t
0]
[
1
0
0]
>>> BuMa.base_ring()
Finite Field in t of size 2^2>>> F4 = GF(Integer(4), names=( r64 ,)); (r64,) = F4._first_ngens(1)>>> BuMa = ele.burau_matrix(root_bur=r64); BuMa
[r64 + 1
1 r64 + 1]
[r64 + 1
r64
0]
[
1
0
0]
>>> BuMa.base_ring()
Finite Field in r64 of size 2^2>>> BuMa = ele.burau_matrix(domain=GF(Integer(5))); BuMa
[2*t + 2
1 3*t + 3]
[2*t + 2 3*t + 4
0]
[
1
0
0]
>>> BuMa.base_ring()
Finite Field in t of size 5^2>>> # needs sage.rings.number_field>>> BuMa, BuMaAd, H = ele.burau_matrix(reduced= unitary ); BuMa[
0 zeta12^3][zeta12^30]>>> BuMa * H * BuMaAd == H
True>>> BuMa.base_ring()
Cyclotomic Field of order 12 and degree 4>>> BuMa, BuMaAd, H = ele.burau_matrix(domain=QQ[I, sqrt(Integer(3))],˓→# needs sage.symbolic...
reduced= unitary ); BuMa
[0 I]
[I 0]
>>> BuMa.base_ring()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 over its base field␣#␣class sage.groups.cubic_braid.CubicBraidGroup(names, cbg_type=None)
Bases: FinitelyPresentedGroup
Factor groups of the Artin braid group mapping their generators to elements of order 3.

198

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

These groups are implemented as a particular case of finitely presented groups similar to the BraidGroup_class.
A cubic braid group can be created by giving the number of strands, and the name of the generators in a similar
way as it works for the BraidGroup_class.
INPUT:• names – see the corresponding documentation of BraidGroup_class• cbg_type – (default: CubicBraidGroup.type.Coxeter; see explanation below) enum type
CubicBraidGroup.type
Setting the keyword cbg_type to one on the values CubicBraidGroup.type.AssionS or
CubicBraidGroup.type.AssionU, the additional relations due to Assion are added:−1 −1
S: 𝑠3 𝑠1 𝑡2 𝑠1 𝑡−1
2 𝑡3 𝑡2 𝑠1 𝑡2 𝑡3 = 1
U: 𝑡1 𝑡3 = 1

for 𝑚 >= 5 in case 𝑆(𝑚),for 𝑚 >= 5 in case 𝑈 (𝑚),where 𝑡𝑖 = (𝑠𝑖 𝑠𝑖+1 )3 . If cbg_type == CubicBraidGroup.type.Coxeter (default) only
the cubic relation on the generators is active (Coxeter’s case of investigation). Note that for 𝑛 =2, 3, 4, the groups do not differ between the three possible values of cbg_type (as finitely presented
groups). However, the CubicBraidGroup.type.Coxeter, CubicBraidGroup.type.AssionS andCubicBraidGroup.type.AssionU are different, so they have different classical realizations implemented.
See also:
Instances can also be constructed more easily by using CubicBraidGroup(), AssionGroupS() and AssionGroupU().
EXAMPLES:
sage: U3 = CubicBraidGroup(3, cbg_type=CubicBraidGroup.type.AssionU); U3
Assion group on 3 strands of type U
sage: U3.gens()(c0, c1)>>> from sage.all import *>>> U3 = CubicBraidGroup(Integer(3), cbg_type=CubicBraidGroup.type.AssionU); U3
Assion group on 3 strands of type U>>> U3.gens()(c0, c1)

Alternative possibilities defining U3:
sage: U3 = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3.gens()(u0, u1)
sage: U3.<u1,u2> = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3.gens()(u1, u2)>>> from sage.all import *>>> U3 = AssionGroupU(Integer(3)); U3
Assion group on 3 strands of type U>>> U3.gens()(u0, u1)(continues on next page)

199

Groups, Release 10.4

(continued from previous page)>>> U3 = AssionGroupU(Integer(3), names=( u1 ,˓→ngens(2); U3
Assion group on 3 strands of type U>>> U3.gens()(u1, u2)u2 ,)); (u1, u2,) = U3._first_

Alternates naming the generators:
sage: U3 = AssionGroupU(3, a, b ); U3
Assion group on 3 strands of type U
sage: U3.gens()(a, b)
sage: C3 = CubicBraidGroup(3, t ); C3
Cubic Braid group on 3 strands
sage: C3.gens()(t0, t1)
sage: U3.is_isomorphic(C3)#I Forcing finiteness test
True
sage: U3.as_classical_group()
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]of (The projective general unitary group of degree 3 over Finite Field of size 2)
sage: C3.as_classical_group()
Subgroup with 2 generators ([ E(3)^20] [1 -E(12)^7][-E(12)^7
1], [0
E(3)^2]) of General Unitary Group of degree 2 over Universal Cyclotomic Field
with respect to positive definite hermitian form[-E(12)^7 + E(12)^11-1][-1 -E(12)^7 + E(12)^11]>>> from sage.all import *>>> U3 = AssionGroupU(Integer(3), a, b ); U3
Assion group on 3 strands of type U>>> U3.gens()(a, b)>>> C3 = CubicBraidGroup(Integer(3), t ); C3
Cubic Braid group on 3 strands>>> C3.gens()(t0, t1)>>> U3.is_isomorphic(C3)#I Forcing finiteness test
True>>> U3.as_classical_group()
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]of (The projective general unitary group of degree 3 over Finite Field of size 2)>>> C3.as_classical_group()
Subgroup with 2 generators ([ E(3)^20] [1 -E(12)^7][-E(12)^7
1], [0
E(3)^2]) of General Unitary Group of degree 2 over Universal Cyclotomic Field
with respect to positive definite hermitian form[-E(12)^7 + E(12)^11-1][-1 -E(12)^7 + E(12)^11]200

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

REFERENCES:• [Cox1957]• [Ass1978]
Element
alias of CubicBraidElement
as_classical_group(embedded=False)
Create an isomorphic image of self as a classical group according to the construction given by Coxeter resp.
Assion.
INPUT:• embedded – boolean (default: False); this boolean effects the cases of Assion groups when
they are realized as projective groups only.
More precisely: if self is of cbg_type
CubicBraidGroup.type.AssionS (for example) and the number of strands n is even,than its classical group is a subgroup of PSp(n,3) (being centralized by the element self.
centralizing_element(projective=True)). By default this group will be given. Setting
embedded = True the classical realization is given as subgroup of its classical enlargement with one
more strand (in this case as subgroup of Sp(n,3)).
OUTPUT:
Depending on the type of self and the number of strands an instance of Sp(n-1,3), GU(n-1,2), subgroup of PSp(n,3), PGU(n,2), or a subgroup of GU(n-1, UCF) (cbg_type ==CubicBraidGroup.type.Coxeter) with respect to a certain Hermitian form attached to the Burau
representation (used by Coxeter and Squier). Here UCF stands for the universal cyclotomic field.
EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: U3 = AssionGroupU(3)sage: U3Cl = U3.as_classical_group(); U3Cl
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of(The projective general unitary group of degree 3 over Finite Field of size␣˓→2)
sage: U3Clemb = U3.as_classical_group(embedded=True); U3Clemb
Subgroup with 2 generators ([0 0 a] [a + 1
aa][0 1 0] [a a + 1a][a 0 a], [aa a + 1]) of General Unitary Group of degree 3 over Finite Field in a of size 2^2
sage: u = U3([-2,1,-2,1]); u(u1^-1*u0)^2
sage: uCl = U3Cl(u); uCl(1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15)
sage: uCle = U3Clemb(u); uCle
[a + 1 a + 1
1][a + 1
0
a]
[
1
a
a]
sage: U3(uCl) == uTrue
sage: U3(uCle) == uTrue
sage: U4 = AssionGroupU(4)sage: U4Cl = U4.as_classical_group(); U4Cl
General Unitary Group of degree 3 over Finite Field in a of size 2^2(continues on next page)201

Groups, Release 10.4

(continued from previous page)

sage: U3Clemb.ambient() == U4Cl
True
sage: # needs sage.rings.number_fieldsage: C4 = CubicBraidGroup(4)sage: C4Cl = C4.as_classical_group(); C4Cl
Subgroup with 3 generators ([ E(3)^200] [1 -E(12)^7[-E(12)^7
10] [0
E(3)^2[001], [0 -E(12)^7

0]
0]
1],

[
1
0
0]
[
0
1 -E(12)^7][
0
0
E(3)^2]) of General Unitary Group of degree 3 over Universal Cyclotomic Field
with respect to positive definite hermitian form[-E(12)^7 + E(12)^11-1
0][-1 -E(12)^7 + E(12)^11-1][
0-1 -E(12)^7 + E(12)^11]>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> U3 = AssionGroupU(Integer(3))>>> U3Cl = U3.as_classical_group(); U3Cl
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of(The projective general unitary group of degree 3 over Finite Field of size␣˓→2)>>> U3Clemb = U3.as_classical_group(embedded=True); U3Clemb
Subgroup with 2 generators ([0 0 a] [a + 1
aa][0 1 0] [a a + 1a][a 0 a], [aa a + 1]) of General Unitary Group of degree 3 over Finite Field in a of size 2^2>>> u = U3([-Integer(2),Integer(1),-Integer(2),Integer(1)]); u(u1^-1*u0)^2>>> uCl = U3Cl(u); uCl(1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15)>>> uCle = U3Clemb(u); uCle
[a + 1 a + 1
1][a + 1
0
a]
[
1
a
a]
>>> U3(uCl) == u
True>>> U3(uCle) == u
True>>> U4 = AssionGroupU(Integer(4))>>> U4Cl = U4.as_classical_group(); U4Cl
General Unitary Group of degree 3 over Finite Field in a of size 2^2>>> U3Clemb.ambient() == U4Cl
True>>> # needs sage.rings.number_field>>> C4 = CubicBraidGroup(Integer(4))>>> C4Cl = C4.as_classical_group(); C4Cl
Subgroup with 3 generators ((continues on next page)

202

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

(continued from previous page)[ E(3)^200] [1 -E(12)^7
0][-E(12)^7
10] [0
E(3)^2
0]
[
0
0
1], [
0 -E(12)^7
1],<BLANKLINE>
[
1
0
0]
[
0
1 -E(12)^7][
0
0
E(3)^2]) of General Unitary Group of degree 3 over Universal Cyclotomic Field
with respect to positive definite hermitian form[-E(12)^7 + E(12)^11-1
0][-1 -E(12)^7 + E(12)^11-1][
0-1 -E(12)^7 + E(12)^11]

as_matrix_group(root_bur=None, domain=None, characteristic=None, var='t', reduced=False)
Create an epimorphic image of self as a matrix group by use of the burau representation.
INPUT:• root_bur – (default: root of unity over) six (resp. twelfth) root of unity in some field• domain – (default: cyclotomic field of order 3 and degree 2, resp. the domain of root_bur if given)base ring for the Burau matrix• characteristic – integer (optional); the characteristic of the domain; if none of the keywords
root_bur, domain and characteristic are given, the default characteristic is 3 (resp. 2)
if self is of cbg_type CubicBraidGroup.type.AssionS (resp. CubicBraidGroup.
type.AssionU)• var – string used for the indeterminate name in case root_bur must be constructed in a splitting field• reduced – boolean (default: False); for more information see the documentation of Braid.
burau_matrix()
EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: C5 = CubicBraidGroup(5)sage: C5Mch5 = C5.as_matrix_group(characteristic=5); C5Mch5
Matrix group over Finite Field in t of size 5^2 with 4 generators ([2*t + 2 3*t + 4
0
0
0]
[
1
0
0
0
0]
[
0
0
1
0
0]
[
0
0
0
1
0]
[
0
0
0
0
1],
[
[
[
[
[

1
0
0
0 2*t + 2 3*t + 4
0
1
0
0
0
0
0
0
0

0
0
0
1
0

0]
0]
0]
0]
1],

[
[
[
[
[

1
0
0
0
0

0
0
0
1
0
0
0 2*t + 2 3*t + 4
0
1
0
0
0
0

0]
0]
0]
0]
1],

[

1

0

0]

0

0

(continues on next page)203

Groups, Release 10.4

(continued from previous page)

[
0
1
0
0
0]
[
0
0
1
0
0]
[
0
0
0 2*t + 2 3*t + 4]
[
0
0
0
1
0]
)
sage: c = C5([3,4,-2,-3,1]); cc2*c3*c1^-1*c2^-1*c0
sage: m = C5Mch5(c); m[2*t + 2 3*t + 4
0
0
0]
[
0
0
0
1
0]
[2*t + 1
0 2*t + 2
3*t 3*t + 3]
[2*t + 200 3*t + 40][0
0 2*t + 2 3*t + 4
0]sage: m_back = C5(m)sage: m_back == cTrue
sage: U5 = AssionGroupU(5); U5
Assion group on 5 strands of type U
sage: U5Mch3 = U5.as_matrix_group(characteristic=3)
Traceback (most recent call last):...
ValueError: Burau representation does not factor through the relations>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> C5 = CubicBraidGroup(Integer(5))>>> C5Mch5 = C5.as_matrix_group(characteristic=Integer(5)); C5Mch5
Matrix group over Finite Field in t of size 5^2 with 4 generators ([2*t + 2 3*t + 4
0
0
0]
[
1
0
0
0
0]
[
0
0
1
0
0]
[
0
0
0
1
0]
[
0
0
0
0
1],
<BLANKLINE>
[
1
0
0
0
0]
[
0 2*t + 2 3*t + 4
0
0]
[
0
1
0
0
0]
[
0
0
0
1
0]
[
0
0
0
0
1],
<BLANKLINE>
[
1
0
0
0
0]
[
0
1
0
0
0]
[
0
0 2*t + 2 3*t + 4
0]
[
0
0
1
0
0]
[
0
0
0
0
1],
<BLANKLINE>
[
1
0
0
0
0]
[
0
1
0
0
0]
[
0
0
1
0
0]
[
0
0
0 2*t + 2 3*t + 4]
[
0
0
0
1
0]
)
>>> c = C5([Integer(3),Integer(4),-Integer(2),-Integer(3),Integer(1)]); cc2*c3*c1^-1*c2^-1*c0>>> m = C5Mch5(c); m[2*t + 2 3*t + 4000](continues on next page)

204

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

(continued from previous page)

[
0
0
0
1
0]
[2*t + 1
0 2*t + 2
3*t 3*t + 3]
[2*t + 200 3*t + 40][0
0 2*t + 2 3*t + 4
0]>>> m_back = C5(m)>>> m_back == c
True>>> U5 = AssionGroupU(Integer(5)); U5
Assion group on 5 strands of type U>>> U5Mch3 = U5.as_matrix_group(characteristic=Integer(3))
Traceback (most recent call last):...
ValueError: Burau representation does not factor through the relations

as_permutation_group(use_classical=True)
Return a permutation group isomorphic to self that has a group isomorphism from self as a conversion.
INPUT:• use_classical – boolean (default: True); the permutation group is calculated via the attached classical matrix group as this results in a smaller degree; if False, the permutation group will be calculatedusing self (as finitely presented group)
EXAMPLES:
sage: C3 = CubicBraidGroup(3)sage: PC3 = C3.as_permutation_group()
sage: assert C3.is_isomorphic(PC3) # random (with respect to the occurrence␣˓→of the info message)#I Forcing finiteness test
sage: PC3.degree()8
sage: c = C3([2,1-2])
sage: C3(PC3(c)) == c
True>>> from sage.all import *>>> C3 = CubicBraidGroup(Integer(3))>>> PC3 = C3.as_permutation_group()>>> assert C3.is_isomorphic(PC3) # random (with respect to the occurrence of␣˓→the info message)#I Forcing finiteness test>>> PC3.degree()8>>> c = C3([Integer(2),Integer(1)-Integer(2)])>>> C3(PC3(c)) == c
True

as_reflection_group()
Return an isomorphic image of self as irreducible complex reflection group.
This is possible only for the finite cubic braid groups of cbg_type CubicBraidGroup.type.
Coxeter.
Note: This method uses the sage implementation of reflection group via the gap3 CHEVIE package. These
must be installed in order to use this method.

205

Groups, Release 10.4

EXAMPLES:
sage: # optional - gap3
sage: C3.<c1,c2> = CubicBraidGroup(3)sage: R3 = C3.as_reflection_group(); R3
Irreducible complex reflection group of rank 2 and type ST4
sage: R3.cartan_matrix()[-2*E(3) - E(3)^2
E(3)^2][-E(3)^2 -2*E(3) - E(3)^2]
sage: R3.simple_roots()
Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)}
sage: R3.simple_coroots()
Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)}>>> from sage.all import *>>> # optional - gap3>>> C3 = CubicBraidGroup(Integer(3), names=( c1 , c2 ,)); (c1, c2,) = C3._
˓→first_ngens(2)>>> R3 = C3.as_reflection_group(); R3
Irreducible complex reflection group of rank 2 and type ST4>>> R3.cartan_matrix()[-2*E(3) - E(3)^2
E(3)^2][-E(3)^2 -2*E(3) - E(3)^2]>>> R3.simple_roots()
Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)}>>> R3.simple_coroots()
Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)}

Conversion maps:
sage: # optional - gap3
sage: r = R3.an_element()
sage: cr = C3(r); cr
c1*c2
sage: mr = r.matrix(); mr[ 1/3*E(3) - 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2][-2/3*E(3) + 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2]
sage: C3Cl = C3.as_classical_group()
sage: C3Cl(cr)[ E(3)^2-E(4)][-E(12)^70]>>> from sage.all import *>>> # optional - gap3>>> r = R3.an_element()>>> cr = C3(r); cr
c1*c2>>> mr = r.matrix(); mr[ 1/3*E(3) - 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2][-2/3*E(3) + 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2]>>> C3Cl = C3.as_classical_group()>>> C3Cl(cr)[ E(3)^2-E(4)][-E(12)^70]

The reflection groups can also be viewed as subgroups of unitary groups over the universal cyclotomic field.
Note that the unitary group corresponding to the reflection group is isomorphic but different from the classicalgroup due to different hermitian forms for the unitary groups they live in:
206

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

sage: # optional - gap3
sage: C4 = CubicBraidGroup(4)sage: R4 = C4.as_reflection_group()
sage: R4.invariant_form()[1 0 0][0 1 0][0 0 1]
sage: _ == C4.classical_invariant_form()
False>>> from sage.all import *>>> # optional - gap3>>> C4 = CubicBraidGroup(Integer(4))>>> R4 = C4.as_reflection_group()>>> R4.invariant_form()[1 0 0][0 1 0][0 0 1]>>> _ == C4.classical_invariant_form()
False

braid_group()
Return a BraidGroup with identical generators, such that there exists an epimorphism to self.
OUTPUT: a BraidGroup having conversion maps to and from self (which is just a section in the latter
case)
EXAMPLES:
sage: U5 = AssionGroupU(5); U5
Assion group on 5 strands of type U
sage: B5 = U5.braid_group(); B5
Braid group on 5 strands
sage: b = B5([4,3,2,-4,1])
sage: u = U5([4,3,2,-4,1])
sage: u == b
False
sage: b.burau_matrix()[ 1 - tt000]
[ 1 - t0t00]
[ 1 - t000t]
[ 1 - t00
1 -1 + t]
[
1
0
0
0
0]
sage: u.burau_matrix()[t + 1t0
00][t + 10t
00][t + 1000t][t + 100
1 t + 1]
[
1
0
0
0
0]
sage: bU = U5(b)sage: uB = B5(u)sage: bU == uTrue
sage: uB == b
True

207

Groups, Release 10.4>>> from sage.all import *>>> U5 = AssionGroupU(Integer(5)); U5
Assion group on 5 strands of type U>>> B5 = U5.braid_group(); B5
Braid group on 5 strands>>> b = B5([Integer(4),Integer(3),Integer(2),-Integer(4),Integer(1)])>>> u = U5([Integer(4),Integer(3),Integer(2),-Integer(4),Integer(1)])>>> u == b
False>>> b.burau_matrix()[ 1 - tt000]
[ 1 - t0t00]
[ 1 - t000t]
[ 1 - t00
1 -1 + t]
[
1
0
0
0
0]
>>> u.burau_matrix()[t + 1t0
00][t + 10t
00][t + 1000t][t + 100
1 t + 1]
[
1
0
0
0
0]
>>> bU = U5(b)>>> uB = B5(u)>>> bU == u
True>>> uB == b
Truecardinality()
To avoid long wait-time on calculations the order will be obtained using the classical realization.
OUTPUT: cardinality of the group as integer or infinity
EXAMPLES:
sage: S15 = AssionGroupS(15)sage: S15.order()109777561863482259035023554842176139436811616256000
sage: C6 = CubicBraidGroup(6)sage: C6.order()+Infinity>>> from sage.all import *>>> S15 = AssionGroupS(Integer(15))>>> S15.order()109777561863482259035023554842176139436811616256000>>> C6 = CubicBraidGroup(Integer(6))>>> C6.order()+Infinity

centralizing_element(embedded=False)
Return the centralizing element defined by the work of Assion (Hilfssatz 1.1.3 and 1.2.3).
INPUT:• embedded – boolean (default; False); this boolean only effects the cases of Assion groups when they
are realized as projective groups. More precisely: if self is of cbg_type CubicBraidGroup.
type.AssionS (for example) and the number of strands n is even, than its classical group is a subgroup

208

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

of PSp(n,3) being centralized by the element return for option embedded=False. Otherwise theimage of this element inside the embedded classical group will be returned (see option embedded ofclassical_group()).
OUTPUT:
Depending on the optional keyword a permutation as an element of PSp(n,3) (type S) or PGU(n,2) (typeU) for n = 0 mod 2 (type S) resp. n = 0 mod 3 (type U) is returned. Otherwise, the centralizing
element is a matrix belonging to Sp(n,3) resp. GU(n,2).
EXAMPLES:
sage: U3 = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3Cl = U3.as_classical_group(); U3Cl
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]of (The projective general unitary group of degree 3 over Finite Field of␣˓→size 2)
sage: c = U3.centralizing_element(); c(1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15)
sage: c in U3Cl
True
sage: P = U3Cl.ambient_group()
sage: P.centralizer(c) == U3Cl
True>>> from sage.all import *>>> U3 = AssionGroupU(Integer(3)); U3
Assion group on 3 strands of type U>>> U3Cl = U3.as_classical_group(); U3Cl
Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]of (The projective general unitary group of degree 3 over Finite Field of␣˓→size 2)>>> c = U3.centralizing_element(); c(1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15)>>> c in U3Cl
True>>> P = U3Cl.ambient_group()>>> P.centralizer(c) == U3Cl
True

Embedded version:
sage: cm = U3.centralizing_element(embedded=True); cm[a + 1 a + 1
1][a + 1
0
a]
[
1
a
a]
sage: U4 = AssionGroupU(4)sage: U4Cl = U4.as_classical_group()
sage: cm in U4Cl
True
sage: [cm * U4Cl(g) == U4Cl(g) * cm for g in U4.gens()][True, True, False]>>> from sage.all import *>>> cm = U3.centralizing_element(embedded=True); cm(continues on next page)

209

Groups, Release 10.4

(continued from previous page)[a + 1 a + 1
1][a + 1
0
a]
[
1
a
a]
>>> U4 = AssionGroupU(Integer(4))>>> U4Cl = U4.as_classical_group()>>> cm in U4Cl
True>>> [cm * U4Cl(g) == U4Cl(g) * cm for g in U4.gens()][True, True, False]classical_invariant_form()
Return the invariant form of the classical realization of self.
OUTPUT:
A square matrix of dimension according to the space the classical realization is operating on. In the case of thefull cubic braid groups and of the Assion groups of cbg_type CubicBraidGroup.type.AssionU
the matrix is Hermitian. In the case of the Assion groups of cbg_type CubicBraidGroup.type.
AssionS it is alternating. Note that the invariant form of the full cubic braid group on more than 5 strands
is degenerated (causing the group to be infinite).
In the case of Assion groups having projective classical groups, the invariant form corresponds to the ambientgroup of its classical embedding.
EXAMPLES:
sage: S3 = AssionGroupS(3)sage: S3.classical_invariant_form()
[0 1]
[2 0]
sage: S4 = AssionGroupS(4)sage: S4.classical_invariant_form()[0 0 0 1][0 0 1 0][0 2 0 0][2 0 0 0]
sage: S5 = AssionGroupS(5)sage: S4.classical_invariant_form() == S5.classical_invariant_form()True
sage: U4 = AssionGroupU(4)sage: U4.classical_invariant_form()[0 0 1][0 1 0][1 0 0]sage: C5 = CubicBraidGroup(5)sage: C5.classical_invariant_form()[-E(12)^7 + E(12)^11
-1
0
␣
˓→ 0]
[
-1 -E(12)^7 + E(12)^11
-1
␣
˓→0]
[
0
-1 -E(12)^7 + E(12)^11
˓→1]
[
0
0
-1 -E(12)^7 + E(12)^˓→11]sage: _.is_singular()False
sage: C6 = CubicBraidGroup(6)(continues on next page)

210

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

(continued from previous page)

sage: C6.classical_invariant_form().is_singular()True>>> from sage.all import *>>> S3 = AssionGroupS(Integer(3))>>> S3.classical_invariant_form()
[0 1]
[2 0]
>>> S4 = AssionGroupS(Integer(4))>>> S4.classical_invariant_form()[0 0 0 1][0 0 1 0][0 2 0 0][2 0 0 0]>>> S5 = AssionGroupS(Integer(5))>>> S4.classical_invariant_form() == S5.classical_invariant_form()
True>>> U4 = AssionGroupU(Integer(4))>>> U4.classical_invariant_form()[0 0 1][0 1 0][1 0 0]>>> C5 = CubicBraidGroup(Integer(5))>>> C5.classical_invariant_form()[-E(12)^7 + E(12)^11
-1
0
␣
˓→ 0]
[
-1 -E(12)^7 + E(12)^11
-1
␣
˓→0]
[
0
-1 -E(12)^7 + E(12)^11
˓→1]
[
0
0
-1 -E(12)^7 + E(12)^˓→11]>>> _.is_singular()False>>> C6 = CubicBraidGroup(Integer(6))>>> C6.classical_invariant_form().is_singular()
True

codegrees()
Return the codegrees of self.
This only makes sense when self is a finite reflection group.
EXAMPLES:
sage: CubicBraidGroup(5).codegrees()(0, 6, 12, 18)>>> from sage.all import *>>> CubicBraidGroup(Integer(5)).codegrees()(0, 6, 12, 18)

cubic_braid_subgroup(nstrands=None)
Return a cubic braid group as subgroup of self on the first nstrands strands.
INPUT:

211

Groups, Release 10.4

• nstrands – (default: self.strands() - 1) integer at least 1 and at most self.strands()
giving the number of strands of the subgroup
Warning: Since self is inherited from UniqueRepresentation, the obtained instance is identical to other instances created with the same arguments (see example below). The ambient group corresponds to the last call of this method.
EXAMPLES:
sage: U5 = AssionGroupU(5)sage: U3s = U5.cubic_braid_subgroup(3)sage: u1, u2 = U3s.gens()
sage: u1 in U5
False
sage: U5(u1) in U5.gens()True
sage: U3s is AssionGroupU(3)True
sage: U3s.ambient() == U5
True>>> from sage.all import *>>> U5 = AssionGroupU(Integer(5))>>> U3s = U5.cubic_braid_subgroup(Integer(3))>>> u1, u2 = U3s.gens()>>> u1 in U5
False>>> U5(u1) in U5.gens()True>>> U3s is AssionGroupU(Integer(3))
True>>> U3s.ambient() == U5
True

degrees()
Return the degrees of self.
This only makes sense when self is a finite reflection group.
EXAMPLES:
sage: CubicBraidGroup(4).degrees()(6, 9, 12)>>> from sage.all import *>>> CubicBraidGroup(Integer(4)).degrees()(6, 9, 12)index_set()
Return the index set of self.
This is the set of integers 0, . . . , 𝑛 − 2 where 𝑛 is the number of strands.
This is only used when self is a finite reflection group.
EXAMPLES:

212

Chapter 13. Cubic Braid Groups

Groups, Release 10.4

sage: CubicBraidGroup(3).index_set()[0, 1]>>> from sage.all import *>>> CubicBraidGroup(Integer(3)).index_set()[0, 1]

is_finite()
Return if self is a finite group or not.
EXAMPLES:
sage: CubicBraidGroup(6).is_finite()
False
sage: AssionGroupS(6).is_finite()True>>> from sage.all import *>>> CubicBraidGroup(Integer(6)).is_finite()
False>>> AssionGroupS(Integer(6)).is_finite()Trueorder()
To avoid long wait-time on calculations the order will be obtained using the classical realization.
OUTPUT: cardinality of the group as integer or infinity
EXAMPLES:
sage: S15 = AssionGroupS(15)sage: S15.order()109777561863482259035023554842176139436811616256000
sage: C6 = CubicBraidGroup(6)sage: C6.order()+Infinity>>> from sage.all import *>>> S15 = AssionGroupS(Integer(15))>>> S15.order()109777561863482259035023554842176139436811616256000>>> C6 = CubicBraidGroup(Integer(6))>>> C6.order()+Infinity

simple_reflections()
Return the generators of self.
This is only used when self is a finite reflection group.
EXAMPLES:
sage: CubicBraidGroup(3).simple_reflections()(c0, c1)213

Groups, Release 10.4>>> from sage.all import *>>> CubicBraidGroup(Integer(3)).simple_reflections()(c0, c1)

strands()
Return the number of strands of the braid group whose image is self.
OUTPUT: Integer
EXAMPLES:
sage: C4 = CubicBraidGroup(4)sage: C4.strands()
4>>> from sage.all import *>>> C4 = CubicBraidGroup(Integer(4))>>> C4.strands()
4

class type(value)
Bases: Enum
Enum class to select the type of the group:• Coxeter – C the full cubic braid group.
• AssionS – S finite factor group of type S considered by Assion• AssionU – U finite factor group of type U considered by Assion
EXAMPLES:
sage: S2 = CubicBraidGroup(2, cbg_type=CubicBraidGroup.type.AssionS); S2
Assion group on 2 strands of type S
sage: U3 = CubicBraidGroup(2, cbg_type= U )Traceback (most recent call last):...
TypeError: the cbg_type must be an instance of <enum CubicBraidGroup.type >>>> from sage.all import *>>> S2 = CubicBraidGroup(Integer(2), cbg_type=CubicBraidGroup.type.AssionS);␣
˓→S2
Assion group on 2 strands of type S>>> U3 = CubicBraidGroup(Integer(2), cbg_type= U )Traceback (most recent call last):...
TypeError: the cbg_type must be an instance of <enum CubicBraidGroup.type >214

AssionS =S

AssionU =U

Coxeter =C

Chapter 13. Cubic Braid Groups

CHAPTERFOURTEEN

INDEXED FREE GROUPS

Free groups and free abelian groups implemented using an indexed set of generators.
AUTHORS:• Travis Scrimshaw (2013-10-16): Initial version
class sage.groups.indexed_free_group.IndexedFreeAbelianGroup(indices, prefix,
category=None, **kwds)
Bases: IndexedGroup, AbelianGroupAn indexed free abelian group.
EXAMPLES:
sage: G = Groups().Commutative().free(index_set=ZZ)
sage: GFree abelian group indexed by Integer Ringsage: G = Groups().Commutative().free(index_set= abcde )sage: GFree abelian group indexed by { a , b , c , d , e }>>> from sage.all import *>>> G = Groups().Commutative().free(index_set=ZZ)>>> GFree abelian group indexed by Integer Ring>>> G = Groups().Commutative().free(index_set= abcde )>>> GFree abelian group indexed by { a , b , c , d , e }class Element(F, x)
Bases: IndexedFreeAbelianMonoidElement, Elementgen(x)The generator indexed by x of self.
EXAMPLES:
sage: G = Groups().Commutative().free(index_set=ZZ)
sage: G.gen(0)F[0]sage: G.gen(2)
F[2]

215

Groups, Release 10.4>>> from sage.all import *>>> G = Groups().Commutative().free(index_set=ZZ)>>> G.gen(Integer(0))
F[0]>>> G.gen(Integer(2))
F[2]

one()
Return the identity element of self.
EXAMPLES:
sage: G = Groups().Commutative().free(index_set=ZZ)
sage: G.one()1>>> from sage.all import *>>> G = Groups().Commutative().free(index_set=ZZ)>>> G.one()
1class sage.groups.indexed_free_group.IndexedFreeGroup(indices, prefix, category=None,**kwds)Bases: IndexedGroup, GroupAn indexed free group.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: GFree group indexed by Integer Ringsage: G = Groups().free(index_set= abcde )sage: GFree group indexed by { a , b , c , d ,e }>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> GFree group indexed by Integer Ring>>> G = Groups().free(index_set= abcde )>>> GFree group indexed by { a , b , c , d ,e }class Element(F, x)
Bases: IndexedFreeMonoidElement
length()Return the length of self.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: a,b,c,d,e = [G.gen(i) for i in range(5)]sage: elt = a*c^-3*b^-2*a
sage: elt.length()7(continues on next page)

216

Chapter 14. Indexed Free Groups

Groups, Release 10.4

(continued from previous page)

sage: len(elt)7
sage: G = Groups().free(index_set=ZZ)
sage: a,b,c,d,e = [G.gen(i) for i in range(5)]sage: elt = a*c^-3*b^-2*a
sage: elt.length()
7
sage: len(elt)7>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> a,b,c,d,e = [G.gen(i) for i in range(Integer(5))]>>> elt = a*c**-Integer(3)*b**-Integer(2)*a>>> elt.length()
7>>> len(elt)7>>> G = Groups().free(index_set=ZZ)>>> a,b,c,d,e = [G.gen(i) for i in range(Integer(5))]>>> elt = a*c**-Integer(3)*b**-Integer(2)*a>>> elt.length()
7>>> len(elt)7

to_word_list()
Return self as a word represented as a list whose entries are the pairs (i, s) where i is the index
and s is the sign.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: a,b,c,d,e = [G.gen(i) for i in range(5)]sage: x = a*b^2*e*a^-1
sage: x.to_word_list()[(0, 1), (1, 1), (1, 1), (4, 1), (0, -1)]>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> a,b,c,d,e = [G.gen(i) for i in range(Integer(5))]>>> x = a*b**Integer(2)*e*a**-Integer(1)>>> x.to_word_list()[(0, 1), (1, 1), (1, 1), (4, 1), (0, -1)]

gen(x)The generator indexed by x of self.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: G.gen(0)F[0](continues on next page)217

Groups, Release 10.4

(continued from previous page)

sage: G.gen(2)F[2]>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> G.gen(Integer(0))
F[0]>>> G.gen(Integer(2))
F[2]

one()
Return the identity element of self.
EXAMPLES:
sage: G = Groups().free(ZZ)
sage: G.one()1>>> from sage.all import *>>> G = Groups().free(ZZ)>>> G.one()
1class sage.groups.indexed_free_group.IndexedGroup(indices, prefix, category=None,names=None, **kwds)
Bases: IndexedMonoid
Base class for free (abelian) groups whose generators are indexed by a set.
gens()
Return the group generators of self.
EXAMPLES:
sage: G = Groups.free(index_set=ZZ)
sage: G.group_generators()
Lazy family (Generator map from Integer Ring toFree group indexed by Integer Ring(i))_{i in Integer Ring}sage: G = Groups().free(index_set= abcde )sage: sorted(G.group_generators())[F[ a ], F[ b ], F[ c ], F[ d ], F[ e ]]>>> from sage.all import *>>> G = Groups.free(index_set=ZZ)>>> G.group_generators()
Lazy family (Generator map from Integer Ring toFree group indexed by Integer Ring(i))_{i in Integer Ring}>>> G = Groups().free(index_set= abcde )>>> sorted(G.group_generators())[F[ a ], F[ b ], F[ c ], F[ d ], F[ e ]]group_generators()
Return the group generators of self.
EXAMPLES:
218

Chapter 14. Indexed Free Groups

Groups, Release 10.4

sage: G = Groups.free(index_set=ZZ)
sage: G.group_generators()
Lazy family (Generator map from Integer Ring toFree group indexed by Integer Ring(i))_{i in Integer Ring}sage: G = Groups().free(index_set= abcde )sage: sorted(G.group_generators())[F[ a ], F[ b ], F[ c ], F[ d ], F[ e ]]>>> from sage.all import *>>> G = Groups.free(index_set=ZZ)>>> G.group_generators()
Lazy family (Generator map from Integer Ring toFree group indexed by Integer Ring(i))_{i in Integer Ring}>>> G = Groups().free(index_set= abcde )>>> sorted(G.group_generators())[F[ a ], F[ b ], F[ c ], F[ d ], F[ e ]]order()
Return the number of elements of self, which is ∞ unless this is the trivial group.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: G.order()+Infinity
sage: G = Groups().Commutative().free(index_set= abc )sage: G.order()+Infinity
sage: G = Groups().Commutative().free(index_set=[])sage: G.order()1>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> G.order()+Infinity>>> G = Groups().Commutative().free(index_set= abc )>>> G.order()+Infinity>>> G = Groups().Commutative().free(index_set=[])>>> G.order()1rank()
Return the rank of self.
This is the number of generators of self.
EXAMPLES:
sage: G = Groups().free(index_set=ZZ)
sage: G.rank()+Infinity
sage: G = Groups().free(index_set= abc )sage: G.rank()
3sage: G = Groups().free(index_set=[])(continues on next page)219

Groups, Release 10.4

(continued from previous page)

sage: G.rank()
0>>> from sage.all import *>>> G = Groups().free(index_set=ZZ)>>> G.rank()+Infinity>>> G = Groups().free(index_set= abc )>>> G.rank()
3>>> G = Groups().free(index_set=[])>>> G.rank()0sage: G = Groups().Commutative().free(index_set=ZZ)
sage: G.rank()+Infinity
sage: G = Groups().Commutative().free(index_set= abc )sage: G.rank()
3sage: G = Groups().Commutative().free(index_set=[])sage: G.rank()
0>>> from sage.all import *>>> G = Groups().Commutative().free(index_set=ZZ)>>> G.rank()+Infinity>>> G = Groups().Commutative().free(index_set= abc )>>> G.rank()
3>>> G = Groups().Commutative().free(index_set=[])>>> G.rank()
0220

Chapter 14. Indexed Free Groups

CHAPTERFIFTEEN

ARTIN GROUPS

Artin groups are implemented as a particular case of finitely presented groups. For finite-type Artin groups, there is a
specific left normal form using the Garside structure associated to the lift the long element of the corresponding Coxeter
group.
AUTHORS:• Travis Scrimshaw (2018-02-05): Initial version
class sage.groups.artin.ArtinGroup(coxeter_matrix, names)
Bases: FinitelyPresentedGroup
An Artin group.
Fix an index set 𝐼. Let 𝑀 = (𝑚𝑖𝑗 )𝑖,𝑗∈𝐼 be a Coxeter matrix. An Artin group is a group 𝐴𝑀 that has apresentation given by generators {𝑠𝑖 | 𝑖 ∈ 𝐼} and relations
𝑠𝑖 𝑠𝑗 𝑠𝑖 · · · = 𝑠𝑗 𝑠𝑖 𝑠𝑗 · · ·
⏟ ⏞
⏟
⏞
𝑚𝑖𝑗

𝑚𝑗𝑖 factors

for all 𝑖, 𝑗 ∈ 𝐼 with the usual convention that 𝑚𝑖𝑗 = ∞ implies no relation between 𝑠𝑖 and 𝑠𝑗 . There is a natural
corresponding Coxeter group 𝑊𝑀 by imposing the additional relations 𝑠2𝑖 = 1 for all 𝑖 ∈ 𝐼. Furthermore, there isa natural section of 𝑊𝑀 by sending a reduced word 𝑠𝑖1 · · · 𝑠𝑖ℓ ↦→ 𝑠𝑖1 · · · 𝑠𝑖ℓ .
Artin groups 𝐴𝑀 are classified based on the Coxeter data:• 𝐴𝑀 is of finite type or spherical if 𝑊𝑀 is finite;• 𝐴𝑀 is of affine type if 𝑊𝑀 is of affine type;• 𝐴𝑀 is of large type if 𝑚𝑖𝑗 ≥ 4 for all 𝑖, 𝑗 ∈ 𝐼;
• 𝐴𝑀 is of extra-large type if 𝑚𝑖𝑗 ≥ 5 for all 𝑖, 𝑗 ∈ 𝐼;
• 𝐴𝑀 is right-angled if 𝑚𝑖𝑗 ∈ {2, ∞} for all 𝑖, 𝑗 ∈ 𝐼.
Artin groups are conjectured to have many nice properties:• Artin groups are torsion free.
• Finite type Artin groups have 𝑍(𝐴𝑀 ) =and infinite type Artin groups have trivial center.

• Artin groups have solvable word problems.
• 𝐻𝑊𝑀 /𝑊𝑀 is a 𝐾(𝐴𝑀 , 1)-space, where 𝐻𝑊 is the hyperplane complement of the Coxeter group 𝑊 acting
on C𝑛 .
These conjectures are known when the Artin group is finite type and a number of other cases. See, e.g., [GP2012]
and references therein.
INPUT:
221

Groups, Release 10.4

• coxeter_data – data defining a Coxeter matrix• names – string or list/tuple/iterable of strings (default: s ); the generator names or name prefix
EXAMPLES:
sage: A.<a,b,c> = ArtinGroup([ B ,3]);
˓→needs sage.rings.number_field
Artin group of type [ B , 3]
sage: ArtinGroup([ B ,3])
˓→needs sage.rings.number_field
Artin group of type [ B , 3]A>>> from sage.all import *>>> A = ArtinGroup([ B ,Integer(3)], names=( a ,˓→first_ngens(3);A˓→number_field
Artin group of type [ B , 3]>>> ArtinGroup([ B ,Integer(3)])˓→# needs sage.rings.number_field
Artin group of type [ B , 3]

#␣

#␣

b ,

c ,)); (a, b, c,) = A._# needs sage.rings.

␣

The input must always include the Coxeter data, but the names can either be a string representing the prefix of thenames or the explicit names of the generators. Otherwise the default prefix of s is used:
sage: ArtinGroup([ B ,2]).generators()
˓→needs sage.rings.number_field(s1, s2)
sage: ArtinGroup([ B ,2], g ).generators()
˓→needs sage.rings.number_field(g1, g2)
sage: ArtinGroup([ B ,2], x,y ).generators()
˓→needs sage.rings.number_field(x, y)>>> from sage.all import *>>> ArtinGroup([ B ,Integer(2)]).generators()˓→# needs sage.rings.number_field(s1, s2)>>> ArtinGroup([ B ,Integer(2)], g ).generators()˓→# needs sage.rings.number_field(g1, g2)>>> ArtinGroup([ B ,Integer(2)], x,y ).generators()˓→# needs sage.rings.number_field(x, y)

#␣

#␣

#␣

␣

␣

␣

REFERENCES:• Wikipedia article Artin_group
See also:
RightAngledArtinGroup
Element
alias of ArtinGroupElement
an_element()
Return an element of self.

222

Chapter 15. Artin Groups

Groups, Release 10.4

EXAMPLES:
sage: A = ArtinGroup([ B ,2])
˓→needs sage.rings.number_fieldsage: A.an_element()
˓→needs sage.rings.number_fields1>>> from sage.all import *>>> A = ArtinGroup([ B ,Integer(2)])˓→# needs sage.rings.number_field>>> A.an_element()
˓→needs sage.rings.number_field
s1

#␣
#␣

␣
#␣

as_permutation_group()
Return an isomorphic permutation group.
This raises a ValueError error since Artin groups are infinite and have no corresponding permutationgroup.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.as_permutation_group()
Traceback (most recent call last):...
ValueError: the group is infinite
sage: A = ArtinGroup([ D ,4], g )˓→needs sage.rings.number_fieldsage: A.as_permutation_group()
˓→needs sage.rings.number_field
Traceback (most recent call last):...
ValueError: the group is infinite#␣#␣>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.as_permutation_group()
Traceback (most recent call last):...
ValueError: the group is infinite>>> A = ArtinGroup([ D ,Integer(4)], g )˓→# needs sage.rings.number_field>>> A.as_permutation_group()
˓→needs sage.rings.number_field
Traceback (most recent call last):...
ValueError: the group is infinite␣#␣

cardinality()
Return the number of elements of self.
OUTPUT: Infinity
223

Groups, Release 10.4

EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.cardinality()+Infinity
sage: A = ArtinGroup([ A ,1])
˓→needs sage.rings.number_fieldsage: A.cardinality()
˓→needs sage.rings.number_field+Infinity#␣#␣>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.cardinality()+Infinity>>> A = ArtinGroup([ A ,Integer(1)])˓→# needs sage.rings.number_field>>> A.cardinality()
˓→needs sage.rings.number_field+Infinity␣#␣

coxeter_group()
Return the Coxeter group of self.
EXAMPLES:
sage: A = ArtinGroup([ D ,4])
˓→needs sage.rings.number_fieldsage: A.coxeter_group()
˓→needs sage.rings.number_field
Finite Coxeter group over Integer Ring with Coxeter matrix:[1 3 2 2][3 1 3 3][2 3 1 2][2 3 2 1]>>> from sage.all import *>>> A = ArtinGroup([ D ,Integer(4)])˓→# needs sage.rings.number_field>>> A.coxeter_group()
˓→needs sage.rings.number_field
Finite Coxeter group over Integer Ring with Coxeter matrix:[1 3 2 2][3 1 3 3][2 3 1 2][2 3 2 1]

#␣
#␣

␣
#␣

coxeter_matrix()
Return the Coxeter matrix of self.
EXAMPLES:

224

Chapter 15. Artin Groups

Groups, Release 10.4

sage: A = ArtinGroup([ B ,3])
˓→needs sage.rings.number_fieldsage: A.coxeter_matrix()
˓→needs sage.rings.number_field[1 3 2][3 1 4][2 4 1]>>> from sage.all import *>>> A = ArtinGroup([ B ,Integer(3)])˓→# needs sage.rings.number_field>>> A.coxeter_matrix()
˓→needs sage.rings.number_field[1 3 2][3 1 4][2 4 1]

#␣
#␣

␣
#␣

coxeter_type()
Return the Coxeter type of self.
EXAMPLES:
sage: A = ArtinGroup([ D ,4])
˓→needs sage.rings.number_fieldsage: A.coxeter_type()
˓→needs sage.rings.number_field
Coxeter type of [ D , 4]>>> from sage.all import *>>> A = ArtinGroup([ D ,Integer(4)])˓→# needs sage.rings.number_field>>> A.coxeter_type()
˓→needs sage.rings.number_field
Coxeter type of [ D , 4]

#␣
#␣

␣
#␣

index_set()
Return the index set of self.
OUTPUT: tuple
EXAMPLES:
sage: A = ArtinGroup([ E ,7])
˓→needs sage.rings.number_fieldsage: A.index_set()˓→needs sage.rings.number_field(1, 2, 3, 4, 5, 6, 7)>>> from sage.all import *>>> A = ArtinGroup([ E ,Integer(7)])˓→# needs sage.rings.number_field>>> A.index_set()˓→needs sage.rings.number_field(1, 2, 3, 4, 5, 6, 7)

#␣
#␣

␣
#␣

order()
Return the number of elements of self.
225

Groups, Release 10.4

OUTPUT: Infinity
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.cardinality()+Infinity
sage: A = ArtinGroup([ A ,1])
˓→needs sage.rings.number_fieldsage: A.cardinality()
˓→needs sage.rings.number_field+Infinity#␣#␣>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.cardinality()+Infinity>>> A = ArtinGroup([ A ,Integer(1)])˓→# needs sage.rings.number_field>>> A.cardinality()
˓→needs sage.rings.number_field+Infinity␣#␣

some_elements()
Return a list of some elements of self.
EXAMPLES:
sage: A = ArtinGroup([ B ,3])
˓→needs sage.rings.number_fieldsage: A.some_elements()
˓→needs sage.rings.number_field[s1, s1*s2*s3, (s1*s2*s3)^3]>>> from sage.all import *>>> A = ArtinGroup([ B ,Integer(3)])˓→# needs sage.rings.number_field>>> A.some_elements()
˓→needs sage.rings.number_field[s1, s1*s2*s3, (s1*s2*s3)^3]

#␣
#␣

␣
#␣

class sage.groups.artin.ArtinGroupElement(parent, x, check=True)
Bases: FinitelyPresentedGroupElement
An element of an Artin group.
It is a particular case of element of a finitely presented group.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A.<s1,s2,s3> = ArtinGroup([ B ,3])
sage: A
Artin group of type [ B , 3]
(continues on next page)

226

Chapter 15. Artin Groups

Groups, Release 10.4

(continued from previous page)

sage: s1 * s2 / s3 / s2
s1*s2*s3^-1*s2^-1
sage: A((1, 2, -3, -2))
s1*s2*s3^-1*s2^-1>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = ArtinGroup([ B ,Integer(3)], names=( s1 , s2 , s3 ,)); (s1, s2, s3,) =␣
˓→A._first_ngens(3)>>> A
Artin group of type [ B , 3]>>> s1 * s2 / s3 / s2
s1*s2*s3^-1*s2^-1>>> A((Integer(1), Integer(2), -Integer(3), -Integer(2)))
s1*s2*s3^-1*s2^-1

coxeter_group_element(W=None)
Return the corresponding Coxeter group element under the natural projection.
INPUT:• W – (default: self.parent().coxeter_group()) the image Coxeter group
OUTPUT: an element of the Coxeter group W
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: B.<s1,s2,s3> = ArtinGroup([ B ,3])
sage: b = s1 * s2 / s3 / s2
sage: b1 = b.coxeter_group_element(); b1[ 1 -1 0][ 2 -1 0][ a -a 1]
sage: b.coxeter_group_element().reduced_word()[1, 2, 3, 2]
sage: A.<s1,s2,s3> = ArtinGroup([ A ,3])
sage: c = s1 * s2 *s3
sage: c1 = c.coxeter_group_element(); c1[4, 1, 2, 3]
sage: c1.reduced_word()[3, 2, 1]
sage: c.coxeter_group_element(W=SymmetricGroup(4))(1,4,3,2)
sage: A.<s1,s2,s3> = BraidGroup(4)sage: c = s1 * s2 * s3^-1
sage: c0 = c.coxeter_group_element(); c0[4, 1, 2, 3]
sage: c1 = c.coxeter_group_element(W=SymmetricGroup(4)); c1(1,4,3,2)>>> from sage.all import *>>> # needs sage.rings.number_field>>> B = ArtinGroup([ B ,Integer(3)], names=( s1 ,˓→) = B._first_ngens(3)>>> b = s1 * s2 / s3 / s2>>> b1 = b.coxeter_group_element(); b1s2 ,s3 ,)); (s1, s2, s3,(continues on next page)

227

Groups, Release 10.4

(continued from previous page)[ 1 -1 0][ 2 -1 0][ a -a 1]>>> b.coxeter_group_element().reduced_word()[1, 2, 3, 2]>>> A = ArtinGroup([ A ,Integer(3)], names=( s1 , s2 , s3 ,)); (s1, s2, s3,
˓→) = A._first_ngens(3)>>> c = s1 * s2 *s3>>> c1 = c.coxeter_group_element(); c1[4, 1, 2, 3]>>> c1.reduced_word()[3, 2, 1]>>> c.coxeter_group_element(W=SymmetricGroup(Integer(4)))(1,4,3,2)>>> A = BraidGroup(Integer(4), names=( s1 , s2 , s3 ,)); (s1, s2, s3,) = A._˓→first_ngens(3)>>> c = s1 * s2 * s3**-Integer(1)>>> c0 = c.coxeter_group_element(); c0[4, 1, 2, 3]>>> c1 = c.coxeter_group_element(W=SymmetricGroup(Integer(4))); c1(1,4,3,2)

From an element of the Coxeter group it is possible to recover the image by the standard section to the Artin
group:
sage: # needs sage.rings.number_fieldsage: B(b1)s1*s2*s3*s2
sage: A(c0)s1*s2*s3
sage: A(c0) == A(c1)True>>> from sage.all import *>>> # needs sage.rings.number_field>>> B(b1)s1*s2*s3*s2>>> A(c0)s1*s2*s3>>> A(c0) == A(c1)
True

exponent_sum()
Return the exponent sum of self.
OUTPUT: integer
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = ArtinGroup([ E ,6])
sage: b = A([1, 4, -3, 2])
sage: b.exponent_sum()2
sage: b = A([])
sage: b.exponent_sum()0(continues on next page)

228

Chapter 15. Artin Groups

Groups, Release 10.4

(continued from previous page)

sage: B = BraidGroup(5)sage: b = B([1, 4, -3, 2])
sage: b.exponent_sum()2
sage: b = B([])
sage: b.exponent_sum()0>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = ArtinGroup([ E ,Integer(6)])>>> b = A([Integer(1), Integer(4), -Integer(3), Integer(2)])>>> b.exponent_sum()2>>> b = A([])>>> b.exponent_sum()0>>> B = BraidGroup(Integer(5))>>> b = B([Integer(1), Integer(4), -Integer(3), Integer(2)])>>> b.exponent_sum()2>>> b = B([])>>> b.exponent_sum()0class sage.groups.artin.FiniteTypeArtinGroup(coxeter_matrix, names)
Bases: ArtinGroupA finite-type Artin group.
An Artin group is finite-type or spherical if the corresponding Coxeter group is finite. Finite type Artin groups are
known to be torsion free, have a Garside structure given by Δ (see delta()) and have a center generated by Δ.
See also:
ArtinGroup
EXAMPLES:
sage: ArtinGroup([ E ,7])
˓→needs sage.rings.number_field
Artin group of type [ E , 7]>>> from sage.all import *>>> ArtinGroup([ E ,Integer(7)])˓→# needs sage.rings.number_field
Artin group of type [ E , 7]#␣␣

Since the word problem for finite-type Artin groups is solvable, their Cayley graph can be locally obtained as follows(see Issue #16059):
sage: def ball(group, radius):....:
ret = set()....:
ret.add(group.one())....:
for length in range(1, radius):(continues on next page)229

Groups, Release 10.4

(continued from previous page)....:
for w in Words(alphabet=group.gens(), length=length):....:
ret.add(prod(w))....:
return ret
sage: A = ArtinGroup([ B ,3])
˓→needs sage.rings.number_fieldsage: GA = A.cayley_graph(elements=ball(A, 4), generators=A.gens()); GA˓→needs sage.rings.number_field
Digraph on 32 vertices>>> from sage.all import *>>> def ball(group, radius):...
ret = set()...
ret.add(group.one())...
for length in range(Integer(1), radius):...
for w in Words(alphabet=group.gens(), length=length):...
ret.add(prod(w))...
return ret>>> A = ArtinGroup([ B ,Integer(3)])˓→# needs sage.rings.number_field>>> GA = A.cayley_graph(elements=ball(A, Integer(4)), generators=A.gens()); GA˓→# needs sage.rings.number_field
Digraph on 32 vertices

#␣
#␣

␣
␣

Since the Artin group has nontrivial relations, this graph contains less vertices than the one associated to the freegroup (which is a tree):sage: F = FreeGroup(3)sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF
˓→needs sage.combinat
Digraph on 40 vertices>>> from sage.all import *>>> F = FreeGroup(Integer(3))>>> GF = F.cayley_graph(elements=ball(F, Integer(4)), generators=F.gens()); GF˓→# needs sage.combinat
Digraph on 40 vertices#␣␣

Element
alias of FiniteTypeArtinGroupElement
delta()
Return the Δ element of self.
EXAMPLES:
sage: A = ArtinGroup([ B ,3])
˓→needs sage.rings.number_fieldsage: A.delta()
˓→needs sage.rings.number_fields3*(s2*s3*s1)^2*s2*s1#␣

sage: A = ArtinGroup([ G ,2])
˓→needs sage.rings.number_fieldsage: A.delta()
˓→needs sage.rings.number_field(s2*s1)^3

#␣

#␣

#␣

(continues on next page)

230

Chapter 15. Artin Groups

Groups, Release 10.4

(continued from previous page)

sage: B = BraidGroup(5)sage: B.delta()
s0*s1*s2*s3*s0*s1*s2*s0*s1*s0>>> from sage.all import *>>> A = ArtinGroup([ B ,Integer(3)])˓→# needs sage.rings.number_field>>> A.delta()
˓→needs sage.rings.number_fields3*(s2*s3*s1)^2*s2*s1␣#␣>>> A = ArtinGroup([ G ,Integer(2)])˓→# needs sage.rings.number_field>>> A.delta()
˓→needs sage.rings.number_field(s2*s1)^3␣#␣>>> B = BraidGroup(Integer(5))>>> B.delta()
s0*s1*s2*s3*s0*s1*s2*s0*s1*s0

class sage.groups.artin.FiniteTypeArtinGroupElement(parent, x, check=True)
Bases: ArtinGroupElement
An element of a finite-type Artin group.
left_normal_form()
Return the left normal form of self.
OUTPUT:
A tuple of simple generators in the left normal form. The first element is a power of Δ, and the rest areelements of the natural section lift from the corresponding Coxeter group.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = ArtinGroup([ B ,3])
sage: A([1]).left_normal_form()(1, s1)
sage: A([-1]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1, s3*(s2*s3*s1)^2*s2)
sage: A([1, 2, 2, 1, 2]).left_normal_form()(1, s1*s2*s1, s2*s1)
sage: A([3, 3, -2]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1,s3*s1*s2*s3*s2*s1, s3, s3*s2*s3)
sage: A([1, 2, 3, -1, 2, -3]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1,(s3*s1*s2)^2*s1, s1*s2*s3*s2)
sage: A([1,2,1,3,2,1,3,2,3,3,2,3,1,2,3,1,2,3,1,2]).left_normal_form()((s3*(s2*s3*s1)^2*s2*s1)^2, s3*s2)
sage: B = BraidGroup(4)sage: b = B([1, 2, 3, -1, 2, -3])
sage: b.left_normal_form()(continues on next page)231

Groups, Release 10.4

(continued from previous page)(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1, s0*s1*s2*s1*s0, s0*s2*s1)
sage: c = B([1])
sage: c.left_normal_form()(1, s0)>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = ArtinGroup([ B ,Integer(3)])>>> A([Integer(1)]).left_normal_form()(1, s1)>>> A([-Integer(1)]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1, s3*(s2*s3*s1)^2*s2)>>> A([Integer(1), Integer(2), Integer(2), Integer(1), Integer(2)]).left_
˓→normal_form()(1, s1*s2*s1, s2*s1)>>> A([Integer(3), Integer(3), -Integer(2)]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1,s3*s1*s2*s3*s2*s1, s3, s3*s2*s3)>>> A([Integer(1), Integer(2), Integer(3), -Integer(1), Integer(2), ˓→Integer(3)]).left_normal_form()(s1^-1*(s2^-1*s1^-1*s3^-1)^2*s2^-1*s3^-1,(s3*s1*s2)^2*s1, s1*s2*s3*s2)>>> A([Integer(1),Integer(2),Integer(1),Integer(3),Integer(2),Integer(1),˓→Integer(3),Integer(2),Integer(3),Integer(3),Integer(2),Integer(3),˓→Integer(1),Integer(2),Integer(3),Integer(1),Integer(2),Integer(3),˓→Integer(1),Integer(2)]).left_normal_form()((s3*(s2*s3*s1)^2*s2*s1)^2, s3*s2)>>> B = BraidGroup(Integer(4))>>> b = B([Integer(1), Integer(2), Integer(3), -Integer(1), Integer(2), ˓→Integer(3)])>>> b.left_normal_form()(s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1, s0*s1*s2*s1*s0, s0*s2*s1)>>> c = B([Integer(1)])>>> c.left_normal_form()(1, s0)232

Chapter 15. Artin Groups

CHAPTERSIXTEEN

RIGHT-ANGLED ARTIN GROUPS

A right-angled Artin group (often abbreviated as RAAG) is a group which has a presentation whose only relations arecommutators between generators. These are also known as graph groups, since they are (uniquely) encoded by (simple)
graphs, or partially commutative groups.
AUTHORS:• Travis Scrimshaw (2013-09-01): Initial version• Travis Scrimshaw (2018-02-05): Made compatible with ArtinGroup
class sage.groups.raag.CohomologyRAAG(R, A)
Bases: CombinatorialFreeModule
The cohomology ring of a right-angled Artin group.
The cohomology ring of a right-angled Artin group 𝐴, defined by the graph 𝐺, with coefficients in a field 𝐹 isisomorphic to the exterior algebra of 𝐹 𝑁 , where 𝑁 is the number of vertices in 𝐺, modulo the quadratic relations𝑒𝑖 ∧ 𝑒𝑗 = 0 if and only if (𝑖, 𝑗) is an edge in 𝐺. This algebra is sometimes also known as the Cartier-Foata algebra.
REFERENCES:• [CQ2019]class Element
Bases: CohomologyRAAGElement
An element in the cohomology ring of a right-angled Artin group.
algebra_generators()
Return the algebra generators of self.
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: H.algebra_generators()
Finite family {0: e0, 1: e1, 2: e2, 3: e3}>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()>>> H.algebra_generators()
Finite family {0: e0, 1: e1, 2: e2, 3: e3}233

Groups, Release 10.4

degree_on_basis(I)Return the degree on the basis element clique.
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: sorted([H.degree_on_basis(I) for I in H.basis().keys()])[0, 1, 1, 1, 1, 2, 2]>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()>>> sorted([H.degree_on_basis(I) for I in H.basis().keys()])[0, 1, 1, 1, 1, 2, 2]

gen(i)
Return the i-th standard generator of the algebra self.
This corresponds to the i-th vertex in the graph (under a fixed ordering of the vertices).
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: H.gen(0)e0sage: H.gen(1)e1>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()>>> H.gen(Integer(0))
e0>>> H.gen(Integer(1))
e1gens()
Return the generators of self (as an algebra).
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: H.gens()(e0, e1, e2, e3)>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()(continues on next page)

234

Chapter 16. Right-Angled Artin Groups

Groups, Release 10.4

(continued from previous page)>>> H.gens()(e0, e1, e2, e3)ngens()
Return the number of algebra generators of self.
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: H.ngens()
4>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()>>> H.ngens()
4

one_basis()
Return the basis element indexing 1 of self.
EXAMPLES:
sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: H = A.cohomology()
sage: H.one_basis()()>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> H = A.cohomology()>>> H.one_basis()()

class sage.groups.raag.RightAngledArtinGroup(G, names)
Bases: ArtinGroupThe right-angled Artin group defined by a graph 𝐺.
Let Γ = {𝑉 (Γ), 𝐸(Γ)} be a simple graph. A right-angled Artin group (commonly abbreviated as RAAG) is thegroup𝐴Γ = ⟨𝑔𝑣 : 𝑣 ∈ 𝑉 (Γ) | [𝑔𝑢 , 𝑔𝑣 ] if {𝑢, 𝑣} ∈/ 𝐸(Γ)⟩.
These are sometimes known as graph groups or partially commutative groups. This RAAG’s contains both freegroups, given by the complete graphs, and free abelian groups, given by disjoint vertices.
Warning: This is the opposite convention of some papers.
Right-angled Artin groups contain many remarkable properties and have a very rich structure despite their simple
presentation. Here are some known facts:
235

Groups, Release 10.4

• The word problem is solvable.
• They are known to be rigid; that is for any finite simple graphs Δ and Γ, we have 𝐴Δ ∼= 𝐴Γ if and only ifΔ∼Γ[Dro1987].
=• They embed as a finite index subgroup of a right-angled Coxeter group (which is the same definition as above
except with the additional relations 𝑔𝑣2 = 1 for all 𝑣 ∈ 𝑉 (Γ)).
• In [BB1997], it was shown they contain subgroups that satisfy the property 𝐹 𝑃2 but are not finitely presented
by considering the kernel of 𝜑 : 𝐴Γ → by 𝑔𝑣 ↦→ 1 (i.e. words of exponent sum 0).
• 𝐴Γ has a finite 𝐾(𝜋, 1) space.
• 𝐴Γ acts freely and cocompactly on a finite dimensional 𝐶𝐴𝑇 (0) space, and so it is biautomatic.
• Given an Artin group 𝐵 with generators 𝑠𝑖 , then any subgroup generated by a collection of 𝑣𝑖 = 𝑠𝑘𝑖 𝑖 where𝑘𝑖 ≥ 2 is a RAAG where [𝑣𝑖 , 𝑣𝑗 ] = 1 if and only if [𝑠𝑖 , 𝑠𝑗 ] = 1 [CP2001].
The normal forms for RAAG’s in Sage are those described in [VW1994] and gathers commuting groups together.
INPUT:• G – a graph• names – a string or a list of generator names
EXAMPLES:
sage: Gamma = Graph(4)sage: G = RightAngledArtinGroup(Gamma)
sage: a,b,c,d = G.gens()
sage: a*c*d^4*a^-3*bv0^-2*v1*v2*v3^4
sage: Gamma = graphs.CompleteGraph(4)sage: G = RightAngledArtinGroup(Gamma)
sage: a,b,c,d = G.gens()
sage: a*c*d^4*a^-3*bv0*v2*v3^4*v0^-3*v1
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G
Right-angled Artin group of Cycle graphsage: a,b,c,d,e = G.gens()
sage: d*b*a*d
v1*v3^2*v0
sage: e^-1*c*b*e*b^-1*c^-4v2^-3>>> from sage.all import *>>> Gamma = Graph(Integer(4))>>> G = RightAngledArtinGroup(Gamma)>>> a,b,c,d = G.gens()>>> a*c*d**Integer(4)*a**-Integer(3)*bv0^-2*v1*v2*v3^4>>> Gamma = graphs.CompleteGraph(Integer(4))>>> G = RightAngledArtinGroup(Gamma)>>> a,b,c,d = G.gens()>>> a*c*d**Integer(4)*a**-Integer(3)*b(continues on next page)

236

Chapter 16. Right-Angled Artin Groups

Groups, Release 10.4

(continued from previous page)v0*v2*v3^4*v0^-3*v1>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G
Right-angled Artin group of Cycle graph>>> a,b,c,d,e = G.gens()>>> d*b*a*d
v1*v3^2*v0>>> e**-Integer(1)*c*b*e*b**-Integer(1)*c**-Integer(4)v2^-3

We create the previous example but with different variable names:
sage: G.<a,b,c,d,e> = RightAngledArtinGroup(Gamma)
sage: G
Right-angled Artin group of Cycle graphsage: d*b*a*d
b*d^2*asage: e^-1*c*b*e*b^-1*c^-4
c^-3>>> from sage.all import *>>> G = RightAngledArtinGroup(Gamma, names=( a , b , c ,˓→d, e,) = G._first_ngens(5)>>> G
Right-angled Artin group of Cycle graph>>> d*b*a*d
b*d^2*a>>> e**-Integer(1)*c*b*e*b**-Integer(1)*c**-Integer(4)
c^-3

d ,

e ,)); (a, b, c,␣

REFERENCES:• [Cha2006]• [BB1997]• [Dro1987]• [CP2001]• [VW1994]• Wikipedia article Artin_group#Right-angled_Artin_groups
class Element(parent, lst)
Bases: ArtinGroupElement
An element of a right-angled Artin group (RAAG).
Elements of RAAGs are modeled as lists of pairs [i, p] where i is the index of a vertex in the defining
graph (with some fixed order of the vertices) and p is the power.
cohomology(F=None)
Return the cohomology ring of self over the field F.
EXAMPLES:

237

Groups, Release 10.4

sage: C4 = graphs.CycleGraph(4)sage: A = groups.misc.RightAngledArtin(C4)sage: A.cohomology()
Cohomology ring of Right-angled Artin group of Cycle graphwith coefficients in Rational Field>>> from sage.all import *>>> C4 = graphs.CycleGraph(Integer(4))>>> A = groups.misc.RightAngledArtin(C4)>>> A.cohomology()
Cohomology ring of Right-angled Artin group of Cycle graphwith coefficients in Rational Fieldgen(i)
Return the i-th generator of self.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.gen(2)v2>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.gen(Integer(2))
v2gens()
Return the generators of self.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.gens()(v0, v1, v2, v3, v4)
sage: Gamma = Graph([( x , y ), ( y ,sage: G = RightAngledArtinGroup(Gamma)
sage: G.gens()(vx, vy, vzeta)

zeta )])>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.gens()(v0, v1, v2, v3, v4)>>> Gamma = Graph([( x , y ), ( y , zeta )])>>> G = RightAngledArtinGroup(Gamma)>>> G.gens()(vx, vy, vzeta)

graph()
Return the defining graph of self.
EXAMPLES:
238

Chapter 16. Right-Angled Artin Groups

Groups, Release 10.4

sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.graph()
Cycle graph: Graph on 5 vertices>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.graph()
Cycle graph: Graph on 5 vertices

ngens()
Return the number of generators of self.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.ngens()
5>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.ngens()
5

one()
Return the identity element 1.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.one()1>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)>>> G.one()1

one_element()
Return the identity element 1.
EXAMPLES:
sage: Gamma = graphs.CycleGraph(5)sage: G = RightAngledArtinGroup(Gamma)
sage: G.one()1>>> from sage.all import *>>> Gamma = graphs.CycleGraph(Integer(5))>>> G = RightAngledArtinGroup(Gamma)(continues on next page)239

Groups, Release 10.4

(continued from previous page)>>> G.one()
1

240

Chapter 16. Right-Angled Artin Groups

CHAPTERSEVENTEENCACTUS GROUPSAUTHORS:• Travis Scrimshaw (1-2023): initial version
class sage.groups.cactus_group.CactusGroup(n)Bases: UniqueRepresentation, GroupThe cactus group.
The 𝑛-fruit cactus group 𝐽𝑛 is the group generated by 𝑠𝑝𝑞 for 1 ≤ 𝑝 < 𝑞 ≤ 𝑛 with relations:• 𝑠2𝑝𝑞 = 1• 𝑠𝑝𝑞 𝑠𝑘𝑙 = 𝑠𝑘𝑙 𝑠𝑝𝑞 if the intervals [𝑝, 𝑞] and [𝑘, 𝑙] are disjoint, and• 𝑠𝑝𝑞 𝑠𝑘𝑙 = 𝑠𝑝+𝑞−𝑙,𝑝+𝑞−𝑘 𝑠𝑝𝑞 if [𝑘, 𝑙] ⊆ [𝑝, 𝑞].
INPUT:• n – integer
EXAMPLES:
We construct the cactus group 𝐽3 and do some basic computations:sage: J3 = groups.misc.Cactus(3)sage: s12,s13,s23 = J3.group_generators()
sage: s12 * s13
s[1,2]*s[1,3]sage: x = s12 * s23; xs[1,2]*s[2,3]sage: x^4s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]sage: s12 * s13 == s13 * s23
True>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> s12,s13,s23 = J3.group_generators()>>> s12 * s13
s[1,2]*s[1,3]>>> x = s12 * s23; xs[1,2]*s[2,3]>>> x**Integer(4)s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]>>> s12 * s13 == s13 * s23
True

241

Groups, Release 10.4

We verify the key equality in Lemma 2.3 in [White2015], which shows that 𝐽5 is generated by 𝑠1𝑞 :sage: J5 = groups.misc.Cactus(5)sage: gens = J5.group_generators()
sage: all(gens[(p,q)] == gens[(1,q)] * gens[(1,q-p+1)] * gens[(1,q)]....:
for p in range(1, 6) for q in range(p+1, 6))
True>>> from sage.all import *>>> J5 = groups.misc.Cactus(Integer(5))>>> gens = J5.group_generators()>>> all(gens[(p,q)] == gens[(Integer(1),q)] * gens[(Integer(1),q-p+Integer(1))] *␣˓→gens[(Integer(1),q)]...
for p in range(Integer(1), Integer(6)) for q in range(p+Integer(1),␣
˓→Integer(6)))
Trueclass Element(parent, data)
Bases: MultiplicativeGroupElement
An element of a cactus group.
to_matrix()
Return self as a matrix.
The resulting matrix is the geometric representation of self.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: s12,s13,s23 = J3.gens()
sage: s12.to_matrix()[ -1
0 2*t]
[ 0
1
0]
[ 0
0
1]
sage: (s12*s13).to_matrix()
[2*t
0 -1]
[ 0 -10][ 100]
sage: (s13*s23).to_matrix()
[2*t
0 -1]
[ 0 -10][ 100]
sage: (s13*s12).to_matrix()[ 001][ 0 -10][ -1
0 2*t]
sage: all(x.to_matrix() * y.to_matrix() == (x*y).to_matrix()....:
for x in J3.gens() for y in J3.gens())
True>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> s12,s13,s23 = J3.gens()>>> s12.to_matrix()[ -1
0 2*t]
[ 0
1
0]
[ 0
0
1]
(continues on next page)242

Chapter 17. Cactus Groups

Groups, Release 10.4

(continued from previous page)>>> (s12*s13).to_matrix()
[2*t
0 -1]
[ 0 -10][ 1
00]>>> (s13*s23).to_matrix()
[2*t
0 -1]
[ 0 -10][ 1
00]>>> (s13*s12).to_matrix()[ 001][ 0 -10][ -1
0 2*t]>>> all(x.to_matrix() * y.to_matrix() == (x*y).to_matrix()...
for x in J3.gens() for y in J3.gens())
True

to_permutation()
Return the image of self under the canonical projection to the permutation group.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: s12,s13,s23 = J3.gens()
sage: s12.to_permutation()[2, 1, 3]
sage: s23.to_permutation()[1, 3, 2]
sage: s13.to_permutation()[3, 2, 1]
sage: elt = s12*s23*s13
sage: elt.to_permutation()[1, 3, 2]
sage: J7 = groups.misc.Cactus(7)sage: J7.group_generators()[3,6].to_permutation()[1, 2, 6, 5, 4, 3, 7]>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> s12,s13,s23 = J3.gens()>>> s12.to_permutation()[2, 1, 3]>>> s23.to_permutation()[1, 3, 2]>>> s13.to_permutation()[3, 2, 1]>>> elt = s12*s23*s13>>> elt.to_permutation()[1, 3, 2]>>> J7 = groups.misc.Cactus(Integer(7))>>> J7.group_generators()[Integer(3),Integer(6)].to_permutation()[1, 2, 6, 5, 4, 3, 7]

We check that this respects the multiplication order of permutations:243

Groups, Release 10.4

sage: P3 = Permutations(3)sage: elt = s12*s23
sage: elt.to_permutation() == P3(s12) * P3(s23)Truesage: Permutations.options.mult= r2l
sage: elt.to_permutation() == P3(s12) * P3(s23)Truesage: Permutations.options.mult= l2r>>> from sage.all import *>>> P3 = Permutations(Integer(3))>>> elt = s12*s23>>> elt.to_permutation() == P3(s12) * P3(s23)True>>> Permutations.options.mult= r2l>>> elt.to_permutation() == P3(s12) * P3(s23)True>>> Permutations.options.mult= l2rbilinear_form(t=None)
Return the t-bilinear form of self.
We define a bilinear form 𝐵 on the group algebra by⎧⎪
if 𝑖 = 𝑝, 𝑗 = 𝑞,⎨1
𝐵(𝑠𝑖𝑗 , 𝑠𝑝𝑞 ) = −𝑡 if [𝑖, 𝑗] ̸⊆ [𝑝, 𝑞] and [𝑝, 𝑞] ̸⊆ [𝑖, 𝑗],⎪⎩0otherwise.
In other words, it is 1 if 𝑠𝑖𝑗 = 𝑠𝑝𝑞 , −𝑡 if 𝑠𝑖𝑗 and 𝑠𝑝𝑞 generate a free group, and 0 otherwise (they commuteor almost commute).
INPUT:• t – (default: 𝑡 in [𝑡]) the variable 𝑡
EXAMPLES:
sage: J = groups.misc.Cactus(4)sage: B = J.bilinear_form()
sage: B
[ 1 0 0 -t -t 0][ 0 1 0 0 -t -t][ 0 0 1 0 0 0][-t 0 0 1 0 -t][-t -t 0 0 1 0]
[ 0 -t 0 -t 0 1]>>> from sage.all import *>>> J = groups.misc.Cactus(Integer(4))>>> B = J.bilinear_form()>>> B[ 1 0 0 -t -t 0][ 0 1 0 0 -t -t][ 0 0 1 0 0 0][-t 0 0 1 0 -t][-t -t 0 0 1 0]
[ 0 -t 0 -t 0 1]

244

Chapter 17. Cactus Groups

Groups, Release 10.4

We reorder the generators so the bilinear form is more “Coxeter-like”. In particular, when we remove thegenerator 𝑠1,4 , we recover the bilinear form in Example 6.2.5 of [DJS2003]:
sage: J.gens()(s[1,2], s[1,3], s[1,4], s[2,3], s[2,4], s[3,4])
sage: S = SymmetricGroup(6)sage: g = S([1,4,6,2,5,3])
sage: B.permute_rows_and_columns(g, g)
sage: B
[ 1 -t 0 0 -t 0][-t 1 -t 0 0 0]
[ 0 -t 1 -t 0 0]
[ 0 0 -t 1 -t 0][-t 0 0 -t 1 0]
[ 0 0 0 0 0 1]>>> from sage.all import *>>> J.gens()(s[1,2], s[1,3], s[1,4], s[2,3], s[2,4], s[3,4])>>> S = SymmetricGroup(Integer(6))>>> g = S([Integer(1),Integer(4),Integer(6),Integer(2),Integer(5),Integer(3)])>>> B.permute_rows_and_columns(g, g)>>> B[ 1 -t 0 0 -t 0][-t 1 -t 0 0 0]
[ 0 -t 1 -t 0 0]
[ 0 0 -t 1 -t 0][-t 0 0 -t 1 0]
[ 0 0 0 0 0 1]

gen(i, j=None)
Return the 𝑖-th generator of self or the generator 𝑠𝑖𝑗 .
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.gen(1)s[1,3]
sage: J3.gen(1,2)
s[1,2]
sage: J3.gen(0,2)
Traceback (most recent call last):...
ValueError: s[0,2] is not a valid generator
sage: J3.gen(1,4)
Traceback (most recent call last):...
ValueError: s[1,4] is not a valid generator
sage: J3.gen(2,1)
Traceback (most recent call last):...
ValueError: s[2,1] is not a valid generator>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.gen(Integer(1))
s[1,3](continues on next page)245

Groups, Release 10.4

(continued from previous page)>>> J3.gen(Integer(1),Integer(2))
s[1,2]>>> J3.gen(Integer(0),Integer(2))
Traceback (most recent call last):...
ValueError: s[0,2] is not a valid generator>>> J3.gen(Integer(1),Integer(4))
Traceback (most recent call last):...
ValueError: s[1,4] is not a valid generator>>> J3.gen(Integer(2),Integer(1))
Traceback (most recent call last):...
ValueError: s[2,1] is not a valid generator

gens()
Return the generators of self as a tuple.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.gens()(s[1,2], s[1,3], s[2,3])>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.gens()(s[1,2], s[1,3], s[2,3])geometric_representation_generators(t=None)
Return the matrices corresponding to the generators of self.
We construct a representation over 𝑅 = [𝑡] of 𝐽𝑛 as follows. Let 𝐸 be the vector space over 𝑅 spanned by{𝜖𝑣 }𝑣 , where 𝑣 is a generator of 𝐽𝑛 . Fix some generator 𝑣, and let 𝐸𝑣 denote the span of 𝜖𝑢 − 𝜖𝑢′ , where 𝑢′
is the reflected interval of 𝑢 in 𝑣, over all 𝑢 such that 𝑢 ⊂ 𝑣. Let 𝐹𝑣 denote the orthogonal complement of𝑅𝜖𝑣 ⊕ 𝐸𝑣 with respect to the bilinear form 𝐵. We define the action of 𝑣 on 𝐸 by
𝜌(𝑣) = −𝐼|𝑅𝜖𝑣 ⊕𝐸𝑣 ⊕ 𝐼|𝐹𝑣 .
By Theorem 6.2.3 of [DJS2003], this defines a representation of 𝐽𝑛 . It is expected that this is a faithfulrepresentation (see Remark 6.2.4 of [DJS2003]). As this arises from a blow-up and an analog of the geometric representation of the corresponding Coxeter group (the symmetric group), we call this the geometricrepresentation.
INPUT:• t – (default: 𝑡 in [𝑡]) the variable 𝑡
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: list(J3.geometric_representation_generators())[[ -1
0 2*t] [ 0 0 1] [ 1
0
0]
[ 0
1
0] [ 0 -1 0] [ 0
1
0]
[ 0
0
1], [ 1 0 0], [2*t
0 -1]
]

246

Chapter 17. Cactus Groups

Groups, Release 10.4>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> list(J3.geometric_representation_generators())[[ -1
0 2*t] [ 0 0 1] [ 1
0
0]
[ 0
1
0] [ 0 -1 0] [ 0
1
0]
[ 0
0
1], [ 1 0 0], [2*t
0 -1]]

We ran the following code with max_tests = 15000 and did not find a counterexample to the faithfulnessof this representation:
sage: visited = set([J3.one()])
sage: cur = set([(J3.one(), J3.one().to_matrix())])
sage: mats = set([J3.one().to_matrix()])
sage: RG = list(J3.geometric_representation_generators())
sage: count = 0
sage: max_tests = 1000
sage: while cur:....:count += 1....:
if count >= max_tests:
....:
break
....:
elt, mat = cur.pop()....:
for g,r in zip(J3, RG):....:val = elt * g....:
if val in visited:....:
continue....:
visited.add(val)....:matp = mat * r....:
matp.set_immutable()....:
assert matp not in mats, f"not injective {val} \n{matp}"....:
mats.add(matp)....:
cur.add((val, matp))>>> from sage.all import *>>> visited = set([J3.one()])>>> cur = set([(J3.one(), J3.one().to_matrix())])>>> mats = set([J3.one().to_matrix()])>>> RG = list(J3.geometric_representation_generators())>>> count = Integer(0)>>> max_tests = Integer(1000)>>> while cur:...
count += Integer(1)...
if count >= max_tests:
...
break
...
elt, mat = cur.pop()...
for g,r in zip(J3, RG):...
val = elt * g...
if val in visited:...
continue...
visited.add(val)...
matp = mat * r...
matp.set_immutable()...
assert matp not in mats, f"not injective {val} \n{matp}"...
mats.add(matp)...
cur.add((val, matp))group_generators()
247

Groups, Release 10.4

Return the group generators of self.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.group_generators()
Finite family {(1, 2): s[1,2], (1, 3): s[1,3], (2, 3): s[2,3]}>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.group_generators()
Finite family {(1, 2): s[1,2], (1, 3): s[1,3], (2, 3): s[2,3]}n()Return the value 𝑛.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.n()
3>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.n()
3one()
Return the identity element in self.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.one()1>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.one()
1

random_element(max_length=10)
Return a random element of self of length at most max_length.
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.random_element() # randoms[1,2]*s[2,3]*s[1,2]*s[1,3]>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.random_element() # randoms[1,2]*s[2,3]*s[1,2]*s[1,3]248

Chapter 17. Cactus Groups

Groups, Release 10.4

right_angled_coxeter_group()
Return the right-angled Coxeter group that self (set-theoretically) embeds into.
This is defined following [Most2019], where it was called the diagram group. It has generators (of order 2)
indexed by subsets of {1, . . . , 𝑛} that commute if and only if one subset is contained in the other or they
are disjoint. For the pure cactus group, this is also a group homomorphism, otherwise it is a group 1-cocycle[BCL2022].
EXAMPLES:
sage: J3 = groups.misc.Cactus(3)sage: J3.right_angled_coxeter_group()
Coxeter group over Rational Field with Coxeter matrix:[ 1 -1 -1 2][-1 1 -1 2][-1 -1 1 2]
[ 2 2 2 1]>>> from sage.all import *>>> J3 = groups.misc.Cactus(Integer(3))>>> J3.right_angled_coxeter_group()
Coxeter group over Rational Field with Coxeter matrix:[ 1 -1 -1 2][-1 1 -1 2][-1 -1 1 2]
[ 2 2 2 1]class sage.groups.cactus_group.PureCactusGroup(n)Bases: KernelSubgroup
The pure cactus group.
The pure cactus group 𝑃 𝐽𝑛 is the kernel of the natural surjection of the cactus group 𝐽𝑛 onto the symmetric group
𝑆𝑛 . In particular, we have the following (non-split) exact sequence:
1 −→ 𝑃 𝐽𝑛 −→ 𝐽𝑛 −→ 𝑆𝑛 −→ 1.

gen(i)
Return the i-th generator of self.
EXAMPLES:
sage: PJ3 = groups.misc.PureCactus(3)sage: PJ3.gen(0)s[2,3]*s[1,2]*s[2,3]*s[1,3]sage: PJ3.gen(1)s[1,2]*s[2,3]*s[1,2]*s[1,3]sage: PJ3.gen(5)Traceback (most recent call last):...
IndexError: tuple index out of range>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))>>> PJ3.gen(Integer(0))
s[2,3]*s[1,2]*s[2,3]*s[1,3](continues on next page)249

Groups, Release 10.4

(continued from previous page)>>> PJ3.gen(Integer(1))
s[1,2]*s[2,3]*s[1,2]*s[1,3]>>> PJ3.gen(Integer(5))
Traceback (most recent call last):...
IndexError: tuple index out of range

gens()
Return the generators of self.
ALGORITHM:
We use Wikipedia article Schreier’s_lemma and compute the traversal using the lex minimum elements (defined by the order of the generators of the ambient cactus group).
EXAMPLES:
We verify Corollary A.2 of [BCL2022]:
sage: PJ3 = groups.misc.PureCactus(3)sage: PJ3.gens()(s[2,3]*s[1,2]*s[2,3]*s[1,3], s[1,2]*s[2,3]*s[1,2]*s[1,3])
sage: a, b = PJ3.gens()
sage: a * b # they are inverses of each other1
sage: J3 = groups.misc.Cactus(3)sage: gen = (J3.gen(1,2)*J3.gen(1,3))^3
sage: gens[1,2]*s[2,3]*s[1,2]*s[1,3]sage: gen == b
True>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))>>> PJ3.gens()(s[2,3]*s[1,2]*s[2,3]*s[1,3], s[1,2]*s[2,3]*s[1,2]*s[1,3])>>> a, b = PJ3.gens()>>> a * b # they are inverses of each other1>>> J3 = groups.misc.Cactus(Integer(3))>>> gen = (J3.gen(Integer(1),Integer(2))*J3.gen(Integer(1),˓→Integer(3)))**Integer(3)>>> gens[1,2]*s[2,3]*s[1,2]*s[1,3]>>> gen == b
True

n()
Return the value 𝑛.
EXAMPLES:
sage: PJ3 = groups.misc.PureCactus(3)sage: PJ3.n()
3250

Chapter 17. Cactus Groups

Groups, Release 10.4>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))>>> PJ3.n()
3251Groups, Release 10.4

252

Chapter 17. Cactus Groups

CHAPTEREIGHTEEN

FUNCTOR THAT CONVERTS A COMMUTATIVE ADDITIVE GROUP
INTO A MULTIPLICATIVE GROUP.

AUTHORS:• Mark Shimozono (2013): initial version
class sage.groups.group_exp.GroupExp
Bases: Functor
A functor that converts a commutative additive group into an isomorphic multiplicative group.
More precisely, given a commutative additive group 𝐺, define the exponential of 𝐺 to be the isomorphic groupwith elements denoted 𝑒𝑔 for every 𝑔 ∈ 𝐺 and but with product in multiplicative notation𝑒𝑔 𝑒ℎ = 𝑒𝑔+ℎ

for all 𝑔, ℎ ∈ 𝐺.

The class GroupExp implements the sage functor which sends a commutative additive group 𝐺 to its exponential.
The creation of an instance of the functor GroupExp requires no input:
sage: E = GroupExp(); E
Functor from Category of commutative additive groups to Category of groups>>> from sage.all import *>>> E = GroupExp(); E
Functor from Category of commutative additive groups to Category of groups

The GroupExp functor (denoted 𝐸 in the examples) can be applied to two kinds of input. The first is a commutative additive group. The output is its exponential. This is accomplished by _apply_functor():sage: EZ = E(ZZ); EZ
Multiplicative form of Integer Ring>>> from sage.all import *>>> EZ = E(ZZ); EZ
Multiplicative form of Integer Ring

Elements of the exponentiated group can be created and manipulated as follows:
sage: x = EZ(-3); x-3sage: x.parent()
Multiplicative form of Integer Ringsage: EZ(-1)*EZ(6) == EZ(5)True(continues on next page)

253

Groups, Release 10.4

(continued from previous page)

sage: EZ(3)^(-1)-3
sage: EZ.one()0>>> from sage.all import *>>> x = EZ(-Integer(3)); x-3>>> x.parent()
Multiplicative form of Integer Ring>>> EZ(-Integer(1))*EZ(Integer(6)) == EZ(Integer(5))
True>>> EZ(Integer(3))**(-Integer(1))-3>>> EZ.one()0

The second kind of input the GroupExp functor accepts, is a homomorphism of commutative additive groups.
The output is the multiplicative form of the homomorphism. This is achieved by _apply_functor_to_morphism():sage: L = RootSystem([ A ,2]).ambient_space()sage: EL = E(L)sage: W = L.weyl_group(prefix="s")sage: s2 = W.simple_reflection(2)sage: def my_action(mu):....:return s2.action(mu)sage: from sage.categories.morphism import SetMorphism
sage: from sage.categories.homset import Hom
sage: f = SetMorphism(Hom(L,L,CommutativeAdditiveGroups()), my_action)
sage: F = E(f); F
Generic endomorphism of Multiplicative form of Ambient space of the Root system␣
˓→of type [ A , 2]
sage: v = L.an_element(); v(2, 2, 3)
sage: y = F(EL(v)); y(2, 3, 2)
sage: y.parent()
Multiplicative form of Ambient space of the Root system of type [ A , 2]>>> from sage.all import *>>> L = RootSystem([ A ,Integer(2)]).ambient_space()>>> EL = E(L)>>> W = L.weyl_group(prefix="s")>>> s2 = W.simple_reflection(Integer(2))>>> def my_action(mu):...
return s2.action(mu)>>> from sage.categories.morphism import SetMorphism>>> from sage.categories.homset import Hom>>> f = SetMorphism(Hom(L,L,CommutativeAdditiveGroups()), my_action)>>> F = E(f); F
Generic endomorphism of Multiplicative form of Ambient space of the Root system␣
˓→of type [ A , 2]>>> v = L.an_element(); v(2, 2, 3)>>> y = F(EL(v)); y(continues on next page)

254

Chapter 18. Functor that converts a commutative additive group into a multiplicative group.

Groups, Release 10.4

(continued from previous page)(2, 3, 2)>>> y.parent()
Multiplicative form of Ambient space of the Root system of type [ A , 2]class sage.groups.group_exp.GroupExpElement(parent, x)
Bases: ElementWrapper, MultiplicativeGroupElement
An element in the exponential of a commutative additive group.
INPUT:• self – the exponentiated group element being created• parent – the exponential group (parent of self)• x – the commutative additive group element being wrapped to form self
EXAMPLES:
sage: G = QQ^2sage: EG = GroupExp()(G)
sage: z = GroupExpElement(EG, vector(QQ, (1,-3))); z(1, -3)sage: z.parent()
Multiplicative form of Vector space of dimension 2 over Rational Field
sage: EG(vector(QQ,(1,-3)))==z
True>>> from sage.all import *>>> G = QQ**Integer(2)>>> EG = GroupExp()(G)>>> z = GroupExpElement(EG, vector(QQ, (Integer(1),-Integer(3)))); z(1, -3)>>> z.parent()
Multiplicative form of Vector space of dimension 2 over Rational Field>>> EG(vector(QQ,(Integer(1),-Integer(3))))==z
True

class sage.groups.group_exp.GroupExp_Class(G)Bases: UniqueRepresentation, Parent
The multiplicative form of a commutative additive group.
INPUT:• 𝐺 – a commutative additive group
OUTPUT: the multiplicative form of 𝐺
EXAMPLES:
sage: GroupExp()(QQ)
Multiplicative form of Rational Field>>> from sage.all import *>>> GroupExp()(QQ)
Multiplicative form of Rational Field

255

Groups, Release 10.4

Element
alias of GroupExpElement
an_element()
Return an element of the multiplicative group.
EXAMPLES:
sage: L = RootSystem([ A ,2]).weight_lattice()
sage: EL = GroupExp()(L)
sage: x = EL.an_element(); x2*Lambda[1] + 2*Lambda[2]sage: x.parent()
Multiplicative form of Weight lattice of the Root system of type [ A , 2]>>> from sage.all import *>>> L = RootSystem([ A ,Integer(2)]).weight_lattice()>>> EL = GroupExp()(L)>>> x = EL.an_element(); x2*Lambda[1] + 2*Lambda[2]>>> x.parent()
Multiplicative form of Weight lattice of the Root system of type [ A , 2]group_generators()
Return generators of self.
EXAMPLES:
sage: GroupExp()(ZZ).group_generators()(1,)>>> from sage.all import *>>> GroupExp()(ZZ).group_generators()
(1,)

one()
Return the identity element of the multiplicative group.
EXAMPLES:
sage: G = GroupExp()(ZZ^2)
sage: G.one()(0, 0)
sage: x = G.an_element(); x(1, 0)
sage: x == x * G.one()True>>> from sage.all import *>>> G = GroupExp()(ZZ**Integer(2))>>> G.one()(0, 0)>>> x = G.an_element(); x(1, 0)>>> x == x * G.one()
True

256

Chapter 18. Functor that converts a commutative additive group into a multiplicative group.

Groups, Release 10.4

product(x, y)
Return the product of 𝑥 and 𝑦 in the multiplicative group.
EXAMPLES:
sage: G = GroupExp()(ZZ)
sage: G.product(G(2),G(7))
9sage: x = G(2)sage: x.__mul__(G(7))
9>>> from sage.all import *>>> G = GroupExp()(ZZ)>>> G.product(G(Integer(2)),G(Integer(7)))
9>>> x = G(Integer(2))>>> x.__mul__(G(Integer(7)))
9257Groups, Release 10.4

258

Chapter 18. Functor that converts a commutative additive group into a multiplicative group.

CHAPTERNINETEEN

SEMIDIRECT PRODUCT OF GROUPSAUTHORS:• Mark Shimozono (2013) initial version
class sage.groups.group_semidirect_product.GroupSemidirectProduct(G, H, twist=None,
act_to_right=True,
prefix0=None,prefix1=None,
print_tuple=False,
category=Categoryof groups)
Bases: CartesianProduct
Return the semidirect product of the groups G and H using the homomorphism twist.
INPUT:• G and H – multiplicative groups• twist – (default: None) a function defining a homomorphism (see below)• act_to_right – True or False (default: True)• prefix0 – (default: None) optional string• prefix1 – (default: None) optional string• print_tuple – True or False (default: False)• category – A category (default: Groups())
A semidirect product of groups 𝐺 and 𝐻 is a group structure on the Cartesian product 𝐺 × 𝐻 whose productagrees with that of 𝐺 on 𝐺 × 1𝐻 and with that of 𝐻 on 1𝐺 × 𝐻, such that either 1𝐺 × 𝐻 or 𝐺 × 1𝐻 is a normal
subgroup. In the former case, the group is denoted 𝐺 n 𝐻 and in the latter, 𝐺 o 𝐻.
If act_to_right is True, this indicates the group 𝐺 n 𝐻 in which 𝐺 acts on 𝐻 by automorphisms. In thiscase there is a group homomorphism 𝜑 ∈ Hom(𝐺, Aut(𝐻)) such that𝑔ℎ𝑔 −1 = 𝜑(𝑔)(ℎ).
The homomorphism 𝜑 is specified by the input twist, which syntactically is the function 𝐺 × 𝐻 → 𝐻 definedby𝑡𝑤𝑖𝑠𝑡(𝑔, ℎ) = 𝜑(𝑔)(ℎ).

259

Groups, Release 10.4

The product on 𝐺 n 𝐻 is defined by(𝑔1 , ℎ1 )(𝑔2 , ℎ2 ) = 𝑔1 ℎ1 𝑔2 ℎ2= 𝑔1 𝑔2 𝑔2−1 ℎ1 𝑔2 ℎ2= (𝑔1 𝑔2 , 𝑡𝑤𝑖𝑠𝑡(𝑔2−1 , ℎ1 )ℎ2 )If act_to_right is False, the group 𝐺 o 𝐻 is specified by a homomorphism 𝜓 ∈ Hom(𝐻, Aut(𝐺)) suchthatℎ𝑔ℎ−1 = 𝜓(ℎ)(𝑔)Then twist is the function 𝐻 × 𝐺 → 𝐺 defined by𝑡𝑤𝑖𝑠𝑡(ℎ, 𝑔) = 𝜓(ℎ)(𝑔).
so that the product in 𝐺 o 𝐻 is defined by(𝑔1 , ℎ1 )(𝑔2 , ℎ2 ) = 𝑔1 ℎ1 𝑔2 ℎ2= 𝑔1 ℎ1 𝑔2 ℎ−1
1 ℎ1 ℎ2= (𝑔1 𝑡𝑤𝑖𝑠𝑡(ℎ1 , 𝑔2 ), ℎ1 ℎ2 )If prefix0 (resp. prefixl) is not None then it is used as a wrapper for printing elements of G (resp. H). If
print_tuple is True then elements are printed in the style (𝑔, ℎ) and otherwise in the style 𝑔 * ℎ.
EXAMPLES:
sage: G = GL(2,QQ)
sage: V = QQ^2sage: EV = GroupExp()(V) # make a multiplicative version of V
sage: def twist(g,v):....:
return EV(g*v.value)
sage: H = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t ); H
Semidirect product of General Linear Group of degree 2
over Rational Field acting on Multiplicative form of Vector spaceof dimension 2 over Rational Field
sage: x = H.an_element(); xt[(1, 0)]sage: x^2t[(2, 0)]sage: # needs sage.rings.number_fieldsage: cartan_type = CartanType([ A ,2])
sage: W = WeylGroup(cartan_type, prefix="s")sage: def twist(w,v):....:
return w*v*(~w)
sage: WW = GroupSemidirectProduct(W, W, twist=twist, print_tuple=True)
sage: s = Family(cartan_type.index_set(), lambda i: W.simple_reflection(i))
sage: y = WW((s[1],s[2])); y(s1, s2)
sage: y^2
(1, s2*s1)
sage: y.inverse()(s1, s1*s2*s1)>>> from sage.all import *>>> G = GL(Integer(2),QQ)(continues on next page)

260

Chapter 19. Semidirect product of groups

Groups, Release 10.4

(continued from previous page)>>> V = QQ**Integer(2)>>> EV = GroupExp()(V) # make a multiplicative version of V>>> def twist(g,v):...
return EV(g*v.value)>>> H = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t ); H
Semidirect product of General Linear Group of degree 2
over Rational Field acting on Multiplicative form of Vector spaceof dimension 2 over Rational Field>>> x = H.an_element(); xt[(1, 0)]>>> x**Integer(2)t[(2, 0)]>>> # needs sage.rings.number_field>>> cartan_type = CartanType([ A ,Integer(2)])>>> W = WeylGroup(cartan_type, prefix="s")>>> def twist(w,v):...
return w*v*(~w)>>> WW = GroupSemidirectProduct(W, W, twist=twist, print_tuple=True)>>> s = Family(cartan_type.index_set(), lambda i: W.simple_reflection(i))>>> y = WW((s[Integer(1)],s[Integer(2)])); y(s1, s2)>>> y**Integer(2)(1, s2*s1)>>> y.inverse()(s1, s1*s2*s1)

Todo:• Functorial constructor for semidirect products for various categories• Twofold Direct product as a special case of semidirect productElement
alias of GroupSemidirectProductElement
act_to_right()
Return True if the left factor acts on the right factor and False if the right factor acts on the left factor.
EXAMPLES:
sage: def twist(x,y):....:
return y
sage: GroupSemidirectProduct(WeylGroup([ A ,2],prefix="s"),....:WeylGroup([ A ,3],prefix="t"), twist).act_to_
˓→right()
True>>> from sage.all import *>>> def twist(x,y):...
return y>>> GroupSemidirectProduct(WeylGroup([ A ,Integer(2)],prefix="s"),...
WeylGroup([ A ,Integer(3)],prefix="t"), twist).act_
˓→to_right()
True

261

Groups, Release 10.4

construction()
Return None.
This overrides the construction functor inherited from CartesianProduct.
EXAMPLES:
sage: def twist(x,y):....:
return y
sage: H = GroupSemidirectProduct(WeylGroup([ A ,2],prefix="s"),....:WeylGroup([ A ,3],prefix="t"), twist)
sage: H.construction()>>> from sage.all import *>>> def twist(x,y):...
return y>>> H = GroupSemidirectProduct(WeylGroup([ A ,Integer(2)],prefix="s"),...
WeylGroup([ A ,Integer(3)],prefix="t"), twist)>>> H.construction()group_generators()
Return generators of self.
EXAMPLES:
sage: twist = lambda x,y: ysage: import __main__sage: __main__.twist = twist
sage: EZ = GroupExp()(ZZ)
sage: GroupSemidirectProduct(EZ, EZ, twist, print_tuple=True).group_
˓→generators()((1, 0), (0, 1))>>> from sage.all import *>>> twist = lambda x,y: y>>> import __main__>>> __main__.twist = twist>>> EZ = GroupExp()(ZZ)>>> GroupSemidirectProduct(EZ, EZ, twist, print_tuple=True).group_generators()((1, 0), (0, 1))

one()
The identity element of the semidirect product group.
EXAMPLES:
sage: G = GL(2,QQ)
sage: V = QQ^2sage: EV = GroupExp()(V) # make a multiplicative version of V
sage: def twist(g,v):....:
return EV(g*v.value)
sage: one = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t ).one(); one
1sage: one.cartesian_projection(0)
[1 0]
[0 1]
sage: one.cartesian_projection(1)(0, 0)

262

Chapter 19. Semidirect product of groups

Groups, Release 10.4>>> from sage.all import *>>> G = GL(Integer(2),QQ)>>> V = QQ**Integer(2)>>> EV = GroupExp()(V) # make a multiplicative version of V>>> def twist(g,v):...
return EV(g*v.value)>>> one = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t ).one(); one
1>>> one.cartesian_projection(Integer(0))
[1 0]
[0 1]
>>> one.cartesian_projection(Integer(1))(0, 0)

opposite_semidirect_product()Create the same semidirect product but with the positions of the groups exchanged.
EXAMPLES:
sage: G = GL(2,QQ)
sage: L = QQ^2sage: EL = GroupExp()(L)
sage: H = GroupSemidirectProduct(G, EL, prefix1= t ,....:twist=lambda g,v: EL(g*v.value)); H
Semidirect product of General Linear Group of degree 2
over Rational Field acting on Multiplicative form of Vector spaceof dimension 2 over Rational Field
sage: h = H((Matrix([[0,1],[1,0]]), EL.an_element())); h[0 1][1 0] * t[(1, 0)]
sage: Hop = H.opposite_semidirect_product(); Hop
Semidirect product of Multiplicative form of Vector spaceof dimension 2 over Rational Field acted upon by
General Linear Group of degree 2 over Rational Field
sage: hop = h.to_opposite(); hopt[(0, 1)] * [0 1][1 0]sage: hop in Hop
True>>> from sage.all import *>>> G = GL(Integer(2),QQ)>>> L = QQ**Integer(2)>>> EL = GroupExp()(L)>>> H = GroupSemidirectProduct(G, EL, prefix1= t ,...
twist=lambda g,v: EL(g*v.value)); H
Semidirect product of General Linear Group of degree 2
over Rational Field acting on Multiplicative form of Vector spaceof dimension 2 over Rational Field>>> h = H((Matrix([[Integer(0),Integer(1)],[Integer(1),Integer(0)]]), EL.an_
˓→element())); h[0 1][1 0] * t[(1, 0)]>>> Hop = H.opposite_semidirect_product(); Hop
Semidirect product of Multiplicative form of Vector spaceof dimension 2 over Rational Field acted upon by
General Linear Group of degree 2 over Rational Field(continues on next page)263

Groups, Release 10.4

(continued from previous page)>>> hop = h.to_opposite(); hopt[(0, 1)] * [0 1][1 0]>>> hop in Hop
True

product(x, y)
The product of elements 𝑥 and 𝑦 in the semidirect product group.
EXAMPLES:
sage: G = GL(2,QQ)
sage: V = QQ^2sage: EV = GroupExp()(V) # make a multiplicative version of V
sage: def twist(g,v):....:
return EV(g*v.value)
sage: S = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t )sage: g = G([[2,1],[3,1]]); g
[2 1]
[3 1]
sage: v = EV.an_element(); v(1, 0)
sage: x = S((g,v)); x[2 1][3 1] * t[(1, 0)]
sage: x*x # indirect doctest[7 3][9 4] * t[(0, 3)]>>> from sage.all import *>>> G = GL(Integer(2),QQ)>>> V = QQ**Integer(2)>>> EV = GroupExp()(V) # make a multiplicative version of V>>> def twist(g,v):...
return EV(g*v.value)>>> S = GroupSemidirectProduct(G, EV, twist=twist, prefix1= t )>>> g = G([[Integer(2),Integer(1)],[Integer(3),Integer(1)]]); g
[2 1]
[3 1]
>>> v = EV.an_element(); v(1, 0)>>> x = S((g,v)); x[2 1][3 1] * t[(1, 0)]>>> x*x # indirect doctest[7 3][9 4] * t[(0, 3)]class sage.groups.group_semidirect_product.GroupSemidirectProductElement
Bases: Element
Element class for GroupSemidirectProduct.
to_opposite()
Send an element to its image in the opposite semidirect product.
EXAMPLES:

264

Chapter 19. Semidirect product of groups

Groups, Release 10.4

sage: # needs sage.rings.number_fieldsage: L = RootSystem([ A ,2]).root_lattice(); L
Root lattice of the Root system of type [ A , 2]
sage: from sage.groups.group_exp import GroupExp
sage: EL = GroupExp()(L)
sage: W = L.weyl_group(prefix="s"); W
Weyl Group of type [ A , 2]
(as a matrix group acting on the root lattice)sage: def twist(w,v):....:
return EL(w.action(v.value))sage: G = GroupSemidirectProduct(W, EL, twist, prefix1= t ); G
Semidirect product of Weyl Group of type [ A , 2] (as a matrix
group acting on the root lattice) acting on Multiplicative form of
Root lattice of the Root system of type [ A , 2]
sage: mu = L.an_element(); mu
2*alpha[1] + 2*alpha[2]sage: w = W.an_element(); w
s1*s2
sage: g = G((w,EL(mu))); gs1*s2 * t[2*alpha[1] + 2*alpha[2]]sage: g.to_opposite()t[-2*alpha[1]] * s1*s2
sage: g.to_opposite().parent()
Semidirect product ofMultiplicative form of Root lattice of the Root system of type [ A , 2]acted upon by Weyl Group of type [ A , 2]
(as a matrix group acting on the root lattice)>>> from sage.all import *>>> # needs sage.rings.number_field>>> L = RootSystem([ A ,Integer(2)]).root_lattice(); L
Root lattice of the Root system of type [ A , 2]>>> from sage.groups.group_exp import GroupExp>>> EL = GroupExp()(L)>>> W = L.weyl_group(prefix="s"); W
Weyl Group of type [ A , 2]
(as a matrix group acting on the root lattice)>>> def twist(w,v):...
return EL(w.action(v.value))>>> G = GroupSemidirectProduct(W, EL, twist, prefix1= t ); G
Semidirect product of Weyl Group of type [ A , 2] (as a matrix
group acting on the root lattice) acting on Multiplicative form of
Root lattice of the Root system of type [ A , 2]>>> mu = L.an_element(); mu
2*alpha[1] + 2*alpha[2]>>> w = W.an_element(); w
s1*s2>>> g = G((w,EL(mu))); gs1*s2 * t[2*alpha[1] + 2*alpha[2]]>>> g.to_opposite()t[-2*alpha[1]] * s1*s2>>> g.to_opposite().parent()
Semidirect product ofMultiplicative form of Root lattice of the Root system of type [ A , 2]acted upon by Weyl Group of type [ A , 2]
(as a matrix group acting on the root lattice)265

Groups, Release 10.4

266

Chapter 19. Semidirect product of groups

CHAPTERTWENTYMISCELLANEOUS GROUPS

This is a collection of groups that may not fit into some of the other infinite families described elsewhere.

267

Groups, Release 10.4

268

Chapter 20. Miscellaneous Groups

CHAPTERTWENTYONESEMIMONOMIAL TRANSFORMATION GROUP

The semimonomial transformation group of degree 𝑛 over a ring 𝑅 is the semidirect product of the monomial transformation group of degree 𝑛 (also known as the complete monomial group over the group of units 𝑅× of 𝑅) and the groupof ring automorphisms.
The multiplication of two elements (𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) with• 𝜑, 𝜓 ∈ 𝑅×𝑛

• 𝜋, 𝜎 ∈ 𝑆𝑛 (with the multiplication 𝜋𝜎 done from left to right (like in GAP) – that is, (𝜋𝜎)(𝑖) = 𝜎(𝜋(𝑖)) for all 𝑖.)• 𝛼, 𝛽 ∈ 𝐴𝑢𝑡(𝑅)is defined by(𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) = (𝜑 · 𝜓 𝜋,𝛼 , 𝜋𝜎, 𝛼 ∘ 𝛽)
where 𝜓 𝜋,𝛼 = (𝛼(𝜓𝜋(1)−1 ), . . . , 𝛼(𝜓𝜋(𝑛)−1 )) and the multiplication of vectors is defined elementwisely. (The indexingof vectors is 0-based here, so 𝜓 = (𝜓0 , 𝜓1 , . . . , 𝜓𝑛−1 ).)Todo: Up to now, this group is only implemented for finite fields because of the limited support of automorphisms forarbitrary rings.
AUTHORS:• Thomas Feulner (2012-11-15): initial version
EXAMPLES:
sage: S = SemimonomialTransformationGroup(GF(4, a ), 4)
sage: G = S.gens()
sage: G[0]*G[1]((a, 1, 1, 1); (1,2,3,4), Ring endomorphism of Finite Field in a of size 2^2
Defn: a |--> a)>>> from sage.all import *>>> S = SemimonomialTransformationGroup(GF(Integer(4), a ), Integer(4))>>> G = S.gens()>>> G[Integer(0)]*G[Integer(1)]((a, 1, 1, 1); (1,2,3,4), Ring endomorphism of Finite Field in a of size 2^2
Defn: a |--> a)class sage.groups.semimonomial_transformations.semimonomial_transformation_group.Semimonomi

269

Groups, Release 10.4

Bases: Action
The left action of SemimonomialTransformationGroup on matrices over the same ring whose numberof columns is equal to the degree. See SemimonomialActionVec for the definition of the action on the row
vectors of such a matrix.

class sage.groups.semimonomial_transformations.semimonomial_transformation_group.Semimonomi

Bases: Action
The natural left action of the semimonomial group on vectors.
−1
The action is defined by: (𝜑, 𝜋, 𝛼) * (𝑣0 , . . . , 𝑣𝑛−1 ) := (𝛼(𝑣𝜋(1)−1 ) · 𝜑−1
0 , . . . , 𝛼(𝑣𝜋(𝑛)−1 ) · 𝜑𝑛−1 ). (The indexingof vectors is 0-based here, so 𝜓 = (𝜓0 , 𝜓1 , . . . , 𝜓𝑛−1 ).)class sage.groups.semimonomial_transformations.semimonomial_transformation_group.Semimonomi
Bases: FiniteGroup, UniqueRepresentation
A semimonomial transformation group over a ring.
The semimonomial transformation group of degree 𝑛 over a ring 𝑅 is the semidirect product of the monomialtransformation group of degree 𝑛 (also known as the complete monomial group over the group of units 𝑅× of 𝑅)
and the group of ring automorphisms.
The multiplication of two elements (𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) with• 𝜑, 𝜓 ∈ 𝑅×𝑛

• 𝜋, 𝜎 ∈ 𝑆𝑛 (with the multiplication 𝜋𝜎 done from left to right (like in GAP) – that is, (𝜋𝜎)(𝑖) = 𝜎(𝜋(𝑖)) for
all 𝑖.)• 𝛼, 𝛽 ∈ 𝐴𝑢𝑡(𝑅)is defined by(𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) = (𝜑 · 𝜓 𝜋,𝛼 , 𝜋𝜎, 𝛼 ∘ 𝛽)
where 𝜓 𝜋,𝛼 = (𝛼(𝜓𝜋(1)−1 ), . . . , 𝛼(𝜓𝜋(𝑛)−1 )) and the multiplication of vectors is defined elementwisely. (Theindexing of vectors is 0-based here, so 𝜓 = (𝜓0 , 𝜓1 , . . . , 𝜓𝑛−1 ).)Todo: Up to now, this group is only implemented for finite fields because of the limited support of automorphisms
for arbitrary rings.
EXAMPLES:
sage: F.<a> = GF(9)sage: S = SemimonomialTransformationGroup(F, 4)
sage: g = S(v = [2, a, 1, 2])
sage: h = S(perm = Permutation( (1,2,3,4) ), autom=F.hom([a**3]))
sage: g*h((2, a, 1, 2); (1,2,3,4),
Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)
sage: h*g((2*a + 1, 1, 2, 2); (1,2,3,4),
Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)
sage: S(g)(continues on next page)

270

Chapter 21. Semimonomial transformation group

Groups, Release 10.4

(continued from previous page)((2, a, 1, 2); (),Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)sage: S(1)((1, 1, 1, 1); (),Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> S = SemimonomialTransformationGroup(F, Integer(4))>>> g = S(v = [Integer(2), a, Integer(1), Integer(2)])>>> h = S(perm = Permutation( (1,2,3,4) ), autom=F.hom([a**Integer(3)]))>>> g*h((2, a, 1, 2); (1,2,3,4),
Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)>>> h*g((2*a + 1, 1, 2, 2); (1,2,3,4),
Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)>>> S(g)((2, a, 1, 2); (),Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)>>> S(Integer(1))((1, 1, 1, 1); (),Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)Element
alias of SemimonomialTransformation
base_ring()
Return the underlying ring of self.
EXAMPLES:
sage: F.<a> = GF(4)sage: SemimonomialTransformationGroup(F, 3).base_ring() is F
True>>> from sage.all import *>>> F = GF(Integer(4), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(3)).base_ring() is F
Truedegree()Return the degree of self.
EXAMPLES:
sage: F.<a> = GF(4)sage: SemimonomialTransformationGroup(F, 3).degree()3>>> from sage.all import *>>> F = GF(Integer(4), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(3)).degree()3271Groups, Release 10.4

gens()
Return a tuple of generators of self.
EXAMPLES:
sage: F.<a> = GF(4)sage: SemimonomialTransformationGroup(F, 3).gens()(((a, 1, 1); (),Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (1,2,3),
Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (1,2),
Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (),Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a + 1))>>> from sage.all import *>>> F = GF(Integer(4), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(3)).gens()(((a, 1, 1); (),Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (1,2,3),
Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (1,2),
Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a),((1, 1, 1); (),Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a + 1))

order()
Return the number of elements of self.
EXAMPLES:
sage: F.<a> = GF(4)sage: SemimonomialTransformationGroup(F, 5).order() == (4-1)**5 *␣˓→factorial(5) * 2
True>>> from sage.all import *>>> F = GF(Integer(4), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(5)).order() == (Integer(4)˓→Integer(1))**Integer(5) * factorial(Integer(5)) * Integer(2)
True

272

Chapter 21. Semimonomial transformation group

CHAPTERTWENTYTWOELEMENTS OF A SEMIMONOMIAL TRANSFORMATION GROUP

The semimonomial transformation group of degree 𝑛 over a ring 𝑅 is the semidirect product of the monomial transformation group of degree 𝑛 (also known as the complete monomial group over the group of units 𝑅× of 𝑅) and the groupof ring automorphisms.
The multiplication of two elements (𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) with• 𝜑, 𝜓 ∈ 𝑅×𝑛

• 𝜋, 𝜎 ∈ 𝑆𝑛 (with the multiplication 𝜋𝜎 done from left to right (like in GAP) – that is, (𝜋𝜎)(𝑖) = 𝜎(𝜋(𝑖)) for all 𝑖.)• 𝛼, 𝛽 ∈ 𝐴𝑢𝑡(𝑅)is defined by(𝜑, 𝜋, 𝛼)(𝜓, 𝜎, 𝛽) = (𝜑 · 𝜓 𝜋,𝛼 , 𝜋𝜎, 𝛼 ∘ 𝛽)with 𝜓 𝜋,𝛼 = (𝛼(𝜓𝜋(1)−1 ), . . . , 𝛼(𝜓𝜋(𝑛)−1 )) and an elementwisely defined multiplication of vectors. (The indexing ofvectors is 0-based here, so 𝜓 = (𝜓0 , 𝜓1 , . . . , 𝜓𝑛−1 ).)The parent is SemimonomialTransformationGroup.
AUTHORS:• Thomas Feulner (2012-11-15): initial version• Thomas Feulner (2013-12-27): Issue #15576 dissolve dependency on
Permutations.options.mul
EXAMPLES:
sage: S = SemimonomialTransformationGroup(GF(4, a ), 4)
sage: G = S.gens()
sage: G[0]*G[1]((a, 1, 1, 1); (1,2,3,4), Ring endomorphism of Finite Field in a of size 2^2
Defn: a |--> a)>>> from sage.all import *>>> S = SemimonomialTransformationGroup(GF(Integer(4), a ), Integer(4))>>> G = S.gens()>>> G[Integer(0)]*G[Integer(1)]((a, 1, 1, 1); (1,2,3,4), Ring endomorphism of Finite Field in a of size 2^2
Defn: a |--> a)class sage.groups.semimonomial_transformations.semimonomial_transformation.
SemimonomialTransformation
Bases: MultiplicativeGroupElement273

Groups, Release 10.4

An element in the semimonomial group over a ring 𝑅. See SemimonomialTransformationGroup for thedetails on the multiplication of two elements.
The init method should never be called directly. Use the call via the parent SemimonomialTransformationGroup. instead.
EXAMPLES:
sage: F.<a> = GF(9)sage: S = SemimonomialTransformationGroup(F, 4)
sage: g = S(v = [2, a, 1, 2])
sage: h = S(perm = Permutation( (1,2,3,4) ), autom=F.hom([a**3]))
sage: g*h((2, a, 1, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2␣
˓→Defn: a |--> 2*a + 1)
sage: h*g((2*a + 1, 1, 2, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^
˓→2 Defn: a |--> 2*a + 1)
sage: S(g)((2, a, 1, 2); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |-->
˓→ a)sage: S(1) # the one element in the group((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |-->
˓→ a)>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> S = SemimonomialTransformationGroup(F, Integer(4))>>> g = S(v = [Integer(2), a, Integer(1), Integer(2)])>>> h = S(perm = Permutation( (1,2,3,4) ), autom=F.hom([a**Integer(3)]))>>> g*h((2, a, 1, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2␣
˓→Defn: a |--> 2*a + 1)>>> h*g((2*a + 1, 1, 2, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^
˓→2 Defn: a |--> 2*a + 1)>>> S(g)((2, a, 1, 2); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |-->
˓→ a)>>> S(Integer(1)) # the one element in the group((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |-->
˓→ a)

get_autom()Return the component corresponding to 𝐴𝑢𝑡(𝑅) of self.
EXAMPLES:
sage: F.<a> = GF(9)sage: SemimonomialTransformationGroup(F, 4).an_element().get_autom()Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(4)).an_element().get_autom()Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1

get_perm()

274

Chapter 22. Elements of a semimonomial transformation group

Groups, Release 10.4

Return the component corresponding to 𝑆𝑛 of self.
EXAMPLES:
sage: F.<a> = GF(9)sage: SemimonomialTransformationGroup(F, 4).an_element().get_perm()[4, 1, 2, 3]>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(4)).an_element().get_perm()[4, 1, 2, 3]

get_v()𝑛

Return the component corresponding to 𝑅𝑖𝑚𝑒𝑠 of self.
EXAMPLES:
sage: F.<a> = GF(9)sage: SemimonomialTransformationGroup(F, 4).an_element().get_v()(a, 1, 1, 1)>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(4)).an_element().get_v()(a, 1, 1, 1)

get_v_inverse()𝑛Return the (elementwise) inverse of the component corresponding to 𝑅𝑖𝑚𝑒𝑠 of self.
EXAMPLES:
sage: F.<a> = GF(9)sage: SemimonomialTransformationGroup(F, 4).an_element().get_v_inverse()(a + 2, 1, 1, 1)>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> SemimonomialTransformationGroup(F, Integer(4)).an_element().get_v_
˓→inverse()(a + 2, 1, 1, 1)

invert_v()𝑛Elementwisely invert all entries of self which correspond to the component 𝑅𝑖𝑚𝑒𝑠 .
The other components of self keep unchanged.
EXAMPLES:
sage: F.<a> = GF(9)sage: x = copy(SemimonomialTransformationGroup(F, 4).an_element())
sage: x.invert_v()
sage: x.get_v() == SemimonomialTransformationGroup(F, 4).an_element().get_v_
˓→inverse()
True

275

Groups, Release 10.4>>> from sage.all import *>>> F = GF(Integer(9), names=( a ,)); (a,) = F._first_ngens(1)>>> x = copy(SemimonomialTransformationGroup(F, Integer(4)).an_element())>>> x.invert_v()>>> x.get_v() == SemimonomialTransformationGroup(F, Integer(4)).an_element().
˓→get_v_inverse()
True

276

Chapter 22. Elements of a semimonomial transformation group

CHAPTERTWENTYTHREE

KERNEL SUBGROUPS

The kernel of a homomorphism implemented as a subgroup.
AUTHORS:• Travis Scrimshaw (1-2023): Initial version
class sage.groups.kernel_subgroup.KernelSubgroup(morphism)
Bases: UniqueRepresentation, Parent
The kernel (normal) subgroup.
Let 𝜑 : 𝐺 → 𝐻 be a group homomorphism. The kernel 𝐾 = {𝜑(𝑔) = 1|𝑔 ∈ 𝐺} is a normal subgroup of 𝐺.
class Element
Bases: ElementWrapper
ambient()
Return the ambient group of self.
EXAMPLES:
sage: PJ3 = groups.misc.PureCactus(3)˓→needs sage.rings.number_fieldsage: PJ3.ambient()
˓→needs sage.rings.number_field
Cactus Group with 3 fruit>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))˓→# needs sage.rings.number_field>>> PJ3.ambient()
˓→needs sage.rings.number_field
Cactus Group with 3 fruit

#␣
#␣

␣
#␣

defining_morphism()
Return the defining morphism of self.
EXAMPLES:
sage: PJ3 = groups.misc.PureCactus(3)˓→needs sage.rings.number_fieldsage: PJ3.defining_morphism()
˓→needs sage.rings.number_field
Conversion via _from_cactus_group_element map:
From: Cactus Group with 3 fruit
To:
Symmetric group of order 3! as a permutation group

#␣
#␣

277

Groups, Release 10.4>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))˓→# needs sage.rings.number_field>>> PJ3.defining_morphism()
˓→needs sage.rings.number_field
Conversion via _from_cactus_group_element map:
From: Cactus Group with 3 fruit
To:
Symmetric group of order 3! as a permutation group␣#␣

gens()
Return the generators of self.
EXAMPLES:
sage: S2 = SymmetricGroup(2)sage: S3 = SymmetricGroup(3)sage: H = Hom(S3, S2)
sage: phi = H(S2.__call__)sage: from sage.groups.kernel_subgroup import KernelSubgroup
sage: K = KernelSubgroup(phi)sage: K.gens()((),)>>> from sage.all import *>>> S2 = SymmetricGroup(Integer(2))>>> S3 = SymmetricGroup(Integer(3))>>> H = Hom(S3, S2)>>> phi = H(S2.__call__)>>> from sage.groups.kernel_subgroup import KernelSubgroup>>> K = KernelSubgroup(phi)>>> K.gens()((),)

lift(x)Lift x to the ambient group of self.
EXAMPLES:
sage: PJ3 = groups.misc.PureCactus(3)˓→needs sage.rings.number_fieldsage: PJ3.lift(PJ3.an_element()).parent()
˓→needs sage.rings.number_field
Cactus Group with 3 fruit>>> from sage.all import *>>> PJ3 = groups.misc.PureCactus(Integer(3))˓→# needs sage.rings.number_field>>> PJ3.lift(PJ3.an_element()).parent()
˓→needs sage.rings.number_field
Cactus Group with 3 fruit

#␣
#␣

␣
#␣

retract(x)Convert x to an element of self.
EXAMPLES:

278

Chapter 23. Kernel Subgroups

Groups, Release 10.4

sage: # needs sage.rings.number_fieldsage: J3 = groups.misc.Cactus(3)sage: s12,s13,s23 = J3.group_generators()
sage: PJ3 = groups.misc.PureCactus(3)sage: elt = PJ3.retract(s23*s12*s23*s13); elt
s[2,3]*s[1,2]*s[2,3]*s[1,3]sage: elt.parent() is PJ3
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> J3 = groups.misc.Cactus(Integer(3))>>> s12,s13,s23 = J3.group_generators()>>> PJ3 = groups.misc.PureCactus(Integer(3))>>> elt = PJ3.retract(s23*s12*s23*s13); elt
s[2,3]*s[1,2]*s[2,3]*s[1,3]>>> elt.parent() is PJ3
True

279

Groups, Release 10.4

280

Chapter 23. Kernel Subgroups

CHAPTERTWENTYFOUR

CLASS FUNCTIONS OF GROUPS.

This module implements a wrapper of GAP’s ClassFunction function.
AUTHORS:• Franco Saliola (November 2008): initial version• Volker Braun (October 2010): Bugfixes, exterior and symmetric power.
sage.groups.class_function.ClassFunction(group, values)
Construct a class function.
INPUT:• group – a group• values – list/tuple/iterable of numbers; the values of the class function on the conjugacy classes, in that
order
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: G.conjugacy_classes()[Conjugacy class of () in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,2,3,4) in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,3)(2,4) in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,4,3,2) in Cyclic group of order 4 as a permutation group]sage: values = [1, -1, 1, -1]
sage: chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation group>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> G.conjugacy_classes()[Conjugacy class of () in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,2,3,4) in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,3)(2,4) in Cyclic group of order 4 as a permutation group,
Conjugacy class of (1,4,3,2) in Cyclic group of order 4 as a permutation group]>>> values = [Integer(1), -Integer(1), Integer(1), -Integer(1)]>>> chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation groupclass sage.groups.class_function.ClassFunction_gap(G, values)
Bases: SageObject
A wrapper of GAP’s ClassFunction function.

281

Groups, Release 10.4

Note: It is not checked whether the given values describes a character, since GAP does not do this.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: values = [1, -1, 1, -1]
sage: chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation group
sage: loads(dumps(chi)) == chi
True>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> values = [Integer(1), -Integer(1), Integer(1), -Integer(1)]>>> chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation group>>> loads(dumps(chi)) == chiTrueadams_operation(k)Return the k-th Adams operation on self.
Let 𝐺 be a finite group. The 𝑘-th Adams operation Ψ𝑘 is given byΨ𝑘 (𝜒)(𝑔) = 𝜒(𝑔 𝑘 ).
The Adams operations turn the representation ring of 𝐺 into a 𝜆-ring.
EXAMPLES:
sage: G = groups.permutation.Alternating(5)sage: chars = G.irreducible_characters()
sage: [chi.adams_operation(2).values() for chi in chars][[1, 1, 1, 1, 1],[3, 3, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1],[3, 3, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2],[4, 4, 1, -1, -1],
[5, 5, -1, 0, 0]]
sage: chars[4].adams_operation(2).decompose()((1, Character of Alternating group of order 5!/2 as a permutation group),(-1, Character of Alternating group of order 5!/2 as a permutation group),(-1, Character of Alternating group of order 5!/2 as a permutation group),(2, Character of Alternating group of order 5!/2 as a permutation group))>>> from sage.all import *>>> G = groups.permutation.Alternating(Integer(5))>>> chars = G.irreducible_characters()>>> [chi.adams_operation(Integer(2)).values() for chi in chars][[1, 1, 1, 1, 1],[3, 3, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1],[3, 3, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2],[4, 4, 1, -1, -1],
[5, 5, -1, 0, 0]]>>> chars[Integer(4)].adams_operation(Integer(2)).decompose()((1, Character of Alternating group of order 5!/2 as a permutation group),(-1, Character of Alternating group of order 5!/2 as a permutation group),(continues on next page)282

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)(-1, Character of Alternating group of order 5!/2 as a permutation group),(2, Character of Alternating group of order 5!/2 as a permutation group))

REFERENCES:• Wikipedia article Adams_operation
central_character()
Return the central character of self.
EXAMPLES:
sage: t = SymmetricGroup(4).trivial_character()sage: t.central_character().values()[1, 6, 3, 8, 6]>>> from sage.all import *>>> t = SymmetricGroup(Integer(4)).trivial_character()>>> t.central_character().values()[1, 6, 3, 8, 6]

decompose()
Return a list of the characters appearing the decomposition of self.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: chi = ClassFunction(S5, [22, -8, 2, 1, 1, 2, -3])
sage: chi.decompose()((3, Character of Symmetric group of order 5! as a permutation group),(2, Character of Symmetric group of order 5! as a permutation group))>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> chi = ClassFunction(S5, [Integer(22), -Integer(8), Integer(2), Integer(1),˓→ Integer(1), Integer(2), -Integer(3)])>>> chi.decompose()((3, Character of Symmetric group of order 5! as a permutation group),(2, Character of Symmetric group of order 5! as a permutation group))

degree()Return the degree of the character self.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: irr = S5.irreducible_characters()
sage: [x.degree() for x in irr]
[1, 4, 5, 6, 5, 4, 1]>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> irr = S5.irreducible_characters()>>> [x.degree() for x in irr]
[1, 4, 5, 6, 5, 4, 1]

283

Groups, Release 10.4

determinant_character()
Return the determinant character of self.
EXAMPLES:
sage: t = ClassFunction(SymmetricGroup(4), [1, -1, 1, 1, -1])
sage: t.determinant_character().values()[1, -1, 1, 1, -1]>>> from sage.all import *>>> t = ClassFunction(SymmetricGroup(Integer(4)), [Integer(1), -Integer(1),␣
˓→Integer(1), Integer(1), -Integer(1)])>>> t.determinant_character().values()[1, -1, 1, 1, -1]

domain()Return the domain of the self.
OUTPUT:
The underlying group of the class function.
EXAMPLES:
sage: ClassFunction(SymmetricGroup(4), [1,-1,1,1,-1]).domain()Symmetric group of order 4! as a permutation group>>> from sage.all import *>>> ClassFunction(SymmetricGroup(Integer(4)), [Integer(1),-Integer(1),˓→Integer(1),Integer(1),-Integer(1)]).domain()Symmetric group of order 4! as a permutation group

exterior_power(n)Return the antisymmetrized product of self with itself n times.
INPUT:• n – positive integer.
OUTPUT: the n-th antisymmetrized power of self as a ClassFunction
EXAMPLES:
sage: chi = ClassFunction(SymmetricGroup(4), gap([3, 1, -1, 0, -1]))
sage: p = chi.exterior_power(3)# the highest antisymmetric power for a 3-d␣
˓→charactersage: pCharacter of Symmetric group of order 4! as a permutation group
sage: p.values()[1, -1, 1, 1, -1]
sage: p == chi.determinant_character()True>>> from sage.all import *>>> chi = ClassFunction(SymmetricGroup(Integer(4)), gap([Integer(3),␣
˓→Integer(1), -Integer(1), Integer(0), -Integer(1)]))>>> p = chi.exterior_power(Integer(3))# the highest antisymmetric power␣˓→for a 3-d character>>> p(continues on next page)284

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)

Character of Symmetric group of order 4! as a permutation group>>> p.values()[1, -1, 1, 1, -1]>>> p == chi.determinant_character()Trueinduct(G)Return the induced character.
INPUT:• G – a supergroup of the underlying group of self
OUTPUT:
A ClassFunction of G defined by induction. Induction is the adjoint functor to restriction, see restrict().
EXAMPLES:
sage: G = SymmetricGroup(5)sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
sage: xi = H.trivial_character(); xi
Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)sage: xi.induct(G)Character of Symmetric group of order 5! as a permutation group
sage: xi.induct(G).values()[10, 4, 2, 1, 1, 0, 0]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> H = G.subgroup([(Integer(1),Integer(2),Integer(3)), (Integer(1),˓→Integer(2)), (Integer(4),Integer(5))])>>> xi = H.trivial_character(); xi
Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)>>> xi.induct(G)Character of Symmetric group of order 5! as a permutation group>>> xi.induct(G).values()[10, 4, 2, 1, 1, 0, 0]

irreducible_constituents()
Return a list of the characters that appear in the decomposition of chi.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: chi = ClassFunction(S5, [22, -8, 2, 1, 1, 2, -3])
sage: irr = chi.irreducible_constituents(); irr(Character of Symmetric group of order 5! as a permutation group,
Character of Symmetric group of order 5! as a permutation group)sage: list(map(list, irr))[[4, -2, 0, 1, 1, 0, -1], [5, -1, 1, -1, -1, 1, 0]]
sage: G = GL(2,3)
sage: chi = ClassFunction(G, [-1, -1, -1, -1, -1, -1, -1, -1])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)(continues on next page)285

Groups, Release 10.4

(continued from previous page)

sage: chi = ClassFunction(G, [1, 1, 1, 1, 1, 1, 1, 1])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)
sage: chi = ClassFunction(G, [2, 2, 2, 2, 2, 2, 2, 2])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)
sage: chi = ClassFunction(G, [-1, -1, -1, -1, 3, -1, -1, 1])
sage: ic = chi.irreducible_constituents(); ic(Character of General Linear Group of degree 2 over Finite Field of size 3,
Character of General Linear Group of degree 2 over Finite Field of size 3)
sage: list(map(list, ic))[[2, -1, 2, -1, 2, 0, 0, 0], [3, 0, 3, 0, -1, 1, 1, -1]]>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> chi = ClassFunction(S5, [Integer(22), -Integer(8), Integer(2), Integer(1),˓→ Integer(1), Integer(2), -Integer(3)])>>> irr = chi.irreducible_constituents(); irr(Character of Symmetric group of order 5! as a permutation group,
Character of Symmetric group of order 5! as a permutation group)>>> list(map(list, irr))[[4, -2, 0, 1, 1, 0, -1], [5, -1, 1, -1, -1, 1, 0]]>>> G = GL(Integer(2),Integer(3))>>> chi = ClassFunction(G, [-Integer(1), -Integer(1), -Integer(1), ˓→Integer(1), -Integer(1), -Integer(1), -Integer(1), -Integer(1)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [Integer(1), Integer(1), Integer(1), Integer(1),␣
˓→Integer(1), Integer(1), Integer(1), Integer(1)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [Integer(2), Integer(2), Integer(2), Integer(2),␣
˓→Integer(2), Integer(2), Integer(2), Integer(2)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [-Integer(1), -Integer(1), -Integer(1), ˓→Integer(1), Integer(3), -Integer(1), -Integer(1), Integer(1)])>>> ic = chi.irreducible_constituents(); ic(Character of General Linear Group of degree 2 over Finite Field of size 3,
Character of General Linear Group of degree 2 over Finite Field of size 3)>>> list(map(list, ic))[[2, -1, 2, -1, 2, 0, 0, 0], [3, 0, 3, 0, -1, 1, 1, -1]]

is_irreducible()
Return True if self cannot be written as the sum of two nonzero characters of self.
EXAMPLES:
sage: S4 = SymmetricGroup(4)sage: irr = S4.irreducible_characters()
sage: [x.is_irreducible() for x in irr]
[True, True, True, True, True]>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> irr = S4.irreducible_characters()(continues on next page)

286

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)>>> [x.is_irreducible() for x in irr]
[True, True, True, True, True]

norm()
Return the norm of self.
EXAMPLES:
sage: A5 = AlternatingGroup(5)sage: [x.norm() for x in A5.irreducible_characters()][1, 1, 1, 1, 1]>>> from sage.all import *>>> A5 = AlternatingGroup(Integer(5))>>> [x.norm() for x in A5.irreducible_characters()][1, 1, 1, 1, 1]

restrict(H)Return the restricted character.
INPUT:• H – a subgroup of the underlying group of self
OUTPUT: a ClassFunction of H defined by restriction
EXAMPLES:
sage: G = SymmetricGroup(5)sage: chi = ClassFunction(G, [3, -3, -1, 0, 0, -1, 3]); chiCharacter of Symmetric group of order 5! as a permutation group
sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
sage: chi.restrict(H)Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)sage: chi.restrict(H).values()[3, -3, -3, -1, 0, 0]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> chi = ClassFunction(G, [Integer(3), -Integer(3), -Integer(1), Integer(0),␣
˓→Integer(0), -Integer(1), Integer(3)]); chiCharacter of Symmetric group of order 5! as a permutation group>>> H = G.subgroup([(Integer(1),Integer(2),Integer(3)), (Integer(1),˓→Integer(2)), (Integer(4),Integer(5))])>>> chi.restrict(H)Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)>>> chi.restrict(H).values()[3, -3, -3, -1, 0, 0]

scalar_product(other)
Return the scalar product of self with other.
EXAMPLES:

287

Groups, Release 10.4

sage: S4 = SymmetricGroup(4)sage: irr = S4.irreducible_characters()
sage: [[x.scalar_product(y) for x in irr] for y in irr][[1, 0, 0, 0, 0],[0, 1, 0, 0, 0],[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 1]]>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> irr = S4.irreducible_characters()>>> [[x.scalar_product(y) for x in irr] for y in irr][[1, 0, 0, 0, 0],[0, 1, 0, 0, 0],[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 1]]symmetric_power(n)Return the symmetrized product of self with itself n times.
INPUT:• n – positive integer
OUTPUT: the n-th symmetrized power of self as a ClassFunction
EXAMPLES:
sage: chi = ClassFunction(SymmetricGroup(4), gap([3, 1, -1, 0, -1]))
sage: p = chi.symmetric_power(3)sage: pCharacter of Symmetric group of order 4! as a permutation group
sage: p.values()[10, 2, -2, 1, 0]>>> from sage.all import *>>> chi = ClassFunction(SymmetricGroup(Integer(4)), gap([Integer(3),␣
˓→Integer(1), -Integer(1), Integer(0), -Integer(1)]))>>> p = chi.symmetric_power(Integer(3))>>> pCharacter of Symmetric group of order 4! as a permutation group>>> p.values()[10, 2, -2, 1, 0]

tensor_product(other)
EXAMPLES:
sage: S3 = SymmetricGroup(3)sage: chi1, chi2, chi3 = S3.irreducible_characters()
sage: chi1.tensor_product(chi3).values()[1, -1, 1]>>> from sage.all import *>>> S3 = SymmetricGroup(Integer(3))>>> chi1, chi2, chi3 = S3.irreducible_characters()(continues on next page)

288

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)>>> chi1.tensor_product(chi3).values()[1, -1, 1]

values()Return the list of values of self on the conjugacy classes.
EXAMPLES:
sage: G = GL(2,3)
sage: [x.values() for x in G.irreducible_characters()] #random[[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, -1, -1, -1],
[2, -1, 2, -1, 2, 0, 0, 0],[2, 1, -2, -1, 0, -zeta8^3 - zeta8, zeta8^3 + zeta8, 0],[2, 1, -2, -1, 0, zeta8^3 + zeta8, -zeta8^3 - zeta8, 0],[3, 0, 3, 0, -1, -1, -1, 1],[3, 0, 3, 0, -1, 1, 1, -1],
[4, -1, -4, 1, 0, 0, 0, 0]]>>> from sage.all import *>>> G = GL(Integer(2),Integer(3))>>> [x.values() for x in G.irreducible_characters()] #random[[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, -1, -1, -1],
[2, -1, 2, -1, 2, 0, 0, 0],[2, 1, -2, -1, 0, -zeta8^3 - zeta8, zeta8^3 + zeta8, 0],[2, 1, -2, -1, 0, zeta8^3 + zeta8, -zeta8^3 - zeta8, 0],[3, 0, 3, 0, -1, -1, -1, 1],[3, 0, 3, 0, -1, 1, 1, -1],
[4, -1, -4, 1, 0, 0, 0, 0]]class sage.groups.class_function.ClassFunction_libgap(G, values)
Bases: SageObject
A wrapper of GAP’s ClassFunction function.
Note: It is not checked whether the given values describes a character, since GAP does not do this.
EXAMPLES:
sage: G = SO(3,3)
sage: values = [1, -1, -1, 1, 2]
sage: chi = ClassFunction(G, values); chiCharacter of Special Orthogonal Group of degree 3 over Finite Field of size 3
sage: loads(dumps(chi)) == chi
True>>> from sage.all import *>>> G = SO(Integer(3),Integer(3))>>> values = [Integer(1), -Integer(1), -Integer(1), Integer(1), Integer(2)]>>> chi = ClassFunction(G, values); chiCharacter of Special Orthogonal Group of degree 3 over Finite Field of size 3>>> loads(dumps(chi)) == chi
True

289

Groups, Release 10.4

adams_operation(k)Return the k-th Adams operation on self.
Let 𝐺 be a finite group. The 𝑘-th Adams operation Ψ𝑘 is given byΨ𝑘 (𝜒)(𝑔) = 𝜒(𝑔 𝑘 ).
The Adams operations turn the representation ring of 𝐺 into a 𝜆-ring.
EXAMPLES:
sage: G = GL(2,3)
sage: chars = G.irreducible_characters()
sage: [chi.adams_operation(2).values() for chi in chars][[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, 1, 1, 1],[2, -1, 2, -1, 2, 2, 2, 2],[2, -1, 2, -1, -2, 0, 0, 2],[2, -1, 2, -1, -2, 0, 0, 2],[3, 0, 3, 0, 3, -1, -1, 3],[3, 0, 3, 0, 3, -1, -1, 3],[4, 1, 4, 1, -4, 0, 0, 4]]
sage: chars[5].adams_operation(3).decompose()((1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(-1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3))>>> from sage.all import *>>> G = GL(Integer(2),Integer(3))>>> chars = G.irreducible_characters()>>> [chi.adams_operation(Integer(2)).values() for chi in chars][[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, 1, 1, 1],[2, -1, 2, -1, 2, 2, 2, 2],[2, -1, 2, -1, -2, 0, 0, 2],[2, -1, 2, -1, -2, 0, 0, 2],[3, 0, 3, 0, 3, -1, -1, 3],[3, 0, 3, 0, 3, -1, -1, 3],[4, 1, 4, 1, -4, 0, 0, 4]]>>> chars[Integer(5)].adams_operation(Integer(3)).decompose()((1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(-1, Character of General Linear Group of degree 2 over Finite Field of size␣˓→3),(1, Character of General Linear Group of degree 2 over Finite Field of size␣
˓→3))

REFERENCES:• Wikipedia article Adams_operation

290

Chapter 24. Class functions of groups.

Groups, Release 10.4

central_character()
Return the central character of self.
EXAMPLES:
sage: t = SymmetricGroup(4).trivial_character()sage: t.central_character().values()[1, 6, 3, 8, 6]>>> from sage.all import *>>> t = SymmetricGroup(Integer(4)).trivial_character()>>> t.central_character().values()[1, 6, 3, 8, 6]

decompose()
Return a list of the characters appearing the decomposition of self.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: chi = ClassFunction(S5, [22, -8, 2, 1, 1, 2, -3])
sage: chi.decompose()((3, Character of Symmetric group of order 5! as a permutation group),(2, Character of Symmetric group of order 5! as a permutation group))>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> chi = ClassFunction(S5, [Integer(22), -Integer(8), Integer(2), Integer(1),˓→ Integer(1), Integer(2), -Integer(3)])>>> chi.decompose()((3, Character of Symmetric group of order 5! as a permutation group),(2, Character of Symmetric group of order 5! as a permutation group))

degree()Return the degree of the character self.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: irr = S5.irreducible_characters()
sage: [x.degree() for x in irr]
[1, 4, 5, 6, 5, 4, 1]>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> irr = S5.irreducible_characters()>>> [x.degree() for x in irr]
[1, 4, 5, 6, 5, 4, 1]

determinant_character()
Return the determinant character of self.
EXAMPLES:
sage: t = ClassFunction(SymmetricGroup(4), [1, -1, 1, 1, -1])
sage: t.determinant_character().values()[1, -1, 1, 1, -1]

291

Groups, Release 10.4>>> from sage.all import *>>> t = ClassFunction(SymmetricGroup(Integer(4)), [Integer(1), -Integer(1),␣
˓→Integer(1), Integer(1), -Integer(1)])>>> t.determinant_character().values()[1, -1, 1, 1, -1]

domain()Return the domain of self.
OUTPUT: the underlying group of the class function
EXAMPLES:
sage: ClassFunction(SymmetricGroup(4), [1,-1,1,1,-1]).domain()Symmetric group of order 4! as a permutation group>>> from sage.all import *>>> ClassFunction(SymmetricGroup(Integer(4)), [Integer(1),-Integer(1),˓→Integer(1),Integer(1),-Integer(1)]).domain()Symmetric group of order 4! as a permutation group

exterior_power(n)Return the antisymmetrized product of self with itself n times.
INPUT:• n – positive integer
OUTPUT: the n-th antisymmetrized power of self as a ClassFunction
EXAMPLES:
sage: chi = ClassFunction(SymmetricGroup(4), [3, 1, -1, 0, -1])
sage: p = chi.exterior_power(3)# the highest antisymmetric power for a 3-d␣
˓→charactersage: pCharacter of Symmetric group of order 4! as a permutation group
sage: p.values()[1, -1, 1, 1, -1]
sage: p == chi.determinant_character()True>>> from sage.all import *>>> chi = ClassFunction(SymmetricGroup(Integer(4)), [Integer(3), Integer(1), ˓→Integer(1), Integer(0), -Integer(1)])>>> p = chi.exterior_power(Integer(3))# the highest antisymmetric power␣˓→for a 3-d character>>> p
Character of Symmetric group of order 4! as a permutation group>>> p.values()[1, -1, 1, 1, -1]>>> p == chi.determinant_character()
True

gap()
Return the underlying LibGAP element.
EXAMPLES:

292

Chapter 24. Class functions of groups.

Groups, Release 10.4

sage: G = CyclicPermutationGroup(4)sage: values = [1, -1, 1, -1]
sage: chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation group
sage: type(chi)<class sage.groups.class_function.ClassFunction_libgap >sage: libgap(chi)ClassFunction( CharacterTable( Group([ (1,2,3,4) ]) ), [ 1, -1, 1, -1 ] )sage: type(_)<class sage.libs.gap.element.GapElement_List >>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> values = [Integer(1), -Integer(1), Integer(1), -Integer(1)]>>> chi = ClassFunction(G, values); chiCharacter of Cyclic group of order 4 as a permutation group>>> type(chi)<class sage.groups.class_function.ClassFunction_libgap >>>> libgap(chi)ClassFunction( CharacterTable( Group([ (1,2,3,4) ]) ), [ 1, -1, 1, -1 ] )>>> type(_)<class sage.libs.gap.element.GapElement_List >induct(G)Return the induced character.
INPUT:• G – a supergroup of the underlying group of self
OUTPUT:
A ClassFunction of G defined by induction. Induction is the adjoint functor to restriction, see restrict().
EXAMPLES:
sage: G = SymmetricGroup(5)sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
sage: xi = H.trivial_character(); xi
Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)sage: xi.induct(G)Character of Symmetric group of order 5! as a permutation group
sage: xi.induct(G).values()[10, 4, 2, 1, 1, 0, 0]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> H = G.subgroup([(Integer(1),Integer(2),Integer(3)), (Integer(1),˓→Integer(2)), (Integer(4),Integer(5))])>>> xi = H.trivial_character(); xi
Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)>>> xi.induct(G)Character of Symmetric group of order 5! as a permutation group>>> xi.induct(G).values()[10, 4, 2, 1, 1, 0, 0]293Groups, Release 10.4

irreducible_constituents()
Return a list of the characters that appear in the decomposition of self.
EXAMPLES:
sage: S5 = SymmetricGroup(5)sage: chi = ClassFunction(S5, [22, -8, 2, 1, 1, 2, -3])
sage: irr = chi.irreducible_constituents(); irr(Character of Symmetric group of order 5! as a permutation group,
Character of Symmetric group of order 5! as a permutation group)sage: list(map(list, irr))[[4, -2, 0, 1, 1, 0, -1], [5, -1, 1, -1, -1, 1, 0]]
sage: G = GL(2,3)
sage: chi = ClassFunction(G, [-1, -1, -1, -1, -1, -1, -1, -1])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)
sage: chi = ClassFunction(G, [1, 1, 1, 1, 1, 1, 1, 1])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)
sage: chi = ClassFunction(G, [2, 2, 2, 2, 2, 2, 2, 2])
sage: chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)
sage: chi = ClassFunction(G, [-1, -1, -1, -1, 3, -1, -1, 1])
sage: ic = chi.irreducible_constituents(); ic(Character of General Linear Group of degree 2 over Finite Field of size 3,
Character of General Linear Group of degree 2 over Finite Field of size 3)
sage: list(map(list, ic))[[2, -1, 2, -1, 2, 0, 0, 0], [3, 0, 3, 0, -1, 1, 1, -1]]>>> from sage.all import *>>> S5 = SymmetricGroup(Integer(5))>>> chi = ClassFunction(S5, [Integer(22), -Integer(8), Integer(2), Integer(1),˓→ Integer(1), Integer(2), -Integer(3)])>>> irr = chi.irreducible_constituents(); irr(Character of Symmetric group of order 5! as a permutation group,
Character of Symmetric group of order 5! as a permutation group)>>> list(map(list, irr))[[4, -2, 0, 1, 1, 0, -1], [5, -1, 1, -1, -1, 1, 0]]>>> G = GL(Integer(2),Integer(3))>>> chi = ClassFunction(G, [-Integer(1), -Integer(1), -Integer(1), ˓→Integer(1), -Integer(1), -Integer(1), -Integer(1), -Integer(1)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [Integer(1), Integer(1), Integer(1), Integer(1),␣
˓→Integer(1), Integer(1), Integer(1), Integer(1)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [Integer(2), Integer(2), Integer(2), Integer(2),␣
˓→Integer(2), Integer(2), Integer(2), Integer(2)])>>> chi.irreducible_constituents()(Character of General Linear Group of degree 2 over Finite Field of size 3,)>>> chi = ClassFunction(G, [-Integer(1), -Integer(1), -Integer(1), ˓→Integer(1), Integer(3), -Integer(1), -Integer(1), Integer(1)])>>> ic = chi.irreducible_constituents(); ic(Character of General Linear Group of degree 2 over Finite Field of size 3,
Character of General Linear Group of degree 2 over Finite Field of size 3)(continues on next page)294

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)>>> list(map(list, ic))[[2, -1, 2, -1, 2, 0, 0, 0], [3, 0, 3, 0, -1, 1, 1, -1]]

is_irreducible()
Return True if self cannot be written as the sum of two nonzero characters of self.
EXAMPLES:
sage: S4 = SymmetricGroup(4)sage: irr = S4.irreducible_characters()
sage: [x.is_irreducible() for x in irr]
[True, True, True, True, True]>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> irr = S4.irreducible_characters()>>> [x.is_irreducible() for x in irr]
[True, True, True, True, True]

norm()
Return the norm of self.
EXAMPLES:
sage: A5 = AlternatingGroup(5)sage: [x.norm() for x in A5.irreducible_characters()][1, 1, 1, 1, 1]>>> from sage.all import *>>> A5 = AlternatingGroup(Integer(5))>>> [x.norm() for x in A5.irreducible_characters()][1, 1, 1, 1, 1]

restrict(H)Return the restricted character.
INPUT:• H – a subgroup of the underlying group of self
OUTPUT: a ClassFunction of H defined by restriction
EXAMPLES:
sage: G = SymmetricGroup(5)sage: chi = ClassFunction(G, [3, -3, -1, 0, 0, -1, 3]); chiCharacter of Symmetric group of order 5! as a permutation group
sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
sage: chi.restrict(H)Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)sage: chi.restrict(H).values()[3, -3, -3, -1, 0, 0]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))(continues on next page)295

Groups, Release 10.4

(continued from previous page)>>> chi = ClassFunction(G, [Integer(3), -Integer(3), -Integer(1), Integer(0),␣
˓→Integer(0), -Integer(1), Integer(3)]); chiCharacter of Symmetric group of order 5! as a permutation group>>> H = G.subgroup([(Integer(1),Integer(2),Integer(3)), (Integer(1),˓→Integer(2)), (Integer(4),Integer(5))])>>> chi.restrict(H)Character of Subgroup generated by [(1,2,3), (1,2), (4,5)] of(Symmetric group of order 5! as a permutation group)>>> chi.restrict(H).values()[3, -3, -3, -1, 0, 0]

scalar_product(other)
Return the scalar product of self with other.
EXAMPLES:
sage: S4 = SymmetricGroup(4)sage: irr = S4.irreducible_characters()
sage: [[x.scalar_product(y) for x in irr] for y in irr][[1, 0, 0, 0, 0],[0, 1, 0, 0, 0],[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 1]]>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> irr = S4.irreducible_characters()>>> [[x.scalar_product(y) for x in irr] for y in irr][[1, 0, 0, 0, 0],[0, 1, 0, 0, 0],[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 1]]symmetric_power(n)Return the symmetrized product of self with itself n times.
INPUT:• n – positive integer
OUTPUT: the n-th symmetrized power of self as a ClassFunction
EXAMPLES:
sage: chi = ClassFunction(SymmetricGroup(4), [3, 1, -1, 0, -1])
sage: p = chi.symmetric_power(3)sage: pCharacter of Symmetric group of order 4! as a permutation group
sage: p.values()[10, 2, -2, 1, 0]>>> from sage.all import *>>> chi = ClassFunction(SymmetricGroup(Integer(4)), [Integer(3), Integer(1), ˓→Integer(1), Integer(0), -Integer(1)])>>> p = chi.symmetric_power(Integer(3))(continues on next page)

296

Chapter 24. Class functions of groups.

Groups, Release 10.4

(continued from previous page)>>> pCharacter of Symmetric group of order 4! as a permutation group>>> p.values()[10, 2, -2, 1, 0]

tensor_product(other)
Return the tensor product of self and other.
EXAMPLES:
sage: S3 = SymmetricGroup(3)sage: chi1, chi2, chi3 = S3.irreducible_characters()
sage: chi1.tensor_product(chi3).values()[1, -1, 1]>>> from sage.all import *>>> S3 = SymmetricGroup(Integer(3))>>> chi1, chi2, chi3 = S3.irreducible_characters()>>> chi1.tensor_product(chi3).values()[1, -1, 1]

values()Return the list of values of self on the conjugacy classes.
EXAMPLES:
sage: G = GL(2,3)
sage: [x.values() for x in G.irreducible_characters()] # random[[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, -1, -1, -1],
[2, -1, 2, -1, 2, 0, 0, 0],[2, 1, -2, -1, 0, -zeta8^3 - zeta8, zeta8^3 + zeta8, 0],[2, 1, -2, -1, 0, zeta8^3 + zeta8, -zeta8^3 - zeta8, 0],[3, 0, 3, 0, -1, -1, -1, 1],[3, 0, 3, 0, -1, 1, 1, -1],
[4, -1, -4, 1, 0, 0, 0, 0]]>>> from sage.all import *>>> G = GL(Integer(2),Integer(3))>>> [x.values() for x in G.irreducible_characters()] # random[[1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, -1, -1, -1],
[2, -1, 2, -1, 2, 0, 0, 0],[2, 1, -2, -1, 0, -zeta8^3 - zeta8, zeta8^3 + zeta8, 0],[2, 1, -2, -1, 0, zeta8^3 + zeta8, -zeta8^3 - zeta8, 0],[3, 0, 3, 0, -1, -1, -1, 1],[3, 0, 3, 0, -1, 1, 1, -1],
[4, -1, -4, 1, 0, 0, 0, 0]]297

Groups, Release 10.4

298

Chapter 24. Class functions of groups.

CHAPTERTWENTYFIVECONJUGACY CLASSES OF GROUPS

This module implements a wrapper of GAP’s ConjugacyClass function.
There are two main classes, ConjugacyClass and ConjugacyClassGAP. All generic methods should go into
ConjugacyClass, whereas ConjugacyClassGAP should only contain wrappers for GAP functions. ConjugacyClass contains some fallback methods in case some group cannot be defined as a GAP object.
Todo:• Implement a non-naive fallback method for computing all the elements of the conjugacy class when the group is
not defined in GAP, as the one in Butler’s paper.
• Define a sage method for gap matrices so that groups of matrices can use the quicker GAP algorithm rather than
the naive one.
EXAMPLES:
Conjugacy classes for groups of permutations:sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: G.conjugacy_class(g)˓→needs sage.combinat
Conjugacy class of cycle type [4] in Symmetric group of order 4! as a permutation␣
˓→group#␣>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> G.conjugacy_class(g)#␣˓→needs sage.combinat
Conjugacy class of cycle type [4] in Symmetric group of order 4! as a permutation␣
˓→group

Conjugacy classes for groups of matrices:sage: F = GF(5)sage: gens = [matrix(F,2,[1,2, -1, 1]), matrix(F,2, [1,1, 0,1])]
sage: H = MatrixGroup(gens)sage: h = H(matrix(F,2,[1,2, -1, 1]))
sage: H.conjugacy_class(h)Conjugacy class of [1 2][4 1] in Matrix group over Finite Field of size 5 with 2 generators ([1 2] [1 1](continues on next page)299

Groups, Release 10.4

(continued from previous page)[4 1], [0 1])>>> from sage.all import *>>> F = GF(Integer(5))>>> gens = [matrix(F,Integer(2),[Integer(1),Integer(2), -Integer(1), Integer(1)]),␣
˓→matrix(F,Integer(2), [Integer(1),Integer(1), Integer(0),Integer(1)])]>>> H = MatrixGroup(gens)>>> h = H(matrix(F,Integer(2),[Integer(1),Integer(2), -Integer(1), Integer(1)]))>>> H.conjugacy_class(h)Conjugacy class of [1 2][4 1] in Matrix group over Finite Field of size 5 with 2 generators ([1 2] [1 1][4 1], [0 1])class sage.groups.conjugacy_classes.ConjugacyClass(group, element)
Bases: Parent
Generic conjugacy classes for elements in a group.
This is the default fall-back implementation to be used whenever GAP cannot handle the group.
EXAMPLES:
sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: ConjugacyClass(G,g)
Conjugacy class of (1,2,3,4) in Symmetric group of order 4! as a
permutation group>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> ConjugacyClass(G,g)
Conjugacy class of (1,2,3,4) in Symmetric group of order 4! as a
permutation groupan_element()
Return a representative of self.
EXAMPLES:
sage: G = SymmetricGroup(3)sage: g = G((1,2,3))
sage: C = ConjugacyClass(G,g)
sage: C.representative()(1,2,3)>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> g = G((Integer(1),Integer(2),Integer(3)))>>> C = ConjugacyClass(G,g)>>> C.representative()(1,2,3)300

Chapter 25. Conjugacy classes of groups

Groups, Release 10.4

is_rational()
Check if self is rational (closed for powers).
EXAMPLES:
sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: c = ConjugacyClass(G,g)
sage: c.is_rational()
False>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> c = ConjugacyClass(G,g)>>> c.is_rational()
False

is_real()Check if self is real (closed for inverses).
EXAMPLES:
sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: c = ConjugacyClass(G,g)
sage: c.is_real()
True>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> c = ConjugacyClass(G,g)>>> c.is_real()
True

list()
Return a list with all the elements of self.
EXAMPLES:
Groups of permutations:sage: G = SymmetricGroup(3)sage: g = G((1,2,3))
sage: c = ConjugacyClass(G,g)
sage: L = c.list()
sage: Set(L) == Set([G((1,3,2)), G((1,2,3))])True>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> g = G((Integer(1),Integer(2),Integer(3)))>>> c = ConjugacyClass(G,g)>>> L = c.list()>>> Set(L) == Set([G((Integer(1),Integer(3),Integer(2))), G((Integer(1),˓→Integer(2),Integer(3)))])
True

301

Groups, Release 10.4

representative()
Return a representative of self.
EXAMPLES:
sage: G = SymmetricGroup(3)sage: g = G((1,2,3))
sage: C = ConjugacyClass(G,g)
sage: C.representative()(1,2,3)>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> g = G((Integer(1),Integer(2),Integer(3)))>>> C = ConjugacyClass(G,g)>>> C.representative()(1,2,3)set()
Return the set of elements of the conjugacy class.
EXAMPLES:
Groups of permutations:sage: G = SymmetricGroup(3)sage: g = G((1,2))
sage: C = ConjugacyClass(G,g)
sage: S = [(2,3), (1,2), (1,3)]
sage: C.set() == Set(G(x) for x in S)
True>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> g = G((Integer(1),Integer(2)))>>> C = ConjugacyClass(G,g)>>> S = [(Integer(2),Integer(3)), (Integer(1),Integer(2)), (Integer(1),˓→Integer(3))]>>> C.set() == Set(G(x) for x in S)
TrueGroups of matrices over finite fields:
sage: F = GF(5)sage: gens = [matrix(F,2,[1,2, -1, 1]), matrix(F,2, [1,1, 0,1])]
sage: H = MatrixGroup(gens)sage: h = H(matrix(F,2,[1,2, -1, 1]))
sage: C = ConjugacyClass(H,h)
sage: S = [[[3, 2], [2, 4]], [[0, 1], [2, 2]], [[3, 4], [1, 4]],\[[0, 3], [4, 2]], [[1, 2], [4, 1]], [[2, 1], [2, 0]],\[[4, 1], [4, 3]], [[4, 4], [1, 3]], [[2, 4], [3, 0]],\[[1, 4], [2, 1]], [[3, 3], [3, 4]], [[2, 3], [4, 0]],\[[0, 2], [1, 2]], [[1, 3], [1, 1]], [[4, 3], [3, 3]],\[[4, 2], [2, 3]], [[0, 4], [3, 2]], [[1, 1], [3, 1]],\[[2, 2], [1, 0]], [[3, 1], [4, 4]]]sage: C.set() == Set(H(x) for x in S)
True

302

Chapter 25. Conjugacy classes of groups

Groups, Release 10.4>>> from sage.all import *>>> F = GF(Integer(5))>>> gens = [matrix(F,Integer(2),[Integer(1),Integer(2), -Integer(1),␣
˓→Integer(1)]), matrix(F,Integer(2), [Integer(1),Integer(1), Integer(0),˓→Integer(1)])]>>> H = MatrixGroup(gens)>>> h = H(matrix(F,Integer(2),[Integer(1),Integer(2), -Integer(1),␣
˓→Integer(1)]))>>> C = ConjugacyClass(H,h)>>> S = [[[Integer(3), Integer(2)], [Integer(2), Integer(4)]], [[Integer(0),␣
˓→Integer(1)], [Integer(2), Integer(2)]], [[Integer(3), Integer(4)],␣
˓→[Integer(1), Integer(4)]],\[[0, 3], [4, 2]], [[1, 2], [4, 1]], [[2, 1], [2, 0]],\[[4, 1], [4, 3]], [[4, 4], [1, 3]], [[2, 4], [3, 0]],\[[1, 4], [2, 1]], [[3, 3], [3, 4]], [[2, 3], [4, 0]],\[[0, 2], [1, 2]], [[1, 3], [1, 1]], [[4, 3], [3, 3]],\[[4, 2], [2, 3]], [[0, 4], [3, 2]], [[1, 1], [3, 1]],\[[2, 2], [1, 0]], [[3, 1], [4, 4]]]>>> C.set() == Set(H(x) for x in S)
True

It is not implemented for infinite groups:
sage: a = matrix(ZZ,2,[1,1,0,1])
sage: b = matrix(ZZ,2,[1,0,1,1])
sage: G = MatrixGroup([a,b])# takes 1ssage: g = G(a)sage: C = ConjugacyClass(G, g)sage: C.set()
Traceback (most recent call last):...
NotImplementedError: Listing the elements of conjugacy classes is not␣
˓→implemented for infinite groups! Use the iter function instead.
>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),[Integer(1),Integer(1),Integer(0),Integer(1)])>>> b = matrix(ZZ,Integer(2),[Integer(1),Integer(0),Integer(1),Integer(1)])>>> G = MatrixGroup([a,b])# takes 1s>>> g = G(a)>>> C = ConjugacyClass(G, g)>>> C.set()
Traceback (most recent call last):...
NotImplementedError: Listing the elements of conjugacy classes is not␣
˓→implemented for infinite groups! Use the iter function instead.

class sage.groups.conjugacy_classes.ConjugacyClassGAP(group, element)
Bases: ConjugacyClassClass for a conjugacy class for groups defined over GAP.
Intended for wrapping GAP methods on conjugacy classes.
INPUT:• group – the group in which the conjugacy class is taken• element – the element generating the conjugacy class
EXAMPLES:
303

Groups, Release 10.4

sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: ConjugacyClassGAP(G,g)
Conjugacy class of (1,2,3,4) in Symmetric group of order 4! as a
permutation group>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> ConjugacyClassGAP(G,g)
Conjugacy class of (1,2,3,4) in Symmetric group of order 4! as a
permutation groupcardinality()
Return the size of this conjugacy class.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: W = WeylGroup([ C ,6])
sage: cc = W.conjugacy_class(W.an_element())
sage: cc.cardinality()
3840
sage: type(cc.cardinality())<class sage.rings.integer.Integer >>>> from sage.all import *>>> # needs sage.rings.number_field>>> W = WeylGroup([ C ,Integer(6)])>>> cc = W.conjugacy_class(W.an_element())>>> cc.cardinality()
3840>>> type(cc.cardinality())<class sage.rings.integer.Integer >set()
Return a Sage Set with all the elements of the conjugacy class.
By default attempts to use GAP construction of the conjugacy class. If GAP method is not implemented forthe given group, and the group is finite, falls back to a naive algorithm.
Warning: The naive algorithm can be really slow and memory intensive.
EXAMPLES:
Groups of permutations:sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4))
sage: C = ConjugacyClassGAP(G,g)
sage: S = [(1,3,2,4), (1,4,3,2), (1,3,4,2), (1,2,3,4), (1,4,2,3), (1,2,4,3)]
sage: C.set() == Set(G(x) for x in S)
True

304

Chapter 25. Conjugacy classes of groups

Groups, Release 10.4>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> C = ConjugacyClassGAP(G,g)>>> S = [(Integer(1),Integer(3),Integer(2),Integer(4)), (Integer(1),˓→Integer(4),Integer(3),Integer(2)), (Integer(1),Integer(3),Integer(4),˓→Integer(2)), (Integer(1),Integer(2),Integer(3),Integer(4)), (Integer(1),˓→Integer(4),Integer(2),Integer(3)), (Integer(1),Integer(2),Integer(4),˓→Integer(3))]>>> C.set() == Set(G(x) for x in S)
True

305

Groups, Release 10.4

306

Chapter 25. Conjugacy classes of groups

CHAPTERTWENTYSIXABELIAN GROUPS

26.1 Multiplicative Abelian Groups
This module lets you compute with finitely generated Abelian groups of the form𝐺=
It is customary to denote the infinite cyclic group
written as an integer vector𝑟⊕

𝑘1 ⊕ · · · ⊕𝑘𝑡

as having order 0, so the data defining the Abelian group can be⃗𝑘 = (0, . . . , 0, 𝑘1 , . . . , 𝑘𝑡 )where there are 𝑟 zeroes and 𝑡 non-zero values. To construct this Abelian group in Sage, you can either specify all entriesof ⃗𝑘 or only the non-zero entries together with the total number of generators:
sage: AbelianGroup([0,0,0,2,3])
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
sage: AbelianGroup(5, [2,3])
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3>>> from sage.all import *>>> AbelianGroup([Integer(0),Integer(0),Integer(0),Integer(2),Integer(3)])
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3>>> AbelianGroup(Integer(5), [Integer(2),Integer(3)])
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3

It is also legal to specify 1 as the order. The corresponding generator will be the neutral element, but it will still take up
an index in the labelling of the generators:
sage: G = AbelianGroup([2,1,3], names= g )sage: G.gens()(g0, 1, g2)>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(1),Integer(3)], names= g )>>> G.gens()(g0, 1, g2)

Note that this presentation is not unique, for example 6 ∼= 2 × 3 . The orders of the generators ⃗𝑘 =(0, . . . , 0, 𝑘1 , . . . , 𝑘𝑡 ) has previously been called invariants in Sage, even though they are not necessarily the (unique)invariant factors of the group. You should now use gens_orders() instead:

307

Groups, Release 10.4

sage: J = AbelianGroup([2,0,3,2,4]); J
Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
sage: J.gens_orders()# use this instead(2, 0, 3, 2, 4)
sage: J.invariants()# deprecated(2, 0, 3, 2, 4)
sage: J.elementary_divisors()# these are the "invariant factors"(2, 2, 12, 0)
sage: for i in range(J.ngens()):....:
print((i, J.gen(i), J.gen(i).order()))# or use this form
(0, f0, 2)(1, f1, +Infinity)(2, f2, 3)(3, f3, 2)(4, f4, 4)>>> from sage.all import *>>> J = AbelianGroup([Integer(2),Integer(0),Integer(3),Integer(2),Integer(4)]);Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4>>> J.gens_orders()# use this instead(2, 0, 3, 2, 4)>>> J.invariants()# deprecated(2, 0, 3, 2, 4)>>> J.elementary_divisors()# these are the "invariant factors"(2, 2, 12, 0)>>> for i in range(J.ngens()):...
print((i, J.gen(i), J.gen(i).order()))# or use this form
(0, f0, 2)(1, f1, +Infinity)(2, f2, 3)(3, f3, 2)(4, f4, 4)J

Background on invariant factors and the Smith normal form (according to section 4.1 of [Cohen1]): An abelian group isa group 𝐴 for which there exists an exact sequence 𝑘 → ℓ → 𝐴 → 1, for some positive integers 𝑘, ℓ with 𝑘 ≤ ℓ. For
example, a finite abelian group has a decomposition
𝐴 = ⟨𝑎1 ⟩ × · · · × ⟨𝑎ℓ ⟩,where ord(𝑎𝑖 ) = 𝑝𝑐𝑖 𝑖 , for some primes 𝑝𝑖 and some positive integers 𝑐𝑖 , 𝑖 = 1, ..., ℓ. GAP calls the list (ordered by size)of the 𝑝𝑐𝑖 𝑖 the abelian invariants. In Sage they will be called invariants. In this situation, 𝑘 = ℓ and 𝜑 : ℓ → 𝐴 is themap 𝜑(𝑥1 , ..., 𝑥ℓ ) = 𝑎𝑥1 1 ...𝑎𝑥ℓ ℓ , for (𝑥1 , ..., 𝑥ℓ ) ∈ ℓ . The matrix of relations 𝑀 : 𝑘 → ℓ is the matrix whose rows
generate the kernel of 𝜑 as a -module. In other words, 𝑀 = (𝑀𝑖𝑗 ) is a ℓ × ℓ diagonal matrix with 𝑀𝑖𝑖 = 𝑝𝑐𝑖 𝑖 . Consider𝑓𝑓𝑓𝑓
now the subgroup 𝐵 ⊂ 𝐴 generated by 𝑏1 = 𝑎11,1 ...𝑎ℓ ℓ,1 , …, 𝑏𝑚 = 𝑎11,𝑚 ...𝑎ℓ ℓ,𝑚 . The kernel of the map 𝜑𝐵 : 𝑚 → 𝐵
𝑦1𝑦𝑚𝑚defined by 𝜑𝐵 (𝑦1 , ..., 𝑦𝑚 ) = 𝑏1 ...𝑏𝑚 , for (𝑦1 , ..., 𝑦𝑚 ) ∈, is the kernel of the matrix⎛⎞
𝑓11 𝑓12 . . . 𝑓1𝑚⎜ 𝑓21 𝑓22 . . . 𝑓2𝑚 ⎟⎜⎟𝐹 =⎜ .
.. ⎟ ,
..
⎝ ..
.
. ⎠
𝑓ℓ,1

𝑓ℓ,2

...

𝑓ℓ,𝑚

regarded as a map 𝑚 → ( /𝑝𝑐11 ) × ... × ( /𝑝𝑐ℓℓ ). In particular, 𝐵 ∼= 𝑚 / ker(𝐹 ). If 𝐵 = 𝐴 then the Smith
normal form (SNF) of a generator matrix of ker(𝐹 ) and the SNF of 𝑀 are the same. The diagonal entries 𝑠𝑖 of the SNF
𝑆 = diag[𝑠1 , 𝑠2 , 𝑠3 , ...𝑠𝑟 , 0, 0, ...0], are called determinantal divisors of 𝐹 . where 𝑟 is the rank. The invariant factors of
𝐴 are:
𝑠1 , 𝑠2 /𝑠1 , 𝑠3 /𝑠2 , ...𝑠𝑟 /𝑠𝑟−1 .
308

Chapter 26. Abelian Groups

Groups, Release 10.4

Sage supports multiplicative abelian groups on any prescribed finite number 𝑛 ≥ 0 of generators. Use the AbelianGroup() function to create an abelian group, and the gen() and gens() methods to obtain the corresponding generators. You can print the generators as arbitrary strings using the optional names argument to the AbelianGroup()function.
EXAMPLE 1:
We create an abelian group in zero or more variables; the syntax T(1) creates the identity element even in the rank zerocase:sage: T = AbelianGroup(0, [])sage: T
Trivial Abelian group
sage: T.gens()()
sage: T(1)1>>> from sage.all import *>>> T = AbelianGroup(Integer(0), [])>>> T
Trivial Abelian group>>> T.gens()()>>> T(Integer(1))
1EXAMPLE 2:
An Abelian group uses a multiplicative representation of elements, but the underlying representation is lists of integer
exponents:
sage: F = AbelianGroup(5, [3,4,5,5,7], names = list("abcde"))sage: F
Multiplicative Abelian group isomorphic to C3 x C4 x C5 x C5 x C7
sage: (a,b,c,d,e) = F.gens()
sage: a*b^2*e*d
a*b^2*d*e
sage: x = b^2*e*d*a^7
sage: xa*b^2*d*e
sage: x.list()[1, 2, 0, 1, 1]>>> from sage.all import *>>> F = AbelianGroup(Integer(5), [Integer(3),Integer(4),Integer(5),Integer(5),˓→Integer(7)], names = list("abcde"))>>> F
Multiplicative Abelian group isomorphic to C3 x C4 x C5 x C5 x C7>>> (a,b,c,d,e) = F.gens()>>> a*b**Integer(2)*e*da*b^2*d*e>>> x = b**Integer(2)*e*d*a**Integer(7)>>> xa*b^2*d*e>>> x.list()[1, 2, 0, 1, 1]

REFERENCES:
26.1. Multiplicative Abelian Groups309

Groups, Release 10.4

Warning: Many basic properties for infinite abelian groups are not implemented.
AUTHORS:• William Stein, David Joyner (2008-12): added (user requested) is_cyclic, fixed elementary_divisors.
• David Joyner (2006-03): (based on free abelian monoids by David Kohel)• David Joyner (2006-05) several significant bug fixes• David Joyner (2006-08) trivial changes to docs, added random, fixed bug in how invariants are recorded• David Joyner (2006-10) added dual_group method• David Joyner (2008-02) fixed serious bug in word_problem• David Joyner (2008-03) fixed bug in trivial group case
• David Loeffler (2009-05) added subgroups method• Volker Braun (2012-11) port to new Parent base. Use tuples for immutables. Rename invariants to gens_orders.
sage.groups.abelian_gps.abelian_group.AbelianGroup(n, gens_orders=None, names='f')Create the multiplicative abelian group in 𝑛 generators with given orders of generators (which need not be prime
powers).
INPUT:• n – integer (optional). If not specified, will be derived
from gens_orders.
• gens_orders – a list of non-negative integers in the form
[𝑎0 , 𝑎1 , . . . , 𝑎𝑛−1 ], typically written in increasing order. This list is padded with zeros if it has length
less than 𝑛. The orders of the commuting generators, with 0 denoting an infinite cyclic factor.
• names – (optional) names of generators
Alternatively, you can also give input in the form AbelianGroup(gens_orders, names="f"), where
the names keyword argument must be explicitly named.
OUTPUT:
Abelian group with generators and invariant type. The default name for generator A.i is fi, as in GAP.
EXAMPLES:
sage: F = AbelianGroup(5, [5,5,7,8,9], names= abcde )sage: F(1)1
sage: (a, b, c, d, e) = F.gens()
sage: mul([ a, b, a, c, b, d, c, d ], F(1))
a^2*b^2*c^2*d^2sage: d * b**2 * c**3b^2*c^3*d
sage: F = AbelianGroup(3, [2]*3); F
Multiplicative Abelian group isomorphic to C2 x C2 x C2
sage: H = AbelianGroup([2,3], names="xy"); H
Multiplicative Abelian group isomorphic to C2 x C3
sage: AbelianGroup(5)Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
sage: AbelianGroup(5).order()+Infinity

310

Chapter 26. Abelian Groups

Groups, Release 10.4>>> from sage.all import *>>> F = AbelianGroup(Integer(5), [Integer(5),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names= abcde )>>> F(Integer(1))
1>>> (a, b, c, d, e) = F.gens()>>> mul([ a, b, a, c, b, d, c, d ], F(Integer(1)))
a^2*b^2*c^2*d^2>>> d * b**Integer(2) * c**Integer(3)b^2*c^3*d>>> F = AbelianGroup(Integer(3), [Integer(2)]*Integer(3)); F
Multiplicative Abelian group isomorphic to C2 x C2 x C2>>> H = AbelianGroup([Integer(2),Integer(3)], names="xy"); H
Multiplicative Abelian group isomorphic to C2 x C3>>> AbelianGroup(Integer(5))
Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z>>> AbelianGroup(Integer(5)).order()+Infinity

Notice that 0’s are prepended if necessary:sage: G = AbelianGroup(5, [2,3,4]); G
Multiplicative Abelian group isomorphic to Z x Z x C2 x C3 x C4
sage: G.gens_orders()(0, 0, 2, 3, 4)>>> from sage.all import *>>> G = AbelianGroup(Integer(5), [Integer(2),Integer(3),Integer(4)]);Multiplicative Abelian group isomorphic to Z x Z x C2 x C3 x C4>>> G.gens_orders()(0, 0, 2, 3, 4)

G

The invariant list must not be longer than the number of generators:
sage: AbelianGroup(2, [2,3,4])
Traceback (most recent call last):...
ValueError: gens_orders (=(2, 3, 4)) must have length n (=2)>>> from sage.all import *>>> AbelianGroup(Integer(2), [Integer(2),Integer(3),Integer(4)])
Traceback (most recent call last):...
ValueError: gens_orders (=(2, 3, 4)) must have length n (=2)

class sage.groups.abelian_gps.abelian_group.AbelianGroup_class(generator_orders,
names,
category=None)
Bases: UniqueRepresentation, AbelianGroupThe parent for Abelian groups with chosen generator orders.
Warning:
directly.

You should use AbelianGroup() to construct Abelian groups and not instantiate this class

26.1. Multiplicative Abelian Groups

311

Groups, Release 10.4

INPUT:• generator_orders – list of integers. The orders of the (commuting) generators. Zero denotes an infinite
cyclic generator.
• names – names of the group generators (optional).
EXAMPLES:
sage: Z2xZ3 = AbelianGroup([2,3])
sage: Z6 = AbelianGroup([6])
sage: Z2xZ3 is Z2xZ3, Z6 is Z6(True, True)
sage: Z2xZ3 is Z6
False
sage: Z2xZ3 == Z6
False
sage: Z2xZ3.is_isomorphic(Z6)True
sage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
sage: F = AbelianGroup(5,[2, 4, 12, 24, 120], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120
sage: F.elementary_divisors()(2, 4, 12, 24, 120)sage: F.category()
Category of finite enumerated commutative groups>>> from sage.all import *>>> Z2xZ3 = AbelianGroup([Integer(2),Integer(3)])>>> Z6 = AbelianGroup([Integer(6)])>>> Z2xZ3 is Z2xZ3, Z6 is Z6(True, True)>>> Z2xZ3 is Z6
False>>> Z2xZ3 == Z6
False>>> Z2xZ3.is_isomorphic(Z6)
True>>> F = AbelianGroup(Integer(5),[Integer(5),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9>>> F = AbelianGroup(Integer(5),[Integer(2), Integer(4), Integer(12), Integer(24),
˓→ Integer(120)], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120>>> F.elementary_divisors()(2, 4, 12, 24, 120)>>> F.category()
Category of finite enumerated commutative groups

Element
alias of AbelianGroupElement
Subgroup
alias of AbelianGroup_subgroup
312

Chapter 26. Abelian Groups

Groups, Release 10.4

cardinality()
Return the order of this group.
EXAMPLES:
sage: G = AbelianGroup(2, [2,3])
sage: G.order()6sage: G = AbelianGroup(3, [2,3,0])
sage: G.order()+Infinity>>> from sage.all import *>>> G = AbelianGroup(Integer(2), [Integer(2),Integer(3)])>>> G.order()6>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(0)])>>> G.order()+Infinity

dual_group(names='X', base_ring=None)
Return the dual group.
INPUT:• names – string or list of strings. The generator names for the dual group.
• base_ring – the base ring. If None (default), then a suitable cyclotomic field is picked automatically.
OUTPUT: the dual abelian group
EXAMPLES:
sage: G = AbelianGroup([2])
sage: G.dual_group()#␣˓→needs sage.rings.number_field
Dual of Abelian Group isomorphic to Z/2Z over Cyclotomic Field of order 2 and␣
˓→degree 1
sage: G.dual_group().gens()#␣˓→needs sage.rings.number_field(X,)
sage: G.dual_group(names= Z ).gens()#␣˓→needs sage.rings.number_field(Z,)
sage: G.dual_group(base_ring=QQ)
Dual of Abelian Group isomorphic to Z/2Z over Rational Field>>> from sage.all import *>>> G = AbelianGroup([Integer(2)])>>> G.dual_group()#␣˓→needs sage.rings.number_field
Dual of Abelian Group isomorphic to Z/2Z over Cyclotomic Field of order 2 and␣
˓→degree 1>>> G.dual_group().gens()#␣˓→needs sage.rings.number_field(X,)>>> G.dual_group(names= Z ).gens()#␣˓→needs sage.rings.number_field(continues on next page)

26.1. Multiplicative Abelian Groups313

Groups, Release 10.4

(continued from previous page)(Z,)>>> G.dual_group(base_ring=QQ)
Dual of Abelian Group isomorphic to Z/2Z over Rational Field

elementary_divisors()
Return the elementary divisors of the group, using Pari.
Note: Here is another algorithm for computing the elementary divisors 𝑑1 , 𝑑2 , 𝑑3 , . . ., of a finite abeliangroup (where 𝑑1 |𝑑2 |𝑑3 | . . . are composed of prime powers dividing the invariants of the group in a way
described below). Just factor the invariants 𝑎𝑖 that define the abelian group. Then the biggest 𝑑𝑖 is the
product of the maximum prime powers dividing some 𝑎𝑗 . In other words, the largest 𝑑𝑖 is the product of 𝑝𝑣 ,where 𝑣 = max(ord𝑝 (𝑎𝑗 ) for all 𝑗). Now divide out all those 𝑝𝑣 ’s into the list of invariants 𝑎𝑖 , and get a newlist of “smaller invariants”. Repeat the above procedure on these “smaller invariants” to compute 𝑑𝑖−1 , andso on. (Thanks to Robert Miller for communicating this algorithm.)
OUTPUT: tuple of integers
EXAMPLES:
sage: G = AbelianGroup(2, [2,3])
sage: G.elementary_divisors()(6,)
sage: G = AbelianGroup(1, [6])sage: G.elementary_divisors()(6,)
sage: G = AbelianGroup(2, [2,6])
sage: G
Multiplicative Abelian group isomorphic to C2 x C6
sage: G.gens_orders()(2, 6)
sage: G.elementary_divisors()(2, 6)
sage: J = AbelianGroup([1,3,5,12])
sage: J.elementary_divisors()(3, 60)sage: G = AbelianGroup(2, [0,6])
sage: G.elementary_divisors()(6, 0)
sage: AbelianGroup([3,4,5]).elementary_divisors()(60,)>>> from sage.all import *>>> G = AbelianGroup(Integer(2), [Integer(2),Integer(3)])>>> G.elementary_divisors()(6,)>>> G = AbelianGroup(Integer(1), [Integer(6)])>>> G.elementary_divisors()(6,)>>> G = AbelianGroup(Integer(2), [Integer(2),Integer(6)])>>> G
Multiplicative Abelian group isomorphic to C2 x C6>>> G.gens_orders()(2, 6)(continues on next page)

314

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> G.elementary_divisors()(2, 6)>>> J = AbelianGroup([Integer(1),Integer(3),Integer(5),Integer(12)])>>> J.elementary_divisors()(3, 60)>>> G = AbelianGroup(Integer(2), [Integer(0),Integer(6)])>>> G.elementary_divisors()(6, 0)>>> AbelianGroup([Integer(3),Integer(4),Integer(5)]).elementary_divisors()(60,)

exponent()
Return the exponent of this abelian group.
EXAMPLES:
sage: G = AbelianGroup([2,3,7]); G
Multiplicative Abelian group isomorphic to C2 x C3 x C7
sage: G.exponent()
42
sage: G = AbelianGroup([2,4,6]); G
Multiplicative Abelian group isomorphic to C2 x C4 x C6
sage: G.exponent()
12>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(7)]); G
Multiplicative Abelian group isomorphic to C2 x C3 x C7>>> G.exponent()42>>> G = AbelianGroup([Integer(2),Integer(4),Integer(6)]); G
Multiplicative Abelian group isomorphic to C2 x C4 x C6>>> G.exponent()
12

gen(i=0)
The 𝑖-th generator of the abelian group.
EXAMPLES:
sage: F = AbelianGroup(5,[],names= a )sage: F.0a0
sage: F.2
a2
sage: F.gens_orders()(0, 0, 0, 0, 0)
sage: G = AbelianGroup([2,1,3])
sage: G.gens()(f0, 1, f2)>>> from sage.all import *>>> F = AbelianGroup(Integer(5),[],names= a )>>> F.gen(0)a0(continues on next page)

26.1. Multiplicative Abelian Groups

315

Groups, Release 10.4

(continued from previous page)>>> F.gen(2)a2>>> F.gens_orders()(0, 0, 0, 0, 0)>>> G = AbelianGroup([Integer(2),Integer(1),Integer(3)])>>> G.gens()(f0, 1, f2)gens()
Return the generators of the group.
OUTPUT:
A tuple of group elements. The generators according to the chosen gens_orders().
EXAMPLES:
sage: F = AbelianGroup(5, [3,2], names= abcde )sage: F.gens()(a, b, c, d, e)
sage: [g.order() for g in F.gens()][+Infinity, +Infinity, +Infinity, 3, 2]>>> from sage.all import *>>> F = AbelianGroup(Integer(5), [Integer(3),Integer(2)], names= abcde )>>> F.gens()(a, b, c, d, e)>>> [g.order() for g in F.gens()][+Infinity, +Infinity, +Infinity, 3, 2]

gens_orders()
Return the orders of the cyclic factors that this group has been defined with.
Use elementary_divisors() if you are looking for an invariant of the group.
OUTPUT: tuple of integers
EXAMPLES:
sage: Z2xZ3 = AbelianGroup([2,3])
sage: Z2xZ3.gens_orders()(2, 3)
sage: Z2xZ3.elementary_divisors()(6,)
sage: Z6 = AbelianGroup([6])
sage: Z6.gens_orders()(6,)
sage: Z6.elementary_divisors()(6,)
sage: Z2xZ3.is_isomorphic(Z6)True
sage: Z2xZ3 is Z6
False

316

Chapter 26. Abelian Groups

Groups, Release 10.4>>> from sage.all import *>>> Z2xZ3 = AbelianGroup([Integer(2),Integer(3)])>>> Z2xZ3.gens_orders()(2, 3)>>> Z2xZ3.elementary_divisors()(6,)>>> Z6 = AbelianGroup([Integer(6)])>>> Z6.gens_orders()(6,)>>> Z6.elementary_divisors()(6,)>>> Z2xZ3.is_isomorphic(Z6)
True>>> Z2xZ3 is Z6
False

identity()
Return the identity element of this group.
EXAMPLES:
sage: G = AbelianGroup([2,2])
sage: e = G.identity()
sage: e1sage: g = G.gen(0)sage: g*ef0
sage: e*g
f0>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(2)])>>> e = G.identity()>>> e
1>>> g = G.gen(Integer(0))>>> g*ef0>>> e*gf0

invariants()
Return the orders of the cyclic factors that this group has been defined with.
For historical reasons this has been called invariants in Sage, even though they are not necessarily the invariant
factors of the group. Use gens_orders() instead:sage: J = AbelianGroup([2,0,3,2,4]); J
Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
sage: J.invariants()# deprecated(2, 0, 3, 2, 4)
sage: J.gens_orders()# use this instead(2, 0, 3, 2, 4)
sage: for i in range(J.ngens()):(continues on next page)

26.1. Multiplicative Abelian Groups

317

Groups, Release 10.4

(continued from previous page)....:
print((i, J.gen(i), J.gen(i).order()))(0, f0, 2)(1, f1, +Infinity)(2, f2, 3)(3, f3, 2)(4, f4, 4)# or this>>> from sage.all import *>>> J = AbelianGroup([Integer(2),Integer(0),Integer(3),Integer(2),˓→Integer(4)]);
J
Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4>>> J.invariants()# deprecated(2, 0, 3, 2, 4)>>> J.gens_orders()# use this instead(2, 0, 3, 2, 4)>>> for i in range(J.ngens()):...
print((i, J.gen(i), J.gen(i).order()))# or this(0, f0, 2)(1, f1, +Infinity)(2, f2, 3)(3, f3, 2)(4, f4, 4)

Use elementary_divisors() if you are looking for an invariant of the group.
OUTPUT: tuple of integers; zero means infinite cyclic factor
EXAMPLES:
sage: J = AbelianGroup([2,3])
sage: J.invariants()(2, 3)
sage: J.elementary_divisors()(6,)>>> from sage.all import *>>> J = AbelianGroup([Integer(2),Integer(3)])>>> J.invariants()(2, 3)>>> J.elementary_divisors()(6,)

is_commutative()
Return True since this group is commutative.
EXAMPLES:
sage: G = AbelianGroup([2,3,9, 0])
sage: G.is_commutative()
True
sage: G.is_abelian()True>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(9), Integer(0)])>>> G.is_commutative()(continues on next page)

318

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

True>>> G.is_abelian()True

is_cyclic()
Return True if the group is a cyclic group.
EXAMPLES:
sage: J = AbelianGroup([2,3])
sage: J.gens_orders()(2, 3)
sage: J.elementary_divisors()(6,)
sage: J.is_cyclic()Truesage: G = AbelianGroup([6])
sage: G.gens_orders()(6,)
sage: G.is_cyclic()Truesage: H = AbelianGroup([2,2])
sage: H.gens_orders()(2, 2)
sage: H.is_cyclic()
False
sage: H = AbelianGroup([2,4])
sage: H.elementary_divisors()(2, 4)
sage: H.is_cyclic()
False
sage: H.permutation_group().is_cyclic()
˓→needs sage.groups
False
sage: T = AbelianGroup([])
sage: T.is_cyclic()Truesage: T = AbelianGroup(1, [0]); T
Multiplicative Abelian group isomorphic to Z
sage: T.is_cyclic()Truesage: B = AbelianGroup([3,4,5])
sage: B.is_cyclic()
True

#␣

>>> from sage.all import *>>> J = AbelianGroup([Integer(2),Integer(3)])>>> J.gens_orders()(2, 3)>>> J.elementary_divisors()(6,)>>> J.is_cyclic()
True>>> G = AbelianGroup([Integer(6)])>>> G.gens_orders()(6,)(continues on next page)

26.1. Multiplicative Abelian Groups319

Groups, Release 10.4

(continued from previous page)>>> G.is_cyclic()
True>>> H = AbelianGroup([Integer(2),Integer(2)])>>> H.gens_orders()(2, 2)>>> H.is_cyclic()
False>>> H = AbelianGroup([Integer(2),Integer(4)])>>> H.elementary_divisors()(2, 4)>>> H.is_cyclic()
False>>> H.permutation_group().is_cyclic()
˓→needs sage.groups
False>>> T = AbelianGroup([])>>> T.is_cyclic()
True>>> T = AbelianGroup(Integer(1), [Integer(0)]); T
Multiplicative Abelian group isomorphic to Z>>> T.is_cyclic()
True>>> B = AbelianGroup([Integer(3),Integer(4),Integer(5)])>>> B.is_cyclic()
True

#␣

is_isomorphic(left, right)
Check whether left and right are isomorphic.
INPUT:• right – anything.
OUTPUT: boolean; whether left and right are isomorphic as abelian groups
EXAMPLES:
sage: G1 = AbelianGroup([2,3,4,5])
sage: G2 = AbelianGroup([2,3,4,5,1])
sage: G1.is_isomorphic(G2)
True>>> from sage.all import *>>> G1 = AbelianGroup([Integer(2),Integer(3),Integer(4),Integer(5)])>>> G2 = AbelianGroup([Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(1)])>>> G1.is_isomorphic(G2)True

is_subgroup(left, right)
Test whether left is a subgroup of right.
EXAMPLES:
sage: G = AbelianGroup([2,3,4,5])
sage: G.is_subgroup(G)True(continues on next page)

320

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

sage: H = G.subgroup([G.1])
˓→needs sage.libs.gap# optional - gap_package_polycyclic
sage: H.is_subgroup(G)˓→needs sage.libs.gap# optional - gap_package_polycyclic
True

#␣
#␣

sage: G.<a, b> = AbelianGroup(2)sage: H.<c> = AbelianGroup(1)sage: H < G
False>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(4),Integer(5)])>>> G.is_subgroup(G)True>>> H = G.subgroup([G.gen(1)])˓→ # needs sage.libs.gap# optional - gap_package_polycyclic>>> H.is_subgroup(G)˓→needs sage.libs.gap# optional - gap_package_polycyclic
True

␣
#␣

>>> G = AbelianGroup(Integer(2), names=( a , b ,)); (a, b,) = G._first_
˓→ngens(2)>>> H = AbelianGroup(Integer(1), names=( c ,)); (c,) = H._first_ngens(1)>>> H < G
False

is_trivial()
Return whether the group is trivial.
A group is trivial if it has precisely one element.
EXAMPLES:
sage: AbelianGroup([2, 3]).is_trivial()
False
sage: AbelianGroup([1, 1]).is_trivial()
True>>> from sage.all import *>>> AbelianGroup([Integer(2), Integer(3)]).is_trivial()
False>>> AbelianGroup([Integer(1), Integer(1)]).is_trivial()
Truelist()
Return tuple of all elements of this group.
EXAMPLES:
sage: G = AbelianGroup([2,3], names = "ab")sage: G.list()(1, b, b^2, a, a*b, a*b^2)

26.1. Multiplicative Abelian Groups

321Groups, Release 10.4>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3)], names = "ab")>>> G.list()(1, b, b^2, a, a*b, a*b^2)
sage: G = AbelianGroup([]); G
Trivial Abelian group
sage: G.list()(1,)>>> from sage.all import *>>> G = AbelianGroup([]); G
Trivial Abelian group>>> G.list()(1,)

ngens()The number of free generators of the abelian group.
EXAMPLES:
sage: F = AbelianGroup(10000)
sage: F.ngens()
10000>>> from sage.all import *>>> F = AbelianGroup(Integer(10000))>>> F.ngens()
10000

number_of_subgroups(order=None)
Return the number of subgroups of this group, possibly only of a specific order.
INPUT:• order – (default: None) find the number of subgroups of this order; if None, this defaults to counting
all subgroups
ALGORITHM:
An infinite group has infinitely many subgroups. All finite subgroups of any group are contained in the torsion
subgroup, which for finitely generated abelian group is itself finite. Hence, we can assume the group is finite.
A finite abelian group is isomorphic to a direct product of its Sylow subgroups, and so we can reduce theproblem further to counting subgroups of finite abelian 𝑝-groups.
Assume a Sylow subgroup is a 𝑝-group of type 𝜆, and using q_subgroups_of_abelian_group()
sum the number of subgroups of type 𝜇 in an abelian 𝑝-group of type 𝜆 for all 𝜇 contained in 𝜆.
EXAMPLES:
sage: AbelianGroup([2,0,0,3,0]).number_of_subgroups()+Infinity
sage: # needs sage.combinat
sage: AbelianGroup([2,3]).number_of_subgroups()4
sage: AbelianGroup([2,4,8]).number_of_subgroups()(continues on next page)

322

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)81
sage: AbelianGroup([2,4,8]).number_of_subgroups(order=4)
19
sage: AbelianGroup([10,15,25,12]).number_of_subgroups()
5760
sage: AbelianGroup([10,15,25,12]).number_of_subgroups(order=45000)
1
sage: AbelianGroup([10,15,25,12]).number_of_subgroups(order=14)
0>>> from sage.all import *>>> AbelianGroup([Integer(2),Integer(0),Integer(0),Integer(3),Integer(0)]).
˓→number_of_subgroups()+Infinity>>> # needs sage.combinat>>> AbelianGroup([Integer(2),Integer(3)]).number_of_subgroups()
4>>> AbelianGroup([Integer(2),Integer(4),Integer(8)]).number_of_subgroups()
81>>> AbelianGroup([Integer(2),Integer(4),Integer(8)]).number_of_
˓→subgroups(order=Integer(4))
19>>> AbelianGroup([Integer(10),Integer(15),Integer(25),Integer(12)]).number_of_
˓→subgroups()
5760>>> AbelianGroup([Integer(10),Integer(15),Integer(25),Integer(12)]).number_of_
˓→subgroups(order=Integer(45000))
1>>> AbelianGroup([Integer(10),Integer(15),Integer(25),Integer(12)]).number_of_
˓→subgroups(order=Integer(14))
0order()
Return the order of this group.
EXAMPLES:
sage: G = AbelianGroup(2, [2,3])
sage: G.order()6sage: G = AbelianGroup(3, [2,3,0])
sage: G.order()+Infinity>>> from sage.all import *>>> G = AbelianGroup(Integer(2), [Integer(2),Integer(3)])>>> G.order()6>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(0)])>>> G.order()+Infinity

permutation_group()
Return the permutation group isomorphic to this abelian group.
If the invariants are 𝑞1 , . . . , 𝑞𝑛 then the generators of the permutation will be of order 𝑞1 , . . . , 𝑞𝑛 , respectively.
26.1. Multiplicative Abelian Groups323

Groups, Release 10.4

EXAMPLES:
sage: G = AbelianGroup(2,[2,3]); G
Multiplicative Abelian group isomorphic to C2 x C3
sage: G.permutation_group()
˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5)]#␣>>> from sage.all import *>>> G = AbelianGroup(Integer(2),[Integer(2),Integer(3)]); G
Multiplicative Abelian group isomorphic to C2 x C3>>> G.permutation_group()
˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5)]#␣

random_element()
Return a random element of this group.
EXAMPLES:
sage: G = AbelianGroup([2,3,9])
sage: G.random_element().parent() is G
True>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(9)])>>> G.random_element().parent() is G
Truesubgroup(gensH, names='f')Create a subgroup of this group.
The “big” group must be defined using “named” generators.
INPUT:• gensH – list of elements which are products of the generators of the ambient abelian group 𝐺 = self
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: H = G.subgroup([a*b,a]); H
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a}
sage: H < G
True
sage: F = G.subgroup([a,b^2])
sage: F
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
sage: F.gens()(a, b^2)sage: F = AbelianGroup(5, [30,64,729], names=list("abcde"))sage: a,b,c,d,e = F.gens()
sage: F.subgroup([a,b])Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b}
sage: F.subgroup([c,e])Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729
generated by {c, e}

324

Chapter 26. Abelian Groups

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(4)], names=( a˓→ ,b , c ,)); (a, b, c,) = G._first_ngens(3); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> H = G.subgroup([a*b,a]); H
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a}>>> H < G
True>>> F = G.subgroup([a,b**Integer(2)])>>> F
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}>>> F.gens()(a, b^2)>>> F = AbelianGroup(Integer(5), [Integer(30),Integer(64),Integer(729)],␣
˓→names=list("abcde"))>>> a,b,c,d,e = F.gens()>>> F.subgroup([a,b])Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b}>>> F.subgroup([c,e])Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729
generated by {c, e}

subgroup_reduced(elts, verbose=False)
Given a list of lists of integers (corresponding to elements of self), find a set of independent generators forthe subgroup generated by these elements, and return the subgroup with these as generators, forgetting theoriginal generators.
This is used by the subgroups routine.
An error will be raised if the elements given are not linearly independent over.

EXAMPLES:
sage: G = AbelianGroup([4,4])
sage: G.subgroup( [ G([1,0]), G([1,2]) ])˓→needs sage.libs.gap# optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0, f0*f1^2}
sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ])˓→needs sage.libs.gap# optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0^2*f1^2, f0^3}#␣#␣>>> from sage.all import *>>> G = AbelianGroup([Integer(4),Integer(4)])>>> G.subgroup( [ G([Integer(1),Integer(0)]), G([Integer(1),Integer(2)]) ]) ␣˓→# needs sage.libs.gap # optional - gap_
˓→package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0, f0*f1^2}>>> AbelianGroup([Integer(4),Integer(4)]).subgroup_reduced( [ [Integer(1),˓→Integer(0)], [Integer(1),Integer(2)] ])# needs sage.libs.gap␣
˓→ # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0^2*f1^2, f0^3}

subgroups(check=False)

26.1. Multiplicative Abelian Groups

325

Groups, Release 10.4

Compute all the subgroups of this abelian group (which must be finite).
INPUT:• check – boolean; if True, performs the same computation in GAP and checks that the number ofsubgroups generated is the same. (I don’t know how to convert GAP’s output back into Sage, so we don’t
actually compare the subgroups).
ALGORITHM:
If the group is cyclic, the problem is easy. Otherwise, write it as a direct product A x B, where B is cyclic.
Compute the subgroups of A (by recursion).
Now, for every subgroup C of A x B, let G be its projection onto A and H its intersection with B. Then there
is a well-defined homomorphism f: G -> B/H that sends a in G to the class mod H of b, where (a,b) is any
element of C lifting a; and every subgroup C arises from a unique triple (G, H, f).
Todo: This is many orders of magnitude slower than Magma. Consider using the much faster method
number_of_subgroups() in case you only need the number of subgroups, possibly of a specific order.
EXAMPLES:
sage: AbelianGroup([2,3]).subgroups()#␣˓→needs sage.libs.gap# optional - gap_package_polycyclic[Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
Trivial Abelian subgroup]sage: len(AbelianGroup([2,4,8]).subgroups())#␣˓→needs sage.libs.gap# optional - gap_package_polycyclic
81>>> from sage.all import *>>> AbelianGroup([Integer(2),Integer(3)]).subgroups()␣˓→# needs sage.libs.gap # optional - gap_package_polycyclic[Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
Trivial Abelian subgroup]>>> len(AbelianGroup([Integer(2),Integer(4),Integer(8)]).subgroups())␣˓→# needs sage.libs.gap # optional - gap_package_
˓→polycyclic
81

torsion_subgroup(n=None)
Return the 𝑛-torsion subgroup of this abelian group when 𝑛 is given, and the torsion subgroup otherwise.
The [𝑛-]torsion subgroup consists of all elements whose order is finite [and divides 𝑛].
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup([2, 3])
sage: G.torsion_subgroup()
Multiplicative Abelian subgroup isomorphic to C2 x C3 generatedby {f0, f1}
sage: G = AbelianGroup([2, 0, 0, 3, 0])(continues on next page)

326

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

sage: G.torsion_subgroup()
Multiplicative Abelian subgroup isomorphic to C2 x C3 generatedby {f0, f3}
sage: G = AbelianGroup([])
sage: G.torsion_subgroup()
Trivial Abelian subgroup
sage: G = AbelianGroup([0, 0])
sage: G.torsion_subgroup()
Trivial Abelian subgroup>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup([Integer(2), Integer(3)])>>> G.torsion_subgroup()
Multiplicative Abelian subgroup isomorphic to C2 x C3 generatedby {f0, f1}>>> G = AbelianGroup([Integer(2), Integer(0), Integer(0), Integer(3),␣
˓→Integer(0)])>>> G.torsion_subgroup()
Multiplicative Abelian subgroup isomorphic to C2 x C3 generatedby {f0, f3}>>> G = AbelianGroup([])>>> G.torsion_subgroup()
Trivial Abelian subgroup>>> G = AbelianGroup([Integer(0), Integer(0)])>>> G.torsion_subgroup()
Trivial Abelian subgroup
sage: G = AbelianGroup([2, 2*3, 2*3*5, 0, 2*3*5*7, 2*3*5*7*11])
sage: G.torsion_subgroup(5)˓→needs sage.libs.gap# optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C5 x C5 x C5
generated by {f2^6, f4^42, f5^462}#␣>>> from sage.all import *>>> G = AbelianGroup([Integer(2), Integer(2)*Integer(3),␣
˓→Integer(2)*Integer(3)*Integer(5), Integer(0),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7)*Integer(11)])>>> G.torsion_subgroup(Integer(5))˓→# needs sage.libs.gap # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C5 x C5 x C5
generated by {f2^6, f4^42, f5^462}

␣

class sage.groups.abelian_gps.abelian_group.AbelianGroup_subgroup(ambient, gens,names='f',category=None)
Bases: AbelianGroup_class
Subgroup subclass of AbelianGroup_class, so instance methods are inherited.
Todo: There should be a way to coerce an element of a subgroup into the ambient group.
ambient_group()

26.1. Multiplicative Abelian Groups

327

Groups, Release 10.4

Return the ambient group related to self.
OUTPUT: a multiplicative Abelian group
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G.<a,b,c> = AbelianGroup([2,3,4])
sage: H = G.subgroup([a, b^2])
sage: H.ambient_group() is G
True>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup([Integer(2),Integer(3),Integer(4)], names=( a ,˓→)); (a, b, c,) = G._first_ngens(3)>>> H = G.subgroup([a, b**Integer(2)])>>> H.ambient_group() is G
True

b ,

c ,

equals(left, right)
Check whether left and right are the same (sub)group.
INPUT:• right – anything
OUTPUT:boolean; if right is a subgroup, test whether left and right are the same subset of the ambient group.
If right is not a subgroup, test whether they are isomorphic groups, see is_isomorphic().
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup(3, [2,3,4], names="abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: a,b,c = G.gens()
sage: F = G.subgroup([a,b^2]); F
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
sage: F<G
True
sage: A = AbelianGroup(1, [6])sage: A.subgroup(list(A.gens())) == A
True
sage: G.<a,b> = AbelianGroup(2)sage: A = G.subgroup([a])
sage: B = G.subgroup([b])
sage: A.equals(B)False
sage: A == B
# sames as A.equals(B)False
sage: A.is_isomorphic(B)True>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(4)], names=(continues on next page)

328

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)"abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> a,b,c = G.gens()>>> F = G.subgroup([a,b**Integer(2)]); F
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}>>> F<G
True>>> A = AbelianGroup(Integer(1), [Integer(6)])>>> A.subgroup(list(A.gens())) == A
True>>> G = AbelianGroup(Integer(2), names=( a , b ,)); (a, b,) = G._first_
˓→ngens(2)>>> A = G.subgroup([a])>>> B = G.subgroup([b])>>> A.equals(B)
False>>> A == B
# sames as A.equals(B)
False>>> A.is_isomorphic(B)True˓→gen(n)
Return the nth generator of this subgroup.
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G.<a,b> = AbelianGroup(2)sage: A = G.subgroup([a])
sage: A.gen(0)a>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup(Integer(2), names=( a , b ,)); (a, b,) = G._first_
˓→ngens(2)>>> A = G.subgroup([a])>>> A.gen(Integer(0))
agens()
Return the generators for this subgroup.
OUTPUT: tuple of group elements generating the subgroup
EXAMPLES:
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G.<a,b> = AbelianGroup(2)sage: A = G.subgroup([a])
sage: G.gens()(a, b)
sage: A.gens()(a,)

26.1. Multiplicative Abelian Groups329

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.libs.gap # optional - gap_package_polycyclic>>> G = AbelianGroup(Integer(2), names=( a , b ,)); (a, b,) = G._first_
˓→ngens(2)>>> A = G.subgroup([a])>>> G.gens()(a, b)>>> A.gens()(a,)

sage.groups.abelian_gps.abelian_group.is_AbelianGroup(x)Return True if x is an Abelian group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group import is_AbelianGroupsage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
sage: is_AbelianGroup(F)doctest:warning...
DeprecationWarning: the function is_AbelianGroup is deprecated;
use isinstance(..., AbelianGroup_class) instead
See https://github.com/sagemath/sage/issues/37898 for details.
Truesage: is_AbelianGroup(AbelianGroup(7, [3]*7))
True>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group import is_AbelianGroup>>> F = AbelianGroup(Integer(5),[Integer(5),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names=list("abcde")); F
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9>>> is_AbelianGroup(F)doctest:warning...
DeprecationWarning: the function is_AbelianGroup is deprecated;
use isinstance(..., AbelianGroup_class) instead
See https://github.com/sagemath/sage/issues/37898 for details.
True>>> is_AbelianGroup(AbelianGroup(Integer(7), [Integer(3)]*Integer(7)))
True

sage.groups.abelian_gps.abelian_group.word_problem(words, g, verbose=False)
𝐺 and 𝐻 are abelian, 𝑔 in 𝐺, 𝐻 is a subgroup of 𝐺 generated by a list (words) of elements of 𝐺. If 𝑔 is in 𝐻,
return the expression for 𝑔 as a word in the elements of (words).
The ‘word problem’ for a finite abelian group 𝐺 boils down to the following matrix-vector analog of the Chineseremainder theorem.
Problem: Fix integers 1 < 𝑛1 ≤ 𝑛2 ≤ ... ≤ 𝑛𝑘 (indeed, these 𝑛𝑖 will all be prime powers), fix a generating set
𝑔𝑖 = (𝑎𝑖1 , ..., 𝑎𝑖𝑘 ) (with 𝑎𝑖𝑗 ∈ Z/𝑛𝑗 Z), for 1 ≤ 𝑖 ≤ ℓ, for the group 𝐺, and let 𝑑 = (𝑑1 , ..., 𝑑𝑘 ) be an element of
the direct product Z/𝑛1 Z × ... × Z/𝑛𝑘 Z. Find, if they exist, integers 𝑐1 , ..., 𝑐ℓ such that 𝑐1 𝑔1 + ... + 𝑐ℓ 𝑔ℓ = 𝑑.
In other words, solve the equation 𝑐𝐴 = 𝑑 for 𝑐 ∈ Zℓ , where 𝐴 is the matrix whose rows are the 𝑔𝑖 ’s. Of course,
it suffices to restrict the 𝑐𝑖 ’s to the range 0 ≤ 𝑐𝑖 ≤ 𝑁 − 1, where 𝑁 denotes the least common multiple of theintegers 𝑛1 , ..., 𝑛𝑘 .
This function does not solve this directly, as perhaps it should. Rather (for both speed and as a model for a similar function valid for more general groups), it pushes it over to GAP, which has optimized (non-deterministic)algorithms for the word problem. Essentially, this function is a wrapper for the GAP function ‘Factorization’.
330

Chapter 26. Abelian Groups

Groups, Release 10.4

EXAMPLES:
sage: # needs sage.libs.gap
sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: w = word_problem([a*b,a*c], b*c); w# random[[a*b, 1], [a*c, 1]]
sage: prod([x^i for x,i in w]) == b*c
True
sage: w = word_problem([a*c,c], a); w# random[[a*c, 1], [c, -1]]
sage: prod([x^i for x,i in w]) == aTruesage: word_problem([a*c,c], a, verbose=True)# randoma = (a*c)^1*(c)^-1[[a*c, 1], [c, -1]]>>> from sage.all import *>>> # needs sage.libs.gap>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(4)], names=( a ,˓→ b ,c ,)); (a, b, c,) = G._first_ngens(3); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> w = word_problem([a*b,a*c], b*c); w# random[[a*b, 1], [a*c, 1]]>>> prod([x**i for x,i in w]) == b*c
True>>> w = word_problem([a*c,c], a); w# random[[a*c, 1], [c, -1]]>>> prod([x**i for x,i in w]) == aTrue>>> word_problem([a*c,c], a, verbose=True)# randoma = (a*c)^1*(c)^-1[[a*c, 1], [c, -1]]
sage: # needs sage.libs.gap
sage: A.<a,b,c,d,e> = AbelianGroup(5, [4, 5, 5, 7, 8])
sage: b1 = a^3*b*c*d^2*e^5sage: b2 = a^2*b*c^2*d^3*e^3sage: b3 = a^7*b^3*c^5*d^4*e^4sage: b4 = a^3*b^2*c^2*d^3*e^5sage: b5 = a^2*b^4*c^2*d^4*e^5sage: w = word_problem([b1,b2,b3,b4,b5], e); w # random[[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1],[a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]]
sage: prod([x^i for x,i in w]) == eTruesage: word_problem([a,b,c,d,e], e)[[e, 1]]
sage: word_problem([a,b,c,d,e], b)[[b, 1]]>>> from sage.all import *>>> # needs sage.libs.gap>>> A = AbelianGroup(Integer(5), [Integer(4), Integer(5), Integer(5), Integer(7),␣
˓→Integer(8)], names=( a ,b , c , d , e ,)); (a, b, c, d, e,) = A._first_
˓→ngens(5)>>> b1 = a**Integer(3)*b*c*d**Integer(2)*e**Integer(5)(continues on next page)

26.1. Multiplicative Abelian Groups

331Groups, Release 10.4

(continued from previous page)>>> b2 = a**Integer(2)*b*c**Integer(2)*d**Integer(3)*e**Integer(3)>>> b3 = a**Integer(7)*b**Integer(3)*c**Integer(5)*d**Integer(4)*e**Integer(4)>>> b4 = a**Integer(3)*b**Integer(2)*c**Integer(2)*d**Integer(3)*e**Integer(5)>>> b5 = a**Integer(2)*b**Integer(4)*c**Integer(2)*d**Integer(4)*e**Integer(5)>>> w = word_problem([b1,b2,b3,b4,b5], e); w # random[[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1],[a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]]>>> prod([x**i for x,i in w]) == e
True>>> word_problem([a,b,c,d,e], e)[[e, 1]]>>> word_problem([a,b,c,d,e], b)[[b, 1]]

Warning:
1. Might have unpleasant effect when the word problem cannot be solved.
2. Uses permutation groups, so may be slow when group is large. The instance method word_problem of theclass AbelianGroupElement is implemented differently (wrapping GAP’s ‘EpimorphismFromFreeGroup’and ‘PreImagesRepresentative’) and may be faster.

26.2 Finitely generated abelian groups with GAP.
This module provides a python wrapper for abelian groups in GAP.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: AbelianGroupGap([3,5])
Abelian group with gap, generator orders (3, 5)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> AbelianGroupGap([Integer(3),Integer(5)])
Abelian group with gap, generator orders (3, 5)

For infinite abelian groups we use the GAP package Polycyclic:
sage: AbelianGroupGap([3,0])# optional - gap_package_polycyclic
Abelian group with gap, generator orders (3, 0)>>> from sage.all import *>>> AbelianGroupGap([Integer(3),Integer(0)])# optional - gap_package_polycyclic
Abelian group with gap, generator orders (3, 0)

AUTHORS:• Simon Brandhorst (2018-01-17): initial version
class sage.groups.abelian_gps.abelian_group_gap.AbelianGroupElement_gap(parent, x,
check=True)
Bases: ElementLibGAP
332

Chapter 26. Abelian Groups

Groups, Release 10.4

An element of an abelian group via libgap.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([3,6])
sage: G.gens()(f1, f2)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(3),Integer(6)])>>> G.gens()(f1, f2)

exponents()
Return the tuple of exponents of this element.
OUTPUT: tuple of integers
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4,7,9])
sage: gens = G.gens()
sage: g = gens[0]^2 * gens[1]^4 * gens[2]^8
sage: g.exponents()(2, 4, 8)
sage: S = G.subgroup(G.gens()[:1])sage: s = S.gens()[0]sage: sf1
sage: s.exponents()(1,)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4),Integer(7),Integer(9)])>>> gens = G.gens()>>> g = gens[Integer(0)]**Integer(2) * gens[Integer(1)]**Integer(4) *␣˓→gens[Integer(2)]**Integer(8)>>> g.exponents()(2, 4, 8)>>> S = G.subgroup(G.gens()[:Integer(1)])>>> s = S.gens()[Integer(0)]>>> s
f1>>> s.exponents()(1,)

It can handle quite large groups too:sage: G = AbelianGroupGap([2^10, 5^10])
sage: f1, f2 = G.gens()
sage: g = f1^123*f2^789
sage: g.exponents()(123, 789)

26.2. Finitely generated abelian groups with GAP.

333

Groups, Release 10.4>>> from sage.all import *>>> G = AbelianGroupGap([Integer(2)**Integer(10), Integer(5)**Integer(10)])>>> f1, f2 = G.gens()>>> g = f1**Integer(123)*f2**Integer(789)>>> g.exponents()(123, 789)

Warning: Crashes for very large groups.

Todo: Make exponents work for very large groups. This could be done by using Pcgs in gap.
order()
Return the order of this element.
OUTPUT: integer or infinity
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4])
sage: g = G.gens()[0]sage: g.order()4
sage: G = AbelianGroupGap([0])# optional - gap_package_polycyclic
sage: g = G.gens()[0]# optional - gap_package_polycyclic
sage: g.order()# optional - gap_package_polycyclic+Infinity>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4)])>>> g = G.gens()[Integer(0)]>>> g.order()4>>> G = AbelianGroupGap([Integer(0)])# optional - gap_package_
˓→polycyclic>>> g = G.gens()[Integer(0)]# optional - gap_package_
˓→polycyclic>>> g.order()# optional - gap_package_polycyclic+Infinity

class sage.groups.abelian_gps.abelian_group_gap.AbelianGroupElement_polycyclic(parent,x,
check=True)
Bases: AbelianGroupElement_gap
An element of an abelian group using the GAP package Polycyclic.
exponents()
Return the tuple of exponents of self.
OUTPUT: tuple of integers
EXAMPLES:
334

Chapter 26. Abelian Groups

Groups, Release 10.4

sage: # optional - gap_package_polycyclic
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4,7,0])
sage: gens = G.gens()
sage: g = gens[0]^2 * gens[1]^4 * gens[2]^8
sage: g.exponents()(2, 4, 8)>>> from sage.all import *>>> # optional - gap_package_polycyclic>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4),Integer(7),Integer(0)])>>> gens = G.gens()>>> g = gens[Integer(0)]**Integer(2) * gens[Integer(1)]**Integer(4) *␣˓→gens[Integer(2)]**Integer(8)>>> g.exponents()(2, 4, 8)

Efficiently handles very large groups:
sage: # optional - gap_package_polycyclic
sage: G = AbelianGroupGap([2^30,5^30,0])
sage: f1, f2, f3 = G.gens()
sage: (f1^12345*f2^123456789).exponents()(12345, 123456789, 0)>>> from sage.all import *>>> # optional - gap_package_polycyclic>>> G = AbelianGroupGap([Integer(2)**Integer(30),Integer(5)**Integer(30),
˓→Integer(0)])>>> f1, f2, f3 = G.gens()>>> (f1**Integer(12345)*f2**Integer(123456789)).exponents()(12345, 123456789, 0)class sage.groups.abelian_gps.abelian_group_gap.AbelianGroupGap(generator_orders)
Bases: AbelianGroup_gap
Abelian groups implemented using GAP.
INPUT:• generator_orders – a list of nonnegative integers where 0 gives a factor isomorphic to
OUTPUT: an abelian group
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: AbelianGroupGap([3,6])
Abelian group with gap, generator orders (3, 6)
sage: AbelianGroupGap([3,6,5])
Abelian group with gap, generator orders (3, 6, 5)
sage: AbelianGroupGap([3,6,0])# optional - gap_package_polycyclic
Abelian group with gap, generator orders (3, 6, 0)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> AbelianGroupGap([Integer(3),Integer(6)])(continues on next page)

26.2. Finitely generated abelian groups with GAP.

335

Groups, Release 10.4

(continued from previous page)

Abelian group with gap, generator orders (3, 6)>>> AbelianGroupGap([Integer(3),Integer(6),Integer(5)])
Abelian group with gap, generator orders (3, 6, 5)>>> AbelianGroupGap([Integer(3),Integer(6),Integer(0)])˓→package_polycyclic
Abelian group with gap, generator orders (3, 6, 0)# optional - gap_

Warning: Needs the GAP package Polycyclic in case the group is infinite.
class sage.groups.abelian_gps.abelian_group_gap.AbelianGroupQuotient_gap(G, N)
Bases: AbelianGroup_gap
Quotients of abelian groups by a subgroup.
Note: Do not call this directly. Instead use quotient().
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([4,3])
sage: N = A.subgroup([A.gen(0)^2])
sage: Q1 = A.quotient(N)sage: Q1
Quotient abelian group with generator orders (2, 3)
sage: Q2 = Q1.quotient(Q1.subgroup(Q1.gens()[:1]))
sage: Q2
Quotient abelian group with generator orders (1, 3)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(4),Integer(3)])>>> N = A.subgroup([A.gen(Integer(0))**Integer(2)])>>> Q1 = A.quotient(N)>>> Q1
Quotient abelian group with generator orders (2, 3)>>> Q2 = Q1.quotient(Q1.subgroup(Q1.gens()[:Integer(1)]))>>> Q2
Quotient abelian group with generator orders (1, 3)

cover()
Return the covering group of this quotient group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: gen = G.gens()[:2]
sage: S = G.subgroup(gen)sage: Q = G.quotient(S)sage: Q.cover() is G
True

336

Chapter 26. Abelian Groups

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> gen = G.gens()[:Integer(2)]>>> S = G.subgroup(gen)>>> Q = G.quotient(S)>>> Q.cover() is G
Truelift(x)Lift an element to the cover.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([4])
sage: N = A.subgroup([A.gen(0)^2])
sage: Q = A.quotient(N)sage: Q.lift(Q.0)
f1>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(4)])>>> N = A.subgroup([A.gen(Integer(0))**Integer(2)])>>> Q = A.quotient(N)>>> Q.lift(Q.gen(0))
f1natural_homomorphism()
Return the defining homomorphism into self.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([4])
sage: N = A.subgroup([A.gen(0)^2])
sage: Q = A.quotient(N)sage: Q.natural_homomorphism()Group morphism:
From: Abelian group with gap, generator orders (4,)
To:
Quotient abelian group with generator orders (2,)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(4)])>>> N = A.subgroup([A.gen(Integer(0))**Integer(2)])>>> Q = A.quotient(N)>>> Q.natural_homomorphism()Group morphism:
From: Abelian group with gap, generator orders (4,)
To:
Quotient abelian group with generator orders (2,)

relations()
Return the relations of this quotient group.
EXAMPLES:
26.2. Finitely generated abelian groups with GAP.

337

Groups, Release 10.4

sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: gen = G.gens()[:2]
sage: S = G.subgroup(gen)sage: Q = G.quotient(S)sage: Q.relations() is S
True>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> gen = G.gens()[:Integer(2)]>>> S = G.subgroup(gen)>>> Q = G.quotient(S)>>> Q.relations() is S
Trueclass sage.groups.abelian_gps.abelian_group_gap.AbelianGroupSubgroup_gap(ambient,
gens)
Bases: AbelianGroup_gap
Subgroups of abelian groups with GAP.
INPUT:• ambient – the ambient group• gens – generators of the subgroup
Note: Do not construct this class directly. Instead use subgroup().
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: gen = G.gens()[:2]
sage: S = G.subgroup(gen)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> gen = G.gens()[:Integer(2)]>>> S = G.subgroup(gen)lift(x)
Coerce to the ambient group.
The terminology comes from the category framework and the more general notion of a subquotient.
INPUT:• x – an element of this subgroup
OUTPUT: the corresponding element of the ambient group
EXAMPLES:

338

Chapter 26. Abelian Groups

Groups, Release 10.4

sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4])
sage: g = G.gen(0)sage: H = G.subgroup([g^2])
sage: h = H.gen(0); hf2
sage: h.parent()
Subgroup of Abelian group with gap, generator orders (4,) generated by (f2,)
sage: H.lift(h)f2sage: H.lift(h).parent()
Abelian group with gap, generator orders (4,)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4)])>>> g = G.gen(Integer(0))>>> H = G.subgroup([g**Integer(2)])>>> h = H.gen(Integer(0)); hf2>>> h.parent()
Subgroup of Abelian group with gap, generator orders (4,) generated by (f2,)>>> H.lift(h)f2>>> H.lift(h).parent()
Abelian group with gap, generator orders (4,)

retract(x)Convert an element of the ambient group into this subgroup.
The terminology comes from the category framework and the more general notion of a subquotient.
INPUT:• x – an element of the ambient group that actually lies in this subgroup.
OUTPUT: the corresponding element of this subgroup
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4])
sage: g = G.gen(0)sage: H = G.subgroup([g^2])
sage: H.retract(g^2)
f2sage: H.retract(g^2).parent()
Subgroup of Abelian group with gap, generator orders (4,) generated by (f2,)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4)])>>> g = G.gen(Integer(0))>>> H = G.subgroup([g**Integer(2)])>>> H.retract(g**Integer(2))
f2>>> H.retract(g**Integer(2)).parent()
Subgroup of Abelian group with gap, generator orders (4,) generated by (f2,)

26.2. Finitely generated abelian groups with GAP.

339

Groups, Release 10.4class sage.groups.abelian_gps.abelian_group_gap.AbelianGroup_gap(G, category,
ambient=None)
Bases: UniqueRepresentation, GroupMixinLibGAP, ParentLibGAP, AbelianGroup
Finitely generated abelian groups implemented in GAP.
Needs the gap package Polycyclic in case the group is infinite.
INPUT:• G – a GAP group• category – a category• ambient – (optional) an AbelianGroupGap
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([3, 2, 5])
sage: G
Abelian group with gap, generator orders (3, 2, 5)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(3), Integer(2), Integer(5)])>>> G
Abelian group with gap, generator orders (3, 2, 5)Element
alias of AbelianGroupElement_gap
all_subgroups()
Return the list of all subgroups of this group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2, 3])
sage: G.all_subgroups()[Subgroup of Abelian group with gap, generator orders (2, 3) generated by (),Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f1,˓→),
Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2,˓→),
Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2,
˓→ f1)]>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2), Integer(3)])>>> G.all_subgroups()[Subgroup of Abelian group with gap, generator orders (2, 3) generated by (),Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f1,˓→),
Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2,˓→),
Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2,
˓→ f1)]

340

Chapter 26. Abelian Groups

Groups, Release 10.4

aut()
Return the group of automorphisms of self.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2, 3])
sage: G.aut()
Full group of automorphisms of Abelian group with gap, generator orders (2, 3)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2), Integer(3)])>>> G.aut()
Full group of automorphisms of Abelian group with gap, generator orders (2, 3)

automorphism_group()
Return the group of automorphisms of self.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2, 3])
sage: G.aut()
Full group of automorphisms of Abelian group with gap, generator orders (2, 3)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2), Integer(3)])>>> G.aut()
Full group of automorphisms of Abelian group with gap, generator orders (2, 3)

elementary_divisors()
Return the elementary divisors of this group.
See sage.groups.abelian_gps.abelian_group_gap.elementary_divisors().
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: G.elementary_divisors()(2, 60)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> G.elementary_divisors()(2, 60)exponent()
Return the exponent of this abelian group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,7])(continues on next page)

26.2. Finitely generated abelian groups with GAP.

341

Groups, Release 10.4

(continued from previous page)

sage: G
Abelian group with gap, generator orders (2, 3, 7)
sage: G = AbelianGroupGap([2,4,6])
sage: G
Abelian group with gap, generator orders (2, 4, 6)
sage: G.exponent()
12>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(7)])>>> G
Abelian group with gap, generator orders (2, 3, 7)>>> G = AbelianGroupGap([Integer(2),Integer(4),Integer(6)])>>> G
Abelian group with gap, generator orders (2, 4, 6)>>> G.exponent()12

gens_orders()
Return the orders of the generators.
Use elementary_divisors() if you are looking for an invariant of the group.
OUTPUT: tuple of integers
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: Z2xZ3 = AbelianGroupGap([2,3])
sage: Z2xZ3.gens_orders()(2, 3)
sage: Z2xZ3.elementary_divisors()(6,)
sage: Z6 = AbelianGroupGap([6])
sage: Z6.gens_orders()(6,)
sage: Z6.elementary_divisors()(6,)
sage: Z2xZ3.is_isomorphic(Z6)True
sage: Z2xZ3 is Z6
False>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> Z2xZ3 = AbelianGroupGap([Integer(2),Integer(3)])>>> Z2xZ3.gens_orders()(2, 3)>>> Z2xZ3.elementary_divisors()(6,)>>> Z6 = AbelianGroupGap([Integer(6)])>>> Z6.gens_orders()(6,)>>> Z6.elementary_divisors()(6,)>>> Z2xZ3.is_isomorphic(Z6)(continues on next page)

342

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

True>>> Z2xZ3 is Z6
False

identity()
Return the identity element of this group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([4,10])
sage: G.identity()1>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(4),Integer(10)])>>> G.identity()1

is_subgroup_of(G)Return if self is a subgroup of G considered in the same ambient group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: gen = G.gens()[:2]
sage: S1 = G.subgroup(gen)sage: S1.is_subgroup_of(G)True
sage: S2 = G.subgroup(G.gens()[1:])sage: S2.is_subgroup_of(S1)
False>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> gen = G.gens()[:Integer(2)]>>> S1 = G.subgroup(gen)>>> S1.is_subgroup_of(G)True>>> S2 = G.subgroup(G.gens()[Integer(1):])>>> S2.is_subgroup_of(S1)
False

is_trivial()
Return True if this group is the trivial group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([])
sage: G
Abelian group with gap, generator orders ()sage: G.is_trivial()(continues on next page)

26.2. Finitely generated abelian groups with GAP.

343

Groups, Release 10.4

(continued from previous page)True
sage: AbelianGroupGap([1]).is_trivial()
True
sage: AbelianGroupGap([1,1,1]).is_trivial()
True
sage: AbelianGroupGap([2]).is_trivial()
False
sage: AbelianGroupGap([2,1]).is_trivial()
False>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([])>>> G
Abelian group with gap, generator orders ()>>> G.is_trivial()
True>>> AbelianGroupGap([Integer(1)]).is_trivial()
True>>> AbelianGroupGap([Integer(1),Integer(1),Integer(1)]).is_trivial()
True>>> AbelianGroupGap([Integer(2)]).is_trivial()
False>>> AbelianGroupGap([Integer(2),Integer(1)]).is_trivial()
False

quotient(N)Return the quotient of this group by the normal subgroup 𝑁 .
INPUT:• N – a subgroup• check – bool (default: True) check if 𝑁 is normal
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: A = AbelianGroupGap([2,3,4,5])
sage: S = A.subgroup(A.gens()[:1])sage: A.quotient(S)Quotient abelian group with generator orders (1, 3, 4, 5)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> A = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> S = A.subgroup(A.gens()[:Integer(1)])>>> A.quotient(S)Quotient abelian group with generator orders (1, 3, 4, 5)

subgroup(gens)
Return the subgroup of this group generated by gens.
INPUT:• gens – a list of elements coercible into this group
OUTPUT: a subgroup344

Chapter 26. Abelian Groups

Groups, Release 10.4

EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: gen = G.gens()[:2]
sage: S = G.subgroup(gen)sage: S
Subgroup of Abelian group with gap, generator orders (2, 3, 4, 5)
generated by (f1, f2)
sage: g = G.an_element()
sage: s = S.an_element()
sage: g * s
f2^2*f3*f5
sage: # optional - gap_package_polycyclic
sage: G = AbelianGroupGap([3,4,0,2])
sage: gen = G.gens()[:2]
sage: S = G.subgroup(gen)sage: g = G.an_element()
sage: s = S.an_element()
sage: g * s
g1^2*g2^2*g3*g4>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> gen = G.gens()[:Integer(2)]>>> S = G.subgroup(gen)>>> S
Subgroup of Abelian group with gap, generator orders (2, 3, 4, 5)
generated by (f1, f2)>>> g = G.an_element()>>> s = S.an_element()>>> g * sf2^2*f3*f5>>> # optional - gap_package_polycyclic>>> G = AbelianGroupGap([Integer(3),Integer(4),Integer(0),Integer(2)])>>> gen = G.gens()[:Integer(2)]>>> S = G.subgroup(gen)>>> g = G.an_element()>>> s = S.an_element()>>> g * s
g1^2*g2^2*g3*g4

26.3 Automorphisms of abelian groups
This implements groups of automorphisms of abelian groups.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,6])
sage: autG = G.aut()

26.3. Automorphisms of abelian groups345

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(6)])>>> autG = G.aut()

Automorphisms act on the elements of the domain:
sage: g = G.an_element()
sage: f = autG.an_element()
sage: fPcgs([ f1, f2, f3 ]) -> [ f1, f1*f2*f3^2, f3^2 ]sage: (g, f(g))(f1*f2, f2*f3^2)>>> from sage.all import *>>> g = G.an_element()>>> f = autG.an_element()>>> f
Pcgs([ f1, f2, f3 ]) -> [ f1, f1*f2*f3^2, f3^2 ]>>> (g, f(g))(f1*f2, f2*f3^2)

Or anything coercible into its domain:
sage: A = AbelianGroup([2,6])
sage: a = A.an_element()
sage: (a, f(a))(f0*f1, f2*f3^2)
sage: A = AdditiveAbelianGroup([2,6])
sage: a = A.an_element()
sage: (a, f(a))((1, 0), f1)
sage: f((1,1))
f2*f3^2>>> from sage.all import *>>> A = AbelianGroup([Integer(2),Integer(6)])>>> a = A.an_element()>>> (a, f(a))(f0*f1, f2*f3^2)>>> A = AdditiveAbelianGroup([Integer(2),Integer(6)])>>> a = A.an_element()>>> (a, f(a))((1, 0), f1)>>> f((Integer(1),Integer(1)))
f2*f3^2

We can compute conjugacy classes:
sage: autG.conjugacy_classes_representatives()(1,
Pcgs([ f1, f2, f3 ]) -> [ f2*f3, f1*f2, f3 ],Pcgs([ f1, f2, f3 ]) -> [ f1*f2*f3, f2*f3^2, f3^2 ],[ f3^2, f1*f2*f3, f1 ] -> [ f3^2, f1, f1*f2*f3 ],Pcgs([ f1, f2, f3 ]) -> [ f2*f3, f1*f2*f3^2, f3^2 ],[ f1*f2*f3, f1, f3^2 ] -> [ f1*f2*f3, f1, f3 ])346

Chapter 26. Abelian Groups

Groups, Release 10.4>>> from sage.all import *>>> autG.conjugacy_classes_representatives()(1,
Pcgs([ f1, f2, f3 ]) -> [ f2*f3, f1*f2, f3 ],Pcgs([ f1, f2, f3 ]) -> [ f1*f2*f3, f2*f3^2, f3^2 ],[ f3^2, f1*f2*f3, f1 ] -> [ f3^2, f1, f1*f2*f3 ],Pcgs([ f1, f2, f3 ]) -> [ f2*f3, f1*f2*f3^2, f3^2 ],[ f1*f2*f3, f1, f3^2 ] -> [ f1*f2*f3, f1, f3 ])the group order:
sage: autG.order()12>>> from sage.all import *>>> autG.order()12or create subgroups and do the same for them:sage: S = autG.subgroup(autG.gens()[:1])sage: S
Subgroup of automorphisms of Abelian group with gap, generator orders (2, 6)
generated by 1 automorphisms>>> from sage.all import *>>> S = autG.subgroup(autG.gens()[:Integer(1)])>>> S
Subgroup of automorphisms of Abelian group with gap, generator orders (2, 6)
generated by 1 automorphisms

Only automorphism groups of finite abelian groups are supported:
sage: G = AbelianGroupGap([0,2])# optional - gap_package_polycyclic
sage: autG = G.aut()# optional - gap_package_polycyclic
Traceback (most recent call last):...
ValueError: only finite abelian groups are supported>>> from sage.all import *>>> G = AbelianGroupGap([Integer(0),Integer(2)])# optional - gap_package_
˓→polycyclic>>> autG = G.aut()# optional - gap_package_polycyclic
Traceback (most recent call last):...
ValueError: only finite abelian groups are supported

AUTHORS:• Simon Brandhorst (2018-02-17): initial version
class sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphism(parent, x,
check=True)
Bases: ElementLibGAP
Automorphisms of abelian groups with gap.
INPUT:
26.3. Automorphisms of abelian groups347

Groups, Release 10.4

• x – a libgap element• parent – the parent AbelianGroupAutomorphismGroup_gap• check – bool (default: True) checks if x is an element of the group
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: f = G.aut().an_element()>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> f = G.aut().an_element()

matrix()Return the matrix defining self.
The 𝑖-th row is the exponent vector of the image of the 𝑖-th generator.
OUTPUT: a square matrix over the integers
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4])
sage: f = G.aut().an_element()
sage: fPcgs([ f1, f2, f3, f4 ]) -> [ f1*f4, f2^2, f1*f3, f4 ]sage: f.matrix()[1 0 2][0 2 0][1 0 1]>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4)])>>> f = G.aut().an_element()>>> f
Pcgs([ f1, f2, f3, f4 ]) -> [ f1*f4, f2^2, f1*f3, f4 ]>>> f.matrix()[1 0 2][0 2 0][1 0 1]Compare with the exponents of the images:
sage: f(G.gens()[0]).exponents()(1, 0, 2)
sage: f(G.gens()[1]).exponents()(0, 2, 0)
sage: f(G.gens()[2]).exponents()(1, 0, 1)>>> from sage.all import *>>> f(G.gens()[Integer(0)]).exponents()(1, 0, 2)(continues on next page)

348

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> f(G.gens()[Integer(1)]).exponents()(0, 2, 0)>>> f(G.gens()[Integer(2)]).exponents()(1, 0, 1)class sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup(AbelianGroupGap)
Bases: AbelianGroupAutomorphismGroup_gap
The full automorphism group of a finite abelian group.
INPUT:• AbelianGroupGap – an instance of AbelianGroup_gap
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: from sage.groups.abelian_gps.abelian_aut import␣˓→AbelianGroupAutomorphismGroupsage: G = AbelianGroupGap([2,3,4,5])
sage: aut = G.aut()>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> from sage.groups.abelian_gps.abelian_aut import AbelianGroupAutomorphismGroup>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = G.aut()

Equivalently:
sage: aut1 = AbelianGroupAutomorphismGroup(G)sage: aut is aut1
True>>> from sage.all import *>>> aut1 = AbelianGroupAutomorphismGroup(G)>>> aut is aut1
True

Element
alias of AbelianGroupAutomorphismclass sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup_gap(domain,
gap_group,
category,
ambient=None)
Bases: CachedRepresentation, GroupMixinLibGAP, Group, ParentLibGAP
Base class for groups of automorphisms of abelian groups.

26.3. Automorphisms of abelian groups349

Groups, Release 10.4

Do not construct this directly.
INPUT:• domain – AbelianGroup_gap• libgap_parent – the libgap element that is the parent in GAP• category – a category• ambient – an instance of a derived class of ParentLibGAP or None (default); the ambient group if
libgap_parent has been defined as a subgroup
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: from sage.groups.abelian_gps.abelian_aut import␣˓→AbelianGroupAutomorphismGroup_gap
sage: domain = AbelianGroupGap([2,3,4,5])
sage: aut = domain.gap().AutomorphismGroupAbelianGroup()
sage: AbelianGroupAutomorphismGroup_gap(domain, aut, Groups().Finite())<group with 6 generators>>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> from sage.groups.abelian_gps.abelian_aut import AbelianGroupAutomorphismGroup_
˓→gap>>> domain = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = domain.gap().AutomorphismGroupAbelianGroup()>>> AbelianGroupAutomorphismGroup_gap(domain, aut, Groups().Finite())<group with 6 generators>

Element
alias of AbelianGroupAutomorphism
covering_matrix_ring()
Return the covering matrix ring of this group.
This is the ring of 𝑛 × 𝑛 matrices overwhere 𝑛 is the number of (independent) generators.

EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: aut = G.aut()
sage: aut.covering_matrix_ring()
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = G.aut()>>> aut.covering_matrix_ring()
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring

domain()Return the domain of this group of automorphisms.
EXAMPLES:

350

Chapter 26. Abelian Groups

Groups, Release 10.4

sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: aut = G.aut()
sage: aut.domain()
Abelian group with gap, generator orders (2, 3, 4, 5)>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = G.aut()>>> aut.domain()
Abelian group with gap, generator orders (2, 3, 4, 5)

is_subgroup_of(G)Return if self is a subgroup of G considered in the same ambient group.
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: G = AbelianGroupGap([2,3,4,5])
sage: aut = G.aut()
sage: gen = aut.gens()
sage: S1 = aut.subgroup(gen[:2])sage: S1.is_subgroup_of(aut)Truesage: S2 = aut.subgroup(aut.gens()[1:])sage: S2.is_subgroup_of(S1)
False>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = G.aut()>>> gen = aut.gens()>>> S1 = aut.subgroup(gen[:Integer(2)])>>> S1.is_subgroup_of(aut)True>>> S2 = aut.subgroup(aut.gens()[Integer(1):])>>> S2.is_subgroup_of(S1)
False

class sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup_subgroup(ambient,
generators)
Bases: AbelianGroupAutomorphismGroup_gap
Groups of automorphisms of abelian groups.
They are subgroups of the full automorphism group.
Note:

Do not construct this class directly;

26.3. Automorphisms of abelian groups

instead use sage.groups.abelian_gps.

351

Groups, Release 10.4

abelian_group_gap.AbelianGroup_gap.subgroup().
INPUT:• ambient – the ambient group• generators – a tuple of gap elements of the ambient group
EXAMPLES:
sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
sage: from sage.groups.abelian_gps.abelian_aut import␣˓→AbelianGroupAutomorphismGroup_subgroup
sage: G = AbelianGroupGap([2,3,4,5])
sage: aut = G.aut()
sage: gen = aut.gens()
sage: AbelianGroupAutomorphismGroup_subgroup(aut, gen)
Subgroup of automorphisms of Abelian group with gap, generator orders (2, 3, 4, 5)
generated by 6 automorphisms>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap>>> from sage.groups.abelian_gps.abelian_aut import AbelianGroupAutomorphismGroup_
˓→subgroup>>> G = AbelianGroupGap([Integer(2),Integer(3),Integer(4),Integer(5)])>>> aut = G.aut()>>> gen = aut.gens()>>> AbelianGroupAutomorphismGroup_subgroup(aut, gen)
Subgroup of automorphisms of Abelian group with gap, generator orders (2, 3, 4, 5)
generated by 6 automorphisms

Element
alias of AbelianGroupAutomorphism

26.4 Multiplicative Abelian Groups With Values
Often, one ends up with a set that forms an Abelian group. It would be nice if one could return an Abelian group class
to encapsulate the data. However, AbelianGroup() is an abstract Abelian group defined by generators and relations.
This module implements AbelianGroupWithValues that allows the group elements to be decorated with values.
An example where this module is used is the unit group of a number field, see sage.rings.number_field.
unit_group. The units form a finitely generated Abelian group. We can think of the elements either as abstract
Abelian group elements or as particular numbers in the number field. The AbelianGroupWithValues() keeps
track of these associated values.
Warning: Really, this requires a group homomorphism from the abstract Abelian group to the set of values. This is
only checked if you pass the check=True option to AbelianGroupWithValues().
EXAMPLES:
Here is352

6 with value −1 assigned to the generator:

Chapter 26. Abelian Groups

Groups, Release 10.4

sage: Z6 = AbelianGroupWithValues([-1], [6], names= g )sage: g = Z6.gen(0)sage: g.value()-1
sage: g*gg^2
sage: (g*g).value()1
sage: for i in range(7):....:print((i, g^i, (g^i).value()))(0, 1, 1)(1, g, -1)(2, g^2, 1)(3, g^3, -1)(4, g^4, 1)(5, g^5, -1)(6, 1, 1)>>> from sage.all import *>>> Z6 = AbelianGroupWithValues([-Integer(1)], [Integer(6)], names= g )>>> g = Z6.gen(Integer(0))>>> g.value()-1>>> g*gg^2>>> (g*g).value()1>>> for i in range(Integer(7)):...
print((i, g**i, (g**i).value()))(0, 1, 1)(1, g, -1)(2, g^2, 1)(3, g^3, -1)(4, g^4, 1)(5, g^5, -1)(6, 1, 1)

The elements come with a coercion embedding into the values_group(), so you can use the group elements insteadof the values:
sage: # needs sage.rings.number_fieldsage: CF3.<zeta> = CyclotomicField(3)sage: Z3.<g> = AbelianGroupWithValues([zeta], [3])sage: Z3.values_group()
Cyclotomic Field of order 3 and degree 2
sage: g.value()zeta
sage: CF3(g)zetasage: g + zeta
2*zetasage: zeta + g
2*zeta>>> from sage.all import *>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3), names=( zeta ,)); (zeta,) = CF3._first_ngens(1)(continues on next page)

26.4. Multiplicative Abelian Groups With Values353

Groups, Release 10.4

(continued from previous page)>>> Z3 = AbelianGroupWithValues([zeta], [Integer(3)], names=( g ,)); (g,) = Z3._first_
˓→ngens(1)>>> Z3.values_group()
Cyclotomic Field of order 3 and degree 2>>> g.value()zeta>>> CF3(g)zeta>>> g + zeta
2*zeta>>> zeta + g
2*zetasage.groups.abelian_gps.values.AbelianGroupWithValues(values, n, gens_orders=None,names='f', check=False,
values_group=None)
Construct an Abelian group with values associated to the generators.
INPUT:• values – a list/tuple/iterable of values that you want to associate to the generators• n – integer (optional). If not specified, will be derived
from gens_orders• gens_orders – a list of non-negative integers in the form
[𝑎0 , 𝑎1 , . . . , 𝑎𝑛−1 ], typically written in increasing order. This list is padded with zeros if it has length
less than n. The orders of the commuting generators, with 0 denoting an infinite cyclic factor.
• names – (optional) names of generators• values_group – a parent or None (default). The common parent of the values. This might be a group,
but can also just contain the values. For example, if the values are units in a ring then the values_groupwould be the whole ring. If None it will be derived from the values.
EXAMPLES:
sage: G = AbelianGroupWithValues([-1], [6])sage: g = G.gen(0)sage: for i in range(7):....:print((i, g^i, (g^i).value()))(0, 1, 1)(1, f, -1)(2, f^2, 1)(3, f^3, -1)(4, f^4, 1)(5, f^5, -1)(6, 1, 1)
sage: G.values_group()
Integer Ring>>> from sage.all import *>>> G = AbelianGroupWithValues([-Integer(1)], [Integer(6)])>>> g = G.gen(Integer(0))>>> for i in range(Integer(7)):...
print((i, g**i, (g**i).value()))(0, 1, 1)(1, f, -1)(continues on next page)354

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)(2, f^2, 1)(3, f^3, -1)(4, f^4, 1)(5, f^5, -1)(6, 1, 1)>>> G.values_group()
Integer Ring

The group elements come with a coercion embedding into the values_group(), so you can use them like theirvalue()
sage: G.values_embedding()
Generic morphism:
From: Multiplicative Abelian group isomorphic to C6
To:
Integer Ringsage: g.value()-1
sage: 0 + g-1
sage: 1 + 2*g-1>>> from sage.all import *>>> G.values_embedding()
Generic morphism:
From: Multiplicative Abelian group isomorphic to C6
To:
Integer Ring>>> g.value()-1>>> Integer(0) + g-1>>> Integer(1) + Integer(2)*g-1class sage.groups.abelian_gps.values.AbelianGroupWithValuesElement(parent,
exponents,
value=None)
Bases: AbelianGroupElement
An element of an Abelian group with values assigned to generators.
INPUT:• exponents – tuple of integers; the exponent vector defining the group element• parent – the parent• value – the value assigned to the group element or None (default); in the latter case, the value is computed
as needed
EXAMPLES:
sage: F = AbelianGroupWithValues([1,-1], [2,4])
sage: a,b = F.gens()
sage: TestSuite(a*b).run()

26.4. Multiplicative Abelian Groups With Values355

Groups, Release 10.4>>> from sage.all import *>>> F = AbelianGroupWithValues([Integer(1),-Integer(1)], [Integer(2),Integer(4)])>>> a,b = F.gens()>>> TestSuite(a*b).run()value()
Return the value of the group element.
OUTPUT: the value according to the values for generators; see gens_values()
EXAMPLES:
sage: G = AbelianGroupWithValues([5], 1)
sage: G.0.value()5>>> from sage.all import *>>> G = AbelianGroupWithValues([Integer(5)], Integer(1))>>> G.gen(0).value()
5class sage.groups.abelian_gps.values.AbelianGroupWithValuesEmbedding(domain,
codomain)
Bases: Morphism
The morphism embedding the Abelian group with values in its values group.
INPUT:• domain – a AbelianGroupWithValues_class• codomain – the values group (need not be in the category of groups, e.g. symbolic ring)
EXAMPLES:
sage: # needs sage.symbolic
sage: Z4.<g> = AbelianGroupWithValues([I], [4])sage: embedding = Z4.values_embedding(); embedding
Generic morphism:
From: Multiplicative Abelian group isomorphic to C4
To:
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
sage: embedding(1)1sage: embedding(g)Isage: embedding(g^2)-1>>> from sage.all import *>>> # needs sage.symbolic>>> Z4 = AbelianGroupWithValues([I], [Integer(4)], names=( g ,)); (g,) = Z4._
˓→first_ngens(1)>>> embedding = Z4.values_embedding(); embedding
Generic morphism:
From: Multiplicative Abelian group isomorphic to C4
To:
Number Field in I with defining polynomial x^2 + 1 with I = 1*I>>> embedding(Integer(1))
1(continues on next page)

356

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> embedding(g)I>>> embedding(g**Integer(2))-1class sage.groups.abelian_gps.values.AbelianGroupWithValues_class(generator_orders,
names, values,
values_group)
Bases: AbelianGroup_class
The class of an Abelian group with values associated to the generator.
INPUT:• generator_orders – tuple of integers; the orders of the generators.
• names – string or list of strings; the names for the generators• values – tuple the same length as the number of generators; the values assigned to the generators.
• values_group – the common parent of the values
EXAMPLES:
sage: G.<a,b> = AbelianGroupWithValues([2,-1], [0,4])
sage: TestSuite(G).run()>>> from sage.all import *>>> G = AbelianGroupWithValues([Integer(2),-Integer(1)], [Integer(0),Integer(4)],␣
˓→names=( a ,b ,)); (a, b,) = G._first_ngens(2)>>> TestSuite(G).run()

Element
alias of AbelianGroupWithValuesElement
gen(i=0)
The 𝑖-th generator of the abelian group.
INPUT:• i – integer (default: 0); the index of the generator
OUTPUT: a group element
EXAMPLES:
sage: F = AbelianGroupWithValues([1,2,3,4,5], 5, [], names= a )sage: F.0a0
sage: F.0.value()1
sage: F.2
a2
sage: F.2.value()3
sage: G = AbelianGroupWithValues([-1,0,1], [2,1,3])
sage: G.gens()(f0, 1, f2)

26.4. Multiplicative Abelian Groups With Values357

Groups, Release 10.4>>> from sage.all import *>>> F = AbelianGroupWithValues([Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5)], Integer(5), [], names= a )>>> F.gen(0)a0>>> F.gen(0).value()1>>> F.gen(2)a2>>> F.gen(2).value()3>>> G = AbelianGroupWithValues([-Integer(1),Integer(0),Integer(1)],␣
˓→[Integer(2),Integer(1),Integer(3)])>>> G.gens()(f0, 1, f2)

gens_values()
Return the values associated to the generators.
OUTPUT: tuple
EXAMPLES:
sage: G = AbelianGroupWithValues([-1,0,1], [2,1,3])
sage: G.gens()(f0, 1, f2)
sage: G.gens_values()(-1, 0, 1)>>> from sage.all import *>>> G = AbelianGroupWithValues([-Integer(1),Integer(0),Integer(1)],␣
˓→[Integer(2),Integer(1),Integer(3)])>>> G.gens()(f0, 1, f2)>>> G.gens_values()(-1, 0, 1)

values_embedding()
Return the embedding of self in values_group().
OUTPUT: a morphism
EXAMPLES:
sage: Z4 = AbelianGroupWithValues([I], [4])˓→needs sage.symbolic
sage: Z4.values_embedding()
˓→needs sage.symbolic
Generic morphism:
From: Multiplicative Abelian group isomorphic to C4
To:
Number Field in I with defining polynomial x^2 + 1 with I = 1*I>>> from sage.all import *>>> Z4 = AbelianGroupWithValues([I], [Integer(4)])˓→# needs sage.symbolic>>> Z4.values_embedding()

#␣
#␣

␣
#␣
(continues on next page)

358

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)needs sage.symbolic
Generic morphism:
From: Multiplicative Abelian group isomorphic to C4
To:
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
˓→values_group()
The common parent of the values.
The values need to form a multiplicative group, but can be embedded in a larger structure. For example, if
the values are units in a ring then the values_group() would be the whole ring.
OUTPUT: the common parent of the values, containing the group generated by all values
EXAMPLES:
sage: G = AbelianGroupWithValues([-1,0,1], [2,1,3])
sage: G.values_group()
Integer Ringsage: Z4 = AbelianGroupWithValues([I], [4])˓→needs sage.symbolic
sage: Z4.values_group()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 with I = 1*I#␣#␣>>> from sage.all import *>>> G = AbelianGroupWithValues([-Integer(1),Integer(0),Integer(1)],␣
˓→[Integer(2),Integer(1),Integer(3)])>>> G.values_group()
Integer Ring>>> Z4 = AbelianGroupWithValues([I], [Integer(4)])˓→# needs sage.symbolic>>> Z4.values_group()
˓→needs sage.symbolic
Number Field in I with defining polynomial x^2 + 1 with I = 1*I␣#␣

26.5 Dual groups of Finite Multiplicative Abelian Groups
The basic idea is very simple. Let G be an abelian group and 𝐺* its dual (i.e., the group of homomorphisms from G to
C× ). Let 𝑔𝑗 , 𝑗 = 1, .., 𝑛, denote generators of 𝐺 - say 𝑔𝑗 is of order 𝑚𝑗 > 1. There are generators 𝑋𝑗 , 𝑗 = 1, .., 𝑛, of
𝐺* for which 𝑋𝑗 (𝑔𝑗 ) = exp(2𝜋𝑖/𝑚𝑗 ) and 𝑋𝑖 (𝑔𝑗 ) = 1 if 𝑖 ̸= 𝑗. These are used to construct 𝐺* .
Sage supports multiplicative abelian groups on any prescribed finite number 𝑛 > 0 of generators. Use AbelianGroup() function to create an abelian group, the dual_group() method to create its dual, and then the gen()and gens() methods to obtain the corresponding generators. You can print the generators as arbitrary strings using theoptional names argument to the dual_group() method.
EXAMPLES:
sage: F = AbelianGroup(5, [2,5,7,8,9], names= abcde )sage: (a, b, c, d, e) = F.gens()
sage: Fd = F.dual_group(names= ABCDE )(continues on next page)

26.5. Dual groups of Finite Multiplicative Abelian Groups359

Groups, Release 10.4

(continued from previous page)

sage: Fd.base_ring()
Cyclotomic Field of order 2520 and degree 576
sage: A,B,C,D,E = Fd.gens()
sage: A(a)-1sage: A(b), A(c), A(d), A(e)(1, 1, 1, 1)
sage: # needs sage.rings.real_mpfr
sage: Fd = F.dual_group(names= ABCDE , base_ring=CC)
sage: Fd.category()
Category of commutative groups
sage: A,B,C,D,E = Fd.gens()
sage: A(a)# abs tol 1e-8
-1.00000000000000 + 0.00000000000000*I
sage: A(b); A(c); A(d); A(e)1.00000000000000
1.00000000000000
1.00000000000000
1.00000000000000>>> from sage.all import *>>> F = AbelianGroup(Integer(5), [Integer(2),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names= abcde )>>> (a, b, c, d, e) = F.gens()>>> Fd = F.dual_group(names= ABCDE )>>> Fd.base_ring()
Cyclotomic Field of order 2520 and degree 576>>> A,B,C,D,E = Fd.gens()>>> A(a)-1>>> A(b), A(c), A(d), A(e)(1, 1, 1, 1)>>> # needs sage.rings.real_mpfr>>> Fd = F.dual_group(names= ABCDE , base_ring=CC)>>> Fd.category()
Category of commutative groups>>> A,B,C,D,E = Fd.gens()>>> A(a)# abs tol 1e-8
-1.00000000000000 + 0.00000000000000*I>>> A(b); A(c); A(d); A(e)1.00000000000000
1.00000000000000
1.00000000000000
1.00000000000000

AUTHORS:• David Joyner (2006-08) (based on abelian_groups)• David Joyner (2006-10) modifications suggested by William Stein• Volker Braun (2012-11) port to new Parent base. Use tuples for immutables. Default to cyclotomic base ring.
class sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class(G,names,
base_ring)
360

Chapter 26. Abelian Groups

Groups, Release 10.4

Bases: UniqueRepresentation, AbelianGroup
Dual of abelian group.
EXAMPLES:
sage: F = AbelianGroup(5,[3,5,7,8,9], names="abcde")
sage: F.dual_group()
Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z
over Cyclotomic Field of order 2520 and degree 576
sage: F = AbelianGroup(4,[15,7,8,9], names="abcd")
sage: F.dual_group(base_ring=CC)
˓→needs sage.rings.real_mpfr
Dual of Abelian Group isomorphic to Z/15Z x Z/7Z x Z/8Z x Z/9Z
over Complex Field with 53 bits of precision#␣>>> from sage.all import *>>> F = AbelianGroup(Integer(5),[Integer(3),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names="abcde")>>> F.dual_group()
Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z
over Cyclotomic Field of order 2520 and degree 576>>> F = AbelianGroup(Integer(4),[Integer(15),Integer(7),Integer(8),Integer(9)],␣
˓→names="abcd")>>> F.dual_group(base_ring=CC)#␣˓→needs sage.rings.real_mpfr
Dual of Abelian Group isomorphic to Z/15Z x Z/7Z x Z/8Z x Z/9Z
over Complex Field with 53 bits of precision

Element
alias of DualAbelianGroupElement
base_ring()
Return the scalars over which the group is dualized.
EXAMPLES:
sage: F = AbelianGroup(3,[5,64,729], names=list("abc"))
sage: Fd = F.dual_group(base_ring=CC)
sage: Fd.base_ring()
Complex Field with 53 bits of precision>>> from sage.all import *>>> F = AbelianGroup(Integer(3),[Integer(5),Integer(64),Integer(729)],␣
˓→names=list("abc"))>>> Fd = F.dual_group(base_ring=CC)>>> Fd.base_ring()
Complex Field with 53 bits of precision

gen(i=0)
The 𝑖-th generator of the abelian group.
EXAMPLES:

26.5. Dual groups of Finite Multiplicative Abelian Groups361

Groups, Release 10.4

sage: F = AbelianGroup(3, [1,2,3], names= a )sage: Fd = F.dual_group(names="A")
sage: Fd.0
1
sage: Fd.1
A1
sage: Fd.gens_orders()(1, 2, 3)>>> from sage.all import *>>> F = AbelianGroup(Integer(3), [Integer(1),Integer(2),Integer(3)], names= a
˓→ )>>> Fd = F.dual_group(names="A")>>> Fd.gen(0)1>>> Fd.gen(1)A1>>> Fd.gens_orders()(1, 2, 3)gens()
Return the generators for the group.
OUTPUT: tuple of group elements generating the group
EXAMPLES:
sage: F = AbelianGroup([7,11]).dual_group()
sage: F.gens()(X0, X1)>>> from sage.all import *>>> F = AbelianGroup([Integer(7),Integer(11)]).dual_group()>>> F.gens()(X0, X1)

gens_orders()
The orders of the generators of the dual group.
OUTPUT: tuple of integers
EXAMPLES:
sage: F = AbelianGroup([5]*1000)
sage: Fd = F.dual_group()
sage: invs = Fd.gens_orders(); len(invs)
1000>>> from sage.all import *>>> F = AbelianGroup([Integer(5)]*Integer(1000))>>> Fd = F.dual_group()>>> invs = Fd.gens_orders(); len(invs)
1000

group()
Return the group that self is the dual of.
EXAMPLES:
362

Chapter 26. Abelian Groups

Groups, Release 10.4

sage: F = AbelianGroup(3,[5,64,729], names=list("abc"))
sage: Fd = F.dual_group(base_ring=CC)
sage: Fd.group() is F
True>>> from sage.all import *>>> F = AbelianGroup(Integer(3),[Integer(5),Integer(64),Integer(729)],␣
˓→names=list("abc"))>>> Fd = F.dual_group(base_ring=CC)>>> Fd.group() is F
Trueinvariants()
The invariants of the dual group.
You should use gens_orders() instead.
EXAMPLES:
sage: F = AbelianGroup([5]*1000)
sage: Fd = F.dual_group()
sage: invs = Fd.gens_orders(); len(invs)
1000>>> from sage.all import *>>> F = AbelianGroup([Integer(5)]*Integer(1000))>>> Fd = F.dual_group()>>> invs = Fd.gens_orders(); len(invs)
1000

is_commutative()
Return True since this group is commutative.
EXAMPLES:
sage: G = AbelianGroup([2,3,9])
sage: Gd = G.dual_group()
sage: Gd.is_commutative()
True
sage: Gd.is_abelian()True>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(9)])>>> Gd = G.dual_group()>>> Gd.is_commutative()
True>>> Gd.is_abelian()True

list()
Return a tuple of all elements of this group.
EXAMPLES:

26.5. Dual groups of Finite Multiplicative Abelian Groups363

Groups, Release 10.4

sage: G = AbelianGroup([2,3], names="ab")sage: Gd = G.dual_group(names="AB")sage: Gd.list()(1, B, B^2, A, A*B, A*B^2)>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3)], names="ab")>>> Gd = G.dual_group(names="AB")>>> Gd.list()(1, B, B^2, A, A*B, A*B^2)ngens()The number of generators of the dual group.
EXAMPLES:
sage: F = AbelianGroup([7]*100)
sage: Fd = F.dual_group()
sage: Fd.ngens()
100>>> from sage.all import *>>> F = AbelianGroup([Integer(7)]*Integer(100))>>> Fd = F.dual_group()>>> Fd.ngens()
100

order()
Return the order of this group.
EXAMPLES:
sage: G = AbelianGroup([2,3,9])
sage: Gd = G.dual_group()
sage: Gd.order()54>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(9)])>>> Gd = G.dual_group()>>> Gd.order()54

random_element()
Return a random element of this dual group.
EXAMPLES:
sage: G = AbelianGroup([2,3,9])
sage: Gd = G.dual_group(base_ring=CC)
˓→needs sage.rings.real_mpfr
sage: Gd.random_element().parent() is Gd
˓→needs sage.rings.real_mpfr
True

#␣
#␣

sage: # needs sage.rings.real_mpfr(continues on next page)364

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

sage: N = 43^2 - 1
sage: G = AbelianGroup([N], names="a")sage: Gd = G.dual_group(names="A", base_ring=CC)
sage: a, = G.gens()
sage: A, = Gd.gens()
sage: x = a^(N/4); y = a^(N/3); z = a^(N/14)
sage: found = [False]*4
sage: while not all(found):....:
X = A*Gd.random_element()....:
found[len([b for b in [x,y,z] if abs(X(b)-1)>10^(-8)])] = True>>> from sage.all import *>>> G = AbelianGroup([Integer(2),Integer(3),Integer(9)])>>> Gd = G.dual_group(base_ring=CC)
˓→needs sage.rings.real_mpfr>>> Gd.random_element().parent() is Gd
˓→needs sage.rings.real_mpfr
True

#␣
#␣

>>> # needs sage.rings.real_mpfr>>> N = Integer(43)**Integer(2) - Integer(1)>>> G = AbelianGroup([N], names="a")>>> Gd = G.dual_group(names="A", base_ring=CC)>>> a, = G.gens()>>> A, = Gd.gens()>>> x = a**(N/Integer(4)); y = a**(N/Integer(3)); z = a**(N/Integer(14))>>> found = [False]*Integer(4)>>> while not all(found):...
X = A*Gd.random_element()...
found[len([b for b in [x,y,z] if abs(X(b)-Integer(1))>Integer(10)**(˓→Integer(8))])] = Truesage.groups.abelian_gps.dual_abelian_group.is_DualAbelianGroup(x)Return True if 𝑥 is the dual group of an abelian group.
EXAMPLES:
sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroupsage: F = AbelianGroup(5,[3,5,7,8,9], names=list("abcde"))sage: Fd = F.dual_group()
sage: is_DualAbelianGroup(Fd)doctest:warning...
DeprecationWarning: the function is_DualAbelianGroup is deprecated;
use isinstance(..., DualAbelianGroup_class) instead
See https://github.com/sagemath/sage/issues/37898 for details.
Truesage: F = AbelianGroup(3,[1,2,3], names= a )sage: Fd = F.dual_group()
sage: Fd.gens()(1, X1, X2)
sage: F.gens()(1, a1, a2)>>> from sage.all import *>>> from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroup>>> F = AbelianGroup(Integer(5),[Integer(3),Integer(5),Integer(7),Integer(8),(continues on next page)

26.5. Dual groups of Finite Multiplicative Abelian Groups

365Groups, Release 10.4

(continued from previous page)

Integer(9)], names=list("abcde"))>>> Fd = F.dual_group()>>> is_DualAbelianGroup(Fd)doctest:warning...
DeprecationWarning: the function is_DualAbelianGroup is deprecated;
use isinstance(..., DualAbelianGroup_class) instead
See https://github.com/sagemath/sage/issues/37898 for details.
True>>> F = AbelianGroup(Integer(3),[Integer(1),Integer(2),Integer(3)], names= a )>>> Fd = F.dual_group()>>> Fd.gens()(1, X1, X2)>>> F.gens()(1, a1, a2)
˓→

26.6 Base class for abelian group elements
This is the base class for both abelian_group_element and dual_abelian_group_element.
As always, elements are immutable once constructed.
class sage.groups.abelian_gps.element_base.AbelianGroupElementBase(parent,
exponents)
Bases: MultiplicativeGroupElement
Base class for abelian group elements
The group element is defined by a tuple whose i-th entry is an integer in the range from 0 (inclusively) to G.
gen(i).order() (exclusively) if the 𝑖-th generator is of finite order, and an arbitrary integer if the 𝑖-th generator
is of infinite order.
INPUT:• exponents – 1 or a list/tuple/iterable of integers. The exponent vector (with respect to the parent generators) defining the group element.
• parent – Abelian group. The parent of the group element.
EXAMPLES:
sage: F = AbelianGroup(3,[7,8,9])
sage: Fd = F.dual_group(names="ABC")˓→needs sage.rings.number_fieldsage: A,B,C = Fd.gens()
˓→needs sage.rings.number_fieldsage: A*B^-1 in Fd
˓→needs sage.rings.number_field
True

#␣
#␣
#␣

>>> from sage.all import *>>> F = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)])>>> Fd = F.dual_group(names="ABC")˓→needs sage.rings.number_field>>> A,B,C = Fd.gens()
˓→needs sage.rings.number_field>>> A*B**-Integer(1) in Fd#␣#␣␣(continues on next page)

366

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)˓→# needs sage.rings.number_fieldTrue

exponents()
The exponents of the generators defining the group element.
OUTPUT:
A tuple of integers for an abelian group element. The integer can be arbitrary if the corresponding generator
has infinite order. If the generator is of finite order, the integer is in the range from 0 (inclusive) to the order(exclusive).
EXAMPLES:
sage: F.<a,b,c,f> = AbelianGroup([7,8,9,0])
sage: (a^3*b^2*c).exponents()(3, 2, 1, 0)
sage: F([3, 2, 1, 0])a^3*b^2*c
sage: (c^42).exponents()(0, 0, 6, 0)
sage: (f^42).exponents()(0, 0, 0, 42)>>> from sage.all import *>>> F = AbelianGroup([Integer(7),Integer(8),Integer(9),Integer(0)], names=( a˓→ ,b , c , f ,)); (a, b, c, f,) = F._first_ngens(4)>>> (a**Integer(3)*b**Integer(2)*c).exponents()(3, 2, 1, 0)>>> F([Integer(3), Integer(2), Integer(1), Integer(0)])
a^3*b^2*c>>> (c**Integer(42)).exponents()(0, 0, 6, 0)>>> (f**Integer(42)).exponents()(0, 0, 0, 42)

is_trivial()
Test whether self is the trivial group element 1.
OUTPUT: boolean
EXAMPLES:
sage: G.<a,b> = AbelianGroup([0,5])
sage: (a^5).is_trivial()
False
sage: (b^5).is_trivial()
True>>> from sage.all import *>>> G = AbelianGroup([Integer(0),Integer(5)], names=( a ,˓→_first_ngens(2)>>> (a**Integer(5)).is_trivial()
False>>> (b**Integer(5)).is_trivial()True

26.6. Base class for abelian group elementsb ,)); (a, b,) = G.

367

Groups, Release 10.4

list()
Return a copy of the exponent vector.
Use exponents() instead.
OUTPUT:
The underlying coordinates used to represent this element. If this is a word in an abelian group on 𝑛 generators,
then this is a list of nonnegative integers of length 𝑛.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: F = AbelianGroup(5,[2, 3, 5, 7, 8], names="abcde")
sage: a,b,c,d,e = F.gens()
sage: Ad = F.dual_group(names="ABCDE")
sage: A,B,C,D,E = Ad.gens()
sage: (A*B*C^2*D^20*E^65).exponents()(1, 1, 2, 6, 1)
sage: X = A*B*C^2*D^2*E^-6sage: X.exponents()(1, 1, 2, 2, 2)>>> from sage.all import *>>> # needs sage.rings.number_field>>> F = AbelianGroup(Integer(5),[Integer(2), Integer(3), Integer(5),␣
˓→Integer(7), Integer(8)], names="abcde")>>> a,b,c,d,e = F.gens()>>> Ad = F.dual_group(names="ABCDE")>>> A,B,C,D,E = Ad.gens()>>> (A*B*C**Integer(2)*D**Integer(20)*E**Integer(65)).exponents()(1, 1, 2, 6, 1)>>> X = A*B*C**Integer(2)*D**Integer(2)*E**-Integer(6)>>> X.exponents()(1, 1, 2, 2, 2)

multiplicative_order()Return the order of this element.
OUTPUT: integer or infinity
EXAMPLES:
sage: F = AbelianGroup(3,[7,8,9])
sage: Fd = F.dual_group()
˓→needs sage.rings.number_fieldsage: A,B,C = Fd.gens()
˓→needs sage.rings.number_fieldsage: (B*C).order()˓→needs sage.rings.number_field
72

#␣
#␣
#␣

sage: F = AbelianGroup(3,[7,8,9]); F
Multiplicative Abelian group isomorphic to C7 x C8 x C9
sage: F.gens()[2].order()9sage: a,b,c = F.gens()
sage: (b*c).order()72(continues on next page)

368

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

sage: G = AbelianGroup(3,[7,8,9])
sage: type((G.0 * G.1).order())==Integer
True>>> from sage.all import *>>> F = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)])>>> Fd = F.dual_group()
˓→needs sage.rings.number_field>>> A,B,C = Fd.gens()
˓→needs sage.rings.number_field>>> (B*C).order()˓→needs sage.rings.number_field
72

#␣
#␣
#␣

>>> F = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)]); F
Multiplicative Abelian group isomorphic to C7 x C8 x C9>>> F.gens()[Integer(2)].order()9>>> a,b,c = F.gens()>>> (b*c).order()72>>> G = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)])>>> type((G.gen(0) * G.gen(1)).order())==Integer
Trueorder()
Return the order of this element.
OUTPUT: integer or infinity
EXAMPLES:
sage: F = AbelianGroup(3,[7,8,9])
sage: Fd = F.dual_group()
˓→needs sage.rings.number_fieldsage: A,B,C = Fd.gens()
˓→needs sage.rings.number_fieldsage: (B*C).order()˓→needs sage.rings.number_field
72

#␣
#␣
#␣

sage: F = AbelianGroup(3,[7,8,9]); F
Multiplicative Abelian group isomorphic to C7 x C8 x C9
sage: F.gens()[2].order()9sage: a,b,c = F.gens()
sage: (b*c).order()72
sage: G = AbelianGroup(3,[7,8,9])
sage: type((G.0 * G.1).order())==Integer
True>>> from sage.all import *>>> F = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)])>>> Fd = F.dual_group()
˓→needs sage.rings.number_field#␣(continues on next page)

26.6. Base class for abelian group elements369

Groups, Release 10.4

(continued from previous page)>>> A,B,C = Fd.gens()
˓→needs sage.rings.number_field>>> (B*C).order()˓→needs sage.rings.number_field
72

#␣
#␣

>>> F = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)]); F
Multiplicative Abelian group isomorphic to C7 x C8 x C9>>> F.gens()[Integer(2)].order()9>>> a,b,c = F.gens()>>> (b*c).order()72>>> G = AbelianGroup(Integer(3),[Integer(7),Integer(8),Integer(9)])>>> type((G.gen(0) * G.gen(1)).order())==Integer
True

26.7 Abelian group elements
AUTHORS:• David Joyner (2006-02); based on free_abelian_monoid_element.py, written by David Kohel.
• David Joyner (2006-05); bug fix in order• David Joyner (2006-08); bug fix+new method in pow for negatives+fixed corresponding examples.
• David Joyner (2009-02): Fixed bug in order.
• Volker Braun (2012-11) port to new Parent base. Use tuples for immutables.
EXAMPLES:
Recall an example from abelian groups:
sage: F = AbelianGroup(5,[4,5,5,7,8],names = list("abcde"))sage: (a,b,c,d,e) = F.gens()
sage: x = a*b^2*e*d^20*e^12
sage: xa*b^2*d^6*e^5sage: x = a^10*b^12*c^13*d^20*e^12
sage: xa^2*b^2*c^3*d^6*e^4
sage: y = a^13*b^19*c^23*d^27*e^72
sage: ya*b^4*c^3*d^6
sage: x*ya^3*b*c*d^5*e^4sage: x.list()[2, 2, 3, 6, 4]>>> from sage.all import *>>> F = AbelianGroup(Integer(5),[Integer(4),Integer(5),Integer(5),Integer(7),˓→Integer(8)],names = list("abcde"))>>> (a,b,c,d,e) = F.gens()>>> x = a*b**Integer(2)*e*d**Integer(20)*e**Integer(12)(continues on next page)

370

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> x
a*b^2*d^6*e^5>>> x = a**Integer(10)*b**Integer(12)*c**Integer(13)*d**Integer(20)*e**Integer(12)>>> xa^2*b^2*c^3*d^6*e^4>>> y = a**Integer(13)*b**Integer(19)*c**Integer(23)*d**Integer(27)*e**Integer(72)>>> ya*b^4*c^3*d^6>>> x*ya^3*b*c*d^5*e^4>>> x.list()[2, 2, 3, 6, 4]class sage.groups.abelian_gps.abelian_group_element.AbelianGroupElement(parent,
exponents)
Bases: AbelianGroupElementBase
Elements of an AbelianGroupINPUT:• x – list/tuple/iterable of integers (the element vector)• parent – the parent AbelianGroup
EXAMPLES:
sage: F = AbelianGroup(5, [3,4,5,8,7],
sage: a, b, c, d, e = F.gens()
sage: a^2 * b^3 * a^2 * b^-4
a*b^3
sage: b^-11b
sage: a^-11
asage: a*b in F
Trueabcde )>>> from sage.all import *>>> F = AbelianGroup(Integer(5), [Integer(3),Integer(4),Integer(5),Integer(8),˓→Integer(7)],abcde )>>> a, b, c, d, e = F.gens()>>> a**Integer(2) * b**Integer(3) * a**Integer(2) * b**-Integer(4)a*b^3>>> b**-Integer(11)b>>> a**-Integer(11)a>>> a*b in F
True

as_permutation()
Return the element of the permutation group G (isomorphic to the abelian group A) associated to a in A.
EXAMPLES:

26.7. Abelian group elements371

Groups, Release 10.4

sage: G = AbelianGroup(3, [2,3,4], names="abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: a,b,c = G.gens()
sage: Gp = G.permutation_group(); Gp
˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5), (6,7,8,9)]
sage: a.as_permutation()
˓→needs sage.libs.gap(1,2)
sage: ap = a.as_permutation(); ap
˓→needs sage.libs.gap(1,2)
sage: ap in Gp
˓→needs sage.groups sage.libs.gap
True

#␣

#␣

#␣

#␣

>>> from sage.all import *>>> G = AbelianGroup(Integer(3), [Integer(2),Integer(3),Integer(4)], names=
˓→"abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> a,b,c = G.gens()>>> Gp = G.permutation_group(); Gp#␣˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5), (6,7,8,9)]>>> a.as_permutation()#␣˓→needs sage.libs.gap(1,2)>>> ap = a.as_permutation(); ap#␣˓→needs sage.libs.gap(1,2)>>> ap in Gp#␣˓→needs sage.groups sage.libs.gap
True

word_problem(words)
G and H are abelian groups, g in G, H is a subgroup of G generated by a list (words) of elements of G. If self
is in H, return the expression for self as a word in the elements of (words).
This function does not solve the word problem in Sage. Rather it pushes it over to GAP, which has optimized(non-deterministic) algorithms for the word problem.
Warning: Don’t use E (or other GAP-reserved letters) as a generator name.

Todo: This needs a rewrite - see stuff in the matrix_grp directory.
EXAMPLES:
sage: # needs sage.libs.gap
sage: G = AbelianGroup(2, [2,3], names="xy")sage: x,y = G.gens()
sage: x.word_problem([x,y])[[x, 1]]
sage: y.word_problem([x,y])(continues on next page)372

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)[[y, 1]]
sage: v = (y*x).word_problem([x,y]); v[[x, 1], [y, 1]]
sage: prod([x^i for x,i in v]) == y*x
True# random>>> from sage.all import *>>> # needs sage.libs.gap>>> G = AbelianGroup(Integer(2), [Integer(2),Integer(3)], names="xy")>>> x,y = G.gens()>>> x.word_problem([x,y])[[x, 1]]>>> y.word_problem([x,y])[[y, 1]]>>> v = (y*x).word_problem([x,y]); v # random[[x, 1], [y, 1]]>>> prod([x**i for x,i in v]) == y*x
Truesage.groups.abelian_gps.abelian_group_element.is_AbelianGroupElement(x)Return True if x is an abelian group element, i.e., an element of type AbelianGroupElement.
EXAMPLES: Though the integer 3 is in the integers, and the integers have an abelian group structure, 3 is not an
AbelianGroupElement:
sage: from sage.groups.abelian_gps.abelian_group_element import is_
˓→AbelianGroupElement
sage: is_AbelianGroupElement(3)doctest:warning...
DeprecationWarning: The function is_AbelianGroupElement is deprecated;
use isinstance(..., AbelianGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
False
sage: F = AbelianGroup(5, [3,4,5,8,7], abcde )sage: is_AbelianGroupElement(F.0)
True>>> from sage.all import *>>> from sage.groups.abelian_gps.abelian_group_element import is_
˓→AbelianGroupElement>>> is_AbelianGroupElement(Integer(3))
doctest:warning...
DeprecationWarning: The function is_AbelianGroupElement is deprecated;
use isinstance(..., AbelianGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
False>>> F = AbelianGroup(Integer(5), [Integer(3),Integer(4),Integer(5),Integer(8),˓→Integer(7)],abcde )>>> is_AbelianGroupElement(F.gen(0))
True

26.7. Abelian group elements373

Groups, Release 10.4

26.8 Elements (characters) of the dual group of a finite Abelian group
To obtain the dual group of a finite Abelian group, use the dual_group() method:
sage: F = AbelianGroup([2,3,5,7,8], names="abcde")
sage: F
Multiplicative Abelian group isomorphic to C2 x C3 x C5 x C7 x C8
sage: Fd = F.dual_group(names="ABCDE"); Fd
Dual of Abelian Group isomorphic to Z/2Z x Z/3Z x Z/5Z x Z/7Z x Z/8Z
over Cyclotomic Field of order 840 and degree 192>>> from sage.all import *>>> F = AbelianGroup([Integer(2),Integer(3),Integer(5),Integer(7),Integer(8)], names=
˓→"abcde")>>> F
Multiplicative Abelian group isomorphic to C2 x C3 x C5 x C7 x C8>>> Fd = F.dual_group(names="ABCDE"); Fd
Dual of Abelian Group isomorphic to Z/2Z x Z/3Z x Z/5Z x Z/7Z x Z/8Z
over Cyclotomic Field of order 840 and degree 192

The elements of the dual group can be evaluated on elements of the original group:sage: a,b,c,d,e = F.gens()
sage: A,B,C,D,E = Fd.gens()
sage: A*B^2*D^7
A*B^2sage: A(a)-1sage: B(b)zeta840^140 - 1
sage: CC(_)# abs tol 1e-8
-0.499999999999995 + 0.866025403784447*I
sage: A(a*b)-1sage: (A*B*C^2*D^20*E^65).exponents()(1, 1, 2, 6, 1)
sage: B^(-1)
B^2>>> from sage.all import *>>> a,b,c,d,e = F.gens()>>> A,B,C,D,E = Fd.gens()>>> A*B**Integer(2)*D**Integer(7)A*B^2>>> A(a)-1>>> B(b)zeta840^140 - 1>>> CC(_)# abs tol 1e-8
-0.499999999999995 + 0.866025403784447*I>>> A(a*b)-1>>> (A*B*C**Integer(2)*D**Integer(20)*E**Integer(65)).exponents()(1, 1, 2, 6, 1)(continues on next page)

374

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> B**(-Integer(1))
B^2

AUTHORS:• David Joyner (2006-07); based on abelian_group_element.py.
• David Joyner (2006-10); modifications suggested by William Stein.
• Volker Braun (2012-11) port to new Parent base. Use tuples for immutables. Default to cyclotomic base ring.
class sage.groups.abelian_gps.dual_abelian_group_element.DualAbelianGroupElement(parent,
exponents)
Bases: AbelianGroupElementBase
Base class for abelian group elements
word_problem(words)
This is a rather hackish method and is included for completeness.
The word problem for an instance of DualAbelianGroup as it can for an AbelianGroup. The reason why is thatword problem for an instance of AbelianGroup simply calls GAP (which has abelian groups implemented)
and invokes “EpimorphismFromFreeGroup” and “PreImagesRepresentative”. GAP does not have duals ofabelian groups implemented. So, by using the same name for the generators, the method below converts the
problem for the dual group to the corresponding problem on the group itself and uses GAP to solve that.
EXAMPLES:
sage: G = AbelianGroup(5,[3, 5, 5, 7, 8], names="abcde")
sage: Gd = G.dual_group(names="abcde")
sage: a,b,c,d,e = Gd.gens()
sage: u = a^3*b*c*d^2*e^5sage: v = a^2*b*c^2*d^3*e^3sage: w = a^7*b^3*c^5*d^4*e^4sage: x = a^3*b^2*c^2*d^3*e^5sage: y = a^2*b^4*c^2*d^4*e^5sage: e.word_problem([u,v,w,x,y])˓→needs sage.libs.gap[[b^2*c^2*d^3*e^5, 245]]#␣>>> from sage.all import *>>> G = AbelianGroup(Integer(5),[Integer(3), Integer(5), Integer(5),␣
˓→Integer(7), Integer(8)], names="abcde")>>> Gd = G.dual_group(names="abcde")>>> a,b,c,d,e = Gd.gens()>>> u = a**Integer(3)*b*c*d**Integer(2)*e**Integer(5)>>> v = a**Integer(2)*b*c**Integer(2)*d**Integer(3)*e**Integer(3)>>> w = a**Integer(7)*b**Integer(3)*c**Integer(5)*d**Integer(4)*e**Integer(4)>>> x = a**Integer(3)*b**Integer(2)*c**Integer(2)*d**Integer(3)*e**Integer(5)>>> y = a**Integer(2)*b**Integer(4)*c**Integer(2)*d**Integer(4)*e**Integer(5)>>> e.word_problem([u,v,w,x,y])#␣˓→needs sage.libs.gap[[b^2*c^2*d^3*e^5, 245]]

26.8. Elements (characters) of the dual group of a finite Abelian group375

Groups, Release 10.4

sage.groups.abelian_gps.dual_abelian_group_element.is_DualAbelianGroupElement(x)Test whether x is a dual Abelian group element.
INPUT:• x – anything
OUTPUT: boolean
EXAMPLES:
sage: from sage.groups.abelian_gps.dual_abelian_group import is_
˓→DualAbelianGroupElement
sage: F = AbelianGroup(5, [5,5,7,8,9], names=list("abcde")).dual_group()
sage: is_DualAbelianGroupElement(F)doctest:warning...
DeprecationWarning: The function is_DualAbelianGroupElement is deprecated;
use isinstance(..., DualAbelianGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
False
sage: is_DualAbelianGroupElement(F.an_element())
True>>> from sage.all import *>>> from sage.groups.abelian_gps.dual_abelian_group import is_
˓→DualAbelianGroupElement>>> F = AbelianGroup(Integer(5), [Integer(5),Integer(5),Integer(7),Integer(8),˓→Integer(9)], names=list("abcde")).dual_group()>>> is_DualAbelianGroupElement(F)doctest:warning...
DeprecationWarning: The function is_DualAbelianGroupElement is deprecated;
use isinstance(..., DualAbelianGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
False>>> is_DualAbelianGroupElement(F.an_element())
True

26.9 Homomorphisms of abelian groups
Todo:• there must be a homspace first• there should be hom and Hom methods in abelian group
AUTHORS:• David Joyner (2006-03-03): initial version
class sage.groups.abelian_gps.abelian_group_morphism.AbelianGroupMap(parent)
Bases: Morphism
A set-theoretic map between AbelianGroups.
class sage.groups.abelian_gps.abelian_group_morphism.AbelianGroupMorphism(G, H,
genss,
imgss)
376

Chapter 26. Abelian Groups

Groups, Release 10.4

Bases: Morphism
Some python code for wrapping GAP’s GroupHomomorphismByImages function for abelian groups. Returns“fail” if gens does not generate self or if the map does not extend to a group homomorphism, self - other.
EXAMPLES:
sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: a,b,c = G.gens()
sage: H = AbelianGroup(2,[2,3],names="xy"); H
Multiplicative Abelian group isomorphic to C2 x C3
sage: x,y = H.gens()
sage: from sage.groups.abelian_gps.abelian_group_morphism import␣˓→AbelianGroupMorphism
sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic>>> from sage.all import *>>> G = AbelianGroup(Integer(3),[Integer(2),Integer(3),Integer(4)],names="abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> a,b,c = G.gens()>>> H = AbelianGroup(Integer(2),[Integer(2),Integer(3)],names="xy"); H
Multiplicative Abelian group isomorphic to C2 x C3>>> x,y = H.gens()>>> from sage.groups.abelian_gps.abelian_group_morphism import␣˓→AbelianGroupMorphism>>> phi = AbelianGroupMorphism(H,G,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic

AUTHORS:• David Joyner (2006-02)
image(S)Return the image of the subgroup S by the morphism.
This only works for finite groups.
INPUT:• S – a subgroup of the domain group G
EXAMPLES:
sage: G = AbelianGroup(2,[2,3],names="xy")sage: x,y = G.gens()
sage: subG = G.subgroup([x])# optional - gap_package_
˓→polycyclic
sage: H = AbelianGroup(3,[2,3,4],names="abc")
sage: a,b,c = H.gens()
sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic
sage: phi.image(subG)# optional - gap_package_
˓→polycyclic
Multiplicative Abelian subgroup isomorphic to C2 generated by {a}26.9. Homomorphisms of abelian groups377

Groups, Release 10.4>>> from sage.all import *>>> G = AbelianGroup(Integer(2),[Integer(2),Integer(3)],names="xy")>>> x,y = G.gens()>>> subG = G.subgroup([x])# optional - gap_package_
˓→polycyclic>>> H = AbelianGroup(Integer(3),[Integer(2),Integer(3),Integer(4)],names="abc˓→")>>> a,b,c = H.gens()>>> phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic>>> phi.image(subG)# optional - gap_package_
˓→polycyclic
Multiplicative Abelian subgroup isomorphic to C2 generated by {a}kernel()Only works for finite groups.
Todo: not done yet; returns a gap object but should return a Sage group.
EXAMPLES:
sage: H = AbelianGroup(3,[2,3,4],names="abc"); H
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: a,b,c = H.gens()
sage: G = AbelianGroup(2,[2,3],names="xy"); G
Multiplicative Abelian group isomorphic to C2 x C3
sage: x,y = G.gens()
sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic
sage: phi.kernel()# optional - gap_package_
˓→polycyclicGroup([ ])sage: H = AbelianGroup(3,[2,2,2],names="abc")
sage: a,b,c = H.gens()
sage: G = AbelianGroup(2,[2,2],names="x")sage: x,y = G.gens()
sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,a])˓→polycyclic
sage: phi.kernel()˓→polycyclicGroup([ f1*f2 ])# optional - gap_package_# optional - gap_package_>>> from sage.all import *>>> H = AbelianGroup(Integer(3),[Integer(2),Integer(3),Integer(4)],names="abc˓→"); H
Multiplicative Abelian group isomorphic to C2 x C3 x C4>>> a,b,c = H.gens()>>> G = AbelianGroup(Integer(2),[Integer(2),Integer(3)],names="xy"); G
Multiplicative Abelian group isomorphic to C2 x C3>>> x,y = G.gens()>>> phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_
˓→polycyclic>>> phi.kernel()# optional - gap_package_
˓→polycyclic(continues on next page)

378

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)Group([])>>> H = AbelianGroup(Integer(3),[Integer(2),Integer(2),Integer(2)],names="abc˓→")>>> a,b,c = H.gens()>>> G = AbelianGroup(Integer(2),[Integer(2),Integer(2)],names="x")>>> x,y = G.gens()>>> phi = AbelianGroupMorphism(G,H,[x,y],[a,a]) # optional - gap_package_
˓→polycyclic>>> phi.kernel()# optional - gap_package_
˓→polycyclicGroup([ f1*f2 ])sage.groups.abelian_gps.abelian_group_morphism.is_AbelianGroupMorphism(f)26.10 Additive Abelian Groups
Additive abelian groups are just modules over . Hence the classes in this module derive from those in the module
sage.modules.fg_pid. The only major differences are in the way elements are printed.
sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup(invs,
remember_generators=True)
Construct a finitely-generated additive abelian group.
INPUT:• invs – list of integers; the invariants. These should all be greater than or equal to zero.
• remember_generators – boolean (default: True); whether or not to fix a set of generators (corresponding to the given invariants, which need not be in Smith form).
⨁︀
OUTPUT: the abelian group 𝑖 /𝑛𝑖 , where 𝑛𝑖 are the invariants
EXAMPLES:
sage: AdditiveAbelianGroup([0, 2, 4])
Additive abelian group isomorphic to Z + Z/2 + Z/4>>> from sage.all import *>>> AdditiveAbelianGroup([Integer(0), Integer(2), Integer(4)])
Additive abelian group isomorphic to Z + Z/2 + Z/4

An example of the remember_generators switch:
sage: G = AdditiveAbelianGroup([0, 2, 3]); G
Additive abelian group isomorphic to Z + Z/2 + Z/3
sage: G.gens()((1, 0, 0), (0, 1, 0), (0, 0, 1))
sage: H = AdditiveAbelianGroup([0, 2, 3], remember_generators = False); H
Additive abelian group isomorphic to Z/6 + Z(continues on next page)

26.10. Additive Abelian Groups379

Groups, Release 10.4

(continued from previous page)

sage: H.gens()((0, 1, 1), (1, 0, 0))>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(0), Integer(2), Integer(3)]); G
Additive abelian group isomorphic to Z + Z/2 + Z/3>>> G.gens()((1, 0, 0), (0, 1, 0), (0, 0, 1))>>> H = AdditiveAbelianGroup([Integer(0), Integer(2), Integer(3)], remember_
˓→generators = False); H
Additive abelian group isomorphic to Z/6 + Z>>> H.gens()((0, 1, 1), (1, 0, 0))There are several ways to create elements of an additive abelian group. Realize that there are two sets of generators:
the “obvious” ones composed of zeros and ones, one for each invariant given to construct the group, the other being
a set of minimal generators. Which set is the default varies with the use of the remember_generators switch.
First with “obvious” generators. Note that a raw list will use the minimal generators and a vector (a module element)
will use the generators that pair up naturally with the invariants. We create the same element repeatedly.
sage: H = AdditiveAbelianGroup([3,2,0], remember_generators=True)
sage: H.gens()((1, 0, 0), (0, 1, 0), (0, 0, 1))
sage: [H.0, H.1, H.2][(1, 0, 0), (0, 1, 0), (0, 0, 1)]
sage: p = H.0+H.1+6*H.2; p(1, 1, 6)
sage: H.smith_form_gens()((2, 1, 0), (0, 0, 1))
sage: q = H.linear_combination_of_smith_form_gens([5,6]); q(1, 1, 6)
sage: p == q
True
sage: r = H(vector([1,1,6])); r(1, 1, 6)
sage: p == r
Truesage: s = H(p)sage: p == s
True>>> from sage.all import *>>> H = AdditiveAbelianGroup([Integer(3),Integer(2),Integer(0)], remember_
˓→generators=True)>>> H.gens()((1, 0, 0), (0, 1, 0), (0, 0, 1))>>> [H.gen(0), H.gen(1), H.gen(2)][(1, 0, 0), (0, 1, 0), (0, 0, 1)]>>> p = H.gen(0)+H.gen(1)+Integer(6)*H.gen(2); p(1, 1, 6)(continues on next page)

380

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> H.smith_form_gens()((2, 1, 0), (0, 0, 1))>>> q = H.linear_combination_of_smith_form_gens([Integer(5),Integer(6)]); q(1, 1, 6)>>> p == q
True>>> r = H(vector([Integer(1),Integer(1),Integer(6)])); r(1, 1, 6)>>> p == r
True>>> s = H(p)>>> p == sTrue

Again, but now where the generators are the minimal set. Coercing a list or a vector works as before, but the default
generators are different.
sage: G = AdditiveAbelianGroup([3,2,0], remember_generators=False)
sage: G.gens()((2, 1, 0), (0, 0, 1))
sage: [G.0, G.1][(2, 1, 0), (0, 0, 1)]
sage: p = 5*G.0+6*G.1; p(1, 1, 6)
sage: H.smith_form_gens()((2, 1, 0), (0, 0, 1))
sage: q = G.linear_combination_of_smith_form_gens([5,6]); q(1, 1, 6)
sage: p == q
True
sage: r = G(vector([1,1,6])); r(1, 1, 6)
sage: p == r
Truesage: s = H(p)sage: p == s
True>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(3),Integer(2),Integer(0)], remember_
˓→generators=False)>>> G.gens()((2, 1, 0), (0, 0, 1))>>> [G.gen(0), G.gen(1)][(2, 1, 0), (0, 0, 1)]>>> p = Integer(5)*G.gen(0)+Integer(6)*G.gen(1); p(1, 1, 6)>>> H.smith_form_gens()((2, 1, 0), (0, 0, 1))>>> q = G.linear_combination_of_smith_form_gens([Integer(5),Integer(6)]); q(continues on next page)

26.10. Additive Abelian Groups381

Groups, Release 10.4

(continued from previous page)(1, 1, 6)>>> p == q
True>>> r = G(vector([Integer(1),Integer(1),Integer(6)])); r(1, 1, 6)>>> p == r
True>>> s = H(p)>>> p == sTrueclass sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroupElement(parent,x,
check=
Bases: FGP_Element
An element of an AdditiveAbelianGroup_class.
class sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_class(cover,relations)
Bases: FGP_Module_class
An additive abelian group, implemented using the -module machinery.
INPUT:• cover – the covering group as -module• relations – the relations as submodule of coverElement
alias of AdditiveAbelianGroupElement
exponent()
Return the exponent of this group (the smallest positive integer 𝑁 such that 𝑁 𝑥 = 0 for all 𝑥 in the group).
If there is no such integer, return 0.
EXAMPLES:
sage: AdditiveAbelianGroup([2,4]).exponent()
4
sage: AdditiveAbelianGroup([0, 2,4]).exponent()
0
sage: AdditiveAbelianGroup([]).exponent()
1>>> from sage.all import *>>> AdditiveAbelianGroup([Integer(2),Integer(4)]).exponent()
4>>> AdditiveAbelianGroup([Integer(0), Integer(2),Integer(4)]).exponent()0>>> AdditiveAbelianGroup([]).exponent()
1

382

Chapter 26. Abelian Groups

Groups, Release 10.4

is_cyclic()
Return True if the group is cyclic.
EXAMPLES:
With no common factors between the orders of the generators, the group will be cyclic.
sage: G = AdditiveAbelianGroup([6, 7, 55])
sage: G.is_cyclic()True>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(6), Integer(7), Integer(55)])>>> G.is_cyclic()
True

Repeating primes in the orders will create a non-cyclic group.
sage: G = AdditiveAbelianGroup([6, 15, 21, 33])
sage: G.is_cyclic()
False>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(6), Integer(15), Integer(21),␣
˓→Integer(33)])>>> G.is_cyclic()
False

A trivial group is trivially cyclic.
sage: T = AdditiveAbelianGroup([1])
sage: T.is_cyclic()True>>> from sage.all import *>>> T = AdditiveAbelianGroup([Integer(1)])>>> T.is_cyclic()True

is_multiplicative()
Return False since this is an additive group.
EXAMPLES:
sage: AdditiveAbelianGroup([0]).is_multiplicative()
False>>> from sage.all import *>>> AdditiveAbelianGroup([Integer(0)]).is_multiplicative()
False

order()
Return the order of this group (integer or infinity).
EXAMPLES:

26.10. Additive Abelian Groups383

Groups, Release 10.4

sage: AdditiveAbelianGroup([2,4]).order()8sage: AdditiveAbelianGroup([0, 2,4]).order()+Infinity
sage: AdditiveAbelianGroup([]).order()1>>> from sage.all import *>>> AdditiveAbelianGroup([Integer(2),Integer(4)]).order()8>>> AdditiveAbelianGroup([Integer(0), Integer(2),Integer(4)]).order()+Infinity>>> AdditiveAbelianGroup([]).order()1short_name()
Return a name for the isomorphism class of this group.
EXAMPLES:
sage: AdditiveAbelianGroup([0, 2,4]).short_name()
Z + Z/2 + Z/4
sage: AdditiveAbelianGroup([0, 2, 3]).short_name()
Z + Z/2 + Z/3>>> from sage.all import *>>> AdditiveAbelianGroup([Integer(0), Integer(2),Integer(4)]).short_name()
Z + Z/2 + Z/4>>> AdditiveAbelianGroup([Integer(0), Integer(2), Integer(3)]).short_name()
Z + Z/2 + Z/3

class sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_fixed_gens(crgBases: AdditiveAbelianGroup_class
A variant which fixes a set of generators, which need not be in Smith form (or indeed independent).
gens()
Return the specified generators for self (as a tuple). Compare self.smithform_gens().
EXAMPLES:
sage: G = AdditiveAbelianGroup([2,3])
sage: G.gens()((1, 0), (0, 1))
sage: G.smith_form_gens()((1, 2),)>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(2),Integer(3)])>>> G.gens()((1, 0), (0, 1))>>> G.smith_form_gens()((1, 2),)384

Chapter 26. Abelian Groups

Groups, Release 10.4

identity()
Return the identity (zero) element of this group.
EXAMPLES:
sage: G = AdditiveAbelianGroup([2, 3])
sage: G.identity()(0, 0)>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(2), Integer(3)])>>> G.identity()(0, 0)

permutation_group()
Return the permutation group attached to this group.
EXAMPLES:
sage: G = AdditiveAbelianGroup([2, 3])
sage: G.permutation_group()
˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5)]>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(2), Integer(3)])>>> G.permutation_group()
˓→needs sage.groups
Permutation Group with generators [(1,2), (3,4,5)]#␣#␣

sage.groups.additive_abelian.additive_abelian_group.cover_and_relations_from_invariants(invs
A utility function to construct modules required to initialize the super class.
Given a list of integers, this routine constructs the obvious pair of free modules such that the quotient of the two
free modules over is naturally isomorphic to the corresponding product of cyclic modules (and hence isomorphic
to a direct sum of cyclic groups).
EXAMPLES:
sage: from sage.groups.additive_abelian.additive_abelian_group import cover_and_
˓→relations_from_invariants as cr
sage: cr([0,2,3])(Ambient free module of rank 3 over the principal ideal domain Integer Ring, Free␣
˓→module of degree 3 and rank 2 over Integer Ring
Echelon basis matrix:[0 2 0][0 0 3])>>> from sage.all import *>>> from sage.groups.additive_abelian.additive_abelian_group import cover_and_
˓→relations_from_invariants as cr>>> cr([Integer(0),Integer(2),Integer(3)])(Ambient free module of rank 3 over the principal ideal domain Integer Ring, Free␣
˓→module of degree 3 and rank 2 over Integer Ring
Echelon basis matrix:[0 2 0][0 0 3])26.10. Additive Abelian Groups385

Groups, Release 10.4

26.11 Wrapper class for abelian groups
This class is intended as a template for anything in Sage that needs the functionality of abelian groups. One can create
an AdditiveAbelianGroupWrapper object from any given set of elements in some given parent, as long as an_add_ method has been defined.
EXAMPLES:
We create a toy example based on the Mordell-Weil group of an elliptic curve over:sage: # needs sage.schemes
sage: E = EllipticCurve( 30a2 )sage: pts = [E(4,-7,1), E(7/4, -11/8, 1), E(3, -2, 1)]
sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [3, 2, 2]); M
Additive abelian group isomorphic to Z/3 + Z/2 + Z/2 embedded in Abeliangroup of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - 19*x + 26
over Rational Field
sage: M.gens()((4 : -7 : 1), (7/4 : -11/8 : 1), (3 : -2 : 1))sage: 3*M.0(0 : 1 : 0)sage: 3000000000000001 * M.0(4 : -7 : 1)sage: M == loads(dumps(M)) # known bug (https://github.com/sagemath/sage/issues/11599
˓→#comment:7)
True>>> from sage.all import *>>> # needs sage.schemes>>> E = EllipticCurve( 30a2 )>>> pts = [E(Integer(4),-Integer(7),Integer(1)), E(Integer(7)/Integer(4), ˓→Integer(11)/Integer(8), Integer(1)), E(Integer(3), -Integer(2), Integer(1))]>>> M = AdditiveAbelianGroupWrapper(pts[Integer(0)].parent(), pts, [Integer(3),␣
˓→Integer(2), Integer(2)]); M
Additive abelian group isomorphic to Z/3 + Z/2 + Z/2 embedded in Abeliangroup of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - 19*x + 26
over Rational Field>>> M.gens()((4 : -7 : 1), (7/4 : -11/8 : 1), (3 : -2 : 1))>>> Integer(3)*M.gen(0)(0 : 1 : 0)>>> Integer(3000000000000001) * M.gen(0)(4 : -7 : 1)>>> M == loads(dumps(M)) # known bug (https://github.com/sagemath/sage/issues/11599
˓→#comment:7)
True

Todo: Think about subgroups and quotients, which probably won’t work in the current implementation – some fiddly
adjustments will be needed in order to be able to pass extra arguments to the subquotient’s init method.
AUTHORS:• David Loeffler (2010)• Lorenz Panny (2017): AdditiveAbelianGroupWrapper.discrete_log()• Lorenz Panny (2023): AdditiveAbelianGroupWrapper.from_generators()
386

Chapter 26. Abelian Groups

Groups, Release 10.4class sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper(univers
gens
invariants
Bases: AdditiveAbelianGroup_fixed_gens
This class is used to wrap a subgroup of an existing additive abelian group as a new additive abelian group.
EXAMPLES:
sage: G2 = AdditiveAbelianGroupWrapper(Zmod(42), [2], [21]); G2
Additive abelian group isomorphic to Z/21 embedded in Ring of integers modulo 42
sage: G6 = AdditiveAbelianGroupWrapper(Zmod(42), [6], [7]); G6
Additive abelian group isomorphic to Z/7 embedded in Ring of integers modulo 42
sage: G = AdditiveAbelianGroupWrapper(Zmod(42), [21,14,6], [2,3,7]); G
Additive abelian group isomorphic to Z/2 + Z/3 + Z/7 embedded in
Ring of integers modulo 42
sage: G.invariants()(42,)>>> from sage.all import *>>> G2 = AdditiveAbelianGroupWrapper(Zmod(Integer(42)), [Integer(2)],␣
˓→[Integer(21)]); G2
Additive abelian group isomorphic to Z/21 embedded in Ring of integers modulo 42>>> G6 = AdditiveAbelianGroupWrapper(Zmod(Integer(42)), [Integer(6)],␣
˓→[Integer(7)]); G6
Additive abelian group isomorphic to Z/7 embedded in Ring of integers modulo 42>>> G = AdditiveAbelianGroupWrapper(Zmod(Integer(42)), [Integer(21),Integer(14),
˓→Integer(6)], [Integer(2),Integer(3),Integer(7)]); G
Additive abelian group isomorphic to Z/2 + Z/3 + Z/7 embedded in
Ring of integers modulo 42>>> G.invariants()(42,)
sage: AdditiveAbelianGroupWrapper(QQbar, [sqrt(2), sqrt(3)], [0, 0])
˓→needs sage.rings.number_field sage.symbolic
Additive abelian group isomorphic to Z + Z embedded in Algebraic Field#␣>>> from sage.all import *>>> AdditiveAbelianGroupWrapper(QQbar, [sqrt(Integer(2)), sqrt(Integer(3))],␣
˓→[Integer(0), Integer(0)])# needs sage.rings.number_field sage.
˓→symbolic
Additive abelian group isomorphic to Z + Z embedded in Algebraic Field
sage: EllipticCurve(GF(419**2), [1,0]).abelian_group() # indirect doctest
˓→needs sage.rings.finite_rings sage.schemes
Additive abelian group isomorphic to Z/420 + Z/420 embedded in
Abelian group of points on Elliptic Curvedefined by y^2 = x^3 + x over Finite Field in z2 of size 419^2#␣>>> from sage.all import *>>> EllipticCurve(GF(Integer(419)**Integer(2)), [Integer(1),Integer(0)]).abelian_
˓→group()# indirect doctest# needs sage.rings.finite_rings sage.schemes
Additive abelian group isomorphic to Z/420 + Z/420 embedded in(continues on next page)

26.11. Wrapper class for abelian groups387

Groups, Release 10.4

(continued from previous page)

Abelian group of points on Elliptic Curvedefined by y^2 = x^3 + x over Finite Field in z2 of size 419^2

Element
alias of AdditiveAbelianGroupWrapperElement
discrete_exp(v)Given a list (or other iterable) of length equal to the number of generators of this group, compute the elementof the ambient group with those exponents in terms of the generators of self.
EXAMPLES:
sage: G = AdditiveAbelianGroupWrapper(QQbar,
˓→needs sage.rings.number_field....:[sqrt(QQbar(2)), -1], [0, 0])
sage: v = G.discrete_exp([3, 5]); v
˓→needs sage.rings.number_field-0.7573593128807148?
sage: v.parent() is QQbar
˓→needs sage.rings.number_field
True

#␣

#␣

#␣

>>> from sage.all import *>>> G = AdditiveAbelianGroupWrapper(QQbar,#␣˓→needs sage.rings.number_field...
[sqrt(QQbar(Integer(2))), -Integer(1)],␣
˓→[Integer(0), Integer(0)])>>> v = G.discrete_exp([Integer(3), Integer(5)]); v␣˓→# needs sage.rings.number_field-0.7573593128807148?
>>> v.parent() is QQbar#␣˓→needs sage.rings.number_field
True

This method is an inverse of discrete_log():
sage: orders = [2, 2*3, 2*3*5, 2*3*5*7, 2*3*5*7*11]
sage: G = AdditiveAbelianGroup(orders)sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(), orders)sage: el = A.random_element()
sage: A.discrete_exp(A.discrete_log(el)) == el
True>>> from sage.all import *>>> orders = [Integer(2), Integer(2)*Integer(3),␣
˓→Integer(2)*Integer(3)*Integer(5),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7)*Integer(11)]>>> G = AdditiveAbelianGroup(orders)>>> A = AdditiveAbelianGroupWrapper(G.gen(0).parent(), G.gens(), orders)>>> el = A.random_element()>>> A.discrete_exp(A.discrete_log(el)) == elTruediscrete_log(x, gens=None)
Given an element of the ambient group, attempt to express it in terms of the generators of this group or the
388

Chapter 26. Abelian Groups

Groups, Release 10.4

given generators of a subgroup.
ALGORITHM:
This reduces to p-groups, then calls _discrete_log_pgroup() which implements a basic version of
the recursive algorithm from [Suth2008].
AUTHORS:• Lorenz Panny (2017)
EXAMPLES:
sage: G = AdditiveAbelianGroup([2, 2*3, 2*3*5, 2*3*5*7, 2*3*5*7*11])
sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(),....:[g.order() for g in G.gens()])
sage: A.discrete_log(A.discrete_exp([1,5,23,127,539]))(1, 5, 23, 127, 539)>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(2), Integer(2)*Integer(3),␣
˓→Integer(2)*Integer(3)*Integer(5),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7)*Integer(11)])>>> A = AdditiveAbelianGroupWrapper(G.gen(0).parent(), G.gens(),...
[g.order() for g in G.gens()])>>> A.discrete_log(A.discrete_exp([Integer(1),Integer(5),Integer(23),
˓→Integer(127),Integer(539)]))(1, 5, 23, 127, 539)
sage: x = polygen(ZZ, x )sage: F.<t> = GF(1009**2, modulus=x**2+11); E = EllipticCurve(j=F(940))
˓→needs sage.rings.finite_rings sage.schemes
sage: P, Q = E(900*t + 228, 974*t + 185), E(1007*t + 214, 865*t + 802)
˓→needs sage.rings.finite_rings sage.schemes
sage: E.abelian_group().discrete_log(123 * P + 777 * Q, [P, Q])
˓→needs sage.rings.finite_rings sage.schemes(123, 777)

#␣
#␣
#␣

>>> from sage.all import *>>> x = polygen(ZZ, x )>>> F = GF(Integer(1009)**Integer(2), modulus=x**Integer(2)+Integer(11),␣
˓→names=( t ,)); (t,) = F._first_ngens(1); E =␣˓→EllipticCurve(j=F(Integer(940)))# needs sage.rings.finite_rings sage.
˓→schemes>>> P, Q = E(Integer(900)*t + Integer(228), Integer(974)*t + Integer(185)),␣
˓→E(Integer(1007)*t + Integer(214), Integer(865)*t + Integer(802))#␣˓→needs sage.rings.finite_rings sage.schemes>>> E.abelian_group().discrete_log(Integer(123) * P + Integer(777) * Q, [P,␣˓→Q])
# needs sage.rings.finite_rings sage.schemes(123, 777)
sage: V = Zmod(8)**2
sage: G = AdditiveAbelianGroupWrapper(V, [[2,2],[4,0]], [4, 2])
sage: G.discrete_log(V([6, 2]))
(1, 1)
sage: G.discrete_log(V([6, 4]))
Traceback (most recent call last):(continues on next page)

26.11. Wrapper class for abelian groups389

Groups, Release 10.4

(continued from previous page)...
ValueError: not in group>>> from sage.all import *>>> V = Zmod(Integer(8))**Integer(2)>>> G = AdditiveAbelianGroupWrapper(V, [[Integer(2),Integer(2)],[Integer(4),˓→Integer(0)]], [Integer(4), Integer(2)])>>> G.discrete_log(V([Integer(6), Integer(2)]))(1, 1)>>> G.discrete_log(V([Integer(6), Integer(4)]))
Traceback (most recent call last):...
ValueError: not in group
sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(2)], [0])˓→needs sage.rings.number_field sage.symbolic
sage: G.discrete_log(QQbar(2*sqrt(2)))˓→needs sage.rings.number_field sage.symbolic
Traceback (most recent call last):...
NotImplementedError: No black-box discrete log for infinite abelian groups#␣#␣>>> from sage.all import *>>> G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(Integer(2))], [Integer(0)]) ␣˓→# needs sage.rings.number_field sage.symbolic>>> G.discrete_log(QQbar(Integer(2)*sqrt(Integer(2))))␣˓→# needs sage.rings.number_field sage.symbolic
Traceback (most recent call last):...
NotImplementedError: No black-box discrete log for infinite abelian groups

static from_generators(gens, universe=None)
This method constructs the subgroup generated by a sequence of finite-order elements in an additive abeliangroup.
The elements need not be independent, hence this can be used to perform tasks such as finding relations
between some given elements of an abelian group, computing the structure of the generated subgroup, enumerating all elements of the subgroup, and solving discrete-logarithm problems.
EXAMPLES:
sage: G = AdditiveAbelianGroup([15, 30, 45])
sage: gs = [G((1,2,3)), G((4,5,6)), G((7,7,7)), G((3,2,1))]
sage: H = AdditiveAbelianGroupWrapper.from_generators(gs); H
Additive abelian group isomorphic to Z/90 + Z/15 embedded in
Additive abelian group isomorphic to Z/15 + Z/30 + Z/45
sage: H.gens()((12, 13, 14), (1, 26, 21))>>> from sage.all import *>>> G = AdditiveAbelianGroup([Integer(15), Integer(30), Integer(45)])>>> gs = [G((Integer(1),Integer(2),Integer(3))), G((Integer(4),Integer(5),˓→Integer(6))), G((Integer(7),Integer(7),Integer(7))), G((Integer(3),˓→Integer(2),Integer(1)))]>>> H = AdditiveAbelianGroupWrapper.from_generators(gs); H(continues on next page)390

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

Additive abelian group isomorphic to Z/90 + Z/15 embedded in
Additive abelian group isomorphic to Z/15 + Z/30 + Z/45>>> H.gens()((12, 13, 14), (1, 26, 21))

generator_orders()
The orders of the generators with which this group was initialised. (Note that these are not necessarily a minimal set of generators.) Generators of infinite order are returned as 0. Compare self.invariants(),
which returns the orders of a minimal set of generators.
EXAMPLES:
sage: V = Zmod(6)**2
sage: G = AdditiveAbelianGroupWrapper(V, [2*V.0, 3*V.1], [3, 2])
sage: G.generator_orders()(3, 2)
sage: G.invariants()(6,)>>> from sage.all import *>>> V = Zmod(Integer(6))**Integer(2)>>> G = AdditiveAbelianGroupWrapper(V, [Integer(2)*V.gen(0), Integer(3)*V.
˓→gen(1)], [Integer(3), Integer(2)])>>> G.generator_orders()(3, 2)>>> G.invariants()(6,)

torsion_subgroup(n=None)
Return the 𝑛-torsion subgroup of this additive abelian group when 𝑛 is given, and the torsion subgroup otherwise.
The [𝑛-]torsion subgroup consists of all elements whose order is finite [and divides 𝑛].
EXAMPLES:
sage: ords = [2, 2*3, 2*3*5, 0, 2*3*5*7, 2*3*5*7*11]
sage: G = AdditiveAbelianGroup(ords)
sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(), ords)
sage: T = A.torsion_subgroup(5)sage: T
Additive abelian group isomorphic to Z/5 + Z/5 + Z/5 embedded in
Additive abelian group isomorphic to Z/2 + Z/6 + Z/30 + Z + Z/210 + Z/2310
sage: T.gens()((0, 0, 6, 0, 0, 0), (0, 0, 0, 0, 42, 0), (0, 0, 0, 0, 0, 462))>>> from sage.all import *>>> ords = [Integer(2), Integer(2)*Integer(3),␣
˓→Integer(2)*Integer(3)*Integer(5), Integer(0),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7),␣
˓→Integer(2)*Integer(3)*Integer(5)*Integer(7)*Integer(11)]>>> G = AdditiveAbelianGroup(ords)>>> A = AdditiveAbelianGroupWrapper(G.gen(0).parent(), G.gens(), ords)>>> T = A.torsion_subgroup(Integer(5))>>> T
Additive abelian group isomorphic to Z/5 + Z/5 + Z/5 embedded in(continues on next page)

26.11. Wrapper class for abelian groups391

Groups, Release 10.4

(continued from previous page)

Additive abelian group isomorphic to Z/2 + Z/6 + Z/30 + Z + Z/210 + Z/2310>>> T.gens()((0, 0, 6, 0, 0, 0), (0, 0, 0, 0, 42, 0), (0, 0, 0, 0, 0, 462))
sage: # needs sage.rings.finite_rings sage.schemes
sage: E = EllipticCurve(GF(487^2), [311,205])
sage: T = E.abelian_group().torsion_subgroup(42); T
Additive abelian group isomorphic to Z/42 + Z/6 embedded in
Abelian group of points on Elliptic Curvedefined by y^2 = x^3 + 311*x + 205 over Finite Field in z2 of size 487^2
sage: [P.order() for P in T.gens()][42, 6]>>> from sage.all import *>>> # needs sage.rings.finite_rings sage.schemes>>> E = EllipticCurve(GF(Integer(487)**Integer(2)), [Integer(311),
˓→Integer(205)])>>> T = E.abelian_group().torsion_subgroup(Integer(42)); T
Additive abelian group isomorphic to Z/42 + Z/6 embedded in
Abelian group of points on Elliptic Curvedefined by y^2 = x^3 + 311*x + 205 over Finite Field in z2 of size 487^2>>> [P.order() for P in T.gens()][42, 6]sage: # needs sage.schemes
sage: E = EllipticCurve( 574i1 )sage: pts = [E(103,172), E(61,18)]
sage: assert pts[0].order() == 7 and pts[1].order() == infinity
sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [7,0]); M
Additive abelian group isomorphic to Z/7 + Z embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field
sage: M.torsion_subgroup()
Additive abelian group isomorphic to Z/7 embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field
sage: M.torsion_subgroup(7)Additive abelian group isomorphic to Z/7 embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field
sage: M.torsion_subgroup(5)Trivial group embedded in Abelian group of points on Elliptic Curvedefined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field>>> from sage.all import *>>> # needs sage.schemes>>> E = EllipticCurve( 574i1 )>>> pts = [E(Integer(103),Integer(172)), E(Integer(61),Integer(18))]>>> assert pts[Integer(0)].order() == Integer(7) and pts[Integer(1)].order()␣
˓→== infinity>>> M = AdditiveAbelianGroupWrapper(pts[Integer(0)].parent(), pts,␣˓→[Integer(7),Integer(0)]); M
Additive abelian group isomorphic to Z/7 + Z embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field(continues on next page)392

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> M.torsion_subgroup()
Additive abelian group isomorphic to Z/7 embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field>>> M.torsion_subgroup(Integer(7))
Additive abelian group isomorphic to Z/7 embedded in
Abelian group of points on Elliptic Curve defined byy^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field>>> M.torsion_subgroup(Integer(5))
Trivial group embedded in Abelian group of points on Elliptic Curvedefined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field

AUTHORS:• Lorenz Panny (2022)
universe()
The ambient group in which this abelian group lives.
EXAMPLES:
sage: G = AdditiveAbelianGroupWrapper(QQbar,
˓→needs sage.rings.number_field....:[sqrt(QQbar(2)), sqrt(QQbar(3))],....:[0, 0])
sage: G.universe()
˓→needs sage.rings.number_field
Algebraic Field>>> from sage.all import *>>> G = AdditiveAbelianGroupWrapper(QQbar,
˓→needs sage.rings.number_field...
[sqrt(QQbar(Integer(2))),␣
˓→sqrt(QQbar(Integer(3)))],...
[Integer(0), Integer(0)])>>> G.universe()
˓→needs sage.rings.number_field
Algebraic Field

#␣

#␣

#␣

#␣

class sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapperElem

Bases: AdditiveAbelianGroupElement
An element of an AdditiveAbelianGroupWrapper.
element()
Return the underlying object that this element wraps.
EXAMPLES:

26.11. Wrapper class for abelian groups393

Groups, Release 10.4

sage: T = EllipticCurve( 65a ).torsion_subgroup().gen(0)#␣˓→needs sage.schemes
sage: T; type(T)#␣˓→needs sage.schemes(0 : 0 : 1)
<class sage.schemes.elliptic_curves.ell_torsion.EllipticCurveTorsionSubgroup_
˓→with_category.element_class >sage: T.element(); type(T.element())#␣˓→needs sage.schemes(0 : 0 : 1)
<class sage.schemes.elliptic_curves.ell_point.EllipticCurvePoint_number_field
˓→ >>>> from sage.all import *>>> T = EllipticCurve( 65a ).torsion_subgroup().gen(Integer(0))␣˓→# needs sage.schemes>>> T; type(T)#␣˓→needs sage.schemes(0 : 0 : 1)
<class sage.schemes.elliptic_curves.ell_torsion.EllipticCurveTorsionSubgroup_
˓→with_category.element_class >>>> T.element(); type(T.element())#␣˓→needs sage.schemes(0 : 0 : 1)
<class sage.schemes.elliptic_curves.ell_point.EllipticCurvePoint_number_field˓→ >class sage.groups.additive_abelian.additive_abelian_wrapper.UnwrappingMorphism(domain)
Bases: Morphism
The embedding into the ambient group. Used by the coercion framework.
sage.groups.additive_abelian.additive_abelian_wrapper.basis_from_generators(gens,ords=None)
Given a generating set of some finite abelian group (additively written), compute and return a basis of the group.
Note: A basis of a finite abelian group is a generating set {𝑔1 , . . . , 𝑔𝑛 } such that each element of the group canbe written as a unique linear combination 𝛼1 𝑔1 + · · · + 𝛼𝑛 𝑔𝑛 with each 𝛼𝑖 ∈ {0, . . . , ord(𝑔𝑖 ) − 1}.
ALGORITHM: [Suth2007], Algorithm 9.1 & Remark 9.1
EXAMPLES:
sage: # needs sage.groups sage.rings.finite_rings
sage: from sage.groups.additive_abelian.additive_abelian_wrapper import basis_
˓→from_generatorssage: E = EllipticCurve(GF(31337^6, a ), j=37)
sage: E.order()
946988065073788930380545280
sage: (R,S), (ordR,ordS) = basis_from_generators(E.gens())
sage: ordR, ordS
(313157428926517503432720, 3024)
sage: R.order() == ordR
True(continues on next page)394

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)

sage: S.order() == ordS
True
sage: ordR * ordS == E.order()True
sage: R.weil_pairing(S, ordR).multiplicative_order() == ordS
True
sage: E.abelian_group().invariants()(3024, 313157428926517503432720)>>> from sage.all import *>>> # needs sage.groups sage.rings.finite_rings>>> from sage.groups.additive_abelian.additive_abelian_wrapper import basis_from_
˓→generators>>> E = EllipticCurve(GF(Integer(31337)**Integer(6), a ), j=Integer(37))>>> E.order()
946988065073788930380545280>>> (R,S), (ordR,ordS) = basis_from_generators(E.gens())>>> ordR, ordS
(313157428926517503432720, 3024)>>> R.order() == ordR
True>>> S.order() == ordS
True>>> ordR * ordS == E.order()True>>> R.weil_pairing(S, ordR).multiplicative_order() == ordS
True>>> E.abelian_group().invariants()(3024, 313157428926517503432720)

26.12 Groups of elements representing (complex) arguments.
This includes• RootsOfUnityGroup (containing all roots of unity)• UnitCircleGroup (representing elements on the unit circle by 𝑒2𝜋·exponent )• ArgumentByElementGroup (whose elements are defined via formal arguments by 𝑒𝐼·arg(element) .
Use the factory ArgumentGroup for creating such a group conveniently.
Note: One main purpose of such groups is in an asymptotic ring s growth group when an element like 𝑧 𝑛(for some constant 𝑧) is split into |𝑧|𝑛 · 𝑒𝐼·arg(𝑧)𝑛 . (Note that the first factor determines the growth of that product, thesecond does not influence the growth.)
AUTHORS:• Daniel Krenn (2018)26.12. Groups of elements representing (complex) arguments.

395

Groups, Release 10.4

26.12.1 Classes and Methods
class sage.groups.misc_gps.argument_groups.AbstractArgument(parent, element,
normalize=True)
Bases: MultiplicativeGroupElement
An element of AbstractArgumentGroup. This abstract class encapsulates an element of the parent’s base,i.e. it can be seen as a wrapper class.
INPUT:• parent – a SageMath parent• element – an element of parent’s base• normalize – a boolean (default: True)class sage.groups.misc_gps.argument_groups.AbstractArgumentGroup(base, category)Bases: UniqueRepresentation, Parent
A group whose elements represent (complex) arguments.
INPUT:• base – a SageMath parent• category – a category
Element
alias of AbstractArgumentclass sage.groups.misc_gps.argument_groups.ArgumentByElement(parent, element,
normalize=True)
Bases: AbstractArgument
An element of ArgumentByElementGroup.
INPUT:• parent – a SageMath parent• element – a nonzero element of the parent’s base• normalize – a boolean (default: True)class sage.groups.misc_gps.argument_groups.ArgumentByElementGroup(base, category)Bases: AbstractArgumentGroupA group of (complex) arguments. The arguments are represented by a the formal argument of an element, i.e., byarg(element).
INPUT:• base – a SageMath parent representing a subset of the complex plane• category – a category
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroupsage: C = ArgumentByElementGroup(CC); C
Unit Circle Group with Argument of Elements in
Complex Field with 53 bits of precision
sage: C(1 + 2*I)#␣(continues on next page)

396

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)needs sage.symbolice^(I*arg(1.00000000000000 + 2.00000000000000*I))˓→>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup>>> C = ArgumentByElementGroup(CC); C
Unit Circle Group with Argument of Elements in
Complex Field with 53 bits of precision>>> C(Integer(1) + Integer(2)*I)˓→# needs sage.symbolice^(I*arg(1.00000000000000 + 2.00000000000000*I))

␣Element
alias of ArgumentByElement
sage.groups.misc_gps.argument_groups.ArgumentGroup =<sage.groups.misc_gps.argument_groups.ArgumentGroupFactory object>
A factory for argument groups.
This is an instance of ArgumentGroupFactory whose documentation provides more details.
class sage.groups.misc_gps.argument_groups.ArgumentGroupFactory
Bases: UniqueFactory
A factory for creating argument groups.
INPUT:• data – an object
The factory will analyze data and interpret it as specification or domain.
• specification – a string
The following is possible:–

Signs give the SignGroup–UU give the RootsOfUnityGroup–UU_P , where P is a string representing a SageMath parent which is interpreted as exponents–

Arg_P , where P is a string representing a SageMath parent which is interpreted as domain• domain – a SageMath parent representing a subset of the complex plane. An instance of ArgumentByElementGroup will be created with the given domain.
• exponents – a SageMath parent representing a subset of the reals. An instance of :class`UnitCircleGroup`
will be created with the given exponents
Exactly one of data, specification, exponents has to be provided.
Further keyword parameters will be carried on to the initialization of the group.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import ArgumentGroupsage: ArgumentGroup( UU )
˓→needs sage.rings.number_field
Group of Roots of Unity#␣(continues on next page)

26.12. Groups of elements representing (complex) arguments.

397

Groups, Release 10.4

(continued from previous page)

sage: # needs sage.rings.number_fieldsage: ArgumentGroup(ZZ)
Sign Groupsage: ArgumentGroup(QQ)
Sign Groupsage: ArgumentGroup( UU_QQ )Group of Roots of Unity
sage: ArgumentGroup(AA)Sign Groupsage: ArgumentGroup(RR)˓→needs sage.rings.number_field
Sign Groupsage: ArgumentGroup( Arg_RR )˓→needs sage.rings.number_field
Sign Groupsage: ArgumentGroup(RIF)
˓→needs sage.rings.real_interval_field
Sign Groupsage: ArgumentGroup(RBF)
Sign Group#␣sage: ArgumentGroup(CC)˓→needs sage.rings.number_field
Unit Circle Group with Exponents inReal Field with 53 bits of precision modulo ZZ
sage: ArgumentGroup( Arg_CC )˓→needs sage.rings.number_field
Unit Circle Group with Exponents inReal Field with 53 bits of precision modulo ZZ
sage: ArgumentGroup(CIF)
Unit Circle Group with Exponents inReal Interval Field with 53 bits of precision modulo ZZ
sage: ArgumentGroup(CBF)
Unit Circle Group with Exponents inReal ball field with 53 bits of precision modulo ZZ#␣sage: ArgumentGroup(CyclotomicField(3))˓→needs sage.rings.number_field
Unit Circle Group with Argument of Elements in
Cyclotomic Field of order 3 and degree 2

#␣

#␣

#␣

#␣

>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import ArgumentGroup>>> ArgumentGroup( UU )
˓→needs sage.rings.number_field
Group of Roots of Unity#␣>>> # needs sage.rings.number_field>>> ArgumentGroup(ZZ)
Sign Group>>> ArgumentGroup(QQ)
Sign Group>>> ArgumentGroup( UU_QQ )(continues on next page)

398

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)Group of Roots of Unity>>> ArgumentGroup(AA)Sign Group>>> ArgumentGroup(RR)˓→needs sage.rings.number_field
Sign Group>>> ArgumentGroup( Arg_RR )˓→needs sage.rings.number_field
Sign Group>>> ArgumentGroup(RIF)
˓→needs sage.rings.real_interval_field
Sign Group>>> ArgumentGroup(RBF)
Sign Group#␣>>> ArgumentGroup(CC)˓→needs sage.rings.number_field
Unit Circle Group with Exponents inReal Field with 53 bits of precision modulo ZZ>>> ArgumentGroup( Arg_CC )˓→needs sage.rings.number_field
Unit Circle Group with Exponents inReal Field with 53 bits of precision modulo ZZ>>> ArgumentGroup(CIF)
Unit Circle Group with Exponents inReal Interval Field with 53 bits of precision modulo ZZ>>> ArgumentGroup(CBF)
Unit Circle Group with Exponents inReal ball field with 53 bits of precision modulo ZZ

#␣

#␣

#␣

#␣

>>> ArgumentGroup(CyclotomicField(Integer(3)))˓→# needs sage.rings.number_field
Unit Circle Group with Argument of Elements in
Cyclotomic Field of order 3 and degree 2␣create_key_and_extra_args(data=None, specification=None, domain=None, exponents=None,**kwds)Normalize the input.
See ArgumentGroupFactory for a description and examples.
create_object(version, key, **kwds)
Create an object from the given arguments.
class sage.groups.misc_gps.argument_groups.RootOfUnity(parent, element, normalize=True)
Bases: UnitCirclePoint
A root of unity (i.e. an element of RootsOfUnityGroup) which is 𝑒2𝜋·exponent for a rational exponent.
exponent_denominator()
Return the denominator of the rational quotient in [0, 1) representing the exponent of this root of unity.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import RootsOfUnityGroupsage: U = RootsOfUnityGroup()(continues on next page)

26.12. Groups of elements representing (complex) arguments.

399

Groups, Release 10.4

(continued from previous page)

sage: a = U(exponent=2/3); azeta3^2sage: a.exponent_denominator()3>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import RootsOfUnityGroup>>> U = RootsOfUnityGroup()>>> a = U(exponent=Integer(2)/Integer(3)); azeta3^2>>> a.exponent_denominator()
3

exponent_numerator()
Return the numerator of the rational quotient in [0, 1) representing the exponent of this root of unity.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import RootsOfUnityGroupsage: U = RootsOfUnityGroup()
sage: a = U(exponent=2/3); azeta3^2sage: a.exponent_numerator()2>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import RootsOfUnityGroup>>> U = RootsOfUnityGroup()>>> a = U(exponent=Integer(2)/Integer(3)); azeta3^2>>> a.exponent_numerator()
2class sage.groups.misc_gps.argument_groups.RootsOfUnityGroup(category)Bases: UnitCircleGroupThe group of all roots of unity.
INPUT:• category – a category
This is a specialized UnitCircleGroup with base.

EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import RootsOfUnityGroupsage: U = RootsOfUnityGroup(); UGroup of Roots of Unity
sage: U(exponent=1/4)
I>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import RootsOfUnityGroup>>> U = RootsOfUnityGroup(); UGroup of Roots of Unity(continues on next page)

400

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> U(exponent=Integer(1)/Integer(4))
I

Element
alias of RootOfUnity
class sage.groups.misc_gps.argument_groups.Sign(parent, element, normalize=True)
Bases: AbstractArgument
An element of SignGroup.
INPUT:• parent – a SageMath parent• element – a nonzero element of the parent’s base• normalize – a boolean (default: True)
is_minus_one()
Return whether this sign is −1.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import SignGroupsage: S = SignGroup()
sage: S(1).is_minus_one()False
sage: S(-1).is_minus_one()True>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import SignGroup>>> S = SignGroup()>>> S(Integer(1)).is_minus_one()
False>>> S(-Integer(1)).is_minus_one()
True

is_one()Return whether this sign is 1.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import SignGroupsage: S = SignGroup()
sage: S(-1).is_one()False
sage: S(1).is_one()True>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import SignGroup>>> S = SignGroup()>>> S(-Integer(1)).is_one()
False>>> S(Integer(1)).is_one()True

26.12. Groups of elements representing (complex) arguments.

401

Groups, Release 10.4class sage.groups.misc_gps.argument_groups.SignGroup(category)Bases: AbstractArgumentGroupA group of the signs −1 and 1.
INPUT:• category – a category
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import SignGroupsage: S = SignGroup(); S
Sign Groupsage: S(-1)-1>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import SignGroup>>> S = SignGroup(); S
Sign Group>>> S(-Integer(1))-1Element
alias of Signclass sage.groups.misc_gps.argument_groups.UnitCircleGroup(base, category)Bases: AbstractArgumentGroupA group of points on the unit circle. These points are represented by 𝑒2𝜋·exponent .
INPUT:• base – a SageMath parent representing a subset of the reals• category – a category
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import UnitCircleGroupsage: R = UnitCircleGroup(RR); R
Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ
sage: R(exponent=2.42)e^(2*pi*0.420000000000000)
sage: Q = UnitCircleGroup(QQ); Q
Unit Circle Group with Exponents in Rational Field modulo ZZ
sage: Q(exponent=6/5)e^(2*pi*1/5)>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import UnitCircleGroup>>> R = UnitCircleGroup(RR); R
Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ>>> R(exponent=RealNumber( 2.42 ))e^(2*pi*0.420000000000000)(continues on next page)402

Chapter 26. Abelian Groups

Groups, Release 10.4

(continued from previous page)>>> Q = UnitCircleGroup(QQ); Q
Unit Circle Group with Exponents in Rational Field modulo ZZ>>> Q(exponent=Integer(6)/Integer(5))
e^(2*pi*1/5)

Element
alias of UnitCirclePoint
class sage.groups.misc_gps.argument_groups.UnitCirclePoint(parent, element,
normalize=True)
Bases: AbstractArgument
An element of UnitCircleGroup which is 𝑒2𝜋·exponent .
INPUT:• parent – a SageMath parent• exponent – a number (of a subset of the reals)• normalize – a boolean (default: True)
property exponent
The exponent of this point on the unit circle.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import UnitCircleGroupsage: C = UnitCircleGroup(RR)
sage: C(exponent=4/3).exponent
0.333333333333333>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import UnitCircleGroup>>> C = UnitCircleGroup(RR)>>> C(exponent=Integer(4)/Integer(3)).exponent
0.333333333333333

is_minus_one()
Return whether this point on the unit circle is −1.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import UnitCircleGroupsage: C = UnitCircleGroup(QQ)
sage: C(exponent=0).is_minus_one()False
sage: C(exponent=1/2).is_minus_one()True
sage: C(exponent=2/3).is_minus_one()
False>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import UnitCircleGroup>>> C = UnitCircleGroup(QQ)>>> C(exponent=Integer(0)).is_minus_one()
False(continues on next page)

26.12. Groups of elements representing (complex) arguments.

403

Groups, Release 10.4

(continued from previous page)>>> C(exponent=Integer(1)/Integer(2)).is_minus_one()
True>>> C(exponent=Integer(2)/Integer(3)).is_minus_one()
False

is_one()Return whether this point on the unit circle is 1.
EXAMPLES:
sage: from sage.groups.misc_gps.argument_groups import UnitCircleGroupsage: C = UnitCircleGroup(QQ)
sage: C(exponent=0).is_one()True
sage: C(exponent=1/2).is_one()False
sage: C(exponent=2/3).is_one()False
sage: C(exponent=42).is_one()True>>> from sage.all import *>>> from sage.groups.misc_gps.argument_groups import UnitCircleGroup>>> C = UnitCircleGroup(QQ)>>> C(exponent=Integer(0)).is_one()
True>>> C(exponent=Integer(1)/Integer(2)).is_one()
False>>> C(exponent=Integer(2)/Integer(3)).is_one()
False>>> C(exponent=Integer(42)).is_one()True

26.13 Groups of imaginary elements
Note: One main purpose of such groups is in an asymptotic ring s growth group when an element like𝑛𝑧 (for some constant 𝑧) is split into 𝑛ℜ𝑧+𝐼ℑ𝑧 . (Note that the first summand in the exponent determines the growth, thesecond does not influence the growth.)
AUTHORS:• Daniel Krenn (2018)

404

Chapter 26. Abelian Groups

Groups, Release 10.4

26.13.1 Classes and Methods
class sage.groups.misc_gps.imaginary_groups.ImaginaryElement(parent, imag)
Bases: AdditiveGroupElement
An element of ImaginaryGroup.
INPUT:• parent – a SageMath parent• imag – an element of parent’s baseimag()
Return the imaginary part of this imaginary element.
EXAMPLES:
sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroupsage: J = ImaginaryGroup(ZZ)
sage: J(I).imag()˓→needs sage.symbolic1
sage: imag_part(J(I)) # indirect doctest
˓→needs sage.symbolic1>>> from sage.all import *>>> from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup>>> J = ImaginaryGroup(ZZ)>>> J(I).imag()˓→needs sage.symbolic1>>> imag_part(J(I)) # indirect doctest
˓→needs sage.symbolic
1

#␣

#␣

#␣

#␣

real()
Return the real part (= 0) of this imaginary element.
EXAMPLES:
sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroupsage: J = ImaginaryGroup(ZZ)
sage: J(I).real()
˓→needs sage.symbolic0
sage: real_part(J(I)) # indirect doctest
˓→needs sage.symbolic0>>> from sage.all import *>>> from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup>>> J = ImaginaryGroup(ZZ)>>> J(I).real()
˓→needs sage.symbolic0>>> real_part(J(I)) # indirect doctest

#␣

#␣

#␣

#␣

(continues on next page)

26.13. Groups of imaginary elements

405

Groups, Release 10.4

(continued from previous page)needs sage.symbolic˓→0class sage.groups.misc_gps.imaginary_groups.ImaginaryGroup(base, category)Bases: UniqueRepresentation, Parent
A group whose elements are purely imaginary.
INPUT:• base – a SageMath parent• category – a category
EXAMPLES:
sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroupsage: J = ImaginaryGroup(ZZ)
sage: J(0)0sage: J(imag=100)
100*I
sage: J(3*I)
˓→needs sage.symbolic
3*I
sage: J(1 + 2*I)
˓→needs sage.symbolic
Traceback (most recent call last):...
ValueError: 2*I + 1 is not in
Imaginary Group over Integer Ring
because it is not purely imaginary>>> from sage.all import *>>> from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup>>> J = ImaginaryGroup(ZZ)>>> J(Integer(0))
0>>> J(imag=Integer(100))
100*I>>> J(Integer(3)*I)˓→# needs sage.symbolic
3*I>>> J(Integer(1) + Integer(2)*I)˓→# needs sage.symbolic
Traceback (most recent call last):...
ValueError: 2*I + 1 is not in
Imaginary Group over Integer Ring
because it is not purely imaginary

#␣

#␣

␣

␣

Element
alias of ImaginaryElement

406

Chapter 26. Abelian Groups

CHAPTERTWENTYSEVENPERMUTATION GROUPS

27.1 Catalog of permutation groups
Type groups.permutation.<tab> to access examples of groups implemented as permutation groups.

27.2 Constructor for permutations
This module contains the generic constructor to build element of the symmetric groups (or more general permutationgroups) called PermutationGroupElement. These objects have a more group theoretic flavor than the more combinatorial Permutation.
sage.groups.perm_gps.constructor.PermutationGroupElement(g, parent=None, check=True)
Builds a permutation from g.
INPUT:• g – either– a list of images– a tuple describing a single cycle– a list of tuples describing the cycle decomposition– a string describing the cycle decomposition• parent – (optional) an ambient permutation group for the result; it is mandatory if you want a permutation
on a domain different from {1, . . . , 𝑛}
• check – (default: True) whether additional check are performed; setting it to False is likely to result infaster code
EXAMPLES:
Initialization as a list of images:
sage: p = PermutationGroupElement([1,4,2,3])
sage: p(2,4,3)sage: p.parent()
Symmetric group of order 4! as a permutation group407

Groups, Release 10.4>>> from sage.all import *>>> p = PermutationGroupElement([Integer(1),Integer(4),Integer(2),Integer(3)])>>> p(2,4,3)>>> p.parent()
Symmetric group of order 4! as a permutation group

Initialization as a list of cycles:
sage: p = PermutationGroupElement([(3,5),(4,6,9)])sage: p(3,5)(4,6,9)
sage: p.parent()
Symmetric group of order 9! as a permutation group>>> from sage.all import *>>> p = PermutationGroupElement([(Integer(3),Integer(5)),(Integer(4),Integer(6),˓→Integer(9))])>>> p(3,5)(4,6,9)>>> p.parent()
Symmetric group of order 9! as a permutation group

Initialization as a string representing a cycle decomposition:
sage: p = PermutationGroupElement( (2,4)(3,5) )sage: p(2,4)(3,5)
sage: p.parent()
Symmetric group of order 5! as a permutation group>>> from sage.all import *>>> p = PermutationGroupElement( (2,4)(3,5) )>>> p(2,4)(3,5)>>> p.parent()
Symmetric group of order 5! as a permutation group

By default the constructor assumes that the domain is {1, . . . , 𝑛} but it can be set to anything via its second parent
argument:
sage: S = SymmetricGroup([ a , b , c , d , e ])sage: PermutationGroupElement([ e , c , b , a , d ], S)( a , e , d )( b , c )sage: PermutationGroupElement(( a , b , c ), S)( a , b , c )sage: PermutationGroupElement([( a , c ), ( b , e )], S)( a , c )( b , e )sage: PermutationGroupElement("( a , b , e )( c , d )", S)( a , b , e )( c , d )>>> from sage.all import *>>> S = SymmetricGroup([ a , b ,>>> PermutationGroupElement([ e ,( a , e , d )( b , c )>>> PermutationGroupElement(( a ,

c ,
c ,

d ,
b ,

e ])
a , d ], S)b ,c ), S)(continues on next page)

408

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)( a , b , c )>>> PermutationGroupElement([( a , c ), ( b , e )], S)( a , c )( b , e )>>> PermutationGroupElement("( a , b , e )( c , d )", S)( a , b , e )( c , d )But in this situation, you might want to use the more direct:
sage: S([ e , c , b , a , d ])( a , e , d )( b , c )sage: S(( a , b , c ))( a , b , c )sage: S([( a , c ), ( b , e )])( a , c )( b , e )sage: S("( a , b , e )( c , d )")( a , b , e )( c , d )>>> from sage.all import *>>> S([ e , c , b , a , d ])( a , e , d )( b , c )>>> S(( a , b , c ))( a , b , c )>>> S([( a , c ), ( b , e )])( a , c )( b , e )>>> S("( a , b , e )( c , d )")( a , b , e )( c , d )sage.groups.perm_gps.constructor.standardize_generator(g, convert_dict=None,
as_cycles=False)Standardize the input for permutation group elements to a list or a list of tuples.
ThiswasfactoredoutofthePermutationGroupElement.__init__
since
PermutationGroup_generic.__init__ needs to do the same computation in order to computethe domain of a group when it’s not explicitly specified.
INPUT:• g – a list, tuple, string, GapElement, PermutationGroupElement, or Permutation• convert_dict – (optional) a dictionary used to convert the points to a number compatible with GAP• as_cycles – (default: False) whether the output should be as cycles or in one-line notation
OUTPUT: the permutation in as a list in one-line notation or a list of cycles as tuples.
EXAMPLES:
sage: from sage.groups.perm_gps.constructor import standardize_generator
sage: standardize_generator( (1,2) )[2, 1]
sage: p = PermutationGroupElement([(1,2)])
sage: standardize_generator(p)[2, 1]
sage: standardize_generator(p._gap_())[2, 1]
sage: standardize_generator((1,2))[2, 1](continues on next page)

27.2. Constructor for permutations

409

Groups, Release 10.4

(continued from previous page)

sage: standardize_generator([(1,2)])[2, 1]
sage: standardize_generator(p, as_cycles=True)[(1, 2)]sage: standardize_generator(p._gap_(), as_cycles=True)[(1, 2)]sage: standardize_generator((1,2), as_cycles=True)[(1, 2)]sage: standardize_generator([(1,2)], as_cycles=True)[(1, 2)]sage: standardize_generator(Permutation([2,1,3]))[2, 1, 3]
sage: standardize_generator(Permutation([2,1,3]), as_cycles=True)[(1, 2), (3,)]>>> from sage.all import *>>> from sage.groups.perm_gps.constructor import standardize_generator>>> standardize_generator( (1,2) )[2, 1]>>> p = PermutationGroupElement([(Integer(1),Integer(2))])>>> standardize_generator(p)[2, 1]>>> standardize_generator(p._gap_())[2, 1]>>> standardize_generator((Integer(1),Integer(2)))[2, 1]>>> standardize_generator([(Integer(1),Integer(2))])[2, 1]>>> standardize_generator(p, as_cycles=True)[(1, 2)]>>> standardize_generator(p._gap_(), as_cycles=True)[(1, 2)]>>> standardize_generator((Integer(1),Integer(2)), as_cycles=True)[(1, 2)]>>> standardize_generator([(Integer(1),Integer(2))], as_cycles=True)[(1, 2)]>>> standardize_generator(Permutation([Integer(2),Integer(1),Integer(3)]))[2, 1, 3]>>> standardize_generator(Permutation([Integer(2),Integer(1),Integer(3)]), as_
˓→cycles=True)[(1, 2), (3,)]
sage: d = { a : 1, b : 2}sage: p = SymmetricGroup([ a , b ]).gen(0); p( a , b )sage: standardize_generator(p, convert_dict=d)[2, 1]
sage: standardize_generator(p._gap_(), convert_dict=d)[2, 1]
sage: standardize_generator(( a , b ), convert_dict=d)[2, 1](continues on next page)

410

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: standardize_generator([( a , b )], convert_dict=d)[2, 1]
sage: standardize_generator(p, convert_dict=d, as_cycles=True)[(1, 2)]sage: standardize_generator(p._gap_(), convert_dict=d, as_cycles=True)[(1, 2)]sage: standardize_generator(( a , b ), convert_dict=d, as_cycles=True)[(1, 2)]sage: standardize_generator([( a , b )], convert_dict=d, as_cycles=True)[(1, 2)]>>> from sage.all import *>>> d = { a : Integer(1), b : Integer(2)}>>> p = SymmetricGroup([ a , b ]).gen(Integer(0)); p( a , b )>>> standardize_generator(p, convert_dict=d)[2, 1]>>> standardize_generator(p._gap_(), convert_dict=d)[2, 1]>>> standardize_generator(( a , b ), convert_dict=d)[2, 1]>>> standardize_generator([( a , b )], convert_dict=d)[2, 1]>>> standardize_generator(p, convert_dict=d, as_cycles=True)[(1, 2)]>>> standardize_generator(p._gap_(), convert_dict=d, as_cycles=True)[(1, 2)]>>> standardize_generator(( a , b ), convert_dict=d, as_cycles=True)[(1, 2)]>>> standardize_generator([( a , b )], convert_dict=d, as_cycles=True)[(1, 2)]sage.groups.perm_gps.constructor.string_to_tuples(g)EXAMPLES:
sage: from sage.groups.perm_gps.constructor import string_to_tuples
sage: string_to_tuples( (1,2,3) )[(1, 2, 3)]
sage: string_to_tuples( (1,2,3)(4,5) )[(1, 2, 3), (4, 5)]
sage: string_to_tuples( (1,2, 3) (4,5) )[(1, 2, 3), (4, 5)]
sage: string_to_tuples( (1,2)(3) )[(1, 2), (3,)]>>> from sage.all import *>>> from sage.groups.perm_gps.constructor import string_to_tuples>>> string_to_tuples( (1,2,3) )[(1, 2, 3)]>>> string_to_tuples( (1,2,3)(4,5) )[(1, 2, 3), (4, 5)]>>> string_to_tuples( (1,2, 3) (4,5) )[(1, 2, 3), (4, 5)]>>> string_to_tuples( (1,2)(3) )(continues on next page)

27.2. Constructor for permutations

411

Groups, Release 10.4

(continued from previous page)[(1, 2), (3,)]

27.3 Permutation groups
A permutation group is a finite group 𝐺 whose elements are permutations of a given finite set 𝑋 (i.e., bijections 𝑋 −→ 𝑋)
and whose group operation is the composition of permutations. The number of elements of 𝑋 is called the degree of 𝐺.
In Sage, a permutation is represented as either a string that defines a permutation using disjoint cycle notation, or a list oftuples, which represent disjoint cycles. That is:(a,...,b)(c,...,d)...(e,...,f) <--> [(a,...,b), (c,...,d),..., (e,...,f)]() = identity <--> []You can make the “named” permutation groups (see permgp_named.py) and use the following constructions:• permutation group generated by elements,• direct_product_permgroups, which takes a list of permutation groups and returns their direct product.
JOKE: Q: What’s hot, chunky, and acts on a polygon? A: Dihedral soup. Renteln, P. and Dundes, A. “Foolproof: A
Sampling of Mathematical Folk Humor.” Notices Amer. Math. Soc. 52, 24-34, 2005.

27.3.1 Index of methods
Here are the methods of a PermutationGroup()
as_finitely_presented_group()
blocks_all()cardinality()
center()centralizer()
character()character_table()cohomology()
cohomology_part()
commutator()
composition_series()
conjugacy_class()
conjugacy_classes()conjugacy_classes_representatives()
conjugacy_classes_subgroups()

Return a finitely presented group isomorphic to self.
Return the list of block systems of imprimitivity.
Return the number of elements of this group.
Return the subgroup of elements that commute with every element of this group.
Return the centralizer of g in self.
Return a group character from values, where values is a list of the values of
the character evaluated on the conjugacy classes.
Return the matrix of values of the irreducible characters of a permutation group
𝐺 at the conjugacy classes of 𝐺.
Computes the group cohomology 𝐻 𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0 and 𝐹 =/𝑝 if 𝑝 > 0 is a prime.
Compute the p-part of the group cohomology 𝐻 𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0
and 𝐹 = /𝑝 if 𝑝 > 0 is a prime.
Return the commutator subgroup of a group, or of a pair of groups.
Return the composition series of this group as a list of permutation groups.
Return the conjugacy class of g inside the group self.
Return a list with all the conjugacy classes of self.
Return a complete list of representatives of conjugacy classes in a permutationgroup 𝐺.
Return a complete list of representatives of conjugacy classes of subgroups in a
permutation group 𝐺.
continues on next page

412

Chapter 27. Permutation Groups

Groups, Release 10.4

Table 1 – continued from previous page
conjugate()
construction()
cosets()degree()derived_series()
direct_product()domain()exponent()
fitting_subgroup()
fixed_points()
frattini_subgroup()gen()
gens()
gens_small()group_id()
group_primitive_id()
has_element()
holomorph()
homology()

homology_part()

id()
intersection()
irreducible_characters()
is_cyclic()
is_elementary_abelian()
is_isomorphic()
is_monomial()
is_nilpotent()
is_normal()
is_perfect()is_pgroup()
is_polycyclic()

is_primitive()
is_regular()is_semi_regular()is_simple()
is_solvable()is_subgroup()
is_supersolvable()

27.3. Permutation groups

Return the group formed by conjugating self with g.
Return the construction of self.
Return a list of the cosets of S in self.
Return the degree of this permutation group.
Return the derived series of this group as a list of permutation groups.
Wraps GAP’s DirectProduct, Embedding, and Projection.
Return the underlying set that this permutation group acts on.
Computes the exponent of the group.
Return the Fitting subgroup of self.
Return the list of points fixed by self, i.e., the subset of .domain() not moved
by any element of self.
Return the Frattini subgroup of self.
Return the 𝑖-th generator of self; that is, the 𝑖-th element of the list self.
gens().
Return tuple of generators of this group.
For this group, returns a generating set which has few elements.
Return the ID code of this group, which is a list of two integers.
Return the index of this group in the GAP database of primitive groups.
Return whether item is an element of this group - however ignores parentage.
The holomorph of a group as a permutation group.
Computes the group homology 𝐻𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0 and 𝐹 =/𝑝 if 𝑝 > 0 is a prime. Wraps HAP’s GroupHomology function, written by
Graham Ellis.
Computes the 𝑝-part of the group homology 𝐻𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0
and 𝐹 = /𝑝 if 𝑝 > 0 is a prime. Wraps HAP’s Homology function, written
by Graham Ellis, applied to the 𝑝-Sylow subgroup of 𝐺.
Return the ID code of this group, which is a list of two integers.
Return the permutation group that is the intersection of self and other.
Return a list of the irreducible characters of self.
Return True if this group is cyclic.
Return True if this group is elementary abelian. An elementary abelian groupis a finite abelian group, where every nontrivial element has order 𝑝, where 𝑝 is aprime.
Return True if the groups are isomorphic.
Return True if the group is monomial. A finite group is monomial if every irreducible complex character is induced from a linear character of a subgroup.
Return True if this group is nilpotent.
Return True if this group is a normal subgroup of other.
Return True if this group is perfect. A group is perfect if it equals its derived
subgroup.
Return True if this group is a 𝑝-group.
Return True if this group is polycyclic. A group is polycyclic if it has a subnormal
series with cyclic factors. (For finite groups, this is the same as if the group issolvable - see is_solvable().)
Return True if self acts primitively on domain.
Return True if self acts regularly on domain.
Return True if self acts semi-regularly on domain.
Return True if the group is simple.
Return True if the group is solvable.
Return True if self is a subgroup of other.
Return True if the group is supersolvable.
continues on next page413

Groups, Release 10.4

Table 1 – continued from previous pageis_transitive()
isomorphism_to()isomorphism_type_info_simple_group()
iteration()largest_moved_point()
list()
lower_central_series()
maximal_normal_subgroups()
minimal_generating_set()
minimal_normal_subgroups()
molien_series()
ngens()
non_fixed_points()
normal_subgroups()
normalizer()
normalizes()
poincare_series()
random_element()
representative_action()semidirect_product()
sign_representation()
socle()
solvable_radical()stabilizer()strong_generating_system()structure_description()subgroup()
subgroups()sylow_subgroup()transversals()trivial_character()upper_central_series()

414

Return True if self acts transitively on domain.
Return an isomorphism from self to right if the groups are isomorphic, otherwise None.
If the group is simple, then this returns the name of the group.

Return an iterator over the elements of this group.
Return the largest point moved by a permutation in this group.
Return list of all elements of this group.
Return the lower central series of this group as a list of permutation groups.
Return the maximal proper normal subgroups of self.
Return a minimal generating set
Return the nontrivial minimal normal subgroups self.
Return the Molien series of a permutation group. The function
Return the number of generators of self.
Return the list of points not fixed by self, i.e., the subset of self.domain()
moved by some element of self.
Return the normal subgroups of this group as a (sorted in increasing order) list of
permutation groups.
Return the normalizer of g in self.
Return True if the group other is normalized by self.
Return the Poincaré series of 𝐺 mod 𝑝 (𝑝 ≥ 2 must be a prime), for 𝑛 large.
Return a random element of this group.
Return an element of self that maps 𝑥 to 𝑦 if it exists.
The semidirect product of self with N.
Return the sign representation of self over base_ring.
Return the socle of self.
Return the solvable radical of self.
Return the subgroup of self which stabilize the given position. self and its
stabilizers must have same degree.
Return a Strong Generating System of self according the given base for the rightaction of self on itself.
Return a string that tries to describe the structure of G.
Wraps the PermutationGroup_subgroup constructor. The argument
gens is a list of elements of self.
Return a list of all the subgroups of self.
Return a Sylow 𝑝-subgroup of the finite group 𝐺, where 𝑝 is a prime.
If G is a permutation group acting on the set 𝑋 = {1, 2, ...., 𝑛} and H is thestabilizer subgroup of <integer>, a right (respectively left) transversal is a set containing exactly one element from each right (respectively left) coset of H. Thismethod returns a right transversal of self by the stabilizer of self on <integer> position.
Return the trivial character of self.
Return the upper central series of this group as a list of permutation groups.

Chapter 27. Permutation Groups

Groups, Release 10.4

AUTHORS:• David Joyner (2005-10-14): first version• David Joyner (2005-11-17)• William Stein (2005-11-26): rewrite to better wrap Gap• David Joyner (2005-12-21)• William Stein and David Joyner (2006-01-04): added conjugacy_class_representatives• David Joyner (2006-03): reorganization into subdirectory perm_gps; added __contains__, has_element; fixed_cmp_; added subgroup class+methods, PGL,PSL,PSp, PSU classes,• David Joyner (2006-06): added PGU, functionality to SymmetricGroup, AlternatingGroup, direct_product_permgroups• David Joyner (2006-08): added degree, ramification_module_decomposition_modular_curve and ramification_module_decomposition_hurwitz_curve methods to PSL(2,q), MathieuGroup, is_isomorphic• Bobby Moretti (2006)-10): Added KleinFourGroup, fixed bug in DihedralGroup• David Joyner (2006-10): added is_subgroup (fixing a bug found by Kiran Kedlaya), is_solvable, normalizer, is_normal_subgroup, Suzuki• David Kohel (2007-02): fixed __contains__ to not enumerate group elements, following the convention for __call__• David Harvey, Mike Hansen, Nick Alexander, William Stein (2007-02,03,04,05): Various patches• Nathan Dunfield (2007-05): added orbits• David Joyner (2007-06): added subgroup method (suggested by David Kohel), composition_series, lower_central_series, upper_central_series, cayley_table, quotient_group, sylow_subgroup, is_cyclic, homology, homology_part, cohomology, cohomology_part, poincare_series, molien_series, is_simple, is_monomial, is_supersolvable, is_nilpotent, is_perfect, is_polycyclic, is_elementary_abelian, is_pgroup, gens_small, isomorphism_type_info_simple_group. moved all the”named” groups to a new file.
• Nick Alexander (2007-07): move is_isomorphic to isomorphism_to, add from_gap_list• William Stein (2007-07): put is_isomorphic back (and make it better)• David Joyner (2007-08): fixed bugs in composition_series, upper/lower_central_series, derived_series,• David Joyner (2008-06): modified is_normal (reported by W. J. Palenstijn), and added normalizes• David Joyner (2008-08): Added example to docstring of cohomology.
• Simon King (2009-04): __cmp__ methods for PermutationGroup_generic and PermutationGroup_subgroup• Nicolas Borie (2009): Added orbit, transversals, stabiliser and strong_generating_system methods• Christopher Swenson (2012): Added a special case to compute the order efficiently. (This patch Copyright 2012
Google Inc. All Rights Reserved. )• Javier Lopez Pena (2013): Added conjugacy classes.
• Sebastian Oehms (2018): added _coerce_map_from_ in order to use isomorphism coming up with as_permutation_group method (Issue #25706)• Christian Stump (2018): Added alternative implementation of strong_generating_system directly using GAP.
• Sebastian Oehms (2018): Added PermutationGroup_generic._Hom_() to use sage.groups.
libgap_morphism.GroupHomset_libgap and PermutationGroup_generic.gap() andPermutationGroup_generic._subgroup_constructor() (for compatibility to libgap framework,see Issue #26750

27.3. Permutation groups

415

Groups, Release 10.4

REFERENCES:• Cameron, P., Permutation Groups. New York: Cambridge University Press, 1999.
• Wielandt, H., Finite Permutation Groups. New York: Academic Press, 1964.
• Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996.
Note: Though Suzuki groups are okay, Ree groups should not be wrapped as permutation groups - the construction is
too slow - unless (for small values or the parameter) they are made using explicit generators.
sage.groups.perm_gps.permgroup.PermutationGroup(gens=None, *args, **kwds)
Return the permutation group associated to 𝑥 (typically a list of generators).
INPUT:• gens – (default: None) list of generators• gap_group – (optional) a gap permutation group• canonicalize – boolean (default: True); if True, sort generators and remove duplicates
OUTPUT: a permutation group
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G
Permutation Group with generators [(3,4), (1,2,3)(4,5)]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G
Permutation Group with generators [(3,4), (1,2,3)(4,5)]

We can also make permutation groups from PARI groups:
sage: # needs sage.libs.pari
sage: H = pari( x^4 - 2*x^3 - 2*x + 1 ).polgalois()
sage: G = PariGroup(H, 4); G
PARI group [8, -1, 3, "D(4)"] of degree 4
sage: H = PermutationGroup(G); H
Transitive group number 3 of degree 4
sage: H.gens()((1,2,3,4), (1,3))>>> from sage.all import *>>> # needs sage.libs.pari>>> H = pari( x^4 - 2*x^3 - 2*x + 1 ).polgalois()>>> G = PariGroup(H, Integer(4)); G
PARI group [8, -1, 3, "D(4)"] of degree 4>>> H = PermutationGroup(G); H
Transitive group number 3 of degree 4>>> H.gens()((1,2,3,4), (1,3))

We can also create permutation groups whose generators are GAP permutation objects:

416

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: p = gap( (1,2)(3,7)(4,6)(5,8) ); p(1,2)(3,7)(4,6)(5,8)
sage: PermutationGroup([p])
Permutation Group with generators [(1,2)(3,7)(4,6)(5,8)]>>> from sage.all import *>>> p = gap( (1,2)(3,7)(4,6)(5,8) ); p(1,2)(3,7)(4,6)(5,8)>>> PermutationGroup([p])
Permutation Group with generators [(1,2)(3,7)(4,6)(5,8)]

Permutation groups can work on any domain. In the following examples, the permutations are specified in list
notation, according to the order of the elements of the domain:
sage: list(PermutationGroup([[ b , c , a ]], domain=[ a , b , c ]))[(), ( a , b , c ), ( a , c , b )]sage: list(PermutationGroup([[ b , c , a ]], domain=[ b , c , a ]))[()]sage: list(PermutationGroup([[ b , c , a ]], domain=[ a , c , b ]))[(), ( a , b )]>>> from sage.all import *>>> list(PermutationGroup([[ b , c , a ]], domain=[ a , b , c ]))[(), ( a , b , c ), ( a , c , b )]>>> list(PermutationGroup([[ b , c , a ]], domain=[ b , c , a ]))[()]>>> list(PermutationGroup([[ b , c , a ]], domain=[ a , c , b ]))[(), ( a , b )]There is an underlying gap object that implements each permutation group:sage: G = PermutationGroup([[(1,2,3,4)]])sage: G._gap_()
Group( [ (1,2,3,4) ] )sage: gap(G)Group( [ (1,2,3,4) ] )sage: gap(G) is G._gap_()
True
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: current_randstate().set_seed_gap()
sage: G1, G2 = G._gap_().DerivedSeries()
sage: G1
Group( [ (3,4), (1,2,3)(4,5) ] )sage: G2.GeneratorsSmallest()[ (3,4,5), (2,3)(4,5), (1,2)(4,5) ]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> G._gap_()
Group( [ (1,2,3,4) ] )>>> gap(G)Group( [ (1,2,3,4) ] )>>> gap(G) is G._gap_()
True>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])(continues on next page)

27.3. Permutation groups

417

Groups, Release 10.4

(continued from previous page)>>> current_randstate().set_seed_gap()>>> G1, G2 = G._gap_().DerivedSeries()>>> G1
Group( [ (3,4), (1,2,3)(4,5) ] )>>> G2.GeneratorsSmallest()[ (3,4,5), (2,3)(4,5), (1,2)(4,5) ]We can create a permutation group from a group action:
sage: a = lambda x: (2*x) % 7
sage: H = PermutationGroup(action=a, domain=range(7))˓→needs sage.combinat
sage: H.orbits()
˓→needs sage.libs.pari((0,), (1, 2, 4), (3, 6, 5))
sage: H.gens()
˓→needs sage.libs.pari((1,2,4), (3,6,5))

#␣
#␣

#␣

>>> from sage.all import *>>> a = lambda x: (Integer(2)*x) % Integer(7)>>> H = PermutationGroup(action=a, domain=range(Integer(7)))˓→# needs sage.combinat>>> H.orbits()
˓→needs sage.libs.pari((0,), (1, 2, 4), (3, 6, 5))>>> H.gens()
˓→needs sage.libs.pari((1,2,4), (3,6,5))

␣
#␣

#␣

Note that we provide generators for the acting group. The permutation group we construct is its homomorphic
image:
sage: # needs sage.combinat
sage: a = lambda g, x: vector(g*x, immutable=True)
sage: X = [vector(x, immutable=True) for x in GF(3)^2]
sage: G = SL(2,3); G.gens()([1 1] [0 1][0 1], [2 0])sage: H = PermutationGroup(G.gens(), action=a, domain=X)
sage: H.orbits()(((0, 0),), ((1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)))sage: H.gens()(((0,1),(1,1),(2,1))((0,2),(2,2),(1,2)),((1,0),(0,2),(2,0),(0,1))((1,1),(1,2),(2,2),(2,1)))>>> from sage.all import *>>> # needs sage.combinat>>> a = lambda g, x: vector(g*x, immutable=True)>>> X = [vector(x, immutable=True) for x in GF(Integer(3))**Integer(2)]>>> G = SL(Integer(2),Integer(3)); G.gens()([1 1] [0 1][0 1], [2 0](continues on next page)

418

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page))>>> H = PermutationGroup(G.gens(), action=a, domain=X)>>> H.orbits()(((0, 0),), ((1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)))>>> H.gens()(((0,1),(1,1),(2,1))((0,2),(2,2),(1,2)),((1,0),(0,2),(2,0),(0,1))((1,1),(1,2),(2,2),(2,1)))The orbits of the conjugation action are the conjugacy classes, i.e., in bijection with integer partitions:sage: a = lambda g, x: g*x*g^-1
sage: [len(PermutationGroup(SymmetricGroup(n).gens(), action=a,
˓→needs sage.combinat....:
domain=SymmetricGroup(n)).orbits())....: for n in range(1, 8)][1, 2, 3, 5, 7, 11, 15]#␣>>> from sage.all import *>>> a = lambda g, x: g*x*g**-Integer(1)>>> [len(PermutationGroup(SymmetricGroup(n).gens(), action=a,
˓→needs sage.combinat...
domain=SymmetricGroup(n)).orbits())... for n in range(Integer(1), Integer(8))][1, 2, 3, 5, 7, 11, 15]#␣class sage.groups.perm_gps.permgroup.PermutationGroup_action(gens, action, domain,
gap_group=None,
category=None,
canonicalize=None)
Bases: PermutationGroup_genericA permutation group given by a finite group action.
EXAMPLES:
A cyclic action:
sage: n = 3
sage: a = lambda x: SetPartition([[e % n + 1 for e in b] for b in x])
sage: S = SetPartitions(n)˓→needs sage.combinat
sage: G = PermutationGroup(action=a, domain=S)
˓→needs sage.combinat
sage: G.orbits()
˓→needs sage.combinat(({{1}, {2}, {3}},),({{1, 2}, {3}}, {{1}, {2, 3}}, {{1, 3}, {2}}),({{1, 2, 3}},))>>> from sage.all import *>>> n = Integer(3)>>> a = lambda x: SetPartition([[e % n + Integer(1) for e in b] for b in x])>>> S = SetPartitions(n)˓→needs sage.combinat>>> G = PermutationGroup(action=a, domain=S)
˓→needs sage.combinat

#␣
#␣
#␣

#␣
#␣

(continues on next page)

27.3. Permutation groups419

Groups, Release 10.4

(continued from previous page)>>> G.orbits()
˓→needs sage.combinat(({{1}, {2}, {3}},),({{1, 2}, {3}}, {{1}, {2, 3}}, {{1, 3}, {2}}),({{1, 2, 3}},))#␣The regular action of the symmetric group:sage: a = lambda g, x: g*x*g^-1
sage: S = SymmetricGroup(3)sage: G = PermutationGroup(S.gens(), action=a, domain=S)
˓→needs sage.combinat
sage: G.orbits()
˓→needs sage.combinat(((),), ((1,3,2), (1,2,3)), ((2,3), (1,3), (1,2)))>>> from sage.all import *>>> a = lambda g, x: g*x*g**-Integer(1)>>> S = SymmetricGroup(Integer(3))>>> G = PermutationGroup(S.gens(), action=a, domain=S)
˓→needs sage.combinat>>> G.orbits()
˓→needs sage.combinat(((),), ((1,3,2), (1,2,3)), ((2,3), (1,3), (1,2)))

#␣
#␣

#␣
#␣

The trivial action of the symmetric group:sage: PermutationGroup(SymmetricGroup(3).gens(),
˓→needs sage.combinat....:
action=lambda g, x: x, domain=[1])Permutation Group with generators [()]

#␣>>> from sage.all import *>>> PermutationGroup(SymmetricGroup(Integer(3)).gens(),˓→# needs sage.combinat...
action=lambda g, x: x, domain=[Integer(1)])
Permutation Group with generators [()]

␣

orbits()Returns the orbits of the elements of the domain under the default group action.
EXAMPLES:
sage: a = lambda x: (2*x) % 7
sage: G = PermutationGroup(action=a, domain=range(7))˓→needs sage.combinat
sage: G.orbits()
˓→needs sage.combinat((0,), (1, 2, 4), (3, 6, 5))>>> from sage.all import *>>> a = lambda x: (Integer(2)*x) % Integer(7)>>> G = PermutationGroup(action=a, domain=range(Integer(7)))˓→# needs sage.combinat>>> G.orbits()

#␣
#␣

␣
#␣
(continues on next page)

420

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)needs sage.combinat((0,), (1, 2, 4), (3, 6, 5))˓→class sage.groups.perm_gps.permgroup.PermutationGroup_generic(gens=None,
gap_group=None,
canonicalize=True,
domain=None,
category=None)
Bases: FiniteGroupA generic permutation group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G
Permutation Group with generators [(3,4), (1,2,3)(4,5)]
sage: G.center()
Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])
sage: G.group_id()[120, 34]
sage: n = G.order(); n120
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: TestSuite(G).run()>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G
Permutation Group with generators [(3,4), (1,2,3)(4,5)]>>> G.center()
Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])>>> G.group_id()[120, 34]>>> n = G.order(); n120>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> TestSuite(G).run()

Element
alias of PermutationGroupElement
Subgroup
alias of PermutationGroup_subgroup
as_finitely_presented_group(reduced=False)
Return a finitely presented group isomorphic to self.
This method acts as wrapper for the GAP function IsomorphismFpGroupByGenerators, whichyields an isomorphism from a given group to a finitely presented group.
INPUT:

27.3. Permutation groups421

Groups, Release 10.4

• reduced – (default False) if True, FinitelyPresentedGroup.simplified is called, attempting to simplify the presentation of the finitely presented group to be returned.
OUTPUT: finite presentation of self, obtained by taking the image of the isomorphism returned by the
GAP function IsomorphismFpGroupByGenerators
ALGORITHM:
Uses GAP.
EXAMPLES:
sage: CyclicPermutationGroup(50).as_finitely_presented_group()
Finitely presented group < a | a^50 >sage: DihedralGroup(4).as_finitely_presented_group()
Finitely presented group < a, b | b^2, a^4, (b*a)^2 >sage: GeneralDihedralGroup([2,2]).as_finitely_presented_group()
Finitely presented group < a, b, c | a^2, b^2, c^2, (c*b)^2, (c*a)^2, (b*a)^2␣˓→>>>> from sage.all import *>>> CyclicPermutationGroup(Integer(50)).as_finitely_presented_group()
Finitely presented group < a | a^50 >>>> DihedralGroup(Integer(4)).as_finitely_presented_group()
Finitely presented group < a, b | b^2, a^4, (b*a)^2 >>>> GeneralDihedralGroup([Integer(2),Integer(2)]).as_finitely_presented_
˓→group()
Finitely presented group < a, b, c | a^2, b^2, c^2, (c*b)^2, (c*a)^2, (b*a)^2␣˓→>

GAP algorithm is not guaranteed to produce minimal or canonical presentation:
sage: G = PermutationGroup([ (1,2,3,4,5) , (1,5)(2,4) ])sage: G.is_isomorphic(DihedralGroup(5))
True
sage: K = G.as_finitely_presented_group(); K
Finitely presented group < a, b | b^2, (b*a)^2, b*a^-3*b*a^2 >sage: K.as_permutation_group().is_isomorphic(DihedralGroup(5))
True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3,4,5) , (1,5)(2,4) ])>>> G.is_isomorphic(DihedralGroup(Integer(5)))
True>>> K = G.as_finitely_presented_group(); K
Finitely presented group < a, b | b^2, (b*a)^2, b*a^-3*b*a^2 >>>> K.as_permutation_group().is_isomorphic(DihedralGroup(Integer(5)))
True

We can attempt to reduce the output presentation:
sage: H = PermutationGroup([ (1,2,3,4,5) , (1,3,5,2,4) ])sage: H.as_finitely_presented_group()
Finitely presented group < a, b | b^-2*a^-1, b*a^-2 >sage: H.as_finitely_presented_group(reduced=True)
Finitely presented group < a | a^5 >422

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> H = PermutationGroup([ (1,2,3,4,5) , (1,3,5,2,4) ])>>> H.as_finitely_presented_group()
Finitely presented group < a, b | b^-2*a^-1, b*a^-2 >>>> H.as_finitely_presented_group(reduced=True)
Finitely presented group < a | a^5 >AUTHORS:• Davis Shurbert (2013-06-21): initial versionbase(seed=None)
Return a (minimum) base of this permutation group.
A base 𝐵 of a permutation group is a subset of the domain of the group such that the only group element
stabilizing all of 𝐵 is the identity.
INPUT:• seed (default: None), if given must be a subset of the domain of a base. When used, an attempt tocreate a base containing all or part of seed will be made.
EXAMPLES:
sage: G = PermutationGroup([(1,2,3),(6,7,8)])
sage: G.base()[1, 6]
sage: G.base([2])[2, 6]
sage: H = PermutationGroup([( a , b , c ),( a , y )])sage: H.base()[ a , b , c ]sage: S = SymmetricGroup(13)sage: S.base()[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
sage: S = MathieuGroup(12)sage: S.base()[1, 2, 3, 4, 5]
sage: S.base([1,3,5,7,9,11]) # create a base for M12 with only odd integers[1, 3, 5, 7, 9]>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)),(Integer(6),˓→Integer(7),Integer(8))])>>> G.base()[1, 6]>>> G.base([Integer(2)])[2, 6]>>> H = PermutationGroup([( a , b , c ),( a , y )])>>> H.base()[ a , b , c ]>>> S = SymmetricGroup(Integer(13))>>> S.base()[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12](continues on next page)

27.3. Permutation groups423

Groups, Release 10.4

(continued from previous page)>>> S = MathieuGroup(Integer(12))>>> S.base()[1, 2, 3, 4, 5]>>> S.base([Integer(1),Integer(3),Integer(5),Integer(7),Integer(9),˓→Integer(11)]) # create a base for M12 with only odd integers[1, 3, 5, 7, 9]

blocks_all(representatives=True)
Return the list of block systems of imprimitivity.
For more information on primitivity, see the Wikipedia article on primitive group actions.
INPUT:• representative – (boolean) whether to return all possible block systems of imprimitivity or only
one of their representatives (the block can be obtained from its representative set 𝑆 by computing theorbit of 𝑆 under self).
This parameter is set to True by default (as it is GAP’s default behaviour).
OUTPUT:
This method returns a description of all block systems. Hence, the output is a “list of lists of lists” or a “listof lists” depending on the value of representatives. A bit more clearly, output is:• A list of length (#number of different block systems) of– block systems, each of them being defined as∗ If representatives=True: a list of representatives of each set of the block system∗ If representatives=False: a partition of the elements defining an imprimitivity block.
See also:• is_primitive()
EXAMPLES:
Picking an interesting group:sage: # needs sage.graphs
sage: g = graphs.DodecahedralGraph()
sage: g.is_vertex_transitive()
True
sage: ag = g.automorphism_group()
sage: ag.is_primitive()
False>>> from sage.all import *>>> # needs sage.graphs>>> g = graphs.DodecahedralGraph()>>> g.is_vertex_transitive()
True>>> ag = g.automorphism_group()>>> ag.is_primitive()
False

Computing its blocks representatives:

424

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: ag.blocks_all()˓→needs sage.graphs[[0, 15]]>>> from sage.all import *>>> ag.blocks_all()˓→needs sage.graphs[[0, 15]]#␣#␣

Now the full block:
sage: sorted(ag.blocks_all(representatives=False)[0])˓→needs sage.graphs[[0, 15], [1, 16], [2, 12], [3, 13], [4, 9],[5, 10], [6, 11], [7, 18], [8, 17], [14, 19]]>>> from sage.all import *>>> sorted(ag.blocks_all(representatives=False)[Integer(0)])˓→# needs sage.graphs[[0, 15], [1, 16], [2, 12], [3, 13], [4, 9],[5, 10], [6, 11], [7, 18], [8, 17], [14, 19]]#␣␣cardinality()
Return the number of elements of this group.
See also: degree().
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: G.order()12sage: G = PermutationGroup([()])
sage: G.order()1sage: G = PermutationGroup([])
sage: G.order()1>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> G.order()12>>> G = PermutationGroup([()])>>> G.order()1>>> G = PermutationGroup([])>>> G.order()1cardinality() is just an alias:
sage: PermutationGroup([(1,2,3)]).cardinality()3

27.3. Permutation groups425

Groups, Release 10.4>>> from sage.all import *>>> PermutationGroup([(Integer(1),Integer(2),Integer(3))]).cardinality()
3

center()Return the subgroup of elements that commute with every element of this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)]])sage: G.center()
Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2,3,4)])
sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])sage: G.center()
Subgroup generated by [()] of(Permutation Group with generators [(1,2), (1,2,3,4)])>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> G.center()
Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2,3,4)])>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2))]])>>> G.center()
Subgroup generated by [()] of(Permutation Group with generators [(1,2), (1,2,3,4)])

centralizer(g)Return the centralizer of g in self.
EXAMPLES:
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: g = G([(1,3)])
sage: G.centralizer(g)Subgroup generated by [(1,3), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])
sage: g = G([(1,2,3,4)])
sage: G.centralizer(g)Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])
sage: H = G.subgroup([G([(1,2,3,4)])])
sage: G.centralizer(H)Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> g = G([(Integer(1),Integer(3))])>>> G.centralizer(g)Subgroup generated by [(1,3), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))])>>> G.centralizer(g)(continues on next page)

426

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> H = G.subgroup([G([(Integer(1),Integer(2),Integer(3),Integer(4))])])>>> G.centralizer(H)Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])character(values)
Return a group character from values, where values is a list of the values of the character evaluated on
the conjugacy classes.
EXAMPLES:
sage: G = AlternatingGroup(4)sage: n = len(G.conjugacy_classes_representatives())
sage: G.character([1]*n)˓→needs sage.rings.number_field
Character of Alternating group of order 4!/2 as a permutation group>>> from sage.all import *>>> G = AlternatingGroup(Integer(4))>>> n = len(G.conjugacy_classes_representatives())>>> G.character([Integer(1)]*n)˓→# needs sage.rings.number_field
Character of Alternating group of order 4!/2 as a permutation group#␣␣character_table()
Return the matrix of values of the irreducible characters of a permutation group 𝐺 at the conjugacy classesof 𝐺.
The columns represent the conjugacy classes of 𝐺 and the rows represent the different irreducible charactersin the ordering given by GAP.
EXAMPLES:
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3)]])sage: G.order()12sage: G.character_table()
˓→needs sage.rings.number_field
[
1
1
1
1]
[
1 -zeta3 - 1
zeta3
1]
[
1
zeta3 -zeta3 - 1
1]
[
3
0
0
-1]
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3)]])sage: CT = gap(G).CharacterTable()#␣>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3))]])>>> G.order()12>>> G.character_table()#␣˓→needs sage.rings.number_field
[
1
1
1
1]
[
1 -zeta3 - 1
zeta31](continues on next page)

27.3. Permutation groups427

Groups, Release 10.4

(continued from previous page)[1
zeta3 -zeta3 - 1
1]
[
3
0
0
-1]
>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3))]])>>> CT = gap(G).CharacterTable()Type CT.Display() to display this nicely.
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: G.order()8sage: G.character_table()
˓→needs sage.rings.number_field[ 1 1 1 1 1]
[ 1 -1 -1 1 1]
[ 1 -1 1 -1 1][ 1 1 -1 -1 1][ 2 0 0 0 -2]
sage: CT = gap(G).CharacterTable()#␣>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> G.order()8>>> G.character_table()#␣˓→needs sage.rings.number_field[ 1 1 1 1 1]
[ 1 -1 -1 1 1]
[ 1 -1 1 -1 1][ 1 1 -1 -1 1][ 2 0 0 0 -2]>>> CT = gap(G).CharacterTable()

Again, type CT.Display() to display this nicely.
sage: # needs sage.rings.number_fieldsage: SymmetricGroup(2).character_table()[ 1 -1][ 1 1]
sage: SymmetricGroup(3).character_table()[ 1 -1 1][ 2 0 -1]
[ 1 1 1]
sage: SymmetricGroup(5).character_table()[ 1 -1 1 1 -1 -1 1][ 4 -2 0 1 1 0 -1][ 5 -1 1 -1 -1 1 0]
[ 6 0 -2 0 0 0 1]
[ 5 1 1 -1 1 -1 0][ 4 2 0 1 -1 0 -1][ 1 1 1 1 1 1 1]
sage: list(AlternatingGroup(6).character_table())[(1, 1, 1, 1, 1, 1, 1), (5, 1, 2, -1, -1, 0, 0), (5, 1, -1, 2, -1, 0, 0),(8, 0, -1, -1, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2),(8, 0, -1, -1, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1),(9, 1, 0, 0, 1, -1, -1), (10, -2, 1, 1, 0, 0, 0)]428

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.rings.number_field>>> SymmetricGroup(Integer(2)).character_table()[ 1 -1][ 1 1]>>> SymmetricGroup(Integer(3)).character_table()[ 1 -1 1][ 2 0 -1]
[ 1 1 1]>>> SymmetricGroup(Integer(5)).character_table()[ 1 -1 1 1 -1 -1 1][ 4 -2 0 1 1 0 -1][ 5 -1 1 -1 -1 1 0]
[ 6 0 -2 0 0 0 1]
[ 5 1 1 -1 1 -1 0][ 4 2 0 1 -1 0 -1][ 1 1 1 1 1 1 1]>>> list(AlternatingGroup(Integer(6)).character_table())[(1, 1, 1, 1, 1, 1, 1), (5, 1, 2, -1, -1, 0, 0), (5, 1, -1, 2, -1, 0, 0),(8, 0, -1, -1, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2),(8, 0, -1, -1, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1),(9, 1, 0, 0, 1, -1, -1), (10, -2, 1, 1, 0, 0, 0)]

Suppose that you have a class function 𝑓 (𝑔) on 𝐺 and you know the values 𝑣1 , . . . , 𝑣𝑛 on the conjugacy class elements in conjugacy_classes_representatives(G) = [𝑔1 , . . . , 𝑔𝑛 ]. Since the irreducible characters 𝜌1 , . . . , 𝜌𝑛 of 𝐺 form an 𝐸-basis of the space of all class functions (𝐸 a “sufficiently large” cyclotomic
field), such a class function is a linear combination of these basis elements, 𝑓 = 𝑐1 𝜌1 + · · · + 𝑐𝑛 𝜌𝑛 . To findthe coefficients 𝑐𝑖 , you simply solve the linear system character_table_values(G) [𝑣1 , ..., 𝑣𝑛 ] =[𝑐1 , ..., 𝑐𝑛 ], where [𝑣1 , . . . , 𝑣𝑛 ] = character_table_values(G) (−1) [𝑐1 , ..., 𝑐𝑛 ].
AUTHORS:• David Joyner and William Stein (2006-01-04)
cohomology(n, p=0)
Computes the group cohomology 𝐻 𝑛 (𝐺, 𝐹 ), where 𝐹 =if 𝑝 = 0 and 𝐹 = /𝑝 if 𝑝 > 0 is a prime.

Wraps HAP’s GroupHomology function, written by Graham Ellis.
REQUIRES: GAP package HAP (in gap_packages-*.spkg).
EXAMPLES:
sage: G = SymmetricGroup(4)sage: G.cohomology(1,2)
˓→hapMultiplicative Abelian group isomorphic to C2
sage: G = SymmetricGroup(3)sage: G.cohomology(5)˓→hapTrivial Abelian group
sage: G.cohomology(5,2)
˓→hapMultiplicative Abelian group isomorphic to C2
sage: G.homology(5,3)
˓→hapTrivial Abelian group
sage: G.homology(5,4)
˓→hap# optional - gap_package_# optional - gap_package_# optional - gap_package_# optional - gap_package_# optional - gap_package_(continues on next page)

27.3. Permutation groups429

Groups, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: p must be 0 or prime>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> G.cohomology(Integer(1),Integer(2))˓→- gap_package_hap
Multiplicative Abelian group isomorphic to C2>>> G = SymmetricGroup(Integer(3))>>> G.cohomology(Integer(5))˓→package_hap
Trivial Abelian group>>> G.cohomology(Integer(5),Integer(2))˓→- gap_package_hap
Multiplicative Abelian group isomorphic to C2>>> G.homology(Integer(5),Integer(3))˓→- gap_package_hap
Trivial Abelian group>>> G.homology(Integer(5),Integer(4))˓→- gap_package_hap
Traceback (most recent call last):...
ValueError: p must be 0 or prime# optional␣

# optional - gap_

# optional␣

# optional␣

# optional␣

This computes 𝐻 4 (𝑆3 , ) and 𝐻 4 (𝑆3 , /2 ), respectively.
AUTHORS:• David Joyner and Graham Ellis
REFERENCES:• G. Ellis, ‘Computing group resolutions’, J. Symbolic Computation. Vol.38, (2004)1077-1118 (Available
at http://hamilton.nuigalway.ie/).
• D. Joyner, ‘A primer on computational group homology and cohomology’, http://front.math.ucdavis.
edu/0706.0549.
cohomology_part(n, p=0)
Compute the p-part of the group cohomology 𝐻 𝑛 (𝐺, 𝐹 ), where 𝐹 =a prime.

if 𝑝 = 0 and 𝐹 = /𝑝 if 𝑝 > 0 is

Wraps HAP’s Homology function, written by Graham Ellis, applied to the 𝑝-Sylow subgroup of 𝐺.
REQUIRES: GAP package HAP (in gap_packages-*.spkg).
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.cohomology_part(7,2)# optional - gap_package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C2
sage: G = SymmetricGroup(3)sage: G.cohomology_part(2,3)# optional - gap_package_hap
Multiplicative Abelian group isomorphic to C3>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))(continues on next page)

430

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G.cohomology_part(Integer(7),Integer(2))˓→gap_package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C2>>> G = SymmetricGroup(Integer(3))>>> G.cohomology_part(Integer(2),Integer(3))˓→gap_package_hap
Multiplicative Abelian group isomorphic to C3# optional -␣# optional -␣

AUTHORS:• David Joyner and Graham Ellis
commutator(other=None)
Return the commutator subgroup of a group, or of a pair of groups.
INPUT:• other – (default: None) a permutation group.
OUTPUT:
Let 𝐺 denote self. If other is None, then this method returns the subgroup of 𝐺 generated by the set ofcommutators,{[𝑔1 , 𝑔2 ]|𝑔1 , 𝑔2 ∈ 𝐺} = {𝑔1−1 𝑔2−1 𝑔1 𝑔2 |𝑔1 , 𝑔2 ∈ 𝐺}
Let 𝐻 denote other, in the case that it is not None. Then this method returns the group generated by theset of commutators,{[𝑔, ℎ]|𝑔 ∈ 𝐺 ℎ ∈ 𝐻} = {𝑔 −1 ℎ−1 𝑔ℎ|𝑔 ∈ 𝐺 ℎ ∈ 𝐻}
The two groups need only be permutation groups, there is no notion of requiring them to explicitly be subgroups of some other group.
Note: For the identical statement, the generators of the returned group can vary from one execution to thenext.
EXAMPLES:
sage: G = DiCyclicGroup(4)sage: G.commutator()
Permutation Group with generators [(1,3,5,7)(2,4,6,8)(9,11,13,15)(10,12,14,
˓→16)]
sage: G = SymmetricGroup(5)sage: H = CyclicPermutationGroup(5)sage: C = G.commutator(H)sage: C.is_isomorphic(AlternatingGroup(5))
True>>> from sage.all import *>>> G = DiCyclicGroup(Integer(4))>>> G.commutator()
Permutation Group with generators [(1,3,5,7)(2,4,6,8)(9,11,13,15)(10,12,14,
˓→16)](continues on next page)

27.3. Permutation groups431

Groups, Release 10.4

(continued from previous page)>>> G = SymmetricGroup(Integer(5))>>> H = CyclicPermutationGroup(Integer(5))>>> C = G.commutator(H)>>> C.is_isomorphic(AlternatingGroup(Integer(5)))
True

An abelian group will have a trivial commutator.
sage: G = CyclicPermutationGroup(10)sage: G.commutator()
Permutation Group with generators [()]>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(10))>>> G.commutator()
Permutation Group with generators [()]The quotient of a group by its commutator is always abelian.
sage: G = DihedralGroup(20)sage: C = G.commutator()sage: Q = G.quotient(C)sage: Q.is_abelian()True>>> from sage.all import *>>> G = DihedralGroup(Integer(20))>>> C = G.commutator()>>> Q = G.quotient(C)>>> Q.is_abelian()
True

When forming commutators from two groups, the order of the groups does not matter.
sage: D = DihedralGroup(3)sage: S = SymmetricGroup(2)sage: C1 = D.commutator(S); C1
Permutation Group with generators [(1,2,3)]
sage: C2 = S.commutator(D); C2
Permutation Group with generators [(1,3,2)]
sage: C1 == C2
True>>> from sage.all import *>>> D = DihedralGroup(Integer(3))>>> S = SymmetricGroup(Integer(2))>>> C1 = D.commutator(S); C1
Permutation Group with generators [(1,2,3)]>>> C2 = S.commutator(D); C2
Permutation Group with generators [(1,3,2)]>>> C1 == C2
TrueThis method calls two different functions in GAP, so this tests that their results are consistent. The commutatorgroups may have different generators, but the groups are equal.

432

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: G = DiCyclicGroup(3)sage: C = G.commutator(); C
Permutation Group with generators [(5,7,6)]
sage: CC = G.commutator(G); CC
Permutation Group with generators [(5,6,7)]
sage: C == CC
True>>> from sage.all import *>>> G = DiCyclicGroup(Integer(3))>>> C = G.commutator(); C
Permutation Group with generators [(5,7,6)]>>> CC = G.commutator(G); CC
Permutation Group with generators [(5,6,7)]>>> C == CCTrue

The second group is checked.
sage: G = SymmetricGroup(2)sage: G.commutator( junk )Traceback (most recent call last):...
TypeError: junk is not a permutation group>>> from sage.all import *>>> G = SymmetricGroup(Integer(2))>>> G.commutator( junk )Traceback (most recent call last):...
TypeError: junk is not a permutation groupcomposition_series()
Return the composition series of this group as a list of permutation groups.
EXAMPLES:
These computations use pseudo-random numbers, so we set the seed for reproducible testing.
sage: set_random_seed(0)sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G.composition_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: CS = G.composition_series()
sage: CS[3]Subgroup generated by [()] of(Permutation Group with generators [(1,2), (1,2,3)(4,5)])>>> from sage.all import *>>> set_random_seed(Integer(0))(continues on next page)

27.3. Permutation groups433

Groups, Release 10.4

(continued from previous page)>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G.composition_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> CS = G.composition_series()>>> CS[Integer(3)]Subgroup generated by [()] of(Permutation Group with generators [(1,2), (1,2,3)(4,5)])

conjugacy_class(g)Return the conjugacy class of g inside the group self.
INPUT:• g – an element of the permutation group self
OUTPUT:The conjugacy class of g in the group self. If self is the group denoted by 𝐺, this method computes theset {𝑥−1 𝑔𝑥 | 𝑥 ∈ 𝐺}
EXAMPLES:
sage: G = DihedralGroup(3)sage: g = G.gen(0)sage: G.conjugacy_class(g)Conjugacy class of (1,2,3) in Dihedral group of order 6 as a permutation group>>> from sage.all import *>>> G = DihedralGroup(Integer(3))>>> g = G.gen(Integer(0))>>> G.conjugacy_class(g)Conjugacy class of (1,2,3) in Dihedral group of order 6 as a permutation groupconjugacy_classes()
Return a list with all the conjugacy classes of self.
EXAMPLES:
sage: G = DihedralGroup(3)sage: G.conjugacy_classes()[Conjugacy class of () in Dihedral group of order 6 as a permutation group,
Conjugacy class of (2,3) in Dihedral group of order 6 as a permutation group,
Conjugacy class of (1,2,3) in Dihedral group of order 6 as a permutation␣
˓→group]>>> from sage.all import *>>> G = DihedralGroup(Integer(3))>>> G.conjugacy_classes()[Conjugacy class of () in Dihedral group of order 6 as a permutation group,(continues on next page)

434

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)Conjugacy class of (2,3) in Dihedral group of order 6 as a permutation group,
Conjugacy class of (1,2,3) in Dihedral group of order 6 as a permutation␣
˓→group]conjugacy_classes_representatives()
Return a complete list of representatives of conjugacy classes in a permutation group 𝐺.
The ordering is that given by GAP.
EXAMPLES:
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: cl = G.conjugacy_classes_representatives(); cl[(), (2,4), (1,2)(3,4), (1,2,3,4), (1,3)(2,4)]
sage: cl[3] in G
True>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> cl = G.conjugacy_classes_representatives(); cl[(), (2,4), (1,2)(3,4), (1,2,3,4), (1,3)(2,4)]>>> cl[Integer(3)] in G
True
sage: G = SymmetricGroup(5)sage: G.conjugacy_classes_representatives()
˓→needs sage.combinat[(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.conjugacy_classes_representatives()
˓→needs sage.combinat[(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]#␣#␣

sage: S = SymmetricGroup([ a , b , c ])sage: S.conjugacy_classes_representatives()
˓→needs sage.combinat[(), ( a , b ), ( a , b , c )]>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c ])>>> S.conjugacy_classes_representatives()
˓→needs sage.combinat[(), ( a , b ), ( a , b , c )]#␣#␣

AUTHORS:• David Joyner and William Stein (2006-01-04)
conjugacy_classes_subgroups()
Return a complete list of representatives of conjugacy classes of subgroups in a permutation group 𝐺.
The ordering is that given by GAP.
EXAMPLES:
27.3. Permutation groups435

Groups, Release 10.4

sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: cl = G.conjugacy_classes_subgroups(); cl[Subgroup generated by [()] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,2)(3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,4)(2,3), (1,2)(3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(2,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,2,3,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,4)(2,3), (1,2)(3,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> cl = G.conjugacy_classes_subgroups(); cl[Subgroup generated by [()] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,2)(3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,4)(2,3), (1,2)(3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(2,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,2,3,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]),Subgroup generated by [(1,4)(2,3), (1,2)(3,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])]sage: G = SymmetricGroup(3)sage: G.conjugacy_classes_subgroups()[Subgroup generated by [()] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3), (2,3)] of(Symmetric group of order 3! as a permutation group)]>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> G.conjugacy_classes_subgroups()[Subgroup generated by [()] of(Symmetric group of order 3! as a permutation group),(continues on next page)

436

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Subgroup generated by [(2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3), (2,3)] of(Symmetric group of order 3! as a permutation group)]

AUTHORS:• David Joyner (2006-10)
conjugate(g)Return the group formed by conjugating self with g.
INPUT:• g – a permutation group element, or an object that converts to a permutation group element, such as alist of integers or a string of cycles.
OUTPUT:
If self is the group denoted by 𝐻, then this method computes the group𝑔 −1 𝐻𝑔 = {𝑔 −1 ℎ𝑔|ℎ ∈ 𝐻}
which is the group 𝐻 conjugated by 𝑔.
There are no restrictions on self and g belonging to a common permutation group, and correspondingly,
there is no relationship (such as a common parent) between self and the output group.
EXAMPLES:
sage: G = DihedralGroup(6)sage: a = PermutationGroupElement("(1,2,3,4)")
sage: G.conjugate(a)Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]>>> from sage.all import *>>> G = DihedralGroup(Integer(6))>>> a = PermutationGroupElement("(1,2,3,4)")>>> G.conjugate(a)Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]The element performing the conjugation can be specified in several ways.
sage: G = DihedralGroup(6)sage: strng = "(1,2,3,4)"
sage: G.conjugate(strng)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
sage: G = DihedralGroup(6)sage: lst = [2,3,4,1]
sage: G.conjugate(lst)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
sage: G = DihedralGroup(6)sage: cycles = [(1,2,3,4)]
sage: G.conjugate(cycles)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]

27.3. Permutation groups437

Groups, Release 10.4>>> from sage.all import *>>> G = DihedralGroup(Integer(6))>>> strng = "(1,2,3,4)">>> G.conjugate(strng)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]>>> G = DihedralGroup(Integer(6))>>> lst = [Integer(2),Integer(3),Integer(4),Integer(1)]>>> G.conjugate(lst)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]>>> G = DihedralGroup(Integer(6))>>> cycles = [(Integer(1),Integer(2),Integer(3),Integer(4))]>>> G.conjugate(cycles)
Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]

Conjugation is a group automorphism, so conjugate groups will be isomorphic.
sage: G = DiCyclicGroup(6)sage: G.degree()11
sage: cycle = [i+1 for i in range(1,11)] + [1]sage: C = G.conjugate(cycle)
sage: G.is_isomorphic(C)True>>> from sage.all import *>>> G = DiCyclicGroup(Integer(6))>>> G.degree()11>>> cycle = [i+Integer(1) for i in range(Integer(1),Integer(11))] +␣˓→[Integer(1)]>>> C = G.conjugate(cycle)>>> G.is_isomorphic(C)True

The conjugating element may be from a symmetric group with larger degree than the group being conjugated.
sage: G = AlternatingGroup(5)sage: G.degree()5
sage: g = "(1,3)(5,6,7)"
sage: H = G.conjugate(g); H
Permutation Group with generators [(1,4,6,3,2), (1,4,6)]
sage: H.degree()6>>> from sage.all import *>>> G = AlternatingGroup(Integer(5))>>> G.degree()5>>> g = "(1,3)(5,6,7)">>> H = G.conjugate(g); H
Permutation Group with generators [(1,4,6,3,2), (1,4,6)]>>> H.degree()6

The conjugating element is checked.

438

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: G = SymmetricGroup(3)sage: G.conjugate("junk")
Traceback (most recent call last):...
TypeError: junk does not convert to a permutation group element>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> G.conjugate("junk")
Traceback (most recent call last):...
TypeError: junk does not convert to a permutation group element

construction()
Return the construction of self.
EXAMPLES:
sage: P1 = PermutationGroup([[(1,2)]])sage: P1.construction()(PermutationGroupFunctor[(1,2)], Permutation Group with generators [()])
sage: PermutationGroup([]).construction() is None
True>>> from sage.all import *>>> P1 = PermutationGroup([[(Integer(1),Integer(2))]])>>> P1.construction()(PermutationGroupFunctor[(1,2)], Permutation Group with generators [()])>>> PermutationGroup([]).construction() is None
True

This allows us to perform computations like the following:
sage: P1 = PermutationGroup([[(1,2)]]); p1 = P1.gen()sage: P2 = PermutationGroup([[(1,3)]]); p2 = P2.gen()sage: p = p1*p2; p(1,2,3)sage: p.parent()
Permutation Group with generators [(1,2), (1,3)]
sage: p.parent().domain(){1, 2, 3}>>> from sage.all import *>>> P1 = PermutationGroup([[(Integer(1),Integer(2))]]); p1 = P1.gen()>>> P2 = PermutationGroup([[(Integer(1),Integer(3))]]); p2 = P2.gen()>>> p = p1*p2; p(1,2,3)>>> p.parent()
Permutation Group with generators [(1,2), (1,3)]>>> p.parent().domain(){1, 2, 3}Note that this will merge permutation groups with different domains:

27.3. Permutation groups439

Groups, Release 10.4

sage: g1 = PermutationGroupElement([(1,2),(3,4,5)])
sage: g2 = PermutationGroup([( a , b )], domain=[ a , b ]).gens()[0]sage: g2
( a , b )sage: p = g1*g2; p(1,2)(3,4,5)( a , b )sage: P = parent(p)sage: P
Permutation Group with generators [( a , b ), (1,2), (1,2,3,4,5)]>>> from sage.all import *>>> g1 = PermutationGroupElement([(Integer(1),Integer(2)),(Integer(3),˓→Integer(4),Integer(5))])>>> g2 = PermutationGroup([( a , b )], domain=[ a , b ]).gens()[Integer(0)]>>> g2( a , b )>>> p = g1*g2; p(1,2)(3,4,5)( a , b )>>> P = parent(p)>>> PPermutation Group with generators [( a , b ), (1,2), (1,2,3,4,5)]

cosets(S, side='right')
Return a list of the cosets of S in self.
INPUT:• S – a subgroup of self. An error is raised if S is not a subgroup.
• side – (default: right ) Determines if right cosets or left cosets are returned. side refers towhere the representative is placed in the products forming the cosets and thus allowable values are only
right and left .
OUTPUT:
A list of lists. Each inner list is a coset of the subgroup in the group. The first element of each coset is thesmallest element (based on the ordering of the elements of self) of all the group elements that have not yet
appeared in a previous coset. The elements of each coset are in the same order as the subgroup elements used
to build the coset’s elements.
As a consequence, the subgroup itself is the first coset, and its first element is the identity element. For eachcoset, the first element listed is the element used as a representative to build the coset. These representatives
form an increasing sequence across the list of cosets, and within a coset the representative is the smallest
element of its coset (both orderings are based on of the ordering of elements of self).
In the case of a normal subgroup, left and right cosets should appear in the same order as part of the outer list.
However, the list of the elements of a particular coset may be in a different order for the right coset versus theorder in the left coset. So, if you check to see if a subgroup is normal, it is necessary to sort each individual
coset first (but not the list of cosets, due to the ordering of the representatives). See below for examples of
this.
Note: This is a naive implementation intended for instructional purposes, and hence is slow for larger groups.
Sage and GAP provide more sophisticated functions for working quickly with cosets of larger groups.
EXAMPLES:
The default is to build right cosets. This example works with the symmetry group of an 8-gon and a normal
subgroup. Notice that a straight check on the equality of the output is not sufficient to check normality, while
440

Chapter 27. Permutation Groups

Groups, Release 10.4

sorting the individual cosets is sufficient to then simply test equality of the list of lists. Study the second coset
in each list to understand the need for sorting the elements of the cosets.
sage: G = DihedralGroup(8)sage: quarter_turn = G( (1,3,5,7)(2,4,6,8) ); quarter_turn(1,3,5,7)(2,4,6,8)
sage: S = G.subgroup([quarter_turn])
sage: rc = G.cosets(S); rc[[(), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,7,5,3)(2,8,6,4)],[(2,8)(3,7)(4,6), (1,7)(2,6)(3,5), (1,5)(2,4)(6,8), (1,3)(4,8)(5,7)],[(1,2)(3,8)(4,7)(5,6), (1,8)(2,7)(3,6)(4,5), (1,6)(2,5)(3,4)(7,8), (1,4)(2,
˓→3)(5,8)(6,7)],[(1,2,3,4,5,6,7,8), (1,4,7,2,5,8,3,6), (1,6,3,8,5,2,7,4), (1,8,7,6,5,4,3,2)]]
sage: lc = G.cosets(S, side= left ); lc[[(), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,7,5,3)(2,8,6,4)],[(2,8)(3,7)(4,6), (1,3)(4,8)(5,7), (1,5)(2,4)(6,8), (1,7)(2,6)(3,5)],[(1,2)(3,8)(4,7)(5,6), (1,4)(2,3)(5,8)(6,7), (1,6)(2,5)(3,4)(7,8), (1,8)(2,
˓→7)(3,6)(4,5)],[(1,2,3,4,5,6,7,8), (1,4,7,2,5,8,3,6), (1,6,3,8,5,2,7,4), (1,8,7,6,5,4,3,2)]]
sage: S.is_normal(G)Truesage: rc == lc
False
sage: rc_sorted = [sorted(c) for c in rc]
sage: lc_sorted = [sorted(c) for c in lc]
sage: rc_sorted == lc_sorted
True>>> from sage.all import *>>> G = DihedralGroup(Integer(8))>>> quarter_turn = G( (1,3,5,7)(2,4,6,8) ); quarter_turn(1,3,5,7)(2,4,6,8)>>> S = G.subgroup([quarter_turn])>>> rc = G.cosets(S); rc[[(), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,7,5,3)(2,8,6,4)],[(2,8)(3,7)(4,6), (1,7)(2,6)(3,5), (1,5)(2,4)(6,8), (1,3)(4,8)(5,7)],[(1,2)(3,8)(4,7)(5,6), (1,8)(2,7)(3,6)(4,5), (1,6)(2,5)(3,4)(7,8), (1,4)(2,
˓→3)(5,8)(6,7)],[(1,2,3,4,5,6,7,8), (1,4,7,2,5,8,3,6), (1,6,3,8,5,2,7,4), (1,8,7,6,5,4,3,2)]]>>> lc = G.cosets(S, side= left ); lc[[(), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,7,5,3)(2,8,6,4)],[(2,8)(3,7)(4,6), (1,3)(4,8)(5,7), (1,5)(2,4)(6,8), (1,7)(2,6)(3,5)],[(1,2)(3,8)(4,7)(5,6), (1,4)(2,3)(5,8)(6,7), (1,6)(2,5)(3,4)(7,8), (1,8)(2,
˓→7)(3,6)(4,5)],[(1,2,3,4,5,6,7,8), (1,4,7,2,5,8,3,6), (1,6,3,8,5,2,7,4), (1,8,7,6,5,4,3,2)]]>>> S.is_normal(G)True>>> rc == lc
False>>> rc_sorted = [sorted(c) for c in rc]>>> lc_sorted = [sorted(c) for c in lc]>>> rc_sorted == lc_sorted
True

An example with the symmetry group of a regular tetrahedron and a subgroup that is not normal. Thus, theright and left cosets are different (and so are the representatives). With each individual coset sorted, a naive
27.3. Permutation groups441

Groups, Release 10.4

test of normality is possible.
sage: A = AlternatingGroup(4)sage: face_turn = A( (1,2,3) ); face_turn(1,2,3)sage: stabilizer = A.subgroup([face_turn])
sage: rc = A.cosets(stabilizer, side= right ); rc[[(), (1,2,3), (1,3,2)],[(2,3,4), (1,3)(2,4), (1,4,2)],[(2,4,3), (1,4,3), (1,2)(3,4)],[(1,2,4), (1,4)(2,3), (1,3,4)]]
sage: lc = A.cosets(stabilizer, side= left ); lc[[(), (1,2,3), (1,3,2)],[(2,3,4), (1,2)(3,4), (1,3,4)],[(2,4,3), (1,2,4), (1,3)(2,4)],[(1,4,2), (1,4,3), (1,4)(2,3)]]
sage: stabilizer.is_normal(A)False
sage: rc_sorted = [sorted(c) for c in rc]
sage: lc_sorted = [sorted(c) for c in lc]
sage: rc_sorted == lc_sorted
False>>> from sage.all import *>>> A = AlternatingGroup(Integer(4))>>> face_turn = A( (1,2,3) ); face_turn(1,2,3)>>> stabilizer = A.subgroup([face_turn])>>> rc = A.cosets(stabilizer, side= right ); rc[[(), (1,2,3), (1,3,2)],[(2,3,4), (1,3)(2,4), (1,4,2)],[(2,4,3), (1,4,3), (1,2)(3,4)],[(1,2,4), (1,4)(2,3), (1,3,4)]]>>> lc = A.cosets(stabilizer, side= left ); lc[[(), (1,2,3), (1,3,2)],[(2,3,4), (1,2)(3,4), (1,3,4)],[(2,4,3), (1,2,4), (1,3)(2,4)],[(1,4,2), (1,4,3), (1,4)(2,3)]]>>> stabilizer.is_normal(A)False>>> rc_sorted = [sorted(c) for c in rc]>>> lc_sorted = [sorted(c) for c in lc]>>> rc_sorted == lc_sorted
False

AUTHOR:• Rob Beezer (2011-01-31)
degree()Return the degree of this permutation group.
EXAMPLES:
sage: S = SymmetricGroup([ a , b , c ])sage: S.degree()(continues on next page)

442

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)3
sage: G = PermutationGroup([(1,3),(4,5)])
sage: G.degree()5>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c ])>>> S.degree()3>>> G = PermutationGroup([(Integer(1),Integer(3)),(Integer(4),Integer(5))])>>> G.degree()
5Note that you can explicitly specify the domain to get a permutation group of smaller degree:
sage: G = PermutationGroup([(1,3),(4,5)], domain=[1,3,4,5])
sage: G.degree()4>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(3)),(Integer(4),Integer(5))],␣
˓→domain=[Integer(1),Integer(3),Integer(4),Integer(5)])>>> G.degree()4

derived_series()
Return the derived series of this group as a list of permutation groups.
EXAMPLES:
These computations use pseudo-random numbers, so we set the seed for reproducible testing.
sage: set_random_seed(0)sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G.derived_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]>>> from sage.all import *>>> set_random_seed(Integer(0))>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G.derived_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]

direct_product(other, maps=True)
Wraps GAP’s DirectProduct, Embedding, and Projection.
Sage calls GAP’s DirectProduct, which chooses an efficient representation for the direct product. The
direct product of permutation groups will be a permutation group again. For a direct product D, the GAP

27.3. Permutation groups443

Groups, Release 10.4

operation Embedding(D,i) returns the homomorphism embedding the i-th factor into D. The GAP operation Projection(D,i) gives the projection of D onto the i-th factor. This method returns a 5-tuple:a permutation group and 4 morphisms.
INPUT:• self, other – permutation groups
OUTPUT:• D – a direct product of the inputs, returned as a permutation group as well
• iota1 – an embedding of self into D• iota2 – an embedding of other into D• pr1 – the projection of D onto self (giving a splitting 1 - other - D - self - 1)
• pr2 – the projection of D onto other (giving a splitting 1 - self - D - other - 1)
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: D = G.direct_product(G, False); D
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G)sage: D; iota1; iota2; pr1; pr2
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )Permutation group morphism:
From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
To:
Cyclic group of order 4 as a permutation group
Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )Permutation group morphism:
From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
To:
Cyclic group of order 4 as a permutation group
Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )sage: g = D([(1,3),(2,4)]); g(1,3)(2,4)
sage: d = D([(1,4,3,2),(5,7),(6,8)]); d(1,4,3,2)(5,7)(6,8)
sage: iota1(g); iota2(g); pr1(d); pr2(d)(1,3)(2,4)(5,7)(6,8)(1,4,3,2)(1,3)(2,4)>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> D = G.direct_product(G, False); D
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]>>> D,iota1,iota2,pr1,pr2 = G.direct_product(G)>>> D; iota1; iota2; pr1; pr2
Permutation Group with generators [(1,2,3,4), (5,6,7,8)](continues on next page)444

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )Permutation group morphism:
From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
To:
Cyclic group of order 4 as a permutation group
Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )Permutation group morphism:
From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
To:
Cyclic group of order 4 as a permutation group
Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )>>> g = D([(Integer(1),Integer(3)),(Integer(2),Integer(4))]); g(1,3)(2,4)>>> d = D([(Integer(1),Integer(4),Integer(3),Integer(2)),(Integer(5),˓→Integer(7)),(Integer(6),Integer(8))]); d(1,4,3,2)(5,7)(6,8)>>> iota1(g); iota2(g); pr1(d); pr2(d)(1,3)(2,4)(5,7)(6,8)(1,4,3,2)(1,3)(2,4)

domain()Return the underlying set that this permutation group acts on.
EXAMPLES:
sage: P = PermutationGroup([(1,2),(3,5)])
sage: P.domain(){1, 2, 3, 4, 5}
sage: S = SymmetricGroup([ a , b , c ])sage: S.domain(){ a , b , c }>>> from sage.all import *>>> P = PermutationGroup([(Integer(1),Integer(2)),(Integer(3),Integer(5))])>>> P.domain(){1, 2, 3, 4, 5}>>> S = SymmetricGroup([ a , b , c ])>>> S.domain(){ a , b , c }exponent()
Computes the exponent of the group.
The exponent 𝑒 of a group 𝐺 is the LCM of the orders of its elements, that is, 𝑒 is the smallest integer suchthat 𝑔 𝑒 = 1 for all 𝑔 ∈ 𝐺.
EXAMPLES:

27.3. Permutation groups445

Groups, Release 10.4

sage: G = AlternatingGroup(4)sage: G.exponent()
6>>> from sage.all import *>>> G = AlternatingGroup(Integer(4))>>> G.exponent()
6

fitting_subgroup()
Return the Fitting subgroup of self.
The Fitting subgroup of a group 𝐺 is the largest nilpotent normal subgroup of 𝐺.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])sage: G.fitting_subgroup()
Subgroup generated by [(2,4), (1,2,3,4), (1,3)] of(Permutation Group with generators [(2,4), (1,2,3,4)])
sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])sage: G.fitting_subgroup()
Subgroup generated by [(1,2)(3,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2), (1,2,3,4)])>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(2),Integer(4))]])>>> G.fitting_subgroup()
Subgroup generated by [(2,4), (1,2,3,4), (1,3)] of(Permutation Group with generators [(2,4), (1,2,3,4)])>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(1),Integer(2))]])>>> G.fitting_subgroup()
Subgroup generated by [(1,2)(3,4), (1,3)(2,4)] of(Permutation Group with generators [(1,2), (1,2,3,4)])

fixed_points()
Return the list of points fixed by self, i.e., the subset of .domain() not moved by any element of self.
EXAMPLES:
sage: G = PermutationGroup([(1,2,3)])
sage: G.fixed_points()[]
sage: G = PermutationGroup([(1,2,3),(5,6)])
sage: G.fixed_points()[4]sage: G = PermutationGroup([[(1,4,7)],[(4,3),(6,7)]])sage: G.fixed_points()[2, 5]>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3))])>>> G.fixed_points()[](continues on next page)

446

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)),(Integer(5),˓→Integer(6))])>>> G.fixed_points()[4]>>> G = PermutationGroup([[(Integer(1),Integer(4),Integer(7))],[(Integer(4),˓→Integer(3)),(Integer(6),Integer(7))]])>>> G.fixed_points()[2, 5]

frattini_subgroup()
Return the Frattini subgroup of self.
The Frattini subgroup of a group 𝐺 is the intersection of all maximal subgroups of 𝐺.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])sage: G.frattini_subgroup()
Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(2,4), (1,2,3,4)])
sage: G = SymmetricGroup(4)sage: G.frattini_subgroup()
Subgroup generated by [()] of(Symmetric group of order 4! as a permutation group)>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(2),Integer(4))]])>>> G.frattini_subgroup()
Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(2,4), (1,2,3,4)])>>> G = SymmetricGroup(Integer(4))>>> G.frattini_subgroup()
Subgroup generated by [()] of(Symmetric group of order 4! as a permutation group)

gap()
This method from sage.groups.libgap_wrapper.ParentLibGAP is added in order to achieve
compatibility and have sage.groups.libgap_morphism.GroupHomset_libgap work for permutation groups, as well
OUTPUT: an instance of sage.libs.gap.element.GapElement representing this group
EXAMPLES:
sage: P8 = PSp(8,3)
sage: P8.gap()<permutation group of size 65784756654489600 with 2 generators>
sage: gap(P8) == P8.gap()
False
sage: S3 = SymmetricGroup(3)sage: S3.gap()
Sym( [ 1 .. 3 ] )sage: gap(S3) == S3.gap()
False

27.3. Permutation groups

447

Groups, Release 10.4>>> from sage.all import *>>> P8 = PSp(Integer(8),Integer(3))>>> P8.gap()<permutation group of size 65784756654489600 with 2 generators>>>> gap(P8) == P8.gap()
False>>> S3 = SymmetricGroup(Integer(3))>>> S3.gap()
Sym( [ 1 .. 3 ] )>>> gap(S3) == S3.gap()
False

gen(i=None)
Return the 𝑖-th generator of self; that is, the 𝑖-th element of the list self.gens().
The argument 𝑖 may be omitted if there is only one generator (but this will raise an error otherwise).
EXAMPLES:
We explicitly construct the alternating group on four elements:
sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4
Permutation Group with generators [(2,3,4), (1,2,3)]
sage: A4.gens()((2,3,4), (1,2,3))
sage: A4.gen(0)(2,3,4)sage: A4.gen(1)(1,2,3)sage: A4.gens()[0]; A4.gens()[1](2,3,4)(1,2,3)sage: P1 = PermutationGroup([[(1,2)]]); P1.gen()(1,2)>>> from sage.all import *>>> A4 = PermutationGroup([[(Integer(1),Integer(2),Integer(3))],[(Integer(2),˓→Integer(3),Integer(4))]]); A4
Permutation Group with generators [(2,3,4), (1,2,3)]>>> A4.gens()((2,3,4), (1,2,3))>>> A4.gen(Integer(0))(2,3,4)>>> A4.gen(Integer(1))(1,2,3)>>> A4.gens()[Integer(0)]; A4.gens()[Integer(1)](2,3,4)(1,2,3)>>> P1 = PermutationGroup([[(Integer(1),Integer(2))]]); P1.gen()(1,2)

gens()
Return tuple of generators of this group.
These need not be minimal, as they are the generators used in defining this group.
EXAMPLES:
448

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: G = PermutationGroup([[(1,2,3)], [(1,2)]])sage: G.gens()((1,2), (1,2,3))>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3))], [(Integer(1),˓→Integer(2))]])>>> G.gens()((1,2), (1,2,3))

Note that the generators need not be minimal, though duplicates are removed:
sage: G = PermutationGroup([[(1,2)], [(1,3)], [(2,3)], [(1,2)]])sage: G.gens()((2,3), (1,2), (1,3))>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2))], [(Integer(1),˓→Integer(3))], [(Integer(2),Integer(3))], [(Integer(1),Integer(2))]])>>> G.gens()((2,3), (1,2), (1,3))

We can use index notation to access the generators returned by self.gens:sage: G = PermutationGroup([[(1,2,3,4), (5,6)], [(1,2)]])sage: g = G.gens()
sage: g[0](1,2)
sage: g[1](1,2,3,4)(5,6)>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4)),␣
˓→(Integer(5),Integer(6))], [(Integer(1),Integer(2))]])>>> g = G.gens()>>> g[Integer(0)](1,2)>>> g[Integer(1)](1,2,3,4)(5,6)

gens_small()
For this group, returns a generating set which has few elements.
As neither irredundancy nor minimal length is proven, it is fast.
EXAMPLES:
sage: R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)"
˓→## R = rightsage: U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)"
˓→## U = top
sage: L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)"
˓→## L = left
sage: F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)"
˓→## F = front
sage: B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)"(continues on next page)

27.3. Permutation groups449

Groups, Release 10.4

(continued from previous page)## B = back or rear
sage: D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)"
˓→## D = down or bottom
sage: G = PermutationGroup([R,L,U,F,B,D])
sage: len(G.gens_small())
2
˓→>>> from sage.all import *>>> R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" #˓→# R = right>>> U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" #˓→# U = top>>> L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" #˓→# L = left>>> F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" #˓→# F = front>>> B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" #˓→# B = back or rear>>> D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" #˓→# D = down or bottom>>> G = PermutationGroup([R,L,U,F,B,D])>>> len(G.gens_small())
2

The output may be unpredictable, due to the use of randomized algorithms in GAP. Note that both thefollowing answers are equally valid.
sage: G = PermutationGroup([[( a , b )], [( b ,sage: G.gens_small() # random[( b , c ), ( a , c , b )] ## (on 64-bit Linux)[( a , b ), ( a , c , b )] ## (on Solaris)
sage: len(G.gens_small()) == 2 # random
Truec )], [( a ,>>> from sage.all import *>>> G = PermutationGroup([[( a , b )], [( b , c )], [( a ,>>> G.gens_small() # random[( b , c ), ( a , c , b )] ## (on 64-bit Linux)[( a , b ), ( a , c , b )] ## (on Solaris)>>> len(G.gens_small()) == Integer(2) # random
Truec )]])c )]])

group_id()
Return the ID code of this group, which is a list of two integers.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: G.group_id()[12, 4]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> G.group_id()[12, 4]450

Chapter 27. Permutation Groups

Groups, Release 10.4

group_primitive_id()
Return the index of this group in the GAP database of primitive groups.
OUTPUT:
A positive integer, following GAP’s conventions. A ValueError is raised if the group is not primitive.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4,5)], [(1,5),(2,4)]])sage: G.group_primitive_id()2
sage: G.degree()5>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5))], [(Integer(1),Integer(5)),(Integer(2),Integer(4))]])>>> G.group_primitive_id()2>>> G.degree()5

From the information of the degree and the identification number, you can recover the isomorphism class of
your group in the GAP database:sage: H = PrimitiveGroup(5,2)
sage: G == H
False
sage: G.is_isomorphic(H)
True>>> from sage.all import *>>> H = PrimitiveGroup(Integer(5),Integer(2))>>> G == H
False>>> G.is_isomorphic(H)True

has_element(item)
Return whether item is an element of this group - however ignores parentage.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: gens = G.gens()
sage: H = DihedralGroup(4)sage: g = G([(1,2,3,4)]); g(1,2,3,4)
sage: G.has_element(g)doctest:warning...
DeprecationWarning: G.has_element(g) is deprecated; use :meth: __contains__ ,␣˓→i.e.,
g in G instead
See https://github.com/sagemath/sage/issues/33831 for details.
Truesage: h = H([(1,2),(3,4)]); h(1,2)(3,4)(continues on next page)

27.3. Permutation groups451

Groups, Release 10.4

(continued from previous page)

sage: G.has_element(h)False>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> gens = G.gens()>>> H = DihedralGroup(Integer(4))>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))]); g(1,2,3,4)>>> G.has_element(g)doctest:warning...
DeprecationWarning: G.has_element(g) is deprecated; use :meth: __contains__ ,␣˓→i.e.,
g in G instead
See https://github.com/sagemath/sage/issues/33831 for details.
True>>> h = H([(Integer(1),Integer(2)),(Integer(3),Integer(4))]); h(1,2)(3,4)>>> G.has_element(h)False

has_regular_subgroup(return_group=False)
Return whether the group contains a regular subgroup.
INPUT:• return_group – (boolean) If True, a regular subgroup is returned if there is one, and None if there
isn’t. When return_group=False (default), only a boolean indicating whether such a group exists
is returned instead.
EXAMPLES:
The symmetric group on 4 elements has a regular subgroup:sage: S4 = groups.permutation.Symmetric(4)sage: S4.has_regular_subgroup()
True
sage: S4.has_regular_subgroup(return_group=True) # random
Subgroup of (Symmetric group of order 4! as a permutation group)
generated by [(1,3)(2,4), (1,4)(2,3)]>>> from sage.all import *>>> S4 = groups.permutation.Symmetric(Integer(4))>>> S4.has_regular_subgroup()
True>>> S4.has_regular_subgroup(return_group=True) # random
Subgroup of (Symmetric group of order 4! as a permutation group)
generated by [(1,3)(2,4), (1,4)(2,3)]

But the automorphism group of Petersen’s graph does not:sage: # needs sage.graphs
sage: G = graphs.PetersenGraph().automorphism_group()
sage: G.has_regular_subgroup()
False

452

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.graphs>>> G = graphs.PetersenGraph().automorphism_group()>>> G.has_regular_subgroup()
False

holomorph()
The holomorph of a group as a permutation group.
The holomorph of a group 𝐺 is the semidirect product 𝐺 o𝑖𝑑 𝐴𝑢𝑡(𝐺), where 𝑖𝑑 is the identity function on
𝐴𝑢𝑡(𝐺), the automorphism group of 𝐺.
See Wikipedia article Holomorph (mathematics)
OUTPUT: the holomorph of a given group as permutation group via a wrapping of GAP’s semidirect productfunction
EXAMPLES:
Thomas and Wood’s ‘Group Tables’ (Shiva Publishing, 1980) tells us that the holomorph of 𝐶5 is the uniquegroup of order 20 with a trivial center.
sage: C5 = CyclicPermutationGroup(5)sage: A = C5.holomorph()
sage: A.order()20
sage: A.is_abelian()False
sage: A.center()
Subgroup generated by [()] of(Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)])
sage: A
Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)]>>> from sage.all import *>>> C5 = CyclicPermutationGroup(Integer(5))>>> A = C5.holomorph()>>> A.order()20>>> A.is_abelian()
False>>> A.center()
Subgroup generated by [()] of(Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)])>>> A
Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)]

Noting that the automorphism group of 𝐷4 is itself 𝐷4 , it can easily be shown that the holomorph is indeed
an internal semidirect product of these two groups.
sage: D4 = DihedralGroup(4)sage: H = D4.holomorph()
sage: H.gens()((2,3,5,8), (2,5)(3,8), (3,8)(4,7), (1,4,6,7)(2,3,5,8), (1,8)(2,7)(3,6)(4,5))
sage: G = H.subgroup([H.gens()[0],H.gens()[1],H.gens()[2]])sage: N = H.subgroup([H.gens()[3],H.gens()[4]])sage: N.is_normal(H)
True(continues on next page)

27.3. Permutation groups453

Groups, Release 10.4

(continued from previous page)

sage: G.is_isomorphic(D4)True
sage: N.is_isomorphic(D4)True
sage: G.intersection(N)Permutation Group with generators [()]
sage: L = [H(x)*H(y) for x in G for y in N]; L.sort()
sage: L1 = H.list(); L1.sort()
sage: L == L1
True>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))>>> H = D4.holomorph()>>> H.gens()((2,3,5,8), (2,5)(3,8), (3,8)(4,7), (1,4,6,7)(2,3,5,8), (1,8)(2,7)(3,6)(4,5))>>> G = H.subgroup([H.gens()[Integer(0)],H.gens()[Integer(1)],H.
˓→gens()[Integer(2)]])>>> N = H.subgroup([H.gens()[Integer(3)],H.gens()[Integer(4)]])>>> N.is_normal(H)
True>>> G.is_isomorphic(D4)True>>> N.is_isomorphic(D4)True>>> G.intersection(N)Permutation Group with generators [()]>>> L = [H(x)*H(y) for x in G for y in N]; L.sort()>>> L1 = H.list(); L1.sort()>>> L == L1
True

Author:• Kevin Halasz (2012-08-14)
homology(n, p=0)
Computes the group homology 𝐻𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0 and 𝐹 =Wraps HAP’s GroupHomology function, written by Graham Ellis.

/𝑝 if 𝑝 > 0 is a prime.

REQUIRES: GAP package HAP (in gap_packages-*.spkg).
AUTHORS:• David Joyner and Graham Ellis
The example below computes 𝐻7 (𝑆5 , ), 𝐻7 (𝑆5 , /2 ), 𝐻7 (𝑆5 , /3 ), and 𝐻7 (𝑆5 , /5 ), respectively.
To compute the 2-part of 𝐻7 (𝑆5 , ), use the method homology_part().
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.homology(7)# optional - gap_package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C4 x C3 x C5
sage: G.homology(7,2)# optional - gap_package_
˓→hapMultiplicative Abelian group isomorphic to C2 x C2 x C2 x C2 x C2
sage: G.homology(7,3)# optional - gap_package_(continues on next page)454

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

hap
Multiplicative Abelian group isomorphic to C3
sage: G.homology(7,5)
˓→hapMultiplicative Abelian group isomorphic to C5
˓→# optional - gap_package_>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.homology(Integer(7))# optional - gap_
˓→package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C4 x C3 x C5>>> G.homology(Integer(7),Integer(2))# optional␣˓→- gap_package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C2 x C2 x C2>>> G.homology(Integer(7),Integer(3))# optional␣˓→- gap_package_hap
Multiplicative Abelian group isomorphic to C3>>> G.homology(Integer(7),Integer(5))# optional␣˓→- gap_package_hap
Multiplicative Abelian group isomorphic to C5

REFERENCES:• G. Ellis, “Computing group resolutions”, J. Symbolic Computation. Vol.38, (2004)1077-1118 (Available
at http://hamilton.nuigalway.ie/.
• D. Joyner, “A primer on computational group homology and cohomology”, http://front.math.ucdavis.
edu/0706.0549
homology_part(n, p=0)
Computes the 𝑝-part of the group homology 𝐻𝑛 (𝐺, 𝐹 ), where 𝐹 = if 𝑝 = 0 and 𝐹 = /𝑝 if 𝑝 > 0 is aprime. Wraps HAP’s Homology function, written by Graham Ellis, applied to the 𝑝-Sylow subgroup of 𝐺.
REQUIRES: GAP package HAP (in gap_packages-*.spkg).
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.homology_part(7,2)# optional - gap_
˓→package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C2 x C2 x C4>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.homology_part(Integer(7),Integer(2))˓→optional - gap_package_hap
Multiplicative Abelian group isomorphic to C2 x C2 x C2 x C2 x C4#␣

AUTHORS:• David Joyner and Graham Ellis
id()
Return the ID code of this group, which is a list of two integers.
Same as group_id().
EXAMPLES:

27.3. Permutation groups455

Groups, Release 10.4

sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: G.group_id()[12, 4]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> G.group_id()[12, 4]

identity()
Return the identity element of this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)]])sage: e = G.identity(); e()sage: g = G.gen(0)sage: g*e
(1,2,3)(4,5)
sage: e*g
(1,2,3)(4,5)# indirect doctest

sage: S = SymmetricGroup([ a , b , c ])sage: S.identity()()>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))]])>>> e = G.identity(); e# indirect doctest()>>> g = G.gen(Integer(0))>>> g*e(1,2,3)(4,5)>>> e*g(1,2,3)(4,5)>>> S = SymmetricGroup([ a , b , c ])>>> S.identity()()

intersection(other)
Return the permutation group that is the intersection of self and other.
INPUT:• other – a permutation group.
OUTPUT:
A permutation group that is the set-theoretic intersection of self with other. The groups are viewed as
subgroups of a symmetric group big enough to contain both group’s symbol sets. So there is no strict notionof the two groups being subgroups of a common parent.
EXAMPLES:

456

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: H = DihedralGroup(4)sage: K = CyclicPermutationGroup(4)sage: H.intersection(K)Permutation Group with generators [(1,2,3,4)]
sage: L = DihedralGroup(5)sage: H.intersection(L)Permutation Group with generators [(1,4)(2,3)]
sage: M = PermutationGroup(["()"])
sage: H.intersection(M)Permutation Group with generators [()]>>> from sage.all import *>>> H = DihedralGroup(Integer(4))>>> K = CyclicPermutationGroup(Integer(4))>>> H.intersection(K)Permutation Group with generators [(1,2,3,4)]>>> L = DihedralGroup(Integer(5))>>> H.intersection(L)Permutation Group with generators [(1,4)(2,3)]>>> M = PermutationGroup(["()"])>>> H.intersection(M)Permutation Group with generators [()]

Some basic properties.
sage: H = DihedralGroup(4)sage: L = DihedralGroup(5)sage: H.intersection(L) == L.intersection(H)True
sage: H.intersection(H) == H
True>>> from sage.all import *>>> H = DihedralGroup(Integer(4))>>> L = DihedralGroup(Integer(5))>>> H.intersection(L) == L.intersection(H)
True>>> H.intersection(H) == H
True

The group other is verified as such.
sage: H = DihedralGroup(4)sage: H.intersection( junk )Traceback (most recent call last):...
TypeError: junk is not a permutation group>>> from sage.all import *>>> H = DihedralGroup(Integer(4))(continues on next page)

27.3. Permutation groups457

Groups, Release 10.4

(continued from previous page)>>> H.intersection( junk )Traceback (most recent call last):...
TypeError: junk is not a permutation groupirreducible_characters()
Return a list of the irreducible characters of self.
EXAMPLES:
sage: irr = SymmetricGroup(3).irreducible_characters()
˓→needs sage.rings.number_fieldsage: [x.values() for x in irr]
˓→needs sage.rings.number_field[[1, -1, 1], [2, 0, -1], [1, 1, 1]]>>> from sage.all import *>>> irr = SymmetricGroup(Integer(3)).irreducible_characters()˓→# needs sage.rings.number_field>>> [x.values() for x in irr]
˓→needs sage.rings.number_field[[1, -1, 1], [2, 0, -1], [1, 1, 1]]

#␣
#␣

␣
#␣

is_abelian()
Return True if this group is abelian.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_abelian()False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_abelian()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_abelian()
False>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_abelian()True

is_commutative()
Return True if this group is commutative.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_commutative()
False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_commutative()
True

458

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_commutative()
False>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_commutative()
True

is_cyclic()
Return True if this group is cyclic.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_cyclic()
False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_cyclic()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_cyclic()
False>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_cyclic()
Trueis_elementary_abelian()
Return True if this group is elementary abelian. An elementary abelian group is a finite abelian group, where
every nontrivial element has order 𝑝, where 𝑝 is a prime.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_elementary_abelian()False
sage: G = PermutationGroup([ (1,2,3) , (4,5,6) ])sage: G.is_elementary_abelian()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_elementary_abelian()
False>>> G = PermutationGroup([ (1,2,3) , (4,5,6) ])>>> G.is_elementary_abelian()
True

is_isomorphic(right)
Return True if the groups are isomorphic.
INPUT:• self – this group• right – a permutation group

27.3. Permutation groups459

Groups, Release 10.4

OUTPUT: boolean; True if self and right are isomorphic groups; False otherwise
EXAMPLES:
sage: v = [ (1,2,3)(4,5) , (1,2,3,4,5) ]sage: G = PermutationGroup(v)sage: H = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_isomorphic(H)False
sage: G.is_isomorphic(G)Truesage: G.is_isomorphic(PermutationGroup(list(reversed(v))))
True>>> from sage.all import *>>> v = [ (1,2,3)(4,5) , (1,2,3,4,5) ]>>> G = PermutationGroup(v)>>> H = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_isomorphic(H)
False>>> G.is_isomorphic(G)
True>>> G.is_isomorphic(PermutationGroup(list(reversed(v))))
True

is_monomial()
Return True if the group is monomial. A finite group is monomial if every irreducible complex character is
induced from a linear character of a subgroup.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_monomial()
True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_monomial()
True

is_nilpotent()
Return True if this group is nilpotent.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_nilpotent()
False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_nilpotent()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_nilpotent()
False>>> G = PermutationGroup([ (1,2,3)(4,5) ])(continues on next page)

460

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G.is_nilpotent()
True

is_normal(other)
Return True if this group is a normal subgroup of other.
EXAMPLES:
sage: AlternatingGroup(4).is_normal(SymmetricGroup(4))
True
sage: H = PermutationGroup([ (1,2,3)(4,5) ])sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: H.is_normal(G)False>>> from sage.all import *>>> AlternatingGroup(Integer(4)).is_normal(SymmetricGroup(Integer(4)))
True>>> H = PermutationGroup([ (1,2,3)(4,5) ])>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> H.is_normal(G)False

is_perfect()
Return True if this group is perfect. A group is perfect if it equals its derived subgroup.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_perfect()
False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_perfect()False>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_perfect()False>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_perfect()False

is_pgroup()
Return True if this group is a 𝑝-group.
A finite group is a 𝑝-group if its order is of the form 𝑝𝑛 for a prime integer 𝑝 and a nonnegative integer 𝑛.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3,4,5) ])sage: G.is_pgroup()
True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3,4,5) ])(continues on next page)

27.3. Permutation groups461

Groups, Release 10.4

(continued from previous page)>>> G.is_pgroup()
True

is_polycyclic()
Return True if this group is polycyclic. A group is polycyclic if it has a subnormal series with cyclic factors.
(For finite groups, this is the same as if the group is solvable - see is_solvable().)
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: G.is_polycyclic()
False
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_polycyclic()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> G.is_polycyclic()
False>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_polycyclic()
True

is_primitive(domain=None)
Return True if self acts primitively on domain.
A group 𝐺 acts primitively on a set 𝑆 if
1. 𝐺 acts transitively on 𝑆 and
2. the action induces no non-trivial block system on 𝑆.
INPUT:• domain (optional)
See also:• blocks_all()
EXAMPLES:
By default, test for primitivity of self on its domain:
sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])sage: G.is_primitive()
True
sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])sage: G.is_primitive()
False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(1),Integer(2))]])>>> G.is_primitive()
True(continues on next page)462

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(2),Integer(4))]])>>> G.is_primitive()
False

You can specify a domain on which to test primitivity:
sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])sage: G.is_primitive([1..4])
False
sage: G = PermutationGroup([[(3,4,5,6)],[(3,4)]]) #S_4 on [3..6]
sage: G.is_primitive(G.non_fixed_points())
True>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(2),Integer(4))]])>>> G.is_primitive((ellipsis_range(Integer(1),Ellipsis,Integer(4))))
False>>> G = PermutationGroup([[(Integer(3),Integer(4),Integer(5),Integer(6))],
˓→[(Integer(3),Integer(4))]]) #S_4 on [3..6]>>> G.is_primitive(G.non_fixed_points())
True

If 𝐺 does not act on the domain, it always returns False:
sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])sage: G.is_primitive([1,2,3])
False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(2),Integer(4))]])>>> G.is_primitive([Integer(1),Integer(2),Integer(3)])
False

is_regular(domain=None)
Return True if self acts regularly on domain.
A group 𝐺 acts regularly on a set 𝑆 if
1. 𝐺 acts transitively on 𝑆 and
2. 𝐺 acts semi-regularly on 𝑆.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)]])sage: G.is_regular()True
sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])sage: G.is_regular()False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))]])(continues on next page)

27.3. Permutation groups463

Groups, Release 10.4

(continued from previous page)>>> G.is_regular()
True>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(5),Integer(6))]])>>> G.is_regular()False

You can pass in a domain on which to test regularity:
sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])sage: G.is_regular([1..4])True
sage: G.is_regular(G.non_fixed_points())
False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(5),Integer(6))]])>>> G.is_regular((ellipsis_range(Integer(1),Ellipsis,Integer(4))))
True>>> G.is_regular(G.non_fixed_points())
False

is_semi_regular(domain=None)
Return True if self acts semi-regularly on domain.
A group 𝐺 acts semi-regularly on a set 𝑆 if the point stabilizers of 𝑆 in 𝐺 are trivial.
domain is optional and may take several forms. See examples.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)]])sage: G.is_semi_regular()True
sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])sage: G.is_semi_regular()False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> G.is_semi_regular()
True>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(5),Integer(6))]])>>> G.is_semi_regular()False

You can pass in a domain to test semi-regularity:
sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])sage: G.is_semi_regular([1..4])True
sage: G.is_semi_regular(G.non_fixed_points())
False

464

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(5),Integer(6))]])>>> G.is_semi_regular((ellipsis_range(Integer(1),Ellipsis,Integer(4))))
True>>> G.is_semi_regular(G.non_fixed_points())
False

is_simple()
Return True if the group is simple.
A group is simple if it has no proper normal subgroups.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_simple()
False>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_simple()False

is_solvable()
Return True if the group is solvable.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_solvable()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_solvable()Trueis_subgroup(other)
Return True if self is a subgroup of other.
EXAMPLES:
sage: G = AlternatingGroup(5)sage: H = SymmetricGroup(5)sage: G.is_subgroup(H)True>>> from sage.all import *>>> G = AlternatingGroup(Integer(5))>>> H = SymmetricGroup(Integer(5))>>> G.is_subgroup(H)True

is_supersolvable()
Return True if the group is supersolvable.

27.3. Permutation groups

465

Groups, Release 10.4

A finite group is supersolvable if it has a normal series with cyclic factors.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: G.is_supersolvable()True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> G.is_supersolvable()True

is_transitive(domain=None)
Return True if self acts transitively on domain.
A group 𝐺 acts transitively on set 𝑆 if for all 𝑥, 𝑦 ∈ 𝑆 there is some 𝑔 ∈ 𝐺 such that 𝑥𝑔 = 𝑦.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.is_transitive()
True
sage: G = PermutationGroup([ (1,2)(3,4)(5,6) ])sage: G.is_transitive()
False>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.is_transitive()
True>>> G = PermutationGroup([ (1,2)(3,4)(5,6) ])>>> G.is_transitive()
False
sage: G = PermutationGroup([[(1,2,3,4,5)],[(1,2)],[(6,7)]])sage: G.is_transitive([1,2,3,4,5])
True
sage: G.is_transitive([1..7])
False
sage: G.is_transitive(G.non_fixed_points())
False
sage: H = PermutationGroup([[(1,2,3)],[(4,5,6)]])sage: H.is_transitive(H.non_fixed_points())
False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5))],[(Integer(1),Integer(2))],[(Integer(6),Integer(7))]])>>> G.is_transitive([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
True>>> G.is_transitive((ellipsis_range(Integer(1),Ellipsis,Integer(7))))
False>>> G.is_transitive(G.non_fixed_points())
False>>> H = PermutationGroup([[(Integer(1),Integer(2),Integer(3))],[(Integer(4),˓→Integer(5),Integer(6))]])(continues on next page)

466

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> H.is_transitive(H.non_fixed_points())
False

If 𝐺 does not act on the domain, it always returns False:
sage: G = PermutationGroup([[(1,2,3,4,5)],[(1,2)]]) #S_5 on [1..5]
sage: G.is_transitive([1,4,5])
False>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5))],[(Integer(1),Integer(2))]]) #S_5 on [1..5]>>> G.is_transitive([Integer(1),Integer(4),Integer(5)])
False

Note that this differs from the definition in GAP, where IsTransitive returns whether the group istransitive on the set of points moved by the group.
sage: G = PermutationGroup([(2,3)])
sage: G.is_transitive()
False
sage: gap(G).IsTransitive()true>>> from sage.all import *>>> G = PermutationGroup([(Integer(2),Integer(3))])>>> G.is_transitive()
False>>> gap(G).IsTransitive()true

is_trivial()
Return True if this group is the trivial group.
A permutation group is trivial, if it consists only of the identity element, that is, if it has no generators or only
trivial generators.
EXAMPLES:
sage: G = PermutationGroup([], domain=["a", "b", "c"])sage: G.is_trivial()
True
sage: SymmetricGroup(0).is_trivial()
True
sage: SymmetricGroup(1).is_trivial()
True
sage: SymmetricGroup(2).is_trivial()
False
sage: DihedralGroup(1).is_trivial()
False>>> from sage.all import *>>> G = PermutationGroup([], domain=["a", "b", "c"])>>> G.is_trivial()
True>>> SymmetricGroup(Integer(0)).is_trivial()(continues on next page)

27.3. Permutation groups

467

Groups, Release 10.4

(continued from previous page)True>>> SymmetricGroup(Integer(1)).is_trivial()
True>>> SymmetricGroup(Integer(2)).is_trivial()
False>>> DihedralGroup(Integer(1)).is_trivial()
False

isomorphism_to(right)
Return an isomorphism from self to right if the groups are isomorphic, otherwise None.
INPUT:• self – this group• right – a permutation group
OUTPUT: None, or a morphism of permutation groups
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: H = PermutationGroup([ (1,2,3)(4,5) ])sage: G.isomorphism_to(H) is None
True
sage: G = PermutationGroup([(1,2,3), (2,3)])
sage: H = PermutationGroup([(1,2,4), (1,4)])
sage: G.isomorphism_to(H) # not tested, see below
Permutation group morphism:
From: Permutation Group with generators [(2,3), (1,2,3)]To:
Permutation Group with generators [(1,2,4), (1,4)]
Defn: [(2,3), (1,2,3)] -> [(2,4), (1,2,4)]>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> H = PermutationGroup([ (1,2,3)(4,5) ])>>> G.isomorphism_to(H) is None
True>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)), (Integer(2),˓→Integer(3))])>>> H = PermutationGroup([(Integer(1),Integer(2),Integer(4)), (Integer(1),˓→Integer(4))])>>> G.isomorphism_to(H) # not tested, see below
Permutation group morphism:
From: Permutation Group with generators [(2,3), (1,2,3)]To:
Permutation Group with generators [(1,2,4), (1,4)]
Defn: [(2,3), (1,2,3)] -> [(2,4), (1,2,4)]

isomorphism_type_info_simple_group()
If the group is simple, then this returns the name of the group.
EXAMPLES:
sage: G = CyclicPermutationGroup(5)sage: G.isomorphism_type_info_simple_group()
rec(name := "Z(5)",parameter := 5,(continues on next page)

468

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)series := "Z",shortname := "C5" )>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(5))>>> G.isomorphism_type_info_simple_group()
rec(name := "Z(5)",parameter := 5,
series := "Z",shortname := "C5" )iteration(algorithm='SGS')
Return an iterator over the elements of this group.
INPUT:• algorithm – (default: "SGS") either– "SGS" – using strong generating system– "BFS" – a breadth first search on the Cayley graph with respect to self.gens()– "DFS" – a depth first search on the Cayley graph with respect to self.gens()
Note: In general, the algorithm "SGS" is faster. Yet, for small groups, "BFS" and "DFS" might be faster.

Note: The order in which the iterator visits the elements differs in the algorithms.
EXAMPLES:
sage: G = PermutationGroup([[(1,2)], [(2,3)]])sage: list(G.iteration())[(), (1,2,3), (1,3,2), (2,3), (1,2), (1,3)]
sage: list(G.iteration(algorithm="BFS"))[(), (2,3), (1,2), (1,2,3), (1,3,2), (1,3)]
sage: list(G.iteration(algorithm="DFS"))[(), (1,2), (1,3,2), (1,3), (1,2,3), (2,3)]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2))], [(Integer(2),˓→Integer(3))]])>>> list(G.iteration())[(), (1,2,3), (1,3,2), (2,3), (1,2), (1,3)]>>> list(G.iteration(algorithm="BFS"))[(), (2,3), (1,2), (1,2,3), (1,3,2), (1,3)]>>> list(G.iteration(algorithm="DFS"))[(), (1,2), (1,3,2), (1,3), (1,2,3), (2,3)]

27.3. Permutation groups469

Groups, Release 10.4

largest_moved_point()
Return the largest point moved by a permutation in this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: G.largest_moved_point()
4
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.largest_moved_point()
10>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> G.largest_moved_point()
4>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.largest_moved_point()
10
sage: G = PermutationGroup([[( a , b , c ),( d , e )]])
sage: G.largest_moved_point()e>>> from sage.all import *>>> G = PermutationGroup([[( a , b , c ),( d , e )]])>>> G.largest_moved_point()eWarning: The name of this function is not good; this function should be deprecated in term of degree:
sage: P = PermutationGroup([[1,2,3,4]])
sage: P.largest_moved_point()
4
sage: P.cardinality()1>>> from sage.all import *>>> P = PermutationGroup([[Integer(1),Integer(2),Integer(3),Integer(4)]])>>> P.largest_moved_point()
4>>> P.cardinality()1list()
Return list of all elements of this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])sage: G.list()[(), (1,4)(2,3), (1,2)(3,4), (1,3)(2,4), (2,4,3), (1,4,2),(1,2,3), (1,3,4), (2,3,4), (1,4,3), (1,2,4), (1,3,2), (3,4),(continues on next page)

470

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)(1,4,2,3), (1,2), (1,3,2,4), (2,4), (1,4,3,2), (1,2,3,4),(1,3), (2,3), (1,4), (1,2,4,3), (1,3,4,2)]
sage: G = PermutationGroup([[( a , b )]], domain=( a ,Permutation Group with generators [( a , b )]sage: G.list()[(), ( a , b )]b )); G>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2))]])>>> G.list()[(), (1,4)(2,3), (1,2)(3,4), (1,3)(2,4), (2,4,3), (1,4,2),(1,2,3), (1,3,4), (2,3,4), (1,4,3), (1,2,4), (1,3,2), (3,4),(1,4,2,3), (1,2), (1,3,2,4), (2,4), (1,4,3,2), (1,2,3,4),(1,3), (2,3), (1,4), (1,2,4,3), (1,3,4,2)]>>> G = PermutationGroup([[( a , b )]], domain=( a ,Permutation Group with generators [( a , b )]>>> G.list()[(), ( a , b )]b )); G

lower_central_series()
Return the lower central series of this group as a list of permutation groups.
EXAMPLES:
These computations use pseudo-random numbers, so we set the seed for reproducible testing.
sage: set_random_seed(0)sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G.lower_central_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]>>> from sage.all import *>>> set_random_seed(Integer(0))>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G.lower_central_series()[Subgroup generated by [(3,4), (1,2,3)(4,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)]),Subgroup generated by [(1,5)(3,4), (1,5)(2,4), (1,3,5)] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]maximal_normal_subgroups()
Return the maximal proper normal subgroups of self.
This raises an error if 𝐺/[𝐺, 𝐺] is infinite, yielding infinitely many maximal normal subgroups.
EXAMPLES:
sage: G = PermutationGroup([(1,2,3),(4,5)])
sage: G.maximal_normal_subgroups()[Subgroup generated by [(1,2,3)] of (Permutation Group with generators [(4,5),(continues on next page)

27.3. Permutation groups

471

Groups, Release 10.4

(continued from previous page)(1,2,3)]),Subgroup generated by [(4,5)] of (Permutation Group with generators [(4,5),␣
˓→(1,2,3)])]˓→>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))])>>> G.maximal_normal_subgroups()[Subgroup generated by [(1,2,3)] of (Permutation Group with generators [(4,5),
˓→ (1,2,3)]),Subgroup generated by [(4,5)] of (Permutation Group with generators [(4,5),␣
˓→(1,2,3)])]minimal_generating_set()
Return a minimal generating set
EXAMPLES:
sage: # needs sage.graphs
sage: g = graphs.CompleteGraph(4)sage: g.relabel([ a , b , c , d ])sage: mgs = g.automorphism_group().minimal_generating_set(); len(mgs)2sage: mgs # random[( b , d , c ), ( a , c , b , d )]>>> from sage.all import *>>> # needs sage.graphs>>> g = graphs.CompleteGraph(Integer(4))>>> g.relabel([ a , b , c , d ])>>> mgs = g.automorphism_group().minimal_generating_set(); len(mgs)2>>> mgs # random[( b , d , c ), ( a , c , b , d )]minimal_normal_subgroups()
Return the nontrivial minimal normal subgroups self.
EXAMPLES:
sage: G = PermutationGroup([(1,2,3),(4,5)])
sage: G.minimal_normal_subgroups()[Subgroup generated by [(4,5)] of (Permutation Group with generators [(4,5),␣
˓→(1,2,3)]),Subgroup generated by [(1,2,3)] of (Permutation Group with generators [(4,5),
˓→ (1,2,3)])]>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))])>>> G.minimal_normal_subgroups()[Subgroup generated by [(4,5)] of (Permutation Group with generators [(4,5),␣
˓→(1,2,3)]),Subgroup generated by [(1,2,3)] of (Permutation Group with generators [(4,5),
˓→ (1,2,3)])]472

Chapter 27. Permutation Groups

Groups, Release 10.4

molien_series()
Return the Molien series of a permutation group. The function∑︁
𝑀 (𝑥) = (1/|𝐺|)det(1 − 𝑥 * 𝑔)−1𝑔∈𝐺

is sometimes called the “Molien series” of 𝐺. GAP’s MolienSeries is associated to a character of agroup 𝐺. How are these related? A group 𝐺, given as a permutation group on 𝑛 points, has a “natural”
representation of dimension 𝑛, given by permutation matrices. The Molien series of 𝐺 is the one associatedto that permutation representation of 𝐺 using the above formula. Character values then count fixed points ofthe corresponding permutations.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.molien_series()-1/(x^15 - x^14 - x^13 + x^10 + x^9 + x^8 - x^7 - x^6 - x^5 + x^2 + x - 1)sage: G = SymmetricGroup(3)sage: G.molien_series()-1/(x^6 - x^5 - x^4 + x^2 + x - 1)>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.molien_series()-1/(x^15 - x^14 - x^13 + x^10 + x^9 + x^8 - x^7 - x^6 - x^5 + x^2 + x - 1)>>> G = SymmetricGroup(Integer(3))>>> G.molien_series()-1/(x^6 - x^5 - x^4 + x^2 + x - 1)

Some further tests (after Issue #15817):
sage: G = PermutationGroup([[(1,2,3,4)]])sage: S4ms = SymmetricGroup(4).molien_series()
sage: G.molien_series() / S4ms
x^5 + 2*x^4 + x^3 + x^2 + 1>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> S4ms = SymmetricGroup(Integer(4)).molien_series()>>> G.molien_series() / S4ms
x^5 + 2*x^4 + x^3 + x^2 + 1

This works for not-transitive groups:
sage: G = PermutationGroup([[(1,2)],[(3,4)]])sage: G.molien_series() / S4msx^4 + x^3 + 2*x^2 + x + 1>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2))],[(Integer(3),˓→Integer(4))]])>>> G.molien_series() / S4msx^4 + x^3 + 2*x^2 + x + 1

This works for groups with fixed points:

27.3. Permutation groups473

Groups, Release 10.4

sage: G = PermutationGroup([[(2,)]])
sage: G.molien_series()
1/(x^2 - 2*x + 1)>>> from sage.all import *>>> G = PermutationGroup([[(Integer(2),)]])>>> G.molien_series()
1/(x^2 - 2*x + 1)

ngens()
Return the number of generators of self.
EXAMPLES:
sage: A4 = PermutationGroup([[(1,2,3)], [(2,3,4)]]); A4
Permutation Group with generators [(2,3,4), (1,2,3)]
sage: A4.ngens()2>>> from sage.all import *>>> A4 = PermutationGroup([[(Integer(1),Integer(2),Integer(3))], [(Integer(2),˓→Integer(3),Integer(4))]]); A4
Permutation Group with generators [(2,3,4), (1,2,3)]>>> A4.ngens()2

non_fixed_points()
Return the list of points not fixed by self, i.e., the subset of self.domain() moved by some elementof self.
EXAMPLES:
sage: G = PermutationGroup([[(3,4,5)],[(7,10)]])sage: G.non_fixed_points()[3, 4, 5, 7, 10]
sage: G = PermutationGroup([[(2,3,6)],[(9,)]]) # note: 9 is fixed
sage: G.non_fixed_points()[2, 3, 6]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(3),Integer(4),Integer(5))],[(Integer(7),˓→Integer(10))]])>>> G.non_fixed_points()[3, 4, 5, 7, 10]>>> G = PermutationGroup([[(Integer(2),Integer(3),Integer(6))],[(Integer(9),˓→)]]) # note: 9 is fixed>>> G.non_fixed_points()[2, 3, 6]

normal_subgroups()
Return the normal subgroups of this group as a (sorted in increasing order) list of permutation groups.
The normal subgroups of 𝐻 = 𝑃 𝑆𝐿(2, 7) × 𝑃 𝑆𝐿(2, 7) are 1, two copies of 𝑃 𝑆𝐿(2, 7) and 𝐻 itself, as thefollowing example shows.
EXAMPLES:

474

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: G = PSL(2,7)
sage: D = G.direct_product(G)sage: H = D[0]sage: NH = H.normal_subgroups()
sage: len(NH)4sage: NH[1].is_isomorphic(G)Truesage: NH[2].is_isomorphic(G)True>>> from sage.all import *>>> G = PSL(Integer(2),Integer(7))>>> D = G.direct_product(G)>>> H = D[Integer(0)]>>> NH = H.normal_subgroups()>>> len(NH)4>>> NH[Integer(1)].is_isomorphic(G)
True>>> NH[Integer(2)].is_isomorphic(G)Truenormalizer(g)Return the normalizer of g in self.
EXAMPLES:
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: g = G([(1,3)])
sage: G.normalizer(g)Subgroup generated by [(1,3), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])
sage: g = G([(1,2,3,4)])
sage: G.normalizer(g)Subgroup generated by [(1,2,3,4), (1,3)(2,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])
sage: H = G.subgroup([G([(1,2,3,4)])])
sage: G.normalizer(H)Subgroup generated by [(1,2,3,4), (1,3)(2,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> g = G([(Integer(1),Integer(3))])>>> G.normalizer(g)Subgroup generated by [(1,3), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))])>>> G.normalizer(g)Subgroup generated by [(1,2,3,4), (1,3)(2,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])>>> H = G.subgroup([G([(Integer(1),Integer(2),Integer(3),Integer(4))])])>>> G.normalizer(H)Subgroup generated by [(1,2,3,4), (1,3)(2,4), (2,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])27.3. Permutation groups

475

Groups, Release 10.4

normalizes(other)
Return True if the group other is normalized by self.
Wraps GAP’s IsNormal function.
A group 𝐺 normalizes a group 𝑈 if and only if for every 𝑔 ∈ 𝐺 and 𝑢 ∈ 𝑈 the element 𝑢𝑔 is a member of
𝑈 . Note that 𝑈 need not be a subgroup of 𝐺.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: H = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: H.normalizes(G)False
sage: G = SymmetricGroup(3)sage: H = PermutationGroup( [ (4,5,6) ] )sage: G.normalizes(H)True
sage: H.normalizes(G)True>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> H = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> H.normalizes(G)False>>> G = SymmetricGroup(Integer(3))>>> H = PermutationGroup( [ (Integer(4),Integer(5),Integer(6)) ] )>>> G.normalizes(H)True>>> H.normalizes(G)True

In the last example, 𝐺 and 𝐻 are disjoint, so each normalizes the other.
one()
Return the identity element of this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)]])sage: e = G.identity(); e()sage: g = G.gen(0)sage: g*e
(1,2,3)(4,5)
sage: e*g
(1,2,3)(4,5)# indirect doctest

sage: S = SymmetricGroup([ a , b , c ])sage: S.identity()()>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))]])>>> e = G.identity(); e# indirect doctest()(continues on next page)

476

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> g = G.gen(Integer(0))>>> g*e(1,2,3)(4,5)>>> e*g(1,2,3)(4,5)>>> S = SymmetricGroup([ a , b , c ])>>> S.identity()()

orbit(point, action='OnPoints')
Return the orbit of a point under a group action.
INPUT:• point – can be a point or any of the list above, depending on the action to be considered.
• action – string. if point is an element from the domain, a tuple of elements of the domain, a tupleof tuples […], this variable describes how the group is acting.
The actions currently available through this method are "OnPoints", "OnTuples", "OnSets","OnPairs", "OnSetsSets", "OnSetsDisjointSets", "OnSetsTuples", "OnTuplesSets", "OnTuplesTuples". They are taken from GAP’s list of group actions, see gap.
help( Group Actions ).
It is set to "OnPoints" by default. See below for examples.
OUTPUT:
The orbit of point as a tuple. Each entry is an image under the action of the permutation group, if necessary
converted to the corresponding container. That is, if action= OnSets then each entry will be a set evenif point was given by a list/tuple/iterable.
EXAMPLES:
sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])sage: G.orbit(3)(3, 4, 1)
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.orbit(3)(3, 4, 10, 1, 2)
sage: G = PermutationGroup([ [( c , d )], [( a , c )] ])sage: G.orbit( a )( a , c , d )>>> from sage.all import *>>> G = PermutationGroup([ [(Integer(3),Integer(4))], [(Integer(1),˓→Integer(3))] ])>>> G.orbit(Integer(3))(3, 4, 1)>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.orbit(Integer(3))(3, 4, 10, 1, 2)>>> G = PermutationGroup([ [( c , d )], [( a , c )] ])>>> G.orbit( a )( a , c , d )Action of 𝑆3 on sets:
27.3. Permutation groups

477

Groups, Release 10.4

sage: S3 = groups.permutation.Symmetric(3)sage: S3.orbit((1,2), action = "OnSets")({1, 2}, {2, 3}, {1, 3})>>> from sage.all import *>>> S3 = groups.permutation.Symmetric(Integer(3))>>> S3.orbit((Integer(1),Integer(2)), action = "OnSets")({1, 2}, {2, 3}, {1, 3})

On tuples:sage: S3.orbit((1,2), action = "OnTuples")((1, 2), (2, 3), (2, 1), (3, 1), (1, 3), (3, 2))>>> from sage.all import *>>> S3.orbit((Integer(1),Integer(2)), action = "OnTuples")((1, 2), (2, 3), (2, 1), (3, 1), (1, 3), (3, 2))

Action of 𝑆4 on sets of disjoint sets:
sage: S4 = groups.permutation.Symmetric(4)sage: O = S4.orbit(((1,2),(3,4)), action="OnSetsDisjointSets")sage: {1, 2} in O[0] and {3, 4} in O[0]Truesage: {1, 4} in O[1] and {2, 3} in O[1]Truesage: all(x[0].union(x[1]) == {1,2,3,4} for x in O)
True>>> from sage.all import *>>> S4 = groups.permutation.Symmetric(Integer(4))>>> O = S4.orbit(((Integer(1),Integer(2)),(Integer(3),Integer(4))), action=
˓→"OnSetsDisjointSets")>>> {Integer(1), Integer(2)} in O[Integer(0)] and {Integer(3), Integer(4)} in␣
˓→O[Integer(0)]True>>> {Integer(1), Integer(4)} in O[Integer(1)] and {Integer(2), Integer(3)} in␣
˓→O[Integer(1)]True>>> all(x[Integer(0)].union(x[Integer(1)]) == {Integer(1),Integer(2),˓→Integer(3),Integer(4)} for x in O)
True

Action of 𝑆4 (on a nonstandard domain) on tuples of sets:
sage: S4 = PermutationGroup([ [( c , d )], [( a , c )], [( a , b )] ])sage: orb = S4.orbit((( a , c ),( b , d )), "OnTuplesSets")sage: expect = (({ a , c }, { b , d }), ({ a , d }, { c , b }),....:({ c , b }, { a , d }), ({ b , d }, { a , c }),....:({ c , d }, { a , b }), ({ a , b }, { c , d }))sage: expect == orb
True>>> from sage.all import *>>> S4 = PermutationGroup([ [( c , d )], [( a , c )], [( a , b )] ])>>> orb = S4.orbit((( a , c ),( b , d )), "OnTuplesSets")(continues on next page)

478

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> expect = (({ a ,...
({ c ,...
({ c ,>>> expect == orb
Truec }, { b ,b }, { a ,d }, { a ,d }), ({ a ,d }), ({ b ,b }), ({ a ,d }, { c ,d }, { a ,b }, { c ,

b }),
c }),
d }))

Action of 𝑆4 (on a very nonstandard domain) on tuples of sets:
sage: S4 = PermutationGroup([ [((11,(12,13)), d )],....:[((12,(12,11)),(11,(12,13)))], [((12,(12,11)), b )] ])sage: orb = S4.orbit((( (11,(12,13)), (12,(12,11))),( b , d )),....:"OnTuplesSets")sage: expect = (({(11, (12, 13)), (12, (12, 11))}, { b , d }),....:({ d , (12, (12, 11))}, {(11, (12, 13)), b }),....:({(11, (12, 13)), b }, { d , (12, (12, 11))}),....:({(11, (12, 13)), d }, { b , (12, (12, 11))}),....:({ b , d }, {(11, (12, 13)), (12, (12, 11))}),....:({ b , (12, (12, 11))}, {(11, (12, 13)), d }))sage: all(x in orb for x in expect) and len(orb) == len(expect)
True>>> from sage.all import *>>> S4 = PermutationGroup([ [((Integer(11),(Integer(12),Integer(13))), d )],...
[((Integer(12),(Integer(12),Integer(11))),(Integer(11),˓→(Integer(12),Integer(13))))], [((Integer(12),(Integer(12),Integer(11))), b˓→ )] ])>>> orb = S4.orbit((( (Integer(11),(Integer(12),Integer(13))), (Integer(12),˓→(Integer(12),Integer(11)))),( b , d )),...
"OnTuplesSets")>>> expect = (({(Integer(11), (Integer(12), Integer(13))), (Integer(12),␣
˓→(Integer(12), Integer(11)))}, { b ,
d }),
...
({ d , (Integer(12), (Integer(12), Integer(11)))},
˓→{(Integer(11), (Integer(12), Integer(13))),
b }),
...
({(Integer(11), (Integer(12), Integer(13))), b }, { d ,␣˓→(Integer(12), (Integer(12), Integer(11)))}),...
({(Integer(11), (Integer(12), Integer(13))), d }, { b ,␣˓→(Integer(12), (Integer(12), Integer(11)))}),...
({ b , d }, {(Integer(11), (Integer(12), Integer(13))),␣
˓→(Integer(12), (Integer(12), Integer(11)))}),...
({ b , (Integer(12), (Integer(12), Integer(11)))},
˓→{(Integer(11), (Integer(12), Integer(13))),d }))>>> all(x in orb for x in expect) and len(orb) == len(expect)
Trueorbits()Return the orbits of the elements of the domain under the default group action.
EXAMPLES:
sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])sage: G.orbits()((1, 3, 4), (2,))
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.orbits()((1, 2, 3, 4, 10), (5,), (6,), (7,), (8,), (9,))(continues on next page)

27.3. Permutation groups479

Groups, Release 10.4

(continued from previous page)

sage: G = PermutationGroup([ [( c , d )], [( a , c )],[( b ,)]])
sage: G.orbits()(( a , c , d ), ( b ,))>>> from sage.all import *>>> G = PermutationGroup([ [(Integer(3),Integer(4))], [(Integer(1),˓→Integer(3))] ])>>> G.orbits()((1, 3, 4), (2,))>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.orbits()((1, 2, 3, 4, 10), (5,), (6,), (7,), (8,), (9,))>>> G = PermutationGroup([ [( c , d )], [( a , c )],[( b ,)]])>>> G.orbits()(( a , c , d ), ( b ,))The answer is cached:sage: G.orbits() is G.orbits()True>>> from sage.all import *>>> G.orbits() is G.orbits()
True

AUTHORS:• Nathan Dunfieldorder()
Return the number of elements of this group.
See also: degree().
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: G.order()12sage: G = PermutationGroup([()])
sage: G.order()1sage: G = PermutationGroup([])
sage: G.order()1>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> G.order()12>>> G = PermutationGroup([()])>>> G.order()1(continues on next page)

480

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G = PermutationGroup([])>>> G.order()1cardinality() is just an alias:
sage: PermutationGroup([(1,2,3)]).cardinality()3>>> from sage.all import *>>> PermutationGroup([(Integer(1),Integer(2),Integer(3))]).cardinality()3

poincare_series(p=2, n=10)
Return the Poincaré series of 𝐺 mod 𝑝 (𝑝 ≥ 2 must be a prime), for 𝑛 large.
In other words, if you input a finite group 𝐺, a prime 𝑝, and a positive integer 𝑛, it returns a quotient ofpolynomials 𝑓 (𝑥) = 𝑃 (𝑥)/𝑄(𝑥) whose coefficient of 𝑥𝑘 equals the rank of the vector space 𝐻𝑘 (𝐺, /𝑝 ),for all 𝑘 in the range 1 ≤ 𝑘 ≤ 𝑛.
REQUIRES: GAP package HAP (in gap_packages-*.spkg).
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.poincare_series(2, 10)
˓→package_hap(x^2 + 1)/(x^4 - x^3 - x + 1)
sage: G = SymmetricGroup(3)sage: G.poincare_series(2, 10)
˓→package_hap-1/(x - 1)

# optional - gap_

# optional - gap_>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.poincare_series(Integer(2), Integer(10))˓→optional - gap_package_hap(x^2 + 1)/(x^4 - x^3 - x + 1)>>> G = SymmetricGroup(Integer(3))>>> G.poincare_series(Integer(2), Integer(10))˓→optional - gap_package_hap-1/(x - 1)#␣#␣

AUTHORS:• David Joyner and Graham Ellis
quotient(N, **kwds)
Return the quotient of this permutation group by the normal subgroup 𝑁 , as a permutation group.
Further named arguments are passed to the permutation group constructor.
Wraps the GAP operator “/”.
EXAMPLES:

27.3. Permutation groups

481

Groups, Release 10.4

sage: G = PermutationGroup([(1,2,3), (2,3)])
sage: N = PermutationGroup([(1,2,3)])
sage: G.quotient(N)Permutation Group with generators [(1,2)]
sage: G.quotient(G)Permutation Group with generators [(), ()]>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)), (Integer(2),˓→Integer(3))])>>> N = PermutationGroup([(Integer(1),Integer(2),Integer(3))])>>> G.quotient(N)Permutation Group with generators [(1,2)]>>> G.quotient(G)Permutation Group with generators [(), ()]random_element()
Return a random element of this group.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])sage: a = G.random_element()
sage: a in G
True
sage: a.parent() is G
True
sage: a^6()>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))], [(Integer(1),Integer(2))]])>>> a = G.random_element()>>> a in G
True>>> a.parent() is G
True>>> a**Integer(6)()

representative_action(x, y)
Return an element of self that maps 𝑥 to 𝑦 if it exists.
This method wraps the gap function RepresentativeAction, which can also return elements that map
a given set of points on another set of points.
INPUT:• x, y – two elements of the domain.
EXAMPLES:
sage: G = groups.permutation.Cyclic(14)sage: g = G.representative_action(1, 10)
sage: all(g(x) == 1 + ((x+9-1)%14) for x in G.domain())
True

482

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> G = groups.permutation.Cyclic(Integer(14))>>> g = G.representative_action(Integer(1), Integer(10))>>> all(g(x) == Integer(1) + ((x+Integer(9)-Integer(1))%Integer(14)) for x in␣
˓→G.domain())
True

semidirect_product(N, mapping, check=True)
The semidirect product of self with N.
INPUT:• N – A group which is acted on by self and naturally embeds as a normal subgroup of the returned
semidirect product.
• mapping – A pair of lists that together define a homomorphism, 𝜑 : self → Aut(N), by giving, in thesecond list, the images of the generators of self in the order given in the first list.
• check – A boolean that, if set to False, will skip the initial tests which are made on mapping. Thismay be beneficial for large N, since in such cases the injectivity test can be expensive. Set to True by
default.
OUTPUT:
The semidirect product of self and N defined by the action of self on N given in mapping (note that ahomomorphism from 𝐴 to the automorphism group of 𝐵 is equivalent to an action of 𝐴 on 𝐵’s underlying
set). The semidirect product of two groups, 𝐻 and 𝑁 , is a construct similar to the direct product in so far as
the elements are the Cartesian product of the elements of 𝐻 and the elements of 𝑁 . The operation, however,is built upon an action of 𝐻 on 𝑁 , and is defined as such:(ℎ1 , 𝑛1 )(ℎ2 , 𝑛2 ) = (ℎ1 ℎ2 , 𝑛ℎ1 2 𝑛2 )This function is a wrapper for GAP’s SemidirectProduct command. The permutation group returned
is built upon a permutation representation of the semidirect product of self and N on a set of size | 𝑁 |.
The generators of N are given as their right regular representations, while the generators of self are definedby the underlying action of self on N. It should be noted that the defining action is not always faithful, and in
this case the inputted representations of the generators of self are placed on additional letters and adjoined
to the output’s generators of self.
EXAMPLES:
Perhaps the most common example of a semidirect product comes from the family of dihedral groups. Eachdihedral group is the semidirect product of 𝐶2 with 𝐶𝑛 , where, by convention, 3 ≤ 𝑛. In this case, thenontrivial element of 𝐶2 acts on 𝐶𝑛 so as to send each element to its inverse.
sage: C2 = CyclicPermutationGroup(2)sage: C8 = CyclicPermutationGroup(8)sage: alpha = PermutationGroupMorphism_im_gens(C8,C8,[(1,8,7,6,5,4,3,2)])
sage: S = C2.semidirect_product(C8,[[(1,2)],[alpha]])sage: S == DihedralGroup(8)False
sage: S.is_isomorphic(DihedralGroup(8))
True
sage: S.gens()((3,4,5,6,7,8,9,10), (1,2)(4,10)(5,9)(6,8))>>> from sage.all import *>>> C2 = CyclicPermutationGroup(Integer(2))(continues on next page)

27.3. Permutation groups483

Groups, Release 10.4

(continued from previous page)>>> C8 = CyclicPermutationGroup(Integer(8))>>> alpha = PermutationGroupMorphism_im_gens(C8,C8,[(Integer(1),Integer(8),˓→Integer(7),Integer(6),Integer(5),Integer(4),Integer(3),Integer(2))])>>> S = C2.semidirect_product(C8,[[(Integer(1),Integer(2))],[alpha]])>>> S == DihedralGroup(Integer(8))
False>>> S.is_isomorphic(DihedralGroup(Integer(8)))
True>>> S.gens()((3,4,5,6,7,8,9,10), (1,2)(4,10)(5,9)(6,8))

A more complicated example can be drawn from [TW1980]. It is there given that a semidirect product of
𝐷4 and 𝐶3 is isomorphic to one of 𝐶2 and the dicyclic group of order 12. This nonabelian group of order 24
has very similar structure to the dicyclic and dihedral groups of order 24, the three being the only groups oforder 24 with a two-element center and 9 conjugacy classes.
sage: D4 = DihedralGroup(4)sage: C3 = CyclicPermutationGroup(3)sage: alpha1 = PermutationGroupMorphism_im_gens(C3,C3,[(1,3,2)])
sage: alpha2 = PermutationGroupMorphism_im_gens(C3,C3,[(1,2,3)])
sage: S1 = D4.semidirect_product(C3,[[(1,2,3,4),(1,3)],[alpha1,alpha2]])
sage: C2 = CyclicPermutationGroup(2)sage: Q = DiCyclicGroup(3)sage: a = Q.gens()[0]; b=Q.gens()[1].inverse()
sage: alpha = PermutationGroupMorphism_im_gens(Q,Q,[a,b])
sage: S2 = C2.semidirect_product(Q,[[(1,2)],[alpha]])sage: S1.is_isomorphic(S2)True
sage: S1.is_isomorphic(DihedralGroup(12))
False
sage: S1.is_isomorphic(DiCyclicGroup(6))
False
sage: S1.center()
Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(5,6,7), (1,2,3,4)(6,7), (1,3)])
sage: len(S1.conjugacy_classes_representatives())
9>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))>>> C3 = CyclicPermutationGroup(Integer(3))>>> alpha1 = PermutationGroupMorphism_im_gens(C3,C3,[(Integer(1),Integer(3),˓→Integer(2))])>>> alpha2 = PermutationGroupMorphism_im_gens(C3,C3,[(Integer(1),Integer(2),˓→Integer(3))])>>> S1 = D4.semidirect_product(C3,[[(Integer(1),Integer(2),Integer(3),˓→Integer(4)),(Integer(1),Integer(3))],[alpha1,alpha2]])>>> C2 = CyclicPermutationGroup(Integer(2))>>> Q = DiCyclicGroup(Integer(3))>>> a = Q.gens()[Integer(0)]; b=Q.gens()[Integer(1)].inverse()>>> alpha = PermutationGroupMorphism_im_gens(Q,Q,[a,b])>>> S2 = C2.semidirect_product(Q,[[(Integer(1),Integer(2))],[alpha]])>>> S1.is_isomorphic(S2)
True>>> S1.is_isomorphic(DihedralGroup(Integer(12)))
False(continues on next page)484

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> S1.is_isomorphic(DiCyclicGroup(Integer(6)))
False>>> S1.center()
Subgroup generated by [(1,3)(2,4)] of(Permutation Group with generators [(5,6,7), (1,2,3,4)(6,7), (1,3)])>>> len(S1.conjugacy_classes_representatives())
9

If your normal subgroup is large, and you are confident that your inputs will successfully create a semidirect
product, then it is beneficial, for the sake of time efficiency, to set the check parameter to False.
sage: C2 = CyclicPermutationGroup(2)sage: C2000 = CyclicPermutationGroup(500)
sage: alpha = PermutationGroupMorphism(C2000,C2000,[C2000.gen().inverse()])
sage: S = C2.semidirect_product(C2000,[[(1,2)],[alpha]],check=False)>>> from sage.all import *>>> C2 = CyclicPermutationGroup(Integer(2))>>> C2000 = CyclicPermutationGroup(Integer(500))>>> alpha = PermutationGroupMorphism(C2000,C2000,[C2000.gen().inverse()])>>> S = C2.semidirect_product(C2000,[[(Integer(1),Integer(2))],[alpha]],˓→check=False)

AUTHOR:• Kevin Halasz (2012-8-12)
sign_representation(base_ring=None)
Return the sign representation of self over base_ring.
INPUT:• base_ring – (optional) the base ring; the default is
EXAMPLES:
sage: G = groups.permutation.Dihedral(4)sage: G.sign_representation()
Sign representation of Dihedral group of order 8
as a permutation group over Integer Ring>>> from sage.all import *>>> G = groups.permutation.Dihedral(Integer(4))>>> G.sign_representation()
Sign representation of Dihedral group of order 8
as a permutation group over Integer Ringsmallest_moved_point()
Return the smallest point moved by a permutation in this group.
EXAMPLES:
sage: G = PermutationGroup([[(3,4)], [(2,3,4)]])sage: G.smallest_moved_point()2
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.smallest_moved_point()
1

27.3. Permutation groups

485

Groups, Release 10.4>>> from sage.all import *>>> G = PermutationGroup([[(Integer(3),Integer(4))], [(Integer(2),Integer(3),˓→Integer(4))]])>>> G.smallest_moved_point()
2>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.smallest_moved_point()
1

Note that this function uses the ordering from the domain:
sage: S = SymmetricGroup([ a , b , c ])sage: S.smallest_moved_point()a>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c ])>>> S.smallest_moved_point()asocle()
Return the socle of self.
The socle of a group 𝐺 is the subgroup generated by all minimal normal subgroups.
EXAMPLES:
sage: G = SymmetricGroup(4)sage: s = G.socle(); sSubgroup generated by [(1,2)(3,4), (1,4)(2,3)] of(Symmetric group of order 4! as a permutation group)>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> s = G.socle(); sSubgroup generated by [(1,2)(3,4), (1,4)(2,3)] of(Symmetric group of order 4! as a permutation group)

The socle of the socle is, essentially, the socle:
sage: s.socle() == s.subgroup(s.gens())
True>>> from sage.all import *>>> s.socle() == s.subgroup(s.gens())
Truesolvable_radical()
Return the solvable radical of self.
The solvable radical (or just radical) of a group 𝐺 is the largest solvable normal subgroup of 𝐺.
EXAMPLES:
sage: G = SymmetricGroup(4)sage: G.solvable_radical()(continues on next page)

486

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Subgroup generated by [(1,2,3,4), (1,2)] of(Symmetric group of order 4! as a permutation group)sage: G = SymmetricGroup(5)sage: G.solvable_radical()Subgroup generated by [()] of(Symmetric group of order 5! as a permutation group)>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> G.solvable_radical()Subgroup generated by [(1,2,3,4), (1,2)] of(Symmetric group of order 4! as a permutation group)>>> G = SymmetricGroup(Integer(5))>>> G.solvable_radical()Subgroup generated by [()] of(Symmetric group of order 5! as a permutation group)

stabilizer(point, action='OnPoints')
Return the subgroup of self which stabilize the given position. self and its stabilizers must have same
degree.
INPUT:• point – a point of the domain(), or a set of points depending on the value of action.
• action – (string; default "OnPoints") should the group be considered to act on points(action="OnPoints") or on sets of points (action="OnSets")? In the latter case, the firstargument must be a subset of domain().
EXAMPLES:
sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])sage: G.stabilizer(1)Subgroup generated by [(3,4)] of (Permutation Group with generators [(3,4),␣
˓→(1,3)])sage: G.stabilizer(3)Subgroup generated by [(1,4)] of (Permutation Group with generators [(3,4),␣
˓→(1,3)])>>> from sage.all import *>>> G = PermutationGroup([ [(Integer(3),Integer(4))], [(Integer(1),˓→Integer(3))] ])>>> G.stabilizer(Integer(1))
Subgroup generated by [(3,4)] of (Permutation Group with generators [(3,4),␣
˓→(1,3)])>>> G.stabilizer(Integer(3))
Subgroup generated by [(1,4)] of (Permutation Group with generators [(3,4),␣
˓→(1,3)])The stabilizer of a set of points:
sage: s10 = groups.permutation.Symmetric(10)sage: s10.stabilizer([1..3],"OnSets").cardinality()
30240
sage: factorial(3)*factorial(7)30240

27.3. Permutation groups

487

Groups, Release 10.4>>> from sage.all import *>>> s10 = groups.permutation.Symmetric(Integer(10))>>> s10.stabilizer((ellipsis_range(Integer(1),Ellipsis,Integer(3))),"OnSets").
˓→cardinality()
30240>>> factorial(Integer(3))*factorial(Integer(7))
30240
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.stabilizer(10)Subgroup generated by [(1,2)(3,4), (2,3,4)] of (Permutation Group with␣
˓→generators [(1,2)(3,4), (1,2,3,4,10)])sage: G.stabilizer(1) == G.subgroup([ (2,3)(4,10) , (2,10,3) ])True
sage: G = PermutationGroup([[(2,3,4)],[(6,7)]])sage: G.stabilizer(1)Subgroup generated by [(6,7), (2,3,4)] of (Permutation Group with generators␣
˓→[(6,7), (2,3,4)])
sage: G.stabilizer(2)Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])
sage: G.stabilizer(3)Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])
sage: G.stabilizer(4)Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])
sage: G.stabilizer(5)Subgroup generated by [(6,7), (2,3,4)] of (Permutation Group with generators␣
˓→[(6,7), (2,3,4)])
sage: G.stabilizer(6)Subgroup generated by [(2,3,4)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])
sage: G.stabilizer(7)Subgroup generated by [(2,3,4)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])
sage: G.stabilizer(8)Traceback (most recent call last):...
ValueError: 8 does not belong to the domain>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.stabilizer(Integer(10))
Subgroup generated by [(1,2)(3,4), (2,3,4)] of (Permutation Group with␣
˓→generators [(1,2)(3,4), (1,2,3,4,10)])>>> G.stabilizer(Integer(1)) == G.subgroup([ (2,3)(4,10) , (2,10,3) ])True>>> G = PermutationGroup([[(Integer(2),Integer(3),Integer(4))],[(Integer(6),˓→Integer(7))]])>>> G.stabilizer(Integer(1))
Subgroup generated by [(6,7), (2,3,4)] of (Permutation Group with generators␣
˓→[(6,7), (2,3,4)])>>> G.stabilizer(Integer(2))
Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])(continues on next page)

488

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G.stabilizer(Integer(3))
Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])>>> G.stabilizer(Integer(4))
Subgroup generated by [(6,7)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])>>> G.stabilizer(Integer(5))
Subgroup generated by [(6,7), (2,3,4)] of (Permutation Group with generators␣
˓→[(6,7), (2,3,4)])>>> G.stabilizer(Integer(6))
Subgroup generated by [(2,3,4)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])>>> G.stabilizer(Integer(7))
Subgroup generated by [(2,3,4)] of (Permutation Group with generators [(6,7),␣
˓→(2,3,4)])>>> G.stabilizer(Integer(8))
Traceback (most recent call last):...
ValueError: 8 does not belong to the domain
sage: G = PermutationGroup([ [( c , d )], [( a , c )] ], domain= abcd )sage: G.stabilizer( a )Subgroup generated by [( c , d )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])sage: G.stabilizer( b )Subgroup generated by [( c , d ), ( a , c )] of (Permutation Group with␣
˓→generators [( c , d ), ( a , c )])sage: G.stabilizer( c )Subgroup generated by [( a , d )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])sage: G.stabilizer( d )Subgroup generated by [( a , c )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])>>> from sage.all import *>>> G = PermutationGroup([ [( c , d )], [( a , c )] ], domain= abcd )>>> G.stabilizer( a )Subgroup generated by [( c , d )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])>>> G.stabilizer( b )Subgroup generated by [( c , d ), ( a , c )] of (Permutation Group with␣
˓→generators [( c , d ), ( a , c )])>>> G.stabilizer( c )Subgroup generated by [( a , d )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])>>> G.stabilizer( d )Subgroup generated by [( a , c )] of (Permutation Group with generators [( c ,˓→ d ), ( a , c )])strong_generating_system(base_of_group=None, implementation='sage')
Return a Strong Generating System of self according the given base for the right action of self on itself.
base_of_group is a list of the positions on which self acts, in any order. The algorithm returns a listof transversals and each transversal is a list of permutations. By default, base_of_group is [1, 2, 3,..., d] where 𝑑 is the degree of the group.
For base_of_group = [pos1 , pos2 , . . . , pos𝑑 ] let 𝐺𝑖 be the subgroup of 𝐺 = self which stabilizes
27.3. Permutation groups489

Groups, Release 10.4

pos1 , pos2 , . . . , pos𝑖 , so
𝐺 = 𝐺0 ⊃ 𝐺1 ⊃ 𝐺2 ⊃ · · · ⊃ 𝐺𝑛 = {𝑒}Then the algorithm returns [𝐺𝑖 .transversals(pos𝑖+1 )]1≤𝑖≤𝑛
INPUT:• base_of_group – (default: [1, 2, 3, ..., d]) a list containing the integers 1, 2, . . . , 𝑑 inany order, where 𝑑 is the degree of self
• implementation – (default: "sage") either– "sage" – use the direct implementation in Sage– "gap" – if used, the base_of_group must be None and the computation is directly performedin GAPOUTPUT: a list of lists of permutations from the group, which forms a strong generating system
Warning: The outputs for implementations "sage" and "gap" differ: First, the output is reversed,
and second, it might be that "sage" does not contain the trivial subgroup while "gap" does.
Also, both algorithms might yield different results based on the order in which base_of_group is
given in the first situation.
EXAMPLES:
sage: G = PermutationGroup([[(7,8)],[(3,4)],[(4,5)]])sage: G.strong_generating_system()[[()], [()], [(), (3,4), (3,5,4)], [(), (4,5)], [()], [()], [(), (7,8)], [()]]
sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])sage: G.strong_generating_system()[[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)],[(), (2,4,3), (2,3,4)],[(), (3,4)],[()]]
sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]])sage: G.strong_generating_system()[[(), (1,2,3), (1,4,6), (1,3,2), (1,5,7,4,6), (1,6,4), (1,7,5,4,6)],[(), (2,3,6), (2,6,3), (2,7,5,6,3), (2,5,6,3)(4,7), (2,4,5,6,3)],[(), (3,5,6), (3,4,7,5,6), (3,6)(5,7), (3,7,4,5,6)],[(), (4,7,5), (4,5,7), (4,6,7)],[(), (5,6,7), (5,7,6)], [()], [()]]
sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]])sage: G.strong_generating_system([5,4,3,2,1])[[(), (1,5,3,4,2), (1,5,4,3,2), (1,5)(2,3), (1,5,2)],[(1,4)(2,3), (1,4,3), (1,4,2), ()],[(1,2,3), (1,3,2), ()], [()], [()]]
sage: G = PermutationGroup([[(3,4)]])sage: G.strong_generating_system()[[()], [()], [(), (3,4)], [()]]
sage: G.strong_generating_system(base_of_group=[3,1,2,4])[[(), (3,4)], [()], [()], [()]]
sage: G = TransitiveGroup(12,17)
sage: G.strong_generating_system()[[(), (1,4,11,2)(3,6,5,8)(7,10,9,12), (1,8,3,2)(4,11,10,9)(5,12,7,6),(1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,12,7,2)(3,10,9,8)(4,11,6,5),(continues on next page)

490

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)(1,11)(2,8)(3,5)(4,10)(6,12)(7,9), (1,10,11,8)(2,3,12,5)(4,9,6,7),(1,3)(2,8)(4,10)(5,7)(6,12)(9,11), (1,2,3,8)(4,9,10,11)(5,6,7,12),(1,6,7,8)(2,3,4,9)(5,10,11,12), (1,5,9)(3,11,7), (1,9,5)(3,7,11)],[(), (2,6,10)(4,12,8), (2,10,6)(4,8,12)],[()], [()], [()], [()], [()], [()], [()], [()], [()], [()]]
sage: A = PermutationGroup([(1,2),(1,2,3,4,5,6,7,8,9)])sage: X = A.strong_generating_system()sage: Y = A.strong_generating_system(implementation="gap")
sage: [len(x) for x in X][9, 8, 7, 6, 5, 4, 3, 2, 1]
sage: [len(y) for y in Y][1, 2, 3, 4, 5, 6, 7, 8, 9]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(7),Integer(8))],[(Integer(3),Integer(4))],
˓→[(Integer(4),Integer(5))]])>>> G.strong_generating_system()[[()], [()], [(), (3,4), (3,5,4)], [(), (4,5)], [()], [()], [(), (7,8)], [()]]>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3),Integer(4))],
˓→[(Integer(1),Integer(2))]])>>> G.strong_generating_system()[[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)],[(), (2,4,3), (2,3,4)],[(), (3,4)],[()]]>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3))],[(Integer(4),˓→Integer(5),Integer(7))],[(Integer(1),Integer(4),Integer(6))]])>>> G.strong_generating_system()[[(), (1,2,3), (1,4,6), (1,3,2), (1,5,7,4,6), (1,6,4), (1,7,5,4,6)],[(), (2,3,6), (2,6,3), (2,7,5,6,3), (2,5,6,3)(4,7), (2,4,5,6,3)],[(), (3,5,6), (3,4,7,5,6), (3,6)(5,7), (3,7,4,5,6)],[(), (4,7,5), (4,5,7), (4,6,7)],[(), (5,6,7), (5,7,6)], [()], [()]]>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3))],[(Integer(2),˓→Integer(3),Integer(4))],[(Integer(3),Integer(4),Integer(5))]])>>> G.strong_generating_system([Integer(5),Integer(4),Integer(3),Integer(2),˓→Integer(1)])[[(), (1,5,3,4,2), (1,5,4,3,2), (1,5)(2,3), (1,5,2)],[(1,4)(2,3), (1,4,3), (1,4,2), ()],[(1,2,3), (1,3,2), ()], [()], [()]]>>> G = PermutationGroup([[(Integer(3),Integer(4))]])>>> G.strong_generating_system()[[()], [()], [(), (3,4)], [()]]>>> G.strong_generating_system(base_of_group=[Integer(3),Integer(1),˓→Integer(2),Integer(4)])[[(), (3,4)], [()], [()], [()]]>>> G = TransitiveGroup(Integer(12),Integer(17))>>> G.strong_generating_system()[[(), (1,4,11,2)(3,6,5,8)(7,10,9,12), (1,8,3,2)(4,11,10,9)(5,12,7,6),(1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,12,7,2)(3,10,9,8)(4,11,6,5),(1,11)(2,8)(3,5)(4,10)(6,12)(7,9), (1,10,11,8)(2,3,12,5)(4,9,6,7),(1,3)(2,8)(4,10)(5,7)(6,12)(9,11), (1,2,3,8)(4,9,10,11)(5,6,7,12),(1,6,7,8)(2,3,4,9)(5,10,11,12), (1,5,9)(3,11,7), (1,9,5)(3,7,11)],[(), (2,6,10)(4,12,8), (2,10,6)(4,8,12)],[()], [()], [()], [()], [()], [()], [()], [()], [()], [()]](continues on next page)

27.3. Permutation groups491

Groups, Release 10.4

(continued from previous page)>>> A = PermutationGroup([(Integer(1),Integer(2)),(Integer(1),Integer(2),˓→Integer(3),Integer(4),Integer(5),Integer(6),Integer(7),Integer(8),˓→Integer(9))])>>> X = A.strong_generating_system()>>> Y = A.strong_generating_system(implementation="gap")>>> [len(x) for x in X][9, 8, 7, 6, 5, 4, 3, 2, 1]>>> [len(y) for y in Y][1, 2, 3, 4, 5, 6, 7, 8, 9]

structure_description(G, latex=False)
Return a string that tries to describe the structure of G.
This methods wraps GAP’s StructureDescription method.
For full details, including the form of the returned string and the algorithm to build it, see GAP’s documentation.
INPUT:• latex – a boolean (default: False); if True, return a LaTeX formatted string
OUTPUT: string
Warning: From GAP’s documentation: The string returned by StructureDescription is not
an isomorphism invariant: non-isomorphic groups can have the same string value, and two isomorphic
groups in different representations can produce different strings.
EXAMPLES:
sage: # needs sage.groups
sage: G = CyclicPermutationGroup(6)sage: G.structure_description()C6
sage: G.structure_description(latex=True)
C_{6}sage: G2 = G.direct_product(G, maps=False)
sage: LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}>>> from sage.all import *>>> # needs sage.groups>>> G = CyclicPermutationGroup(Integer(6))>>> G.structure_description()
C6>>> G.structure_description(latex=True)
C_{6}>>> G2 = G.direct_product(G, maps=False)>>> LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}This method is mainly intended for small groups or groups with few normal subgroups. Even then there aresome surprises:

492

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: D3 = DihedralGroup(3)˓→# needs sage.groups
sage: D3.structure_description()˓→# needs sage.groupsS3␣␣>>> from sage.all import *>>> D3 = DihedralGroup(Integer(3))˓→# needs sage.groups>>> D3.structure_description()
˓→# needs sage.groups
S3␣

We use the Sage notation for the degree of dihedral groups:
sage: D4 = DihedralGroup(4)˓→# needs sage.groups
sage: D4.structure_description()˓→# needs sage.groups
D4␣␣>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))˓→# needs sage.groups>>> D4.structure_description()
˓→# needs sage.groups
D4

␣

Works for finitely presented groups (Issue #17573):
sage: F.<x, y> = FreeGroup()˓→# needs sage.groups
sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]˓→# needs sage.groups
sage: G.structure_description()˓→# needs sage.groups
C7

␣
␣
␣

>>> from sage.all import *>>> F = FreeGroup(names=( x , y ,)); (x, y,) = F._first_ngens(2)# needs sage.
˓→groups>>> G = F / [x**Integer(2)*y**-Integer(1), x**Integer(3)*y**Integer(2),␣
˓→x*y*x**-Integer(1)*y**-Integer(1)]# needs␣
˓→sage.groups>>> G.structure_description()
˓→# needs sage.groups
C7

And matrix groups (Issue #17573):
sage: groups.matrix.GL(4,2).structure_description()˓→# needs sage.libs.gap sage.modules
A8␣>>> from sage.all import *>>> groups.matrix.GL(Integer(4),Integer(2)).structure_description()␣(continues on next page)

27.3. Permutation groups493

Groups, Release 10.4

(continued from previous page)˓→# needs sage.libs.gap sage.modules

A8

subgroup(gens=None, gap_group=None, domain=None, category=None, canonicalize=True, check=True)
Wraps the PermutationGroup_subgroup constructor. The argument gens is a list of elements of
self.
EXAMPLES:
sage: G = PermutationGroup([(1,2,3),(3,4,5)])
sage: g = G((1,2,3))
sage: G.subgroup([g])
Subgroup generated by [(1,2,3)] of(Permutation Group with generators [(3,4,5), (1,2,3)])>>> from sage.all import *>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3)),(Integer(3),˓→Integer(4),Integer(5))])>>> g = G((Integer(1),Integer(2),Integer(3)))>>> G.subgroup([g])
Subgroup generated by [(1,2,3)] of(Permutation Group with generators [(3,4,5), (1,2,3)])

subgroups()
Return a list of all the subgroups of self.
OUTPUT:
Each possible subgroup of self is contained once in the returned list. The list is in order, according to thesize of the subgroups, from the trivial subgroup with one element on through up to the whole group. Conjugacy
classes of subgroups are contiguous in the list.
Warning: For even relatively small groups this method can take a very long time to execute, or create
vast amounts of output. Likely both. Its purpose is instructional, as it can be useful for studying small
groups. The 156 subgroups of the full symmetric group on 5 symbols of order 120, 𝑆5 , can be computedin about a minute on commodity hardware in 2011. The 64 subgroups of the cyclic group of order30030 = 2 · 3 · 5 · 7 · 11 · 13 takes about twice as long.
For faster results, which still exhibit the structure of the possible subgroups, use conjugacy_classes_subgroups().
EXAMPLES:
sage: G = SymmetricGroup(3)sage: G.subgroups()[Subgroup generated by [()] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3)] of(continues on next page)494

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3), (2,3)] of(Symmetric group of order 3! as a permutation group)]
sage: G = CyclicPermutationGroup(14)sage: G.subgroups()[Subgroup generated by [()] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14),(1,2,3,4,5,6,7,8,9,10,11,12,13,14)] of(Cyclic group of order 14 as a permutation group)]>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> G.subgroups()[Subgroup generated by [()] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3)] of(Symmetric group of order 3! as a permutation group),
Subgroup generated by [(1,2,3), (2,3)] of(Symmetric group of order 3! as a permutation group)]>>> G = CyclicPermutationGroup(Integer(14))>>> G.subgroups()[Subgroup generated by [()] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of(Cyclic group of order 14 as a permutation group),
Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14),(1,2,3,4,5,6,7,8,9,10,11,12,13,14)] of(Cyclic group of order 14 as a permutation group)]

AUTHOR:• Rob Beezer (2011-01-24)
sylow_subgroup(p)Return a Sylow 𝑝-subgroup of the finite group 𝐺, where 𝑝 is a prime.
This is a 𝑝-subgroup of 𝐺 whose index in 𝐺 is coprime to 𝑝.
Wraps the GAP function SylowSubgroup.
EXAMPLES:

27.3. Permutation groups495Groups, Release 10.4

sage: G = PermutationGroup([ (1,2,3) , (2,3) ])sage: G.sylow_subgroup(2)Subgroup generated by [(2,3)] of(Permutation Group with generators [(2,3), (1,2,3)])
sage: G.sylow_subgroup(5)Subgroup generated by [()] of(Permutation Group with generators [(2,3), (1,2,3)])>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3) , (2,3) ])>>> G.sylow_subgroup(Integer(2))
Subgroup generated by [(2,3)] of(Permutation Group with generators [(2,3), (1,2,3)])>>> G.sylow_subgroup(Integer(5))
Subgroup generated by [()] of(Permutation Group with generators [(2,3), (1,2,3)])transversals(point)
If G is a permutation group acting on the set 𝑋 = {1, 2, ...., 𝑛} and H is the stabilizer subgroup of <integer>,a right (respectively left) transversal is a set containing exactly one element from each right (respectively left)
coset of H. This method returns a right transversal of self by the stabilizer of self on <integer> position.
EXAMPLES:
sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])sage: G.transversals(1)[(), (1,3,4), (1,4,3)]
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])sage: G.transversals(1)[(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]
sage: G = PermutationGroup([ [( c , d )], [( a , c )] ])sage: G.transversals( a )[(), ( a , c , d ), ( a , d , c )]>>> from sage.all import *>>> G = PermutationGroup([ [(Integer(3),Integer(4))], [(Integer(1),˓→Integer(3))] ])>>> G.transversals(Integer(1))[(), (1,3,4), (1,4,3)]>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4),Integer(10))]])>>> G.transversals(Integer(1))[(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]>>> G = PermutationGroup([ [( c , d )], [( a , c )] ])>>> G.transversals( a )[(), ( a , c , d ), ( a , d , c )]trivial_character()
Return the trivial character of self.
EXAMPLES:
sage: SymmetricGroup(3).trivial_character()˓→needs sage.rings.number_field
Character of Symmetric group of order 3! as a permutation group

496

#␣

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> SymmetricGroup(Integer(3)).trivial_character()˓→# needs sage.rings.number_field
Character of Symmetric group of order 3! as a permutation group␣

upper_central_series()
Return the upper central series of this group as a list of permutation groups.
EXAMPLES:
These computations use pseudo-random numbers, so we set the seed for reproducible testing:sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: G.upper_central_series()[Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> G.upper_central_series()[Subgroup generated by [()] of(Permutation Group with generators [(3,4), (1,2,3)(4,5)])]class sage.groups.perm_gps.permgroup.PermutationGroup_subgroup(ambient, gens=None,
gap_group=None,
domain=None,
category=None,
canonicalize=True,
check=True)
Bases: PermutationGroup_generic
Subgroup subclass of PermutationGroup_generic, so instance methods are inherited.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: gens = G.gens()
sage: H = DihedralGroup(4)sage: H.subgroup(gens)
Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)sage: K = H.subgroup(gens)sage: K.list()[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
sage: K.ambient_group()
Dihedral group of order 8 as a permutation group
sage: K.gens()((1,2,3,4),)>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> gens = G.gens()>>> H = DihedralGroup(Integer(4))>>> H.subgroup(gens)
Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)(continues on next page)

27.3. Permutation groups497

Groups, Release 10.4

(continued from previous page)>>> K = H.subgroup(gens)>>> K.list()[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]>>> K.ambient_group()
Dihedral group of order 8 as a permutation group>>> K.gens()((1,2,3,4),)ambient_group()
Return the ambient group related to self.
EXAMPLES:
An example involving the dihedral group on four elements, 𝐷8 :sage: G = DihedralGroup(4)sage: H = CyclicPermutationGroup(4)sage: gens = H.gens()
sage: S = PermutationGroup_subgroup(G, list(gens))
sage: S.ambient_group()
Dihedral group of order 8 as a permutation group
sage: S.ambient_group() == G
True>>> from sage.all import *>>> G = DihedralGroup(Integer(4))>>> H = CyclicPermutationGroup(Integer(4))>>> gens = H.gens()>>> S = PermutationGroup_subgroup(G, list(gens))>>> S.ambient_group()
Dihedral group of order 8 as a permutation group>>> S.ambient_group() == G
True

is_normal(other=None)
Return True if this group is a normal subgroup of other. If other is not specified, then it is assumed tobe the ambient group.
EXAMPLES:
sage: S = SymmetricGroup([ a , b , c ])sage: H = S.subgroup([( a , b , c )]); H
Subgroup generated by [( a , b , c )] of(Symmetric group of order 3! as a permutation group)sage: H.is_normal()True>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c ])>>> H = S.subgroup([( a , b , c )]); H
Subgroup generated by [( a , b , c )] of(Symmetric group of order 3! as a permutation group)>>> H.is_normal()Truesage.groups.perm_gps.permgroup.direct_product_permgroups(P)
Takes the direct product of the permutation groups listed in P.
498

Chapter 27. Permutation Groups

Groups, Release 10.4

EXAMPLES:
sage: G1 = AlternatingGroup([1,2,4,5])
sage: G2 = AlternatingGroup([3,4,6,7])
sage: D = direct_product_permgroups([G1,G2,G1])
sage: D.order()1728
sage: D = direct_product_permgroups([G1])sage: D == G1
True
sage: direct_product_permgroups([])
Symmetric group of order 0! as a permutation group>>> from sage.all import *>>> G1 = AlternatingGroup([Integer(1),Integer(2),Integer(4),Integer(5)])>>> G2 = AlternatingGroup([Integer(3),Integer(4),Integer(6),Integer(7)])>>> D = direct_product_permgroups([G1,G2,G1])>>> D.order()1728>>> D = direct_product_permgroups([G1])>>> D == G1
True>>> direct_product_permgroups([])
Symmetric group of order 0! as a permutation group

sage.groups.perm_gps.permgroup.from_gap_list(G, src)
Convert a string giving a list of GAP permutations into a list of elements of G.
EXAMPLES:
sage: from sage.groups.perm_gps.permgroup import from_gap_list
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])sage: L = from_gap_list(G, "[(1,2,3)(4,5), (3,4)]"); L[(1,2,3)(4,5), (3,4)]
sage: L[0].parent() is G
True
sage: L[1].parent() is G
True>>> from sage.all import *>>> from sage.groups.perm_gps.permgroup import from_gap_list>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]])>>> L = from_gap_list(G, "[(1,2,3)(4,5), (3,4)]"); L[(1,2,3)(4,5), (3,4)]>>> L[Integer(0)].parent() is G
True>>> L[Integer(1)].parent() is G
Truesage.groups.perm_gps.permgroup.hap_decorator(f)A decorator for permutation group methods that require HAP. It checks to see that HAP is installed as well as
checks that the argument p is either 0 or prime.
EXAMPLES:

27.3. Permutation groups499

Groups, Release 10.4

sage: # optional - gap_package_hap
sage: from sage.groups.perm_gps.permgroup import hap_decorator
sage: def foo(self, n, p=0): print("Done")sage: foo = hap_decorator(foo)sage: foo(None, 3)
Done
sage: foo(None, 3, 0)
Done
sage: foo(None, 3, 5)
Done
sage: foo(None, 3, 4)
Traceback (most recent call last):...
ValueError: p must be 0 or prime>>> from sage.all import *>>> # optional - gap_package_hap>>> from sage.groups.perm_gps.permgroup import hap_decorator>>> def foo(self, n, p=Integer(0)): print("Done")>>> foo = hap_decorator(foo)>>> foo(None, Integer(3))
Done>>> foo(None, Integer(3), Integer(0))
Done>>> foo(None, Integer(3), Integer(5))
Done>>> foo(None, Integer(3), Integer(4))
Traceback (most recent call last):...
ValueError: p must be 0 or prime

sage.groups.perm_gps.permgroup.load_hap()
Load the GAP hap package into the default GAP interpreter interface.
EXAMPLES:
sage: sage.groups.perm_gps.permgroup.load_hap()
˓→hap>>> from sage.all import *>>> sage.groups.perm_gps.permgroup.load_hap()# optional - gap_package_# optional - gap_package_hap

27.4 “Named” Permutation groups (such as the symmetric group,
S_n)
You can construct the following permutation groups:• SymmetricGroup, 𝑆𝑛 of order 𝑛! (𝑛 can also be a list 𝑋 of distinct positive integers, in which case it returns
𝑆𝑋 )• AlternatingGroup, 𝐴𝑛 of order 𝑛!/2 (n can also be a list 𝑋 of distinct positive integers, in which case it
returns 𝐴𝑋 )• DihedralGroup, 𝐷𝑛 of order 2𝑛500

Chapter 27. Permutation Groups

Groups, Release 10.4

• GeneralDihedralGroup, 𝐷𝑖ℎ(𝐺), where 𝐺 is an abelian group• CyclicPermutationGroup, 𝐶𝑛 of order 𝑛• DiCyclicGroup, nonabelian groups of order 4𝑚 with a unique element of order 2• TransitiveGroup, 𝑛-th` transitive group of degree 𝑑 from the GAP tables of transitive groups• TransitiveGroups(d), TransitiveGroups(), set of all of the above• PrimitiveGroup, 𝑛-th` primitive group of degree 𝑑 from the GAP tables of primitive groups• PrimitiveGroups(d), PrimitiveGroups(), set of all of the above• MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24.
• KleinFourGroup, subgroup of 𝑆4 of order 4 which is not 𝐶2 × 𝐶2
• QuaternionGroup, non-abelian group of order 8, {±1, ±𝐼, ±𝐽, ±𝐾}• SplitMetacyclicGroup, nonabelian groups of order 𝑝𝑚 with cyclic subgroups of index p• SemidihedralGroup, nonabelian 2-groups with cyclic subgroups of index 2• PGL(n,q), projective general linear group of 𝑛 × 𝑛 matrices over the finite field F( 𝑞)• PSL(n,q), projective special linear group of 𝑛 × 𝑛 matrices over the finite field F( 𝑞)• PSp(2n,q), projective symplectic linear group of 2𝑛 × 2𝑛 matrices over the finite field F( 𝑞)• PSU(n,q), projective special unitary group of 𝑛 × 𝑛 matrices having coefficients in the finite field F( 𝑞 2 ) that
respect a fixed nondegenerate sesquilinear form, of determinant 1.
• PGU(n,q), projective general unitary group of 𝑛 × 𝑛 matrices having coefficients in the finite field F( 𝑞 2 ) that
respect a fixed nondegenerate sesquilinear form, modulo the centre.
• SuzukiGroup(q), Suzuki group over F( 𝑞), 2 𝐵2 (22𝑘+1 ) = 𝑆𝑧(22𝑘+1 ).
• ComplexReflectionGroup, the complex reflection group 𝐺(𝑚, 𝑝, 𝑛) or the exceptional complex reflectiongroup 𝐺𝑚
• SmallPermutationGroup, a permutation realization of a group specified by its GAP id.
AUTHOR:• David Joyner (2007-06): split from permgp.py (suggested by Nick Alexander)
REFERENCES:• Cameron, P., Permutation Groups. New York: Cambridge University Press, 1999.
• Wielandt, H., Finite Permutation Groups. New York: Academic Press, 1964.
• Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996.
Note: Though Suzuki groups are okay, Ree groups should not be wrapped as permutation groups - the construction is
too slow - unless (for small values or the parameter) they are made using explicit generators.
class sage.groups.perm_gps.permgroup_named.AlternatingGroup(domain=None)
Bases: PermutationGroup_symalt
The alternating group of order 𝑛!/2, as a permutation group.
INPUT:• n – a positive integer, or list or tuple thereof

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

501

Groups, Release 10.4

Note: This group is also available via groups.permutation.Alternating().
EXAMPLES:
sage: G = AlternatingGroup(6)sage: G.order()360
sage: G
Alternating group of order 6!/2 as a permutation group
sage: G.category()
Category of finite enumerated permutation groups
sage: TestSuite(G).run() # long time
sage: G = AlternatingGroup([1,2,4,5])
sage: G
Alternating group of order 4!/2 as a permutation group
sage: G.domain(){1, 2, 4, 5}
sage: G.category()
Category of finite enumerated permutation groups
sage: TestSuite(G).run()>>> from sage.all import *>>> G = AlternatingGroup(Integer(6))>>> G.order()
360
>>> G
Alternating group of order 6!/2 as a permutation group>>> G.category()
Category of finite enumerated permutation groups>>> TestSuite(G).run() # long time>>> G = AlternatingGroup([Integer(1),Integer(2),Integer(4),Integer(5)])>>> G
Alternating group of order 4!/2 as a permutation group>>> G.domain(){1, 2, 4, 5}>>> G.category()
Category of finite enumerated permutation groups>>> TestSuite(G).run()class sage.groups.perm_gps.permgroup_named.ComplexReflectionGroup(m, p=None,n=None)Bases: PermutationGroup_unique
A finite complex reflection group as a permutation group.
We can realize 𝐺(𝑚, 1, 𝑛) as 𝑚 copies of the symmetric group 𝑆𝑛 with 𝑠𝑖 for 1 ≤ 𝑖 < 𝑛 acting as the usual
adjacent transposition on each copy of 𝑆𝑛 . We construct the cycle 𝑠𝑛 = (𝑛, 2𝑛, . . . , 𝑚𝑛).
We construct 𝐺(𝑚, 𝑝, 𝑛) as a subgroup of 𝐺(𝑚, 1, 𝑛) by 𝑠𝑖 ↦→ 𝑠𝑖 for all 1 ≤ 𝑖 < 𝑛,𝑠𝑛 ↦→ 𝑠−1
𝑛 𝑠𝑛−1 𝑠𝑛 ,𝑠𝑛+1 ↦→ 𝑠𝑝𝑛 .

Note that if 𝑝 = 𝑚, then 𝑠𝑛+1 = 1, in which case we do not consider it as a generator.
The exceptional complex reflection groups 𝐺𝑚 (in the Shephard-Todd classification) are not yet implemented.
502

Chapter 27. Permutation Groups

Groups, Release 10.4

INPUT:
One of the following:• m, p, n – positive integers to construct 𝐺(𝑚, 𝑝, 𝑛)• m – integer such that 4 ≤ 𝑚 ≤ 37 to construct an exceptional complex reflection 𝐺𝑚
Note: This group is also available via groups.permutation.ComplexReflection().

Note: The convention for the index set is for 𝐺(𝑚, 1, 𝑛) to have the complex reflection of order 𝑚 correspond to2
𝑠𝑛 ; i.e., 𝑠𝑚
𝑛 = 1 and 𝑠𝑖 = 1 for all 𝑖 < 𝑚.
EXAMPLES:
sage: G = groups.permutation.ComplexReflection(3, 1, 5)
sage: G.order()29160
sage: G
Complex reflection group G(3, 1, 5) as a permutation group
sage: G.category()
Join of Category of finite enumerated permutation groups
and Category of finite complex reflection groups
sage: G = groups.permutation.ComplexReflection(3, 3, 4)
sage: G.cardinality()648
sage: s1, s2, s3, s4 = G.simple_reflections()
sage: s4*s2*s4 == s2*s4*s2
True
sage: (s4*s3*s2)^2 == (s2*s4*s3)^2
True
sage: G = groups.permutation.ComplexReflection(6, 2, 3)
sage: G.cardinality()648
sage: s1, s2, s3, s4 = G.simple_reflections()
sage: s3^2 == G.one()True
sage: s4^3 == G.one()True
sage: s4 * s3 * s2 == s3 * s2 * s4
Truesage: (s3*s2*s1)^2 == (s1*s3*s2)^2
True
sage: s3 * s1 * s3 == s1 * s3 * s1
Truesage: s4 * s3 * (s2*s3)^(2-1) == s2 * s4
Truesage: G = groups.permutation.ComplexReflection(4, 2, 5)
sage: G.cardinality()
61440
sage: G = groups.permutation.ComplexReflection(4)Traceback (most recent call last):(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)503

Groups, Release 10.4

(continued from previous page)...
NotImplementedError: exceptional complex reflection groups are not yet implemented>>> from sage.all import *>>> G = groups.permutation.ComplexReflection(Integer(3), Integer(1), Integer(5))>>> G.order()
29160
>>> G
Complex reflection group G(3, 1, 5) as a permutation group>>> G.category()
Join of Category of finite enumerated permutation groups
and Category of finite complex reflection groups>>> G = groups.permutation.ComplexReflection(Integer(3), Integer(3), Integer(4))>>> G.cardinality()648>>> s1, s2, s3, s4 = G.simple_reflections()>>> s4*s2*s4 == s2*s4*s2
True>>> (s4*s3*s2)**Integer(2) == (s2*s4*s3)**Integer(2)True>>> G = groups.permutation.ComplexReflection(Integer(6), Integer(2), Integer(3))>>> G.cardinality()648>>> s1, s2, s3, s4 = G.simple_reflections()>>> s3**Integer(2) == G.one()True>>> s4**Integer(3) == G.one()True>>> s4 * s3 * s2 == s3 * s2 * s4
True>>> (s3*s2*s1)**Integer(2) == (s1*s3*s2)**Integer(2)True>>> s3 * s1 * s3 == s1 * s3 * s1
True>>> s4 * s3 * (s2*s3)**(Integer(2)-Integer(1)) == s2 * s4
True>>> G = groups.permutation.ComplexReflection(Integer(4), Integer(2), Integer(5))>>> G.cardinality()
61440>>> G = groups.permutation.ComplexReflection(Integer(4))
Traceback (most recent call last):...
NotImplementedError: exceptional complex reflection groups are not yet implemented

REFERENCES:• Wikipedia article Complex_reflection_group
codegrees()
Return the codegrees of self.

504

Chapter 27. Permutation Groups

Groups, Release 10.4

Let 𝐺 be a complex reflection group. The codegrees 𝑑*1 ≤ 𝑑*2 ≤ · · · ≤ 𝑑*ℓ of 𝐺 can be defined by:
ℓ
∏︁
𝑖=1

(𝑞 − 𝑑*𝑖 − 1) =∑︁𝑔

det(𝑔)𝑞 dim(𝑉 ) ,𝑔∈𝐺

where 𝑉 is the natural complex vector space that 𝐺 acts on and ℓ is the rank().
If 𝑚 = 1, then we are in the special case of the symmetric group and the codegrees are (𝑛−2, 𝑛−3, . . . 1, 0).
Otherwise the codegrees are ((𝑛 − 1)𝑚, (𝑛 − 2)𝑚, . . . , 𝑚, 0).
EXAMPLES:
sage: C = groups.permutation.ComplexReflection(4, 1, 3)
sage: C.codegrees()(8, 4, 0)
sage: G = groups.permutation.ComplexReflection(3, 3, 4)
sage: G.codegrees()(6, 5, 3, 0)
sage: S = groups.permutation.ComplexReflection(1, 1, 3)
sage: S.codegrees()(1, 0)>>> from sage.all import *>>> C = groups.permutation.ComplexReflection(Integer(4), Integer(1),␣
˓→Integer(3))>>> C.codegrees()(8, 4, 0)>>> G = groups.permutation.ComplexReflection(Integer(3), Integer(3),␣
˓→Integer(4))>>> G.codegrees()(6, 5, 3, 0)>>> S = groups.permutation.ComplexReflection(Integer(1), Integer(1),␣
˓→Integer(3))>>> S.codegrees()(1, 0)

degrees()
Return the degrees of self.
The degrees of a complex reflection group are the degrees of the fundamental invariants of the ring of polynomial invariants.
If 𝑚 = 1, then we are in the special case of the symmetric group and the degrees are (2, 3, . . . , 𝑛, 𝑛 + 1).
Otherwise the degrees are (𝑚, 2𝑚, . . . , (𝑛 − 1)𝑚, 𝑛𝑚/𝑝).
EXAMPLES:
sage: C = groups.permutation.ComplexReflection(4, 1, 3)
sage: C.degrees()(4, 8, 12)
sage: G = groups.permutation.ComplexReflection(4, 2, 3)
sage: G.degrees()(4, 6, 8)
sage: Gp = groups.permutation.ComplexReflection(4, 4, 3)
sage: Gp.degrees()(3, 4, 8)
sage: S = groups.permutation.ComplexReflection(1, 1, 3)
sage: S.degrees()(2, 3)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

505

Groups, Release 10.4>>> from sage.all import *>>> C = groups.permutation.ComplexReflection(Integer(4), Integer(1),␣
˓→Integer(3))>>> C.degrees()(4, 8, 12)>>> G = groups.permutation.ComplexReflection(Integer(4), Integer(2),␣
˓→Integer(3))>>> G.degrees()(4, 6, 8)>>> Gp = groups.permutation.ComplexReflection(Integer(4), Integer(4),␣
˓→Integer(3))>>> Gp.degrees()(3, 4, 8)>>> S = groups.permutation.ComplexReflection(Integer(1), Integer(1),␣
˓→Integer(3))>>> S.degrees()(2, 3)

Check that the product of the degrees is equal to the cardinality:
sage: prod(C.degrees()) == C.cardinality()
True
sage: prod(G.degrees()) == G.cardinality()
True
sage: prod(Gp.degrees()) == Gp.cardinality()
True
sage: prod(S.degrees()) == S.cardinality()
True>>> from sage.all import *>>> prod(C.degrees()) == C.cardinality()
True>>> prod(G.degrees()) == G.cardinality()
True>>> prod(Gp.degrees()) == Gp.cardinality()
True>>> prod(S.degrees()) == S.cardinality()
Trueindex_set()
Return the index set of self.
EXAMPLES:
sage: G = groups.permutation.ComplexReflection(4, 1, 3)
sage: G.index_set()(1, 2, 3)
sage: G = groups.permutation.ComplexReflection(1, 1, 3)
sage: G.index_set()(1, 2)
sage: G = groups.permutation.ComplexReflection(4, 2, 3)
sage: G.index_set()(1, 2, 3, 4)
sage: G = groups.permutation.ComplexReflection(4, 4, 3)(continues on next page)

506

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: G.index_set()(1, 2, 3)
sage: G = groups.permutation.ComplexReflection(10, 2, 1)
sage: G.index_set()(1,)
sage: G = groups.permutation.ComplexReflection(10, 10, 1)
sage: G.index_set()()>>> from sage.all import *>>> G = groups.permutation.ComplexReflection(Integer(4), Integer(1),␣
˓→Integer(3))>>> G.index_set()(1, 2, 3)>>> G = groups.permutation.ComplexReflection(Integer(1), Integer(1),␣
˓→Integer(3))>>> G.index_set()(1, 2)>>> G = groups.permutation.ComplexReflection(Integer(4), Integer(2),␣
˓→Integer(3))>>> G.index_set()(1, 2, 3, 4)>>> G = groups.permutation.ComplexReflection(Integer(4), Integer(4),␣
˓→Integer(3))>>> G.index_set()(1, 2, 3)>>> G = groups.permutation.ComplexReflection(Integer(10), Integer(2),␣
˓→Integer(1))>>> G.index_set()(1,)>>> G = groups.permutation.ComplexReflection(Integer(10), Integer(10),␣
˓→Integer(1))>>> G.index_set()()

simple_reflection(i)Return the i-th simple reflection of self.
EXAMPLES:
sage: G = groups.permutation.ComplexReflection(3, 1, 4)
sage: G.simple_reflection(2)(2,3)(6,7)(10,11)
sage: G.simple_reflection(4)(4,8,12)sage: G = groups.permutation.ComplexReflection(1, 1, 4)
sage: G.simple_reflections()
Finite family {1: (1,2), 2: (2,3), 3: (3,4)}(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

507

Groups, Release 10.4

(continued from previous page)

sage: G = groups.permutation.ComplexReflection(10, 2, 1)
sage: G.simple_reflections()
Finite family {1: (1,3,5,7,9)(2,4,6,8,10)}
sage: G = groups.permutation.ComplexReflection(10, 10, 1)
sage: G.simple_reflections()
Finite family {}>>> from sage.all import *>>> G = groups.permutation.ComplexReflection(Integer(3), Integer(1),␣
˓→Integer(4))>>> G.simple_reflection(Integer(2))(2,3)(6,7)(10,11)>>> G.simple_reflection(Integer(4))(4,8,12)>>> G = groups.permutation.ComplexReflection(Integer(1), Integer(1),␣
˓→Integer(4))>>> G.simple_reflections()
Finite family {1: (1,2), 2: (2,3), 3: (3,4)}>>> G = groups.permutation.ComplexReflection(Integer(10), Integer(2),␣
˓→Integer(1))>>> G.simple_reflections()
Finite family {1: (1,3,5,7,9)(2,4,6,8,10)}>>> G = groups.permutation.ComplexReflection(Integer(10), Integer(10),␣
˓→Integer(1))>>> G.simple_reflections()
Finite family {}class sage.groups.perm_gps.permgroup_named.CyclicPermutationGroup(n)Bases: PermutationGroup_uniqueA cyclic group of order 𝑛, as a permutation group.
INPUT:• n – a positive integer
Note: This group is also available via groups.permutation.Cyclic().
EXAMPLES:
sage: G = CyclicPermutationGroup(8)sage: G.order()8sage: G
Cyclic group of order 8 as a permutation group
sage: G.category()
Category of finite enumerated permutation groups
sage: TestSuite(G).run()sage: C = CyclicPermutationGroup(10)sage: C.is_abelian()True(continues on next page)

508

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: C = CyclicPermutationGroup(10)sage: C.as_AbelianGroup()
Multiplicative Abelian group isomorphic to C2 x C5>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(8))>>> G.order()8>>> G
Cyclic group of order 8 as a permutation group>>> G.category()
Category of finite enumerated permutation groups>>> TestSuite(G).run()>>> C = CyclicPermutationGroup(Integer(10))>>> C.is_abelian()
True>>> C = CyclicPermutationGroup(Integer(10))>>> C.as_AbelianGroup()
Multiplicative Abelian group isomorphic to C2 x C5

as_AbelianGroup()
Return the corresponding AbelianGroup instance.
EXAMPLES:
sage: C = CyclicPermutationGroup(8)sage: C.as_AbelianGroup()
Multiplicative Abelian group isomorphic to C8>>> from sage.all import *>>> C = CyclicPermutationGroup(Integer(8))>>> C.as_AbelianGroup()
Multiplicative Abelian group isomorphic to C8

is_abelian()
Return True if this group is abelian.
EXAMPLES:
sage: C = CyclicPermutationGroup(8)sage: C.is_abelian()True>>> from sage.all import *>>> C = CyclicPermutationGroup(Integer(8))>>> C.is_abelian()True

is_commutative()
Return True if this group is commutative.
EXAMPLES:
sage: C = CyclicPermutationGroup(8)sage: C.is_commutative()
True

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

509

Groups, Release 10.4>>> from sage.all import *>>> C = CyclicPermutationGroup(Integer(8))>>> C.is_commutative()
True

class sage.groups.perm_gps.permgroup_named.DiCyclicGroup(n)Bases: PermutationGroup_unique
The dicyclic group of order 4𝑛, for 𝑛 ≥ 2.
INPUT:• n – a positive integer, two or greater
OUTPUT:
This is a nonabelian group similar in some respects to the dihedral group of the same order, but with far fewer
elements of order 2 (it has just one). The permutation representation constructed here is based on the presentation⟨𝑎, 𝑥 | 𝑎2𝑛 = 1, 𝑥2 = 𝑎𝑛 , 𝑥−1 𝑎𝑥 = 𝑎−1 ⟩For 𝑛 = 2 this is the group of quaternions (±1, ±𝐼, ±𝐽, ±𝐾), which is the nonabelian group of order 8 that is not
the dihedral group 𝐷4 , the symmetries of a square. For 𝑛 = 3 this is the nonabelian group of order 12 that is not
the dihedral group 𝐷6 nor the alternating group 𝐴4 . This group of order 12 is also the semi-direct product of 𝐶2
by 𝐶4 , 𝐶3 o 𝐶4 . [Con]When the order of the group is a power of 2 it is known as a “generalized quaternion group.”
IMPLEMENTATION:
The presentation above means every element can be written as 𝑎𝑖 𝑥𝑗 with 0 ≤ 𝑖 < 2𝑛, 𝑗 = 0, 1. We code 𝑎𝑖 as the
symbol 𝑖 + 1 and code 𝑎𝑖 𝑥 as the symbol 2𝑛 + 𝑖 + 1. The two generators are then represented using a left regular
representation.
Note: This group is also available via groups.permutation.DiCyclic().
EXAMPLES:
A dicyclic group of order 384, with a large power of 2 as a divisor:
sage: n = 3*2^5sage: G = DiCyclicGroup(n)sage: G.order()384
sage: a = G.gen(0)sage: x = G.gen(1)sage: a^(2*n)()
sage: a^n==x^2
True
sage: x^-1*a*x==a^-1
True>>> from sage.all import *>>> n = Integer(3)*Integer(2)**Integer(5)>>> G = DiCyclicGroup(n)>>> G.order()384(continues on next page)

510

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> a = G.gen(Integer(0))>>> x = G.gen(Integer(1))>>> a**(Integer(2)*n)()>>> a**n==x**Integer(2)True>>> x**-Integer(1)*a*x==a**-Integer(1)True

A large generalized quaternion group (order is a power of 2):
sage: n = 2^10sage: G = DiCyclicGroup(n)sage: G.order()4096
sage: a = G.gen(0)sage: x = G.gen(1)sage: a^(2*n)()
sage: a^n==x^2
True
sage: x^-1*a*x==a^-1
True>>> from sage.all import *>>> n = Integer(2)**Integer(10)>>> G = DiCyclicGroup(n)>>> G.order()4096>>> a = G.gen(Integer(0))>>> x = G.gen(Integer(1))>>> a**(Integer(2)*n)()>>> a**n==x**Integer(2)True>>> x**-Integer(1)*a*x==a**-Integer(1)True

Just like the dihedral group, the dicyclic group has an element whose order is half the order of the group. Unlike
the dihedral group, the dicyclic group has only one element of order 2. Like the dihedral groups of even order,
the center of the dicyclic group is a subgroup of order 2 (thus has the unique element of order 2 as its non-identity
element).
sage: G = DiCyclicGroup(3*5*4)
sage: G.order()240sage: two = [g for g in G if g.order()==2]; two[(1,5)(2,6)(3,7)(4,8)(9,13)(10,14)(11,15)(12,16)]
sage: G.center().order()2>>> from sage.all import *>>> G = DiCyclicGroup(Integer(3)*Integer(5)*Integer(4))>>> G.order()240>>> two = [g for g in G if g.order()==Integer(2)]; two(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

511

Groups, Release 10.4

(continued from previous page)[(1,5)(2,6)(3,7)(4,8)(9,13)(10,14)(11,15)(12,16)]>>> G.center().order()2

For small orders, we check this is really a group we do not have in Sage otherwise.
sage: G = DiCyclicGroup(2)sage: H = DihedralGroup(4)sage: G.is_isomorphic(H)False
sage: G = DiCyclicGroup(3)sage: H = DihedralGroup(6)sage: K = AlternatingGroup(6)sage: G.is_isomorphic(H) or G.is_isomorphic(K)False>>> from sage.all import *>>> G = DiCyclicGroup(Integer(2))>>> H = DihedralGroup(Integer(4))>>> G.is_isomorphic(H)
False>>> G = DiCyclicGroup(Integer(3))>>> H = DihedralGroup(Integer(6))>>> K = AlternatingGroup(Integer(6))>>> G.is_isomorphic(H) or G.is_isomorphic(K)
False

AUTHOR:• Rob Beezer (2009-10-18)
is_abelian()
Return True if this group is abelian.
EXAMPLES:
sage: D = DiCyclicGroup(12)sage: D.is_abelian()False>>> from sage.all import *>>> D = DiCyclicGroup(Integer(12))>>> D.is_abelian()
False

is_commutative()
Return True if this group is commutative.
EXAMPLES:
sage: D = DiCyclicGroup(12)sage: D.is_commutative()
False>>> from sage.all import *>>> D = DiCyclicGroup(Integer(12))(continues on next page)

512

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> D.is_commutative()
False

class sage.groups.perm_gps.permgroup_named.DihedralGroup(n)Bases: PermutationGroup_unique
The Dihedral group of order 2𝑛 for any integer 𝑛 ≥ 1.
INPUT:• n – a positive integer
OUTPUT: the dihedral group of order 2𝑛, as a permutation group
Note: This group is also available via groups.permutation.Dihedral().
EXAMPLES:
sage: DihedralGroup(1)Dihedral group of order 2 as a permutation group
sage: DihedralGroup(2)Dihedral group of order 4 as a permutation group
sage: DihedralGroup(2).gens()((3,4), (1,2))
sage: DihedralGroup(5).gens()((1,2,3,4,5), (1,5)(2,4))
sage: sorted(DihedralGroup(5))[(), (2,5)(3,4), (1,2)(3,5), (1,2,3,4,5), (1,3)(4,5), (1,3,5,2,4),(1,4)(2,3), (1,4,2,5,3), (1,5,4,3,2), (1,5)(2,4)]
sage: G = DihedralGroup(6)sage: G.order()12sage: G = DihedralGroup(5)sage: G.order()10sage: G
Dihedral group of order 10 as a permutation group
sage: G.gens()((1,2,3,4,5), (1,5)(2,4))
sage: DihedralGroup(0)Traceback (most recent call last):...
ValueError: n must be positive>>> from sage.all import *>>> DihedralGroup(Integer(1))
Dihedral group of order 2 as a permutation group>>> DihedralGroup(Integer(2))
Dihedral group of order 4 as a permutation group>>> DihedralGroup(Integer(2)).gens()((3,4), (1,2))(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

513

Groups, Release 10.4

(continued from previous page)>>> DihedralGroup(Integer(5)).gens()((1,2,3,4,5), (1,5)(2,4))>>> sorted(DihedralGroup(Integer(5)))[(), (2,5)(3,4), (1,2)(3,5), (1,2,3,4,5), (1,3)(4,5), (1,3,5,2,4),(1,4)(2,3), (1,4,2,5,3), (1,5,4,3,2), (1,5)(2,4)]>>> G = DihedralGroup(Integer(6))>>> G.order()12>>> G = DihedralGroup(Integer(5))>>> G.order()10>>> G
Dihedral group of order 10 as a permutation group>>> G.gens()((1,2,3,4,5), (1,5)(2,4))>>> DihedralGroup(Integer(0))
Traceback (most recent call last):...
ValueError: n must be positiveclass sage.groups.perm_gps.permgroup_named.GeneralDihedralGroup(factors)
Bases: PermutationGroup_generic
The Generalized Dihedral Group generated by the abelian group with direct factors in the input list.
INPUT:• factors – a list of the sizes of the cyclic factors of the abelian group being dihedralized (this will be sorted
once entered)
OUTPUT:For a given abelian group (noting that each finite abelian group can be represented as the direct product of cyclic
groups), the General Dihedral Group it generates is simply the semi-direct product of the given group with 𝐶2 ,where the nonidentity element of 𝐶2 acts on the abelian group by turning each element into its inverse. In this
implementation, each input abelian group will be standardized so as to act on a minimal amount of letters. This
will be done by breaking the direct factors into products of p-groups, before this new set of factors is ordered fromsmallest to largest for complete standardization. Note that the generalized dihedral group corresponding to a cyclic
group, 𝐶𝑛 , is simply the dihedral group 𝐷𝑛 .
EXAMPLES:
As is noted in [TW1980], 𝐷𝑖ℎ(𝐶3 × 𝐶3 ) has the presentation⟨𝑎, 𝑏, 𝑐 | 𝑎3 , 𝑏3 , 𝑐2 , 𝑎𝑏 = 𝑏𝑎, 𝑎𝑐 = 𝑐𝑎−1 , 𝑏𝑐 = 𝑐𝑏−1 ⟩Note also the fact, verified by [TW1980], that the dihedralization of 𝐶3 × 𝐶3 is the only nonabelian group of order
18 with no element of order 6.
sage: G = GeneralDihedralGroup([3,3])
sage: G
Generalized dihedral group generated by C3 x C3
sage: G.order()18
sage: G.gens()(continues on next page)

514

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)((4,5,6), (2,3)(5,6), (1,2,3))
sage: a = G.gens()[2]; b = G.gens()[0]; c = G.gens()[1]sage: a.order() == 3, b.order() == 3, c.order() == 2
(True, True, True)
sage: a*b == b*a, a*c == c*a.inverse(), b*c == c*b.inverse()(True, True, True)
sage: G.subgroup([a,b,c]) == G
True
sage: G.is_abelian()False
sage: all(x.order() != 6 for x in G)
True>>> from sage.all import *>>> G = GeneralDihedralGroup([Integer(3),Integer(3)])>>> G
Generalized dihedral group generated by C3 x C3>>> G.order()18>>> G.gens()((4,5,6), (2,3)(5,6), (1,2,3))>>> a = G.gens()[Integer(2)]; b = G.gens()[Integer(0)]; c = G.gens()[Integer(1)]>>> a.order() == Integer(3), b.order() == Integer(3), c.order() == Integer(2)(True, True, True)>>> a*b == b*a, a*c == c*a.inverse(), b*c == c*b.inverse()(True, True, True)>>> G.subgroup([a,b,c]) == G
True>>> G.is_abelian()
False>>> all(x.order() != Integer(6) for x in G)
True

If all of the direct factors are 𝐶2 , then the action turning each element into its inverse is trivial, and the semi-direct
product becomes a direct product.
sage: G = GeneralDihedralGroup([2,2,2])
sage: G.order()16
sage: G.gens()((7,8), (5,6), (3,4), (1,2))
sage: G.is_abelian()True
sage: H = KleinFourGroup()
sage: G.is_isomorphic(H.direct_product(H)[0])True>>> from sage.all import *>>> G = GeneralDihedralGroup([Integer(2),Integer(2),Integer(2)])>>> G.order()16>>> G.gens()((7,8), (5,6), (3,4), (1,2))>>> G.is_abelian()
True>>> H = KleinFourGroup()(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

515

Groups, Release 10.4

(continued from previous page)>>> G.is_isomorphic(H.direct_product(H)[Integer(0)])
True

If two nonidentical input lists generate isomorphic abelian groups, then they will generate identical groups (witheach direct factor broken up into its prime factors), but they will still have distinct descriptions. Note that if
gcd(𝑛, 𝑚) = 1, then 𝐶𝑛 × 𝐶𝑚 ∼= 𝐶𝑛𝑚 , while the general dihedral groups generated by isomorphic abelian groups
should be themselves isomorphic.
sage: G = GeneralDihedralGroup([6,34,46,14])
sage: H = GeneralDihedralGroup([7,17,3,46,2,2,2])
sage: G == H, G.gens() == H.gens()(True, True)
sage: [x.order() for x in G.gens()][23, 17, 7, 2, 3, 2, 2, 2, 2]
sage: G
Generalized dihedral group generated by C6 x C34 x C46 x C14
sage: H
Generalized dihedral group generated by C7 x C17 x C3 x C46 x C2 x C2 x C2>>> from sage.all import *>>> G = GeneralDihedralGroup([Integer(6),Integer(34),Integer(46),Integer(14)])>>> H = GeneralDihedralGroup([Integer(7),Integer(17),Integer(3),Integer(46),
˓→Integer(2),Integer(2),Integer(2)])>>> G == H, G.gens() == H.gens()(True, True)>>> [x.order() for x in G.gens()][23, 17, 7, 2, 3, 2, 2, 2, 2]>>> G
Generalized dihedral group generated by C6 x C34 x C46 x C14>>> H
Generalized dihedral group generated by C7 x C17 x C3 x C46 x C2 x C2 x C2

A cyclic input yields a Classical Dihedral Group.
sage: G = GeneralDihedralGroup([6])
sage: D = DihedralGroup(6)sage: G.is_isomorphic(D)True>>> from sage.all import *>>> G = GeneralDihedralGroup([Integer(6)])>>> D = DihedralGroup(Integer(6))>>> G.is_isomorphic(D)
True

A Generalized Dihedral Group will always have size twice the underlying group, be solvable (as it has an abeliansubgroup with index 2), and, unless the underlying group is of the form 𝐶2 𝑛 , be nonabelian (by the structure
theorem of finite abelian groups and the fact that a semi-direct product is a direct product only when the underlying
action is trivial).
sage: G = GeneralDihedralGroup([6,18,33,60])
sage: (6*18*33*60)*2
427680sage: G.order()427680(continues on next page)

516

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: G.is_solvable()True
sage: G.is_abelian()False>>> from sage.all import *>>> G = GeneralDihedralGroup([Integer(6),Integer(18),Integer(33),Integer(60)])>>> (Integer(6)*Integer(18)*Integer(33)*Integer(60))*Integer(2)427680>>> G.order()427680>>> G.is_solvable()
True>>> G.is_abelian()
False

AUTHOR:• Kevin Halasz (2012-7-12)class sage.groups.perm_gps.permgroup_named.JankoGroup(n)Bases: PermutationGroup_unique
Janko Groups 𝐽1, 𝐽2, and 𝐽3. (Note that 𝐽4 is too big to be treated here.)
INPUT:• n – integer among {1, 2, 3}.
EXAMPLES:
sage: G = groups.permutation.Janko(1); G˓→gap_package_atlasrep internet
Janko group J1 of order 175560 as a permutation group>>> from sage.all import *>>> G = groups.permutation.Janko(Integer(1)); G˓→optional - gap_package_atlasrep internet
Janko group J1 of order 175560 as a permutation group# optional -␣#␣class sage.groups.perm_gps.permgroup_named.KleinFourGroupBases: PermutationGroup_unique
The Klein 4 Group, which has order 4 and exponent 2, viewed as a subgroup of 𝑆4 .
OUTPUT: the Klein 4 group of order 4, as a permutation group of degree 4
Note: This group is also available via groups.permutation.KleinFour().
EXAMPLES:
sage: G = KleinFourGroup(); G
The Klein 4 group of order 4, as a permutation group
sage: sorted(G)[(), (3,4), (1,2), (1,2)(3,4)]

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

517

Groups, Release 10.4>>> from sage.all import *>>> G = KleinFourGroup(); G
The Klein 4 group of order 4, as a permutation group>>> sorted(G)[(), (3,4), (1,2), (1,2)(3,4)]

AUTHOR:– Bobby Moretti (2006-10)class sage.groups.perm_gps.permgroup_named.MathieuGroup(n)Bases: PermutationGroup_unique
The Mathieu group of degree 𝑛.
INPUT:• n – a positive integer in {9, 10, 11, 12, 21, 22, 23, 24}.
OUTPUT: the Mathieu group of degree 𝑛, as a permutation group
Note: This group is also available via groups.permutation.Mathieu().
EXAMPLES:
sage: G = MathieuGroup(12); G
Mathieu group of degree 12 and order 95040 as a permutation group>>> from sage.all import *>>> G = MathieuGroup(Integer(12)); G
Mathieu group of degree 12 and order 95040 as a permutation groupclass sage.groups.perm_gps.permgroup_named.PGL(n, q, name='a')Bases: PermutationGroup_plg
The projective general linear groups over F( 𝑞).
INPUT:• n – positive integer; the degree• q – prime power; the size of the ground field• name – (default: a ) variable name of indeterminate of finite field F( 𝑞)
OUTPUT: PGL(𝑛, 𝑞)
Note: This group is also available via groups.permutation.PGL().
EXAMPLES:
sage: G = PGL(2,3); G
Permutation Group with generators [(3,4), (1,2,4)]
sage: print(G)The projective general linear group of degree 2 over Finite Field of size 3
sage: G.base_ring()
Finite Field of size 3(continues on next page)

518

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: G.order()24
sage: G = PGL(2, 9, b ); G#␣˓→needs sage.rings.finite_rings
Permutation Group with generators [(3,10,9,8,4,7,6,5), (1,2,4)(5,6,8)(7,9,10)]
sage: G.base_ring()
Finite Field in b of size 3^2
sage: G.category()
Category of finite enumerated permutation groups
sage: TestSuite(G).run() # long time>>> from sage.all import *>>> G = PGL(Integer(2),Integer(3)); G
Permutation Group with generators [(3,4), (1,2,4)]>>> print(G)The projective general linear group of degree 2 over Finite Field of size 3>>> G.base_ring()
Finite Field of size 3>>> G.order()24>>> G = PGL(Integer(2), Integer(9), b ); G˓→
# needs sage.rings.finite_rings
Permutation Group with generators [(3,10,9,8,4,7,6,5), (1,2,4)(5,6,8)(7,9,10)]>>> G.base_ring()
Finite Field in b of size 3^2␣>>> G.category()
Category of finite enumerated permutation groups>>> TestSuite(G).run() # long timeclass sage.groups.perm_gps.permgroup_named.PGU(n, q, name='a')Bases: PermutationGroup_pug
The projective general unitary groups over F( 𝑞).
INPUT:• n – positive integer; the degree• q – prime power; the size of the ground field• name – (default: a ) variable name of indeterminate of finite field F( 𝑞)
OUTPUT: PGU(𝑛, 𝑞)
Note: This group is also available via groups.permutation.PGU().
EXAMPLES:
sage: PGU(2,3)#␣˓→needs sage.rings.finite_rings
The projective general unitary group of degree 2 over Finite Field of size 3
sage: G = PGU(2, 8, name= alpha ); G#␣(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

519

Groups, Release 10.4

(continued from previous page)needs sage.rings.finite_rings
The projective general unitary group of degree 2
over Finite Field in alpha of size 2^3
sage: G.base_ring()
˓→needs sage.rings.finite_rings
Finite Field in alpha of size 2^3˓→#␣>>> from sage.all import *>>> PGU(Integer(2),Integer(3))˓→# needs sage.rings.finite_rings
The projective general unitary group of degree 2 over Finite Field of size 3>>> G = PGU(Integer(2), Integer(8), name= alpha ); G˓→
# needs sage.rings.finite_rings
The projective general unitary group of degree 2
over Finite Field in alpha of size 2^3>>> G.base_ring()
˓→sage.rings.finite_rings
Finite Field in alpha of size 2^3␣␣# needs␣

class sage.groups.perm_gps.permgroup_named.PSL(n, q, name='a')Bases: PermutationGroup_plg
The projective special linear groups over F( 𝑞).
INPUT:• n – positive integer; the degree• q – either a prime power (the size of the ground field) or a finite field• name – (default: a ) variable name of indeterminate of finite field F( 𝑞)
OUTPUT: the group PSL(𝑛, 𝑞)
Note: This group is also available via groups.permutation.PSL().
EXAMPLES:
sage: G = PSL(2,3); G
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
sage: G.order()12sage: G.base_ring()
Finite Field of size 3
sage: print(G)The projective special linear group of degree 2 over Finite Field of size 3>>> from sage.all import *>>> G = PSL(Integer(2),Integer(3)); G
Permutation Group with generators [(2,3,4), (1,2)(3,4)]>>> G.order()12>>> G.base_ring()
Finite Field of size 3>>> print(G)The projective special linear group of degree 2 over Finite Field of size 3520

Chapter 27. Permutation Groups

Groups, Release 10.4

We create two groups over nontrivial finite fields:
sage: G = PSL(2, 4, b ); G˓→needs sage.rings.finite_rings
Permutation Group with generators [(3,4,5), (1,2,3)]
sage: G.base_ring()
Finite Field in b of size 2^2
sage: G = PSL(2, 8); G˓→needs sage.rings.finite_rings
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]
sage: G.base_ring()
Finite Field in a of size 2^3#␣#␣

sage: G.category()
Category of finite enumerated permutation groups
sage: TestSuite(G).run() # long time>>> from sage.all import *>>> G = PSL(Integer(2), Integer(4), b ); G˓→
# needs sage.rings.finite_rings
Permutation Group with generators [(3,4,5), (1,2,3)]>>> G.base_ring()
Finite Field in b of size 2^2>>> G = PSL(Integer(2), Integer(8)); G˓→# needs sage.rings.finite_rings
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]>>> G.base_ring()
Finite Field in a of size 2^3␣␣>>> G.category()
Category of finite enumerated permutation groups>>> TestSuite(G).run() # long time

ramification_module_decomposition_hurwitz_curve()
Helps compute the decomposition of the ramification module for the Hurwitz curves X (over C say) with
automorphism group G = PSL(2,q), q a “Hurwitz prime” (ie, p is ±1 (mod 7)). Using this computation
and Borne’s formula helps determine the G-module structure of the RR spaces of equivariant divisors can be
determined explicitly.
The output is a list of integer multiplicities: [m1,…,mn], where n is the number of conj classes of G=PSL(2,p)
and mi is the multiplicity of pi_i in the ramification module of a Hurwitz curve with automorphism group G.
Here IrrRepns(G) = [pi_1,…,pi_n] (in the order listed in the output of self.character_table()).
REFERENCE:David Joyner, Amy Ksir, Roger Vogeler, “Group representations on Riemann-Roch spaces of some Hurwitz
curves,” preprint, 2006.
EXAMPLES:
sage: G = PSL(2,13)
sage: G.ramification_module_decomposition_hurwitz_curve()
˓→- gap_packages[0, 7, 7, 12, 12, 12, 13, 15, 14]>>> from sage.all import *>>> G = PSL(Integer(2),Integer(13))>>> G.ramification_module_decomposition_hurwitz_curve()# random, optional␣

# random, optional -␣(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

521

Groups, Release 10.4

(continued from previous page)

gap_packages[0, 7, 7, 12, 12, 12, 13, 15, 14]˓→This means, for example, that the trivial representation does not occur in the ramification module of a Hurwitz
curve with automorphism group PSL(2,13), since the trivial representation is listed first and that entry has
multiplicity 0. The “randomness” is due to the fact that GAP randomly orders the conjugacy classes of thesame order in the list of all conjugacy classes. Similarly, there is some randomness to the ordering of thecharacters.
If you try to use this function on a group PSL(2,q) where q is not a (smallish) “Hurwitz prime”, an error
message will be printed.
ramification_module_decomposition_modular_curve()
Helps compute the decomposition of the ramification module for the modular curve X(p) (over CC say)with automorphism group G = PSL(2,q), q a prime > 5. Using this computation and Borne’s formula helps
determine the G-module structure of the RR spaces of equivariant divisors can be determined explicitly.
The output is a list of integer multiplicities: [m1,…,mn], where n is the number of conj classes of G=PSL(2,p)
and mi is the multiplicity of pi_i in the ramification module of a modular curve with automorphism group G.
Here IrrRepns(G) = [pi_1,…,pi_n] (in the order listed in the output of self.character_table()).
REFERENCE: D. Joyner and A. Ksir, ‘Modular representations
on some Riemann-Roch spaces of modular curves 𝑋(𝑁 )’, Computational Aspects of Algebraic Curves,(Editor: T. Shaska) Lecture Notes in Computing, WorldScientific, 2005.)
EXAMPLES:
sage: G = PSL(2,7)
sage: G.ramification_module_decomposition_modular_curve()
˓→- gap_packages[0, 4, 3, 6, 7, 8]>>> from sage.all import *>>> G = PSL(Integer(2),Integer(7))>>> G.ramification_module_decomposition_modular_curve()
˓→gap_packages[0, 4, 3, 6, 7, 8]# random, optional␣

# random, optional -␣This means, for example, that the trivial representation does not occur in the ramification module of X(7),since the trivial representation is listed first and that entry has multiplicity 0. The “randomness” is due to thefact that GAP randomly orders the conjugacy classes of the same order in the list of all conjugacy classes.
Similarly, there is some randomness to the ordering of the characters.
sage.groups.perm_gps.permgroup_named.PSP
alias of PSp
class sage.groups.perm_gps.permgroup_named.PSU(n, q, name='a')Bases: PermutationGroup_pug
The projective special unitary groups over F( 𝑞).
INPUT:• n – positive integer; the degree• q – prime power; the size of the ground field• name – (default: ‘a’) variable name of indeterminate of finite field GF(q)522

Chapter 27. Permutation Groups

Groups, Release 10.4

OUTPUT: PSU(n,q)
Note: This group is also available via groups.permutation.PSU().
EXAMPLES:
sage: PSU(2,3)#␣˓→needs sage.rings.finite_rings
The projective special unitary group of degree 2 over Finite Field of size 3
sage: G = PSU(2, 8, name= alpha ); G#␣˓→needs sage.rings.finite_rings
The projective special unitary group of degree 2 over Finite Field in alpha of␣˓→size 2^3
sage: G.base_ring()#␣˓→needs sage.rings.finite_rings
Finite Field in alpha of size 2^3>>> from sage.all import *>>> PSU(Integer(2),Integer(3))˓→# needs sage.rings.finite_rings
The projective special unitary group of degree 2 over Finite Field of size 3

␣>>> G = PSU(Integer(2), Integer(8), name= alpha ); G␣˓→
# needs sage.rings.finite_rings
The projective special unitary group of degree 2 over Finite Field in alpha of␣˓→size 2^3>>> G.base_ring()# needs␣
˓→sage.rings.finite_rings
Finite Field in alpha of size 2^3class sage.groups.perm_gps.permgroup_named.PSp(n, q, name='a')Bases: PermutationGroup_plg
The projective symplectic linear groups over F( 𝑞).
INPUT:• n – positive integer; the degree• q – prime power; the size of the ground field• name – (default: a ) variable name of indeterminate of finite field F( 𝑞)
OUTPUT: PSp(𝑛, 𝑞)
Note: This group is also available via groups.permutation.PSp().
EXAMPLES:
sage: G = PSp(2,3); G
Permutation Group with generators [(2,3,4), (1,2)(3,4)]
sage: G.order()12sage: G = PSp(4,3); G
Permutation Group with generators [(3,4)(6,7)(9,10)(12,13)(17,20)(18,21)(19,(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)523

Groups, Release 10.4

(continued from previous page)22)(23,32)(24,33)(25,34)(26,38)(27,39)(28,40)(29,35)(30,36)(31,37), (1,5,14,17,
˓→27,22,19,36,3)(2,6,32)(4,7,23,20,37,13,16,26,40)(8,24,29,30,39,10,33,11,34)(9,
˓→15,35)(12,25,38)(21,28,31)]
sage: G.order()25920
sage: print(G)The projective symplectic linear group of degree 4 over Finite Field of size 3
sage: G.base_ring()
Finite Field of size 3
˓→sage: G = PSp(2, 8, name= alpha ); G˓→needs sage.rings.finite_rings
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]
sage: G.base_ring()
Finite Field in alpha of size 2^3#␣>>> from sage.all import *>>> G = PSp(Integer(2),Integer(3)); G
Permutation Group with generators [(2,3,4), (1,2)(3,4)]>>> G.order()12>>> G = PSp(Integer(4),Integer(3)); G
Permutation Group with generators [(3,4)(6,7)(9,10)(12,13)(17,20)(18,21)(19,
˓→22)(23,32)(24,33)(25,34)(26,38)(27,39)(28,40)(29,35)(30,36)(31,37), (1,5,14,17,
˓→27,22,19,36,3)(2,6,32)(4,7,23,20,37,13,16,26,40)(8,24,29,30,39,10,33,11,34)(9,
˓→15,35)(12,25,38)(21,28,31)]>>> G.order()25920>>> print(G)The projective symplectic linear group of degree 4 over Finite Field of size 3>>> G.base_ring()
Finite Field of size 3>>> G = PSp(Integer(2), Integer(8), name= alpha ); G˓→
# needs sage.rings.finite_rings
Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)]>>> G.base_ring()
Finite Field in alpha of size 2^3␣class sage.groups.perm_gps.permgroup_named.PermutationGroup_plg(gens=None,
gap_group=None,
canonicalize=True,
domain=None,
category=None)
Bases: PermutationGroup_unique
base_ring()
EXAMPLES:
sage: G = PGL(2,3)
sage: G.base_ring()
Finite Field of size 3
sage: G = PSL(2,3)
sage: G.base_ring()
Finite Field of size 3524

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> G = PGL(Integer(2),Integer(3))>>> G.base_ring()
Finite Field of size 3>>> G = PSL(Integer(2),Integer(3))>>> G.base_ring()
Finite Field of size 3

matrix_degree()
EXAMPLES:
sage: G = PSL(2,3)
sage: G.matrix_degree()2>>> from sage.all import *>>> G = PSL(Integer(2),Integer(3))>>> G.matrix_degree()2class sage.groups.perm_gps.permgroup_named.PermutationGroup_pug(gens=None,
gap_group=None,
canonicalize=True,
domain=None,
category=None)
Bases: PermutationGroup_plg
field_of_definition()
EXAMPLES:
sage: PSU(2,3).field_of_definition()
˓→needs sage.rings.finite_rings
Finite Field in a of size 3^2>>> from sage.all import *>>> PSU(Integer(2),Integer(3)).field_of_definition()˓→# needs sage.rings.finite_rings
Finite Field in a of size 3^2#␣␣class sage.groups.perm_gps.permgroup_named.PermutationGroup_symalt(gens=None,
gap_group=None,
canonicalize=True,
domain=None,
category=None)
Bases: PermutationGroup_uniqueThis is a class used to factor out some of the commonality in the SymmetricGroup and AlternatingGroup
classes.
class sage.groups.perm_gps.permgroup_named.PermutationGroup_unique(gens=None,
gap_group=None,
canonicalize=True,
domain=None,
category=None)
27.4. “Named” Permutation groups (such as the symmetric group, S_n)

525

Groups, Release 10.4

Bases: CachedRepresentation, PermutationGroup_generic
Todo: Fix the broken hash.
sage: G = SymmetricGroup(6)sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])sage: hash(G) == hash(G3) # todo: Should be True!
False>>> from sage.all import *>>> G = SymmetricGroup(Integer(6))>>> G3 = G.subgroup([G((Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(6))),G((Integer(1),Integer(2)))])>>> hash(G) == hash(G3) # todo: Should be True!
False

class sage.groups.perm_gps.permgroup_named.PrimitiveGroup(d, n)
Bases: PermutationGroup_unique
The primitive group from the GAP tables of primitive groups.
INPUT:• d – non-negative integer. the degree of the group.
• n – positive integer. the index of the group in the GAP database, starting at 1
OUTPUT: the n-th primitive group of degree d
EXAMPLES:
sage: PrimitiveGroup(0,1)
Trivial group
sage: PrimitiveGroup(1,1)
Trivial group
sage: G = PrimitiveGroup(5, 2); GD(2*5)
sage: G.gens()((2,4)(3,5), (1,2,3,5,4))
sage: G.category()
Category of finite enumerated permutation groups>>> from sage.all import *>>> PrimitiveGroup(Integer(0),Integer(1))
Trivial group>>> PrimitiveGroup(Integer(1),Integer(1))
Trivial group>>> G = PrimitiveGroup(Integer(5), Integer(2)); GD(2*5)>>> G.gens()((2,4)(3,5), (1,2,3,5,4))>>> G.category()
Category of finite enumerated permutation groups

526

Chapter 27. Permutation Groups

Groups, Release 10.4

Warning: this follows GAP’s naming convention of indexing the primitive groups starting from 1:
sage: PrimitiveGroup(5,0)
Traceback (most recent call last):...
ValueError: index n must be in {1,..,5}>>> from sage.all import *>>> PrimitiveGroup(Integer(5),Integer(0))
Traceback (most recent call last):...
ValueError: index n must be in {1,..,5}

Only primitive groups of “small” degree are available in GAP’s database:sage: PrimitiveGroup(2^12,1)
Traceback (most recent call last):...
GAPError: Error, Primitive groups of degree 4096 are not known!
>>> from sage.all import *>>> PrimitiveGroup(Integer(2)**Integer(12),Integer(1))
Traceback (most recent call last):...
GAPError: Error, Primitive groups of degree 4096 are not known!

group_primitive_id()
Return the index of this group in the GAP database of primitive groups.
OUTPUT: a positive integer, following GAP’s conventions
EXAMPLES:
sage: G = PrimitiveGroup(5,2); G.group_primitive_id()2>>> from sage.all import *>>> G = PrimitiveGroup(Integer(5),Integer(2)); G.group_primitive_id()2

sage.groups.perm_gps.permgroup_named.PrimitiveGroups(d=None)
Return the set of all primitive groups of a given degree d
INPUT:• d – integer (optional)
OUTPUT:
The set of all primitive groups of a given degree d up to isomorphisms using GAP. If d is not specified, it returns
the set of all primitive groups up to isomorphisms stored in GAP.
EXAMPLES:
sage: PrimitiveGroups(3)Primitive Groups of degree 3
sage: PrimitiveGroups(7)(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

527

Groups, Release 10.4

(continued from previous page)

Primitive Groups of degree 7
sage: PrimitiveGroups(8)Primitive Groups of degree 8
sage: PrimitiveGroups()
Primitive Groups>>> from sage.all import *>>> PrimitiveGroups(Integer(3))
Primitive Groups of degree 3>>> PrimitiveGroups(Integer(7))
Primitive Groups of degree 7>>> PrimitiveGroups(Integer(8))
Primitive Groups of degree 8>>> PrimitiveGroups()
Primitive Groups

The database is currently limited:sage: PrimitiveGroups(2^12).cardinality()
Traceback (most recent call last):...
GAPError: Error, Primitive groups of degree 4096 are not known!
>>> from sage.all import *>>> PrimitiveGroups(Integer(2)**Integer(12)).cardinality()
Traceback (most recent call last):...
GAPError: Error, Primitive groups of degree 4096 are not known!

Todo: This enumeration helper could be extended based on PrimitiveGroupsIterator in GAP. Thismethod allows to enumerate groups with specified properties such as transitivity, solvability, …, without creating
all groups.
class sage.groups.perm_gps.permgroup_named.PrimitiveGroupsAll
Bases: DisjointUnionEnumeratedSets
The infinite set of all primitive groups up to isomorphisms.
EXAMPLES:
sage: L = PrimitiveGroups(); L
Primitive Groups
sage: L.category()
Category of facade infinite enumerated sets
sage: L.cardinality()+Infinity
sage: p = L.__iter__()sage: (next(p), next(p), next(p), next(p),....: next(p), next(p), next(p), next(p))(Trivial group, Trivial group, S(2), A(3), S(3), A(4), S(4), C(5))>>> from sage.all import *>>> L = PrimitiveGroups(); L(continues on next page)

528

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Primitive Groups>>> L.category()
Category of facade infinite enumerated sets>>> L.cardinality()+Infinity>>> p = L.__iter__()>>> (next(p), next(p), next(p), next(p),... next(p), next(p), next(p), next(p))(Trivial group, Trivial group, S(2), A(3), S(3), A(4), S(4), C(5))

class sage.groups.perm_gps.permgroup_named.PrimitiveGroupsOfDegree(n)Bases: CachedRepresentation, Parent
The set of all primitive groups of a given degree up to isomorphisms.
EXAMPLES:
sage: S = PrimitiveGroups(5); S
Primitive Groups of degree 5
sage: S.list()[C(5), D(2*5), AGL(1, 5), A(5), S(5)]sage: S.an_element()
C(5)>>> from sage.all import *>>> S = PrimitiveGroups(Integer(5)); S
Primitive Groups of degree 5>>> S.list()[C(5), D(2*5), AGL(1, 5), A(5), S(5)]>>> S.an_element()
C(5)

We write the cardinality of all primitive groups of degree 5:
sage: for G in PrimitiveGroups(5):....:print(G.cardinality())
5
10
20
60
120
>>> from sage.all import *>>> for G in PrimitiveGroups(Integer(5)):...
print(G.cardinality())
5
10
20
60
120

cardinality()
Return the cardinality of self.
OUTPUT: integer; the number of primitive groups of a given degree up to isomorphism
EXAMPLES:
27.4. “Named” Permutation groups (such as the symmetric group, S_n)

529

Groups, Release 10.4

sage: PrimitiveGroups(0).cardinality()1sage: PrimitiveGroups(2).cardinality()1sage: PrimitiveGroups(7).cardinality()
7
sage: PrimitiveGroups(12).cardinality()
6
sage: [PrimitiveGroups(i).cardinality() for i in range(11)][1, 1, 1, 2, 2, 5, 4, 7, 7, 11, 9]>>> from sage.all import *>>> PrimitiveGroups(Integer(0)).cardinality()1>>> PrimitiveGroups(Integer(2)).cardinality()1>>> PrimitiveGroups(Integer(7)).cardinality()
7>>> PrimitiveGroups(Integer(12)).cardinality()
6>>> [PrimitiveGroups(i).cardinality() for i in range(Integer(11))][1, 1, 1, 2, 2, 5, 4, 7, 7, 11, 9]class sage.groups.perm_gps.permgroup_named.QuaternionGroupBases: DiCyclicGroupThe quaternion group of order 8.
OUTPUT:
The quaternion group of order 8, as a permutation group. See the DiCyclicGroup class for a generalization ofthis construction.
Note: This group is also available via groups.permutation.Quaternion().
EXAMPLES:
The quaternion group is one of two non-abelian groups of order 8, the other being the dihedral group 𝐷4 . One way todescribe this group is with three generators, 𝐼, 𝐽, 𝐾, so the whole group is then given as the set {±1, ±𝐼, ±𝐽, ±𝐾}
with relations such as 𝐼 2 = 𝐽 2 = 𝐾 2 = −1, 𝐼𝐽 = 𝐾 and 𝐽𝐼 = −𝐾.
The examples below illustrate how to use this group in a similar manner, by testing some of these relations. The
representation used here is the left-regular representation.
sage: Q = QuaternionGroup()
sage: I = Q.gen(0)sage: J = Q.gen(1)sage: K = I*J
sage: [I,J,K][(1,2,3,4)(5,6,7,8), (1,5,3,7)(2,8,4,6), (1,8,3,6)(2,7,4,5)]
sage: neg_one = I^2; neg_one(1,3)(2,4)(5,7)(6,8)
sage: J^2 == neg_one and K^2 == neg_one
True
sage: J*I == neg_one*K
True
sage: Q.center().order() == 2
(continues on next page)

530

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)True
sage: neg_one in Q.center()True>>> from sage.all import *>>> Q = QuaternionGroup()>>> I = Q.gen(Integer(0))>>> J = Q.gen(Integer(1))>>> K = I*J>>> [I,J,K][(1,2,3,4)(5,6,7,8), (1,5,3,7)(2,8,4,6), (1,8,3,6)(2,7,4,5)]>>> neg_one = I**Integer(2); neg_one(1,3)(2,4)(5,7)(6,8)>>> J**Integer(2) == neg_one and K**Integer(2) == neg_one
True>>> J*I == neg_one*K
True>>> Q.center().order() == Integer(2)True>>> neg_one in Q.center()True

AUTHOR:• Rob Beezer (2009-10-09)
class sage.groups.perm_gps.permgroup_named.SemidihedralGroup(m)Bases: PermutationGroup_unique
The semidihedral group of order 2𝑚 .
INPUT:• m – a positive integer; the power of 2 that is the group’s order
OUTPUT:
The semidihedral group of order 2𝑚 . These groups can be thought of as a semidirect product of 𝐶2𝑚−1 with 𝐶2 ,where the nontrivial element of 𝐶2 is sent to the element of the automorphism group of 𝐶2𝑚−1 that sends elements
to their −1 + 2𝑚−2 th power. Thus, the group has the presentation:⟨𝑥, 𝑦 | 𝑥2

𝑚−1

, 𝑦 2 , 𝑦 −1 𝑥𝑦 = 𝑥−1+2

𝑚−2⟩

This family is notable because it is made up of non-abelian 2-groups that all contain cyclic subgroups of index 2.
It is one of only four such families.
EXAMPLES:In [Gor1980] it is shown that the semidihedral groups have center of order 2. It is also shown that they have a
Frattini subgroup equal to their commutator, which is a cyclic subgroup of order 2𝑚−2 .
sage: G = SemidihedralGroup(12)sage: G.order() == 2^12Truesage: G.commutator() == G.frattini_subgroup()
True
sage: G.commutator().order() == 2^10Truesage: G.commutator().is_cyclic()(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

531

Groups, Release 10.4

(continued from previous page)True
sage: G.center().order()2sage: G = SemidihedralGroup(4)sage: len([H for H in G.subgroups() if H.is_cyclic() and H.order() == 8])1
sage: G.gens()((2,4)(3,7)(6,8), (1,2,3,4,5,6,7,8))
sage: x = G.gens()[1]; y = G.gens()[0]sage: x.order() == 2^3; y.order() == 2
True
True
sage: y*x*y == x^(-1+2^2)
True>>> from sage.all import *>>> G = SemidihedralGroup(Integer(12))>>> G.order() == Integer(2)**Integer(12)True>>> G.commutator() == G.frattini_subgroup()
True>>> G.commutator().order() == Integer(2)**Integer(10)True>>> G.commutator().is_cyclic()
True>>> G.center().order()2>>> G = SemidihedralGroup(Integer(4))>>> len([H for H in G.subgroups() if H.is_cyclic() and H.order() == Integer(8)])
1>>> G.gens()((2,4)(3,7)(6,8), (1,2,3,4,5,6,7,8))>>> x = G.gens()[Integer(1)]; y = G.gens()[Integer(0)]>>> x.order() == Integer(2)**Integer(3); y.order() == Integer(2)
True
True
>>> y*x*y == x**(-Integer(1)+Integer(2)**Integer(2))
True

AUTHOR:• Kevin Halasz (2012-8-7)class sage.groups.perm_gps.permgroup_named.SmallPermutationGroup(order, gap_id)
Bases: PermutationGroup_generic
A GAP SmallGroup, returned as a permutation group.
GAP contains a library SGL of small groups, each identified by its GAP SmallGroup id. (MAGMA uses the same
identifiers). The GAP SmallGroup id is a pair [n,k] consisting of n, the order of the group, and k, an index
determining the group specifically. This class can construct the group as a permutation group from this data.
INPUT:• order – the order of the group• gap_id – the numerical index in the GAP id of the group
532

Chapter 27. Permutation Groups

Groups, Release 10.4

Generators may be obtained through the gens() method. These could change for a particular group in later
releases of GAP. In many instances the degree of the constructed group SmallPermutationGroup(n,k)
will be a permutation group on 𝑛 letters, but this will not always be true.
EXAMPLES:
sage: G = SmallPermutationGroup(12,4); GGroup of order 12 and GAP Id 4 as a permutation group
sage: G.gens()((1,2)(3,5)(4,10)(6,8)(7,12)(9,11),(1,3)(2,5)(4,7)(6,9)(8,11)(10,12),(1,4,8)(2,6,10)(3,7,11)(5,9,12))
sage: G.character_table()
˓→needs sage.rings.number_field[ 1 1 1 1 1 1]
[ 1 -1 -1 1 1 -1][ 1 -1 1 1 -1 1][ 1 1 -1 1 -1 -1][ 2 0 -2 -1 0 1]
[ 2 0 2 -1 0 -1]
sage: def numgps(n): return ZZ(libgap.NumberSmallGroups(n))
sage: all(SmallPermutationGroup(n,k).id() == [n,k]....:for n in [1..64] for k in [1..numgps(n)])
Truesage: H = SmallPermutationGroup(6,1)
sage: H.is_abelian()False
sage: [H.centralizer(g) for g in H.conjugacy_classes_representatives()][Subgroup generated by [(1,2)(3,6)(4,5), (1,3,5)(2,4,6)] of(Group of order 6 and GAP Id 1 as a permutation group),
Subgroup generated by [(1,2)(3,6)(4,5)] of(Group of order 6 and GAP Id 1 as a permutation group),
Subgroup generated by [(1,3,5)(2,4,6), (1,5,3)(2,6,4)] of(Group of order 6 and GAP Id 1 as a permutation group)]>>> from sage.all import *>>> G = SmallPermutationGroup(Integer(12),Integer(4)); GGroup of order 12 and GAP Id 4 as a permutation group>>> G.gens()((1,2)(3,5)(4,10)(6,8)(7,12)(9,11),(1,3)(2,5)(4,7)(6,9)(8,11)(10,12),(1,4,8)(2,6,10)(3,7,11)(5,9,12))>>> G.character_table()
˓→needs sage.rings.number_field[ 1 1 1 1 1 1]
[ 1 -1 -1 1 1 -1][ 1 -1 1 1 -1 1][ 1 1 -1 1 -1 -1][ 2 0 -2 -1 0 1]
[ 2 0 2 -1 0 -1]>>> def numgps(n): return ZZ(libgap.NumberSmallGroups(n))>>> all(SmallPermutationGroup(n,k).id() == [n,k]...
for n in (ellipsis_range(Integer(1),Ellipsis,Integer(64))) for k in␣˓→(ellipsis_range(Integer(1),Ellipsis,numgps(n))))True>>> H = SmallPermutationGroup(Integer(6),Integer(1))>>> H.is_abelian()
False

#␣

#␣

(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

533

Groups, Release 10.4

(continued from previous page)>>> [H.centralizer(g) for g in H.conjugacy_classes_representatives()][Subgroup generated by [(1,2)(3,6)(4,5), (1,3,5)(2,4,6)] of(Group of order 6 and GAP Id 1 as a permutation group),
Subgroup generated by [(1,2)(3,6)(4,5)] of(Group of order 6 and GAP Id 1 as a permutation group),
Subgroup generated by [(1,3,5)(2,4,6), (1,5,3)(2,6,4)] of(Group of order 6 and GAP Id 1 as a permutation group)]

gap_small_group()
Return the GAP small group object corresponding to self.
GAP realizes some small groups as PermutationGroup, others as PcGroups (polycyclic groups). The
SmallPermutationGroup class always returns a PermutationGroup, but in the process of creating
this group a GAP SmallGroup is generated. This method returns that group.
EXAMPLES:
sage: SmallPermutationGroup(168,41).gap_small_group()<pc group of size 168 with 5 generators>
sage: SmallPermutationGroup(168,42).gap_small_group()Group([ (3,4)(5,6), (1,2,3)(4,5,7) ])>>> from sage.all import *>>> SmallPermutationGroup(Integer(168),Integer(41)).gap_small_group()<pc group of size 168 with 5 generators>>>> SmallPermutationGroup(Integer(168),Integer(42)).gap_small_group()Group([ (3,4)(5,6), (1,2,3)(4,5,7) ])order()
Return the order of the group corresponding to self.
EXAMPLES:
sage: [SmallPermutationGroup(21,k).order() for k in [1,2]][21, 21]>>> from sage.all import *>>> [SmallPermutationGroup(Integer(21),k).order() for k in [Integer(1),˓→Integer(2)]][21, 21]class sage.groups.perm_gps.permgroup_named.SplitMetacyclicGroup(p, m)
Bases: PermutationGroup_unique
The split metacyclic group of order 𝑝𝑚 .
INPUT:• p – a prime number that is the prime underlying this p-group• m – a positive integer such that the order of this group is the 𝑝𝑚 . Be aware that, for even 𝑝, 𝑚 must be greaterthan 3, while for odd 𝑝, 𝑚 must be greater than 2.
OUTPUT:
The split metacyclic group of order 𝑝𝑚 . This family of groups has presentation⟨𝑥, 𝑦 | 𝑥𝑝
534

𝑚−1

, 𝑦 𝑝 , 𝑦 −1 𝑥𝑦 = 𝑥1+𝑝

𝑚−2⟩

Chapter 27. Permutation Groups

Groups, Release 10.4

This family is notable because, for odd 𝑝, these are the only 𝑝-groups with a cyclic subgroup of index 𝑝, a result proven in [Gor1980]. It is also shown in [Gor1980] that this is one of four families containing nonabelian
2-groups with a cyclic subgroup of index 2 (with the others being the dicyclic groups, the dihedral groups, and thesemidihedral groups).
EXAMPLES:
Using the last relation in the group’s presentation, one can see that the elements of the form 𝑦 𝑖 𝑥, 0 ≤ 𝑖 ≤ 𝑝 − 1
𝑚−2+𝑝all have order 𝑝𝑚−1 , as it can be shown that their 𝑝 th powers are all 𝑥𝑝, an element with order 𝑝𝑚−2 .
Manipulation of the same relation shows that none of these elements are powers of any other. Thus, there are𝑝 cyclic maximal subgroups in each split metacyclic group. It is also proven in [Gor1980] that this family has
commutator subgroup of order 𝑝, and the Frattini subgroup is equal to the center, with this group being cyclicof order 𝑝𝑚−2 . These characteristics are necessary to identify these groups in the case that 𝑝 = 2, although thepossession of a cyclic maximal subgroup in a non-abelian 𝑝-group is enough for odd 𝑝 given the group’s order.
sage: G = SplitMetacyclicGroup(2,8)
sage: G.order() == 2**8
True
sage: G.is_abelian()False
sage: len([H for H in G.subgroups() if H.order() == 2^7 and H.is_cyclic()])
2
sage: G.commutator().order()2sage: G.frattini_subgroup() == G.center()Truesage: G.center().order() == 2^6
True
sage: G.center().is_cyclic()Truesage: G = SplitMetacyclicGroup(3,3)
sage: len([H for H in G.subgroups() if H.order() == 3^2 and H.is_cyclic()])
3
sage: G.commutator().order()3sage: G.frattini_subgroup() == G.center()Truesage: G.center().order()3>>> from sage.all import *>>> G = SplitMetacyclicGroup(Integer(2),Integer(8))>>> G.order() == Integer(2)**Integer(8)True>>> G.is_abelian()
False>>> len([H for H in G.subgroups() if H.order() == Integer(2)**Integer(7) and H.is_
˓→cyclic()])
2>>> G.commutator().order()2>>> G.frattini_subgroup() == G.center()
True>>> G.center().order() == Integer(2)**Integer(6)True>>> G.center().is_cyclic()(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

535

Groups, Release 10.4

(continued from previous page)

True>>> G = SplitMetacyclicGroup(Integer(3),Integer(3))>>> len([H for H in G.subgroups() if H.order() == Integer(3)**Integer(2) and H.is_
˓→cyclic()])
3>>> G.commutator().order()3>>> G.frattini_subgroup() == G.center()
True>>> G.center().order()3

AUTHOR:• Kevin Halasz (2012-8-7)class sage.groups.perm_gps.permgroup_named.SuzukiGroup(q, name='a')Bases: PermutationGroup_unique
The Suzuki group over F( 𝑞), 2 𝐵2 (22𝑘+1 ) = 𝑆𝑧(22𝑘+1 ).
A wrapper for the GAP function SuzukiGroup.
INPUT:• q – 2𝑛 , an odd power of 2; the size of the ground field. (Strictly speaking, 𝑛 should be greater than 1, or else
this group is not simple.)• name – (default: a ) variable name of indeterminate of finite field F( 𝑞)
OUTPUT: a Suzuki group
Note: This group is also available via groups.permutation.Suzuki().
EXAMPLES:
sage: SuzukiGroup(8)#␣˓→needs sage.rings.finite_rings
Permutation Group with generators [(1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,
˓→52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,
˓→54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,
˓→56),(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,
˓→31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,
˓→49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64)]
sage: print(SuzukiGroup(8))#␣˓→needs sage.rings.finite_rings
The Suzuki group over Finite Field in a of size 2^3
sage: # needs sage.rings.finite_rings
sage: G = SuzukiGroup(32, name= alpha )sage: G.order()32537600
sage: G.order().factor()
2^10 * 5^2 * 31 * 41
sage: G.base_ring()
Finite Field in alpha of size 2^5536

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> SuzukiGroup(Integer(8))␣˓→ # needs sage.rings.finite_rings
Permutation Group with generators [(1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,
˓→52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,
˓→54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,
˓→56),(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,
˓→31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,
˓→49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64)]>>> print(SuzukiGroup(Integer(8)))␣˓→ # needs sage.rings.finite_rings
The Suzuki group over Finite Field in a of size 2^3>>> # needs sage.rings.finite_rings>>> G = SuzukiGroup(Integer(32), name= alpha )>>> G.order()32537600>>> G.order().factor()
2^10 * 5^2 * 31 * 41>>> G.base_ring()
Finite Field in alpha of size 2^5

REFERENCES:• Wikipedia article Group_of_Lie_type#Suzuki-Ree_groups
base_ring()
EXAMPLES:
sage: G = SuzukiGroup(32, name= alpha )˓→needs sage.rings.finite_rings
sage: G.base_ring()
˓→needs sage.rings.finite_rings
Finite Field in alpha of size 2^5>>> from sage.all import *>>> G = SuzukiGroup(Integer(32), name= alpha )˓→# needs sage.rings.finite_rings>>> G.base_ring()
˓→needs sage.rings.finite_rings
Finite Field in alpha of size 2^5

#␣
#␣

␣
#␣

class sage.groups.perm_gps.permgroup_named.SuzukiSporadicGroupBases: PermutationGroup_unique
Suzuki Sporadic Group
EXAMPLES:
sage: G = groups.permutation.SuzukiSporadic(); G˓→gap_package_atlasrep internet
Sporadic Suzuki group acting on 1782 points>>> from sage.all import *>>> G = groups.permutation.SuzukiSporadic(); G˓→gap_package_atlasrep internet
Sporadic Suzuki group acting on 1782 points

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

# optional -␣# optional -␣537

Groups, Release 10.4class sage.groups.perm_gps.permgroup_named.SymmetricGroup(domain=None)
Bases: PermutationGroup_symalt
The full symmetric group of order 𝑛!, as a permutation group.
If 𝑛 is a list or tuple of positive integers then it returns the symmetric group of the associated set.
INPUT:• n – a positive integer, or list or tuple thereof
Note: This group is also available via groups.permutation.Symmetric().
EXAMPLES:
sage: G = SymmetricGroup(8)sage: G.order()40320
sage: G
Symmetric group of order 8! as a permutation group
sage: G.degree()8
sage: S8 = SymmetricGroup(8)sage: G = SymmetricGroup([1,2,4,5])
sage: G
Symmetric group of order 4! as a permutation group
sage: G.domain(){1, 2, 4, 5}
sage: G = SymmetricGroup(4)sage: G
Symmetric group of order 4! as a permutation group
sage: G.domain(){1, 2, 3, 4}
sage: G.category()
Join of Category of finite enumerated permutation groups andCategory of finite Weyl groups andCategory of well generated finite irreducible complex reflection groups>>> from sage.all import *>>> G = SymmetricGroup(Integer(8))>>> G.order()
40320
>>> G
Symmetric group of order 8! as a permutation group>>> G.degree()8>>> S8 = SymmetricGroup(Integer(8))>>> G = SymmetricGroup([Integer(1),Integer(2),Integer(4),Integer(5)])>>> G
Symmetric group of order 4! as a permutation group>>> G.domain(){1, 2, 4, 5}>>> G = SymmetricGroup(Integer(4))>>> G
Symmetric group of order 4! as a permutation group>>> G.domain(){1, 2, 3, 4}(continues on next page)

538

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> G.category()
Join of Category of finite enumerated permutation groups andCategory of finite Weyl groups andCategory of well generated finite irreducible complex reflection groups

Element
alias of SymmetricGroupElement
algebra(base_ring, category=None)
Return the symmetric group algebra associated to self.
INPUT:• base_ring – a ring
• category – a category (default: the category of self)
If self is the symmetric group on 1, . . . , 𝑛, then this is special cased to take advantage of the features inSymmetricGroupAlgebra. Otherwise the usual group algebra is returned.
EXAMPLES:
sage: S4 = SymmetricGroup(4)sage: S4.algebra(QQ)˓→needs sage.combinat
Symmetric group algebra of order 4 over Rational Field#␣

sage: S3 = SymmetricGroup([1,2,3])
sage: A = S3.algebra(QQ); A
˓→needs sage.combinat
Symmetric group algebra of order 3 over Rational Field
sage: a = S3.an_element(); a(2,3)
sage: A(a)˓→needs sage.combinat(2,3)>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> S4.algebra(QQ)˓→needs sage.combinat
Symmetric group algebra of order 4 over Rational Field>>> S3 = SymmetricGroup([Integer(1),Integer(2),Integer(3)])>>> A = S3.algebra(QQ); A
˓→needs sage.combinat
Symmetric group algebra of order 3 over Rational Field>>> a = S3.an_element(); a(2,3)>>> A(a)˓→needs sage.combinat
(2,3)

#␣

#␣

#␣

#␣

#␣

We illustrate the choice of the category:sage: A.category()
˓→needs sage.combinat
Join of Category of Coxeter group algebras over Rational Field#␣(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

539

Groups, Release 10.4

(continued from previous page)and Category of finite group algebras over Rational Field
and Category of finite dimensional cellular algebras with basis
over Rational Field
sage: A = S3.algebra(QQ, category=Semigroups())˓→needs sage.combinat
sage: A.category()
˓→needs sage.combinat
Category of finite dimensional unital cellular semigroup algebras
over Rational Field>>> from sage.all import *>>> A.category()
˓→needs sage.combinat
Join of Category of Coxeter group algebras over Rational Field
and Category of finite group algebras over Rational Field
and Category of finite dimensional cellular algebras with basis
over Rational Field>>> A = S3.algebra(QQ, category=Semigroups())˓→needs sage.combinat>>> A.category()
˓→needs sage.combinat
Category of finite dimensional unital cellular semigroup algebras
over Rational Field

#␣
#␣

#␣

#␣
#␣

In the following case, a usual group algebra is returned:
sage: S = SymmetricGroup([2,3,5])
sage: S.algebra(QQ)#␣˓→needs sage.combinat
Algebra of Symmetric group of order 3! as a permutation group over Rational␣
˓→Field
sage: a = S.an_element(); a(3,5)
sage: S.algebra(QQ)(a)#␣˓→needs sage.combinat(3,5)>>> from sage.all import *>>> S = SymmetricGroup([Integer(2),Integer(3),Integer(5)])>>> S.algebra(QQ)#␣˓→needs sage.combinat
Algebra of Symmetric group of order 3! as a permutation group over Rational␣
˓→Field>>> a = S.an_element(); a(3,5)>>> S.algebra(QQ)(a)#␣˓→needs sage.combinat(3,5)

cartan_type()
Return the Cartan type of self
The symmetric group 𝑆𝑛 is a Coxeter group of type 𝐴𝑛−1 .
EXAMPLES:

540

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: A = SymmetricGroup([2,3,7]); A.cartan_type()[ A , 2]sage: A = SymmetricGroup([]); A.cartan_type()[ A , 0]>>> from sage.all import *>>> A = SymmetricGroup([Integer(2),Integer(3),Integer(7)]); A.cartan_type()[ A , 2]>>> A = SymmetricGroup([]); A.cartan_type()[ A , 0]conjugacy_class(g)Return the conjugacy class of g inside the symmetric group self.
INPUT:• g – a partition or an element of the symmetric group self
OUTPUT: a conjugacy class of a symmetric group
EXAMPLES:
sage: G = SymmetricGroup(5)sage: g = G((1,2,3,4))
sage: G.conjugacy_class(g)˓→needs sage.combinat
Conjugacy class of cycle type [4, 1] inSymmetric group of order 5! as a permutation group>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4)))>>> G.conjugacy_class(g)˓→needs sage.combinat
Conjugacy class of cycle type [4, 1] inSymmetric group of order 5! as a permutation group#␣#␣conjugacy_classes()
Return a list of the conjugacy classes of self.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.conjugacy_classes()
˓→needs sage.combinat[Conjugacy class of cycle type [1, 1, 1, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [2, 1, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [2, 2, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [3, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [3, 2] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [4, 1] in#␣(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

541

Groups, Release 10.4

(continued from previous page)

Symmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [5] inSymmetric group of order 5! as a permutation group]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.conjugacy_classes()
˓→needs sage.combinat[Conjugacy class of cycle type [1, 1, 1, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [2, 1, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [2, 2, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [3, 1, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [3, 2] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [4, 1] inSymmetric group of order 5! as a permutation group,
Conjugacy class of cycle type [5] inSymmetric group of order 5! as a permutation group]#␣

conjugacy_classes_iterator()
Iterate over the conjugacy classes of self.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: list(G.conjugacy_classes_iterator()) == G.conjugacy_classes()
˓→needs sage.combinat
True>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> list(G.conjugacy_classes_iterator()) == G.conjugacy_classes()
˓→needs sage.combinat
True

#␣

#␣

conjugacy_classes_representatives()
Return a complete list of representatives of conjugacy classes in a permutation group 𝐺.
Let 𝑆𝑛 be the symmetric group on 𝑛 letters. The conjugacy classes are indexed by partitions 𝜆 of 𝑛. The
ordering of the conjugacy classes is reverse lexicographic order of the partitions.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: G.conjugacy_classes_representatives()
˓→needs sage.combinat[(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5),(1,2,3,4), (1,2,3,4,5)]>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> G.conjugacy_classes_representatives()#␣#␣(continues on next page)542

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)needs sage.combinat[(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5),(1,2,3,4), (1,2,3,4,5)]˓→

sage: S = SymmetricGroup([ a , b , c ])sage: S.conjugacy_classes_representatives()
˓→needs sage.combinat[(), ( a , b ), ( a , b , c )]>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c ])>>> S.conjugacy_classes_representatives()
˓→needs sage.combinat[(), ( a , b ), ( a , b , c )]#␣#␣coxeter_matrix()
Return the Coxeter matrix of self.
EXAMPLES:
sage: A = SymmetricGroup([2,3,7, a ]); A.coxeter_matrix()
˓→needs sage.graphs[1 3 2][3 1 3][2 3 1]#␣>>> from sage.all import *>>> A = SymmetricGroup([Integer(2),Integer(3),Integer(7), a ]); A.coxeter_
˓→matrix()# needs sage.graphs[1 3 2][3 1 3][2 3 1]index_set()
Return the index set for the descents of the symmetric group self.
EXAMPLES:
sage: S8 = SymmetricGroup(8)sage: S8.index_set()(1, 2, 3, 4, 5, 6, 7)
sage: S = SymmetricGroup([3,1,4,5])
sage: S.index_set()(3, 1, 4)>>> from sage.all import *>>> S8 = SymmetricGroup(Integer(8))>>> S8.index_set()(1, 2, 3, 4, 5, 6, 7)>>> S = SymmetricGroup([Integer(3),Integer(1),Integer(4),Integer(5)])>>> S.index_set()(3, 1, 4)27.4. “Named” Permutation groups (such as the symmetric group, S_n)543

Groups, Release 10.4

major_index(parameter=None)
Return the major index generating polynomial of self.
This is a gadget counting the elements of self by major index.
INPUT:• parameter – an element of a ring; the result is more explicit with a formal variable (default: element
q of Univariate Polynomial Ring in q over Integer Ring)∑︁
𝑃 (𝑞) =
𝑞 major index(𝑔)𝑔∈𝑆𝑛

EXAMPLES:
sage: S4 = SymmetricGroup(4)sage: S4.major_index()
˓→needs sage.combinatq^6 + 3*q^5 + 5*q^4 + 6*q^3 + 5*q^2 + 3*q + 1
sage: K.<t> = QQ[]
sage: S4.major_index(t)˓→needs sage.combinatt^6 + 3*t^5 + 5*t^4 + 6*t^3 + 5*t^2 + 3*t + 1#␣#␣>>> from sage.all import *>>> S4 = SymmetricGroup(Integer(4))>>> S4.major_index()
˓→needs sage.combinatq^6 + 3*q^5 + 5*q^4 + 6*q^3 + 5*q^2 + 3*q + 1>>> K = QQ[ t ]; (t,) = K._first_ngens(1)>>> S4.major_index(t)˓→needs sage.combinatt^6 + 3*t^5 + 5*t^4 + 6*t^3 + 5*t^2 + 3*t + 1#␣#␣

reflections()
Return the list of all reflections in self.
EXAMPLES:
sage: A = SymmetricGroup(3)sage: A.reflections()[(1,2), (1,3), (2,3)]>>> from sage.all import *>>> A = SymmetricGroup(Integer(3))>>> A.reflections()[(1,2), (1,3), (2,3)]

simple_reflection(i)For 𝑖 in the index set of self, return the elementary transposition 𝑠𝑖 = (𝑖, 𝑖 + 1).
EXAMPLES:
sage: A = SymmetricGroup(5)sage: A.simple_reflection(3)(3,4)
sage: A = SymmetricGroup([2,3,7])(continues on next page)544

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: A.simple_reflections()
Finite family {2: (2,3), 3: (3,7)}>>> from sage.all import *>>> A = SymmetricGroup(Integer(5))>>> A.simple_reflection(Integer(3))(3,4)>>> A = SymmetricGroup([Integer(2),Integer(3),Integer(7)])>>> A.simple_reflections()
Finite family {2: (2,3), 3: (3,7)}

young_subgroup(comp)
Return the Young subgroup associated with the composition comp.
EXAMPLES:
sage: S = SymmetricGroup(8)sage: c = Composition([2,2,2,2])
sage: S.young_subgroup(c)Subgroup generated by [(1,2), (3,4), (5,6), (7,8)] of(Symmetric group of order 8! as a permutation group)sage: S = SymmetricGroup([ a , b , c ])sage: S.young_subgroup([2,1])
Subgroup generated by [( a , b )] of(Symmetric group of order 3! as a permutation group)sage: Y = S.young_subgroup([2,2,2,2,2])
Traceback (most recent call last):...
ValueError: the composition is not of expected size>>> from sage.all import *>>> S = SymmetricGroup(Integer(8))>>> c = Composition([Integer(2),Integer(2),Integer(2),Integer(2)])>>> S.young_subgroup(c)Subgroup generated by [(1,2), (3,4), (5,6), (7,8)] of(Symmetric group of order 8! as a permutation group)>>> S = SymmetricGroup([ a , b , c ])>>> S.young_subgroup([Integer(2),Integer(1)])
Subgroup generated by [( a , b )] of(Symmetric group of order 3! as a permutation group)>>> Y = S.young_subgroup([Integer(2),Integer(2),Integer(2),Integer(2),˓→Integer(2)])
Traceback (most recent call last):...
ValueError: the composition is not of expected sizeclass sage.groups.perm_gps.permgroup_named.TransitiveGroup(d, n)
Bases: PermutationGroup_unique
The transitive group from the GAP tables of transitive groups.
INPUT:
27.4. “Named” Permutation groups (such as the symmetric group, S_n)

545

Groups, Release 10.4

• d – non-negative integer; the degree• n – positive integer; the index of the group in the GAP database, starting at 1
OUTPUT: the 𝑛-th transitive group of degree 𝑑Note: This group is also available via groups.permutation.Transitive().
EXAMPLES:
sage: TransitiveGroup(0,1)
Transitive group number 1 of degree 0
sage: TransitiveGroup(1,1)
Transitive group number 1 of degree 1
sage: G = TransitiveGroup(5, 2); G
Transitive group number 2 of degree 5
sage: G.gens()((1,2,3,4,5), (1,4)(2,3))
sage: G.category()
Category of finite enumerated permutation groups>>> from sage.all import *>>> TransitiveGroup(Integer(0),Integer(1))
Transitive group number 1 of degree 0>>> TransitiveGroup(Integer(1),Integer(1))
Transitive group number 1 of degree 1>>> G = TransitiveGroup(Integer(5), Integer(2)); G
Transitive group number 2 of degree 5>>> G.gens()((1,2,3,4,5), (1,4)(2,3))>>> G.category()
Category of finite enumerated permutation groups

Warning: this follows GAP’s naming convention of indexing the transitive groups starting from 1:
sage: TransitiveGroup(5,0)
Traceback (most recent call last):...
ValueError: index n must be in {1,..,5}>>> from sage.all import *>>> TransitiveGroup(Integer(5),Integer(0))
Traceback (most recent call last):...
ValueError: index n must be in {1,..,5}

Warning: only transitive groups of “small” degree are available in GAP’s database:sage: TransitiveGroup(32,1)
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31

546

Chapter 27. Permutation Groups

Groups, Release 10.4

are available in GAP s database>>> from sage.all import *>>> TransitiveGroup(Integer(32),Integer(1))
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31
are available in GAP s databasedegree()Return the degree of this permutation group
EXAMPLES:
sage: TransitiveGroup(8, 44).degree()8>>> from sage.all import *>>> TransitiveGroup(Integer(8), Integer(44)).degree()8transitive_number()
Return the index of this group in the GAP database, starting at 1
EXAMPLES:
sage: TransitiveGroup(8, 44).transitive_number()44>>> from sage.all import *>>> TransitiveGroup(Integer(8), Integer(44)).transitive_number()44

sage.groups.perm_gps.permgroup_named.TransitiveGroups(d=None)
INPUT:• d – integer (optional)
Return the set of all transitive groups of a given degree d up to isomorphisms. If d is not specified, it returns theset of all transitive groups up to isomorphisms.
EXAMPLES:
sage: TransitiveGroups(3)Transitive Groups of degree 3
sage: TransitiveGroups(7)Transitive Groups of degree 7
sage: TransitiveGroups(8)Transitive Groups of degree 8
sage: TransitiveGroups()
Transitive Groups>>> from sage.all import *>>> TransitiveGroups(Integer(3))
Transitive Groups of degree 3(continues on next page)

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

547

Groups, Release 10.4

(continued from previous page)>>> TransitiveGroups(Integer(7))
Transitive Groups of degree 7>>> TransitiveGroups(Integer(8))
Transitive Groups of degree 8>>> TransitiveGroups()
Transitive Groups

Warning: in practice, the database currently only contains transitive groups up to degree 31:
sage: TransitiveGroups(32).cardinality()
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31
are available in GAP s database>>> from sage.all import *>>> TransitiveGroups(Integer(32)).cardinality()
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31
are available in GAP s databaseclass sage.groups.perm_gps.permgroup_named.TransitiveGroupsAll
Bases: DisjointUnionEnumeratedSets
The infinite set of all transitive groups up to isomorphisms.
EXAMPLES:
sage: L = TransitiveGroups(); L
Transitive Groups
sage: L.category()
Category of facade infinite enumerated sets
sage: L.cardinality()+Infinity
sage: p = L.__iter__()sage: (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p))(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)>>> from sage.all import *>>> L = TransitiveGroups(); L
Transitive Groups>>> L.category()
Category of facade infinite enumerated sets>>> L.cardinality()+Infinity>>> p = L.__iter__()>>> (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p))(continues on next page)

548

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)(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)class sage.groups.perm_gps.permgroup_named.TransitiveGroupsOfDegree(n)Bases: CachedRepresentation, Parent
The set of all transitive groups of a given (small) degree up to isomorphism.
EXAMPLES:
sage: S = TransitiveGroups(4); S
Transitive Groups of degree 4
sage: list(S)[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]
sage: TransitiveGroups(5).an_element()
Transitive group number 1 of degree 5>>> from sage.all import *>>> S = TransitiveGroups(Integer(4)); S
Transitive Groups of degree 4>>> list(S)[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]>>> TransitiveGroups(Integer(5)).an_element()
Transitive group number 1 of degree 5

We write the cardinality of all transitive groups of degree 5:
sage: for G in TransitiveGroups(5):....:print(G.cardinality())
5
10
20
60
120
>>> from sage.all import *>>> for G in TransitiveGroups(Integer(5)):...
print(G.cardinality())
5
10
20
60
120

27.4. “Named” Permutation groups (such as the symmetric group, S_n)

549

Groups, Release 10.4

cardinality()
Return the cardinality of self, that is the number of transitive groups of a given degree.
EXAMPLES:
sage: TransitiveGroups(0).cardinality()1sage: TransitiveGroups(2).cardinality()1sage: TransitiveGroups(7).cardinality()
7
sage: TransitiveGroups(12).cardinality()301
sage: [TransitiveGroups(i).cardinality() for i in range(11)][1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]>>> from sage.all import *>>> TransitiveGroups(Integer(0)).cardinality()1>>> TransitiveGroups(Integer(2)).cardinality()1>>> TransitiveGroups(Integer(7)).cardinality()
7>>> TransitiveGroups(Integer(12)).cardinality()301>>> [TransitiveGroups(i).cardinality() for i in range(Integer(11))][1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]

Warning: GAP comes with a database containing all transitive groups up to degree 31:
sage: TransitiveGroups(32).cardinality()
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31
are available in GAP s database>>> from sage.all import *>>> TransitiveGroups(Integer(32)).cardinality()
Traceback (most recent call last):...
NotImplementedError: only the transitive groups of degree at most 31
are available in GAP s database

27.5 Permutation group elements
AUTHORS:• David Joyner (2006-02)• David Joyner (2006-03): word problem method and reorganization• Robert Bradshaw (2007-11): convert to Cython• Sebastian Oehms (2018-11): Added gap() as synonym to _gap_() (compatibility to libgap framework, seeIssue #26750)

550

Chapter 27. Permutation Groups

Groups, Release 10.4

• Sebastian Oehms (2019-02): Implemented gap() properly (Issue #27234)
There are several ways to define a permutation group element:• Define a permutation group 𝐺, then use G.gens() and multiplication * to construct elements.
• Define a permutation group 𝐺, then use, e.g., G([(1,2),(3,4,5)]) to construct an element of the group.
You could also use G( (1,2)(3,4,5) )• Use, e.g., PermutationGroupElement([(1,2),(3,4,5)]) or PermutationGroupElement( (1,2)(3,4,5) ) to make a permutation group element with parent 𝑆5 .
EXAMPLES:
We illustrate construction of permutation using several different methods.
First we construct elements by multiplying together generators for a group:sage: G = PermutationGroup([ (1,2)(3,4) , (3,4,5,6) ], canonicalize=False)
sage: s = G.gens()
sage: s[0](1,2)(3,4)
sage: s[1](3,4,5,6)
sage: s[0]*s[1](1,2)(3,5,6)
sage: (s[0]*s[1]).parent()
Permutation Group with generators [(1,2)(3,4), (3,4,5,6)]>>> from sage.all import *>>> G = PermutationGroup([ (1,2)(3,4) , (3,4,5,6) ], canonicalize=False)>>> s = G.gens()>>> s[Integer(0)](1,2)(3,4)>>> s[Integer(1)](3,4,5,6)>>> s[Integer(0)]*s[Integer(1)](1,2)(3,5,6)>>> (s[Integer(0)]*s[Integer(1)]).parent()
Permutation Group with generators [(1,2)(3,4), (3,4,5,6)]

Next we illustrate creation of a permutation using coercion into an already-created group:sage: g = G([(1,2),(3,5,6)])
sage: g(1,2)(3,5,6)
sage: g.parent()
Permutation Group with generators [(1,2)(3,4), (3,4,5,6)]
sage: g == s[0]*s[1]True>>> from sage.all import *>>> g = G([(Integer(1),Integer(2)),(Integer(3),Integer(5),Integer(6))])>>> g(1,2)(3,5,6)>>> g.parent()
Permutation Group with generators [(1,2)(3,4), (3,4,5,6)]>>> g == s[Integer(0)]*s[Integer(1)]True

27.5. Permutation group elements

551

Groups, Release 10.4

We can also use a string or one-line notation to specify the permutation:
sage: h = G( (1,2)(3,5,6) )sage: i = G([2,1,5,4,6,3])
sage: g == h == iTrue>>> from sage.all import *>>> h = G( (1,2)(3,5,6) )>>> i = G([Integer(2),Integer(1),Integer(5),Integer(4),Integer(6),Integer(3)])>>> g == h == iTrue

The Rubik’s cube group:sage: f = [(17,19,24,22),(18,21,23,20),( 6,25,43,16),( 7,28,42,13),( 8,30,41,11)]
sage: b = [(33,35,40,38),(34,37,39,36),( 3, 9,46,32),( 2,12,47,29),( 1,14,48,27)]
sage: l = [( 9,11,16,14),(10,13,15,12),( 1,17,41,40),( 4,20,44,37),( 6,22,46,35)]
sage: r = [(25,27,32,30),(26,29,31,28),( 3,38,43,19),( 5,36,45,21),( 8,33,48,24)]
sage: u = [( 1, 3, 8, 6),( 2, 5, 7, 4),( 9,33,25,17),(10,34,26,18),(11,35,27,19)]
sage: d = [(41,43,48,46),(42,45,47,44),(14,22,30,38),(15,23,31,39),(16,24,32,40)]
sage: cube = PermutationGroup([f, b, l, r, u, d])sage: F, B, L, R, U, D = cube.gens()
sage: cube.order()43252003274489856000
sage: F.order()4>>> from sage.all import *>>> f = [(Integer(17),Integer(19),Integer(24),Integer(22)),(Integer(18),Integer(21),
˓→Integer(23),Integer(20)),( Integer(6),Integer(25),Integer(43),Integer(16)),(␣
˓→Integer(7),Integer(28),Integer(42),Integer(13)),( Integer(8),Integer(30),
˓→Integer(41),Integer(11))]>>> b = [(Integer(33),Integer(35),Integer(40),Integer(38)),(Integer(34),Integer(37),
˓→Integer(39),Integer(36)),( Integer(3), Integer(9),Integer(46),Integer(32)),(␣
˓→Integer(2),Integer(12),Integer(47),Integer(29)),( Integer(1),Integer(14),
˓→Integer(48),Integer(27))]>>> l = [( Integer(9),Integer(11),Integer(16),Integer(14)),(Integer(10),Integer(13),
˓→Integer(15),Integer(12)),( Integer(1),Integer(17),Integer(41),Integer(40)),(␣
˓→Integer(4),Integer(20),Integer(44),Integer(37)),( Integer(6),Integer(22),
˓→Integer(46),Integer(35))]>>> r = [(Integer(25),Integer(27),Integer(32),Integer(30)),(Integer(26),Integer(29),
˓→Integer(31),Integer(28)),( Integer(3),Integer(38),Integer(43),Integer(19)),(␣
˓→Integer(5),Integer(36),Integer(45),Integer(21)),( Integer(8),Integer(33),
˓→Integer(48),Integer(24))]>>> u = [( Integer(1), Integer(3), Integer(8), Integer(6)),( Integer(2), Integer(5),␣
˓→Integer(7), Integer(4)),( Integer(9),Integer(33),Integer(25),Integer(17)),
˓→(Integer(10),Integer(34),Integer(26),Integer(18)),(Integer(11),Integer(35),
˓→Integer(27),Integer(19))]>>> d = [(Integer(41),Integer(43),Integer(48),Integer(46)),(Integer(42),Integer(45),
˓→Integer(47),Integer(44)),(Integer(14),Integer(22),Integer(30),Integer(38)),
˓→(Integer(15),Integer(23),Integer(31),Integer(39)),(Integer(16),Integer(24),
˓→Integer(32),Integer(40))]>>> cube = PermutationGroup([f, b, l, r, u, d])>>> F, B, L, R, U, D = cube.gens()>>> cube.order()43252003274489856000(continues on next page)

552

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> F.order()4

We create element of a permutation group of large degree:
sage: G = SymmetricGroup(30)sage: s = G(srange(30,0,-1)); s(1,30)(2,29)(3,28)(4,27)(5,26)(6,25)(7,24)(8,23)(9,22)(10,21)(11,20)(12,19)(13,18)(14,
˓→17)(15,16)>>> from sage.all import *>>> G = SymmetricGroup(Integer(30))>>> s = G(srange(Integer(30),Integer(0),-Integer(1))); s(1,30)(2,29)(3,28)(4,27)(5,26)(6,25)(7,24)(8,23)(9,22)(10,21)(11,20)(12,19)(13,18)(14,
˓→17)(15,16)class sage.groups.perm_gps.permgroup_element.PermutationGroupElement
Bases: MultiplicativeGroupElement
An element of a permutation group.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ]); G
Permutation Group with generators [(1,2,3)(4,5)]
sage: g = G.random_element()
sage: g in G
True
sage: g = G.gen(0); g(1,2,3)(4,5)
sage: print(g)(1,2,3)(4,5)
sage: g*g
(1,3,2)sage: g**(-1)(1,3,2)(4,5)
sage: g**2
(1,3,2)sage: G = PermutationGroup([(1,2,3)])
sage: g = G.gen(0); g(1,2,3)sage: g.order()3>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ]); G
Permutation Group with generators [(1,2,3)(4,5)]>>> g = G.random_element()>>> g in G
True>>> g = G.gen(Integer(0)); g(1,2,3)(4,5)>>> print(g)(1,2,3)(4,5)>>> g*g(1,3,2)(continues on next page)

27.5. Permutation group elements

553

Groups, Release 10.4

(continued from previous page)>>> g**(-Integer(1))(1,3,2)(4,5)>>> g**Integer(2)(1,3,2)>>> G = PermutationGroup([(Integer(1),Integer(2),Integer(3))])>>> g = G.gen(Integer(0)); g(1,2,3)>>> g.order()3This example illustrates how permutations act on multivariate polynomials.
sage: R = PolynomialRing(RationalField(), 5, ["x","y","z","u","v"])sage: x, y, z, u, v = R.gens()
sage: f = x**2 - y**2 + 3*z**2
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: sigma = G.gen(0)sage: f * sigma
3*x^2 + y^2 - z^2>>> from sage.all import *>>> R = PolynomialRing(RationalField(), Integer(5), ["x","y","z","u","v"])>>> x, y, z, u, v = R.gens()>>> f = x**Integer(2) - y**Integer(2) + Integer(3)*z**Integer(2)>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> sigma = G.gen(Integer(0))>>> f * sigma
3*x^2 + y^2 - z^2cycle_string(singletons=False)
Return string representation of this permutation.
EXAMPLES:
sage: g = PermutationGroupElement([(1,2,3),(4,5)])
sage: g.cycle_string()(1,2,3)(4,5)
sage: g = PermutationGroupElement([3,2,1])
sage: g.cycle_string(singletons=True)(1,3)(2)>>> from sage.all import *>>> g = PermutationGroupElement([(Integer(1),Integer(2),Integer(3)),˓→(Integer(4),Integer(5))])>>> g.cycle_string()(1,2,3)(4,5)>>> g = PermutationGroupElement([Integer(3),Integer(2),Integer(1)])>>> g.cycle_string(singletons=True)(1,3)(2)cycle_tuples(singletons=False)
Return self as a list of disjoint cycles, represented as tuples rather than permutation group elements.
INPUT:

554

Chapter 27. Permutation Groups

Groups, Release 10.4

• singletons – boolean (default: False) whether or not consider the cycle that correspond to fixed
point
EXAMPLES:
sage: p = PermutationGroupElement( (2,6)(4,5,1) )sage: p.cycle_tuples()[(1, 4, 5), (2, 6)]
sage: p.cycle_tuples(singletons=True)[(1, 4, 5), (2, 6), (3,)]>>> from sage.all import *>>> p = PermutationGroupElement( (2,6)(4,5,1) )>>> p.cycle_tuples()[(1, 4, 5), (2, 6)]>>> p.cycle_tuples(singletons=True)[(1, 4, 5), (2, 6), (3,)]

EXAMPLES:
sage: S = SymmetricGroup(4)sage: S.gen(0).cycle_tuples()[(1, 2, 3, 4)]>>> from sage.all import *>>> S = SymmetricGroup(Integer(4))>>> S.gen(Integer(0)).cycle_tuples()[(1, 2, 3, 4)]
sage: S = SymmetricGroup([ a , b , c , d ])sage: S.gen(0).cycle_tuples()[( a , b , c , d )]sage: S([( a , b ), ( c , d )]).cycle_tuples()[( a , b ), ( c , d )]>>> from sage.all import *>>> S = SymmetricGroup([ a , b , c , d ])>>> S.gen(Integer(0)).cycle_tuples()[( a , b , c , d )]>>> S([( a , b ), ( c , d )]).cycle_tuples()[( a , b ), ( c , d )]cycle_type(singletons=True, as_list=False)
Return the partition that gives the cycle type of self as an element of its parent.
INPUT:• g – an element of the permutation group self.parent()• singletons – True or False depending on whether or not trivial cycles should be counted (default:
True)• as_list – True or False depending on whether the cycle type should be returned as a list or asa Partition (default: False)
OUTPUT: a Partition, or list if is_list is True, giving the cycle type of self
If speed is a concern, then as_list=True should be used.
EXAMPLES:
27.5. Permutation group elements

555

Groups, Release 10.4

sage: # needs sage.combinat
sage: G = DihedralGroup(3)sage: [g.cycle_type() for g in G][[1, 1, 1], [3], [3], [2, 1], [2, 1], [2, 1]]
sage: PermutationGroupElement( (1,2,3)(4,5)(6,7,8) ).cycle_type()[3, 3, 2]
sage: G = SymmetricGroup(3); G( (1,2) ).cycle_type()[2, 1]
sage: G = SymmetricGroup(4); G( (1,2) ).cycle_type()[2, 1, 1]
sage: G = SymmetricGroup(4); G( (1,2) ).cycle_type(singletons=False)[2]
sage: G = SymmetricGroup(4); G( (1,2) ).cycle_type(as_list=False)[2, 1, 1]>>> from sage.all import *>>> # needs sage.combinat>>> G = DihedralGroup(Integer(3))>>> [g.cycle_type() for g in G][[1, 1, 1], [3], [3], [2, 1], [2, 1], [2, 1]]>>> PermutationGroupElement( (1,2,3)(4,5)(6,7,8) ).cycle_type()[3, 3, 2]>>> G = SymmetricGroup(Integer(3)); G( (1,2) ).cycle_type()[2, 1]>>> G = SymmetricGroup(Integer(4)); G( (1,2) ).cycle_type()[2, 1, 1]>>> G = SymmetricGroup(Integer(4)); G( (1,2) ).cycle_type(singletons=False)[2]>>> G = SymmetricGroup(Integer(4)); G( (1,2) ).cycle_type(as_list=False)[2, 1, 1]

cycles()Return self as a list of disjoint cycles.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5,6,7) ])sage: g = G.0
sage: g.cycles()[(1,2,3), (4,5,6,7)]
sage: a, b = g.cycles()sage: a(1), b(1)(2, 1)>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5,6,7) ])>>> g = G.gen(0)>>> g.cycles()[(1,2,3), (4,5,6,7)]>>> a, b = g.cycles()>>> a(Integer(1)), b(Integer(1))(2, 1)

dict()
Return a dictionary associating each element of the domain with its image.
EXAMPLES:

556

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: G = SymmetricGroup(4)sage: g = G((1,2,3,4)); g(1,2,3,4)
sage: v = g.dict(); v{1: 2, 2: 3, 3: 4, 4: 1}
sage: type(v[1])<... int >sage: x = G([2,1]); x(1,2)
sage: x.dict(){1: 2, 2: 1, 3: 3, 4: 4}>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> g = G((Integer(1),Integer(2),Integer(3),Integer(4))); g(1,2,3,4)>>> v = g.dict(); v{1: 2, 2: 3, 3: 4, 4: 1}>>> type(v[Integer(1)])<... int >>>> x = G([Integer(2),Integer(1)]); x(1,2)>>> x.dict(){1: 2, 2: 1, 3: 3, 4: 4}

domain()Return the domain of self.
EXAMPLES:
sage: G = SymmetricGroup(4)sage: x = G([2,1,4,3]); x(1,2)(3,4)
sage: v = x.domain(); v[2, 1, 4, 3]
sage: type(v[0])<... int >sage: x = G([2,1]); x(1,2)
sage: x.domain()[2, 1, 3, 4]>>> from sage.all import *>>> G = SymmetricGroup(Integer(4))>>> x = G([Integer(2),Integer(1),Integer(4),Integer(3)]); x(1,2)(3,4)>>> v = x.domain(); v[2, 1, 4, 3]>>> type(v[Integer(0)])<... int >>>> x = G([Integer(2),Integer(1)]); x(1,2)>>> x.domain()[2, 1, 3, 4]

gap()
Return self as a libgap element.
27.5. Permutation group elements

557

Groups, Release 10.4

EXAMPLES:
sage: S = SymmetricGroup(4)sage: p = S( (2,4) )sage: p_libgap = libgap(p)sage: p_libgap.Order()2sage: S(p_libgap) == pTrue
sage: # needs sage.rings.finite_rings
sage: P = PGU(8,2)
sage: p, q = P.gens()
sage: p_libgap = p.gap()>>> from sage.all import *>>> S = SymmetricGroup(Integer(4))>>> p = S( (2,4) )>>> p_libgap = libgap(p)>>> p_libgap.Order()2>>> S(p_libgap) == p
True>>> # needs sage.rings.finite_rings>>> P = PGU(Integer(8),Integer(2))>>> p, q = P.gens()>>> p_libgap = p.gap()

has_descent(i, side='right', positive=False)
Return whether self has a left (resp. right) descent at position i. If positive is True, then test for anon descent instead.
Beware that, since permutations are acting on the right, the meaning of descents is the reverse of the usual
convention. Hence, self has a left descent at position i if self(i) > self(i+1).
INPUT:• i – an element of the index set• side – "left" or "right" (default: "right")• positive – a boolean (default: False)
EXAMPLES:
sage: S = SymmetricGroup([1,2,3])
sage: S.one().has_descent(1)False
sage: S.one().has_descent(2)False
sage: s = S.simple_reflections()
sage: x = s[1]*s[2]sage: x.has_descent(1, side="right")
False
sage: x.has_descent(2, side="right")
Truesage: x.has_descent(1, side="left")
True(continues on next page)

558

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

sage: x.has_descent(2, side="left")
False
sage: S._test_has_descent()>>> from sage.all import *>>> S = SymmetricGroup([Integer(1),Integer(2),Integer(3)])>>> S.one().has_descent(Integer(1))
False>>> S.one().has_descent(Integer(2))
False>>> s = S.simple_reflections()>>> x = s[Integer(1)]*s[Integer(2)]>>> x.has_descent(Integer(1), side="right")
False>>> x.has_descent(Integer(2), side="right")
True>>> x.has_descent(Integer(1), side="left")True>>> x.has_descent(Integer(2), side="left")
False>>> S._test_has_descent()

The symmetric group acting on a set not of the form (1, . . . , 𝑛) is also supported:
sage: S = SymmetricGroup([2,4,1])
sage: s = S.simple_reflections()
sage: x = s[2]*s[4]sage: x.has_descent(4)True
sage: S._test_has_descent()>>> from sage.all import *>>> S = SymmetricGroup([Integer(2),Integer(4),Integer(1)])>>> s = S.simple_reflections()>>> x = s[Integer(2)]*s[Integer(4)]>>> x.has_descent(Integer(4))
True>>> S._test_has_descent()

inverse()Return the inverse permutation.
OUTPUT:For an element of a permutation group, this method returns the inverse element, which is both the inverse
function and the inverse as an element of a group.
EXAMPLES:
sage: s = PermutationGroupElement("(1,2,3)(4,5)")
sage: s.inverse()(1,3,2)(4,5)
sage: A = AlternatingGroup(4)sage: t = A("(1,2,3)")
sage: t.inverse()(1,3,2)27.5. Permutation group elements559

Groups, Release 10.4>>> from sage.all import *>>> s = PermutationGroupElement("(1,2,3)(4,5)")>>> s.inverse()(1,3,2)(4,5)>>> A = AlternatingGroup(Integer(4))>>> t = A("(1,2,3)")>>> t.inverse()(1,3,2)

There are several ways (syntactically) to get an inverse of a permutation group element.
sage: s = PermutationGroupElement("(1,2,3,4)(6,7,8)")
sage: s.inverse() == s^-1
True
sage: s.inverse() == ~sTrue>>> from sage.all import *>>> s = PermutationGroupElement("(1,2,3,4)(6,7,8)")>>> s.inverse() == s**-Integer(1)True>>> s.inverse() == ~sTruematrix()Return a deg × deg permutation matrix associated to the permutation self.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: g = G.gen(0)sage: g.matrix()[0 1 0 0 0]
[0 0 1 0 0]
[1 0 0 0 0]
[0 0 0 0 1]
[0 0 0 1 0]>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> g = G.gen(Integer(0))>>> g.matrix()[0 1 0 0 0]
[0 0 1 0 0]
[1 0 0 0 0]
[0 0 0 0 1]
[0 0 0 1 0]

multiplicative_order()Return the order of this group element, which is the smallest positive integer 𝑛 for which 𝑔 𝑛 = 1.
EXAMPLES:
sage: s = PermutationGroupElement( (1,2)(3,5,6) )sage: s.multiplicative_order()6

560

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> s = PermutationGroupElement( (1,2)(3,5,6) )>>> s.multiplicative_order()6order() is just an alias for multiplicative_order():sage: s.order()6>>> from sage.all import *>>> s.order()6orbit(n, sorted=True)
Return the orbit of the integer 𝑛 under this group element, as a sorted list.
EXAMPLES:
sage: G = PermutationGroup([ (1,2,3)(4,5) ])sage: g = G.gen(0)sage: g.orbit(4)[4, 5]
sage: g.orbit(3)[1, 2, 3]
sage: g.orbit(10)[10]>>> from sage.all import *>>> G = PermutationGroup([ (1,2,3)(4,5) ])>>> g = G.gen(Integer(0))>>> g.orbit(Integer(4))[4, 5]>>> g.orbit(Integer(3))[1, 2, 3]>>> g.orbit(Integer(10))[10]sage: s = SymmetricGroup([ a ,( a , b )sage: s.orbit( a )[ a , b ]>>> from sage.all import *>>> s = SymmetricGroup([ a ,( a , b )>>> s.orbit( a )[ a , b ]b ]).gen(0); sb ]).gen(Integer(0)); ssign()
Return the sign of self, which is (−1)𝑠 , where 𝑠 is the number of swaps.
EXAMPLES:

27.5. Permutation group elements

561

Groups, Release 10.4

sage: s = PermutationGroupElement( (1,2)(3,5,6) )sage: s.sign()-1>>> from sage.all import *>>> s = PermutationGroupElement( (1,2)(3,5,6) )>>> s.sign()-1

ALGORITHM: Only even cycles contribute to the sign, thus∑︀

𝑠𝑖𝑔𝑛(𝑠𝑖𝑔𝑚𝑎) = (−1)

𝑐 𝑙𝑒𝑛(𝑐)−1where the sum is over cycles in self.
tuple()
Return tuple of images of the domain under self.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: s = G([2,1,5,3,4])
sage: s.tuple()(2, 1, 5, 3, 4)
sage: S = SymmetricGroup([ a ,sage: S.gen().tuple()( b , a )b ])>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> s = G([Integer(2),Integer(1),Integer(5),Integer(3),Integer(4)])>>> s.tuple()(2, 1, 5, 3, 4)>>> S = SymmetricGroup([ a ,>>> S.gen().tuple()( b , a )b ])word_problem(words, display=True, as_list=False)
Try to solve the word problem for self.
INPUT:• words – a list of elements of the ambient group, generating a subgroup• display – boolean (default True) whether to display additional information• as_list – boolean (default False) whether to return the result as a list of pairs (generator, exponent)
OUTPUT:• a pair of strings, both representing the same wordor
• a list of pairs representing the word, each pair being (generator as a string, exponent as an integer)
Let 𝐺 be the ambient permutation group, containing the given element 𝑔. Let 𝐻 be the subgroup of 𝐺
generated by the list words of elements of 𝐺. If 𝑔 is in 𝐻, this function returns an expression for 𝑔 as aword in the elements of words and their inverses.
562

Chapter 27. Permutation Groups

Groups, Release 10.4

This function does not solve the word problem in Sage. Rather it pushes it over to GAP, which has optimized
algorithms for the word problem. Essentially, this function is a wrapper for the GAP functions EpimorphismFromFreeGroup and PreImagesRepresentative.
EXAMPLES:
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]], canonicalize=False)
sage: g1, g2 = G.gens()
sage: h = g1^2*g2*g1
sage: h.word_problem([g1,g2], False)( x1^2*x2^-1*x1 , (1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5) )sage: h.word_problem([g1,g2])x1^2*x2^-1*x1[[ (1,2,3)(4,5) , 2], [ (3,4) , -1], [ (1,2,3)(4,5) , 1]]( x1^2*x2^-1*x1 , (1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5) )sage: h.word_problem([g1,g2], False, as_list=True)[[ (1,2,3)(4,5) , 2], [ (3,4) , -1], [ (1,2,3)(4,5) , 1]]>>> from sage.all import *>>> G = PermutationGroup([[(Integer(1),Integer(2),Integer(3)),(Integer(4),˓→Integer(5))],[(Integer(3),Integer(4))]], canonicalize=False)>>> g1, g2 = G.gens()>>> h = g1**Integer(2)*g2*g1>>> h.word_problem([g1,g2], False)( x1^2*x2^-1*x1 , (1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5) )>>> h.word_problem([g1,g2])x1^2*x2^-1*x1[[ (1,2,3)(4,5) , 2], [ (3,4) , -1], [ (1,2,3)(4,5) , 1]]( x1^2*x2^-1*x1 , (1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5) )>>> h.word_problem([g1,g2], False, as_list=True)[[ (1,2,3)(4,5) , 2], [ (3,4) , -1], [ (1,2,3)(4,5) , 1]]class sage.groups.perm_gps.permgroup_element.SymmetricGroupElement
Bases: PermutationGroupElement
An element of the symmetric group.
absolute_length()
Return the absolute length of self.
The absolute length is the size minus the number of its disjoint cycles. Alternatively, it is the length of theshortest expression of the element as a product of reflections.
See also:
absolute_le()
EXAMPLES:
sage: S = SymmetricGroup(3)sage: [x.absolute_length() for x in S]
˓→needs sage.combinat[0, 2, 2, 1, 1, 1]

27.5. Permutation group elements

#␣

563

Groups, Release 10.4>>> from sage.all import *>>> S = SymmetricGroup(Integer(3))>>> [x.absolute_length() for x in S]
˓→needs sage.combinat[0, 2, 2, 1, 1, 1]#␣

has_left_descent(i)Return whether 𝑖 is a left descent of self.
EXAMPLES:
sage: W = SymmetricGroup(4)sage: w = W.from_reduced_word([1,3,2,1])
sage: [i for i in W.index_set() if w.has_left_descent(i)][1, 3]>>> from sage.all import *>>> W = SymmetricGroup(Integer(4))>>> w = W.from_reduced_word([Integer(1),Integer(3),Integer(2),Integer(1)])>>> [i for i in W.index_set() if w.has_left_descent(i)][1, 3]

sage.groups.perm_gps.permgroup_element.is_PermutationGroupElement(x)Return True if x is a PermutationGroupElement.
EXAMPLES:
sage: p = PermutationGroupElement([(1,2),(3,4,5)])
sage: from sage.groups.perm_gps.permgroup_element import is_
˓→PermutationGroupElement
sage: is_PermutationGroupElement(p)doctest:warning...
DeprecationWarning: The function is_PermutationGroupElement is deprecated;
use isinstance(..., PermutationGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
True>>> from sage.all import *>>> p = PermutationGroupElement([(Integer(1),Integer(2)),(Integer(3),Integer(4),˓→Integer(5))])>>> from sage.groups.perm_gps.permgroup_element import is_PermutationGroupElement>>> is_PermutationGroupElement(p)doctest:warning...
DeprecationWarning: The function is_PermutationGroupElement is deprecated;
use isinstance(..., PermutationGroupElement) instead.
See https://github.com/sagemath/sage/issues/38184 for details.
Truesage.groups.perm_gps.permgroup_element.make_permgroup_element(G, x)
Return a PermutationGroupElement given the permutation group G and the permutation x in list notation.
This is function is used when unpickling old (pre-domain) versions of permutation groups and their elements. This
now does a bit of processing and calls make_permgroup_element_v2() which is used in unpickling thecurrent PermutationGroupElements.
EXAMPLES:

564

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element
sage: S = SymmetricGroup(3)sage: make_permgroup_element(S, [1,3,2])(2,3)>>> from sage.all import *>>> from sage.groups.perm_gps.permgroup_element import make_permgroup_element>>> S = SymmetricGroup(Integer(3))>>> make_permgroup_element(S, [Integer(1),Integer(3),Integer(2)])(2,3)

sage.groups.perm_gps.permgroup_element.make_permgroup_element_v2(G, x, domain)
Return a PermutationGroupElement given the permutation group G, the permutation x in list notation, andthe domain domain of the permutation group.
This is function is used when unpickling permutation groups and their elements.
EXAMPLES:
sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element_v2
sage: S = SymmetricGroup(3)sage: make_permgroup_element_v2(S, [1,3,2], S.domain())(2,3)>>> from sage.all import *>>> from sage.groups.perm_gps.permgroup_element import make_permgroup_element_v2>>> S = SymmetricGroup(Integer(3))>>> make_permgroup_element_v2(S, [Integer(1),Integer(3),Integer(2)], S.domain())(2,3)

27.6 Permutation group homomorphisms
AUTHORS:• David Joyner (2006-03-21): first version• David Joyner (2008-06): fixed kernel and image to return a group, instead of a string.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: H = DihedralGroup(4)sage: g = G([(1,2,3,4)])
sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
sage: phi.image(G)Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)sage: phi.kernel()
Subgroup generated by [()] of (Cyclic group of order 4 as a permutation group)sage: phi.image(g)(1,2,3,4)
sage: phi(g)(1,2,3,4)
sage: phi.codomain()
Dihedral group of order 8 as a permutation group(continues on next page)

27.6. Permutation group homomorphisms

565

Groups, Release 10.4

(continued from previous page)

sage: phi.codomain()
Dihedral group of order 8 as a permutation group
sage: phi.domain()
Cyclic group of order 4 as a permutation group>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> H = DihedralGroup(Integer(4))>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))])>>> phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))>>> phi.image(G)Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)>>> phi.kernel()
Subgroup generated by [()] of (Cyclic group of order 4 as a permutation group)>>> phi.image(g)(1,2,3,4)>>> phi(g)(1,2,3,4)>>> phi.codomain()
Dihedral group of order 8 as a permutation group>>> phi.codomain()
Dihedral group of order 8 as a permutation group>>> phi.domain()
Cyclic group of order 4 as a permutation groupclass sage.groups.perm_gps.permgroup_morphism.PermutationGroupMorphism
Bases: Morphism
A set-theoretic map between PermutationGroups.
image(J)Compute the subgroup of the codomain 𝐻 which is the image of 𝐽.
𝐽 must be a subgroup of the domain 𝐺.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: H = DihedralGroup(4)sage: g = G([(1,2,3,4)])
sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
sage: phi.image(G)Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)sage: phi.image(g)(1,2,3,4)>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> H = DihedralGroup(Integer(4))>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))])>>> phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))>>> phi.image(G)Subgroup generated by [(1,2,3,4)] of(Dihedral group of order 8 as a permutation group)(continues on next page)

566

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> phi.image(g)(1,2,3,4)
sage: G = PSL(2,7)
sage: D = G.direct_product(G)sage: H = D[0]sage: pr1 = D[3]sage: pr1.image(G)Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of(The projective special linear group of degree 2 over Finite Field of size 7)
sage: G.is_isomorphic(pr1.image(G))
True>>> from sage.all import *>>> G = PSL(Integer(2),Integer(7))>>> D = G.direct_product(G)>>> H = D[Integer(0)]>>> pr1 = D[Integer(3)]>>> pr1.image(G)Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of(The projective special linear group of degree 2 over Finite Field of size 7)>>> G.is_isomorphic(pr1.image(G))
True

Check that Issue #28324 is fixed:
sage: # needs sage.rings.number_fieldsage: R.<x> = QQ[]
sage: f = x^4 + x^2 - 3
sage: L.<a> = f.splitting_field()sage: G = L.galois_group()
sage: D4 = DihedralGroup(4)sage: h = D4.isomorphism_to(G)sage: h.image(D4).is_isomorphic(G)Truesage: all(h.image(g) in G for g in D4.gens())
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> f = x**Integer(4) + x**Integer(2) - Integer(3)>>> L = f.splitting_field(names=( a ,)); (a,) = L._first_ngens(1)>>> G = L.galois_group()>>> D4 = DihedralGroup(Integer(4))>>> h = D4.isomorphism_to(G)>>> h.image(D4).is_isomorphic(G)True>>> all(h.image(g) in G for g in D4.gens())
Truekernel()Return the kernel of this homomorphism as a permutation group.
EXAMPLES:

27.6. Permutation group homomorphisms

567

Groups, Release 10.4

sage: G = CyclicPermutationGroup(4)sage: H = DihedralGroup(4)sage: g = G([(1,2,3,4)])
sage: phi = PermutationGroupMorphism_im_gens(G, H, [1])sage: phi.kernel()
Subgroup generated by [(1,2,3,4)] of(Cyclic group of order 4 as a permutation group)>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> H = DihedralGroup(Integer(4))>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))])>>> phi = PermutationGroupMorphism_im_gens(G, H, [Integer(1)])>>> phi.kernel()
Subgroup generated by [(1,2,3,4)] of(Cyclic group of order 4 as a permutation group)sage: G = PSL(2,7)
sage: D = G.direct_product(G)sage: H = D[0]sage: pr1 = D[3]sage: G.is_isomorphic(pr1.kernel())
True>>> from sage.all import *>>> G = PSL(Integer(2),Integer(7))>>> D = G.direct_product(G)>>> H = D[Integer(0)]>>> pr1 = D[Integer(3)]>>> G.is_isomorphic(pr1.kernel())
Trueclass sage.groups.perm_gps.permgroup_morphism.PermutationGroupMorphism_from_gap(G,H,
gap_hom)
Bases: PermutationGroupMorphism
This is a Python trick to allow Sage programmers to create a group homomorphism using GAP using very general constructions. An example of its usage is in the direct_product instance method of the PermutationGroup_generic class in permgroup.py.
Basic syntax:
PermutationGroupMorphism_from_gap(domain_group,
range_group,
phi:=gap_hom_command; , phi ). And don’t forget the line: from sage.groups.perm_gps.
permgroup_morphism import PermutationGroupMorphism_from_gap in your program.
EXAMPLES:
sage: from sage.groups.perm_gps.permgroup_morphism import␣˓→PermutationGroupMorphism_from_gap
sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])sage: H = G.subgroup([G([(1,2,3,4)])])
sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity)
Permutation group morphism:
From: Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])(continues on next page)

568

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

To:
Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
Defn: Identity>>> from sage.all import *>>> from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_
˓→from_gap>>> G = PermutationGroup([[(Integer(1),Integer(2)),(Integer(3),Integer(4))],␣
˓→[(Integer(1),Integer(2),Integer(3),Integer(4))]])>>> H = G.subgroup([G([(Integer(1),Integer(2),Integer(3),Integer(4))])])>>> PermutationGroupMorphism_from_gap(H, G, gap.Identity)
Permutation group morphism:
From: Subgroup generated by [(1,2,3,4)] of(Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])To:
Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
Defn: Identity

class sage.groups.perm_gps.permgroup_morphism.PermutationGroupMorphism_id
Bases: PermutationGroupMorphismclass sage.groups.perm_gps.permgroup_morphism.PermutationGroupMorphism_im_gens(G,H,
gens=None)
Bases: PermutationGroupMorphism
Some python code for wrapping GAP’s GroupHomomorphismByImages function but only for permutationgroups. Can be expensive if G is large. This returns “fail” if gens does not generate self or if the map does notextend to a group homomorphism, self - other.
EXAMPLES:
sage: G = CyclicPermutationGroup(4)sage: H = DihedralGroup(4)sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())); phi
Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Dihedral group of order 8 as a permutation group
Defn: [(1,2,3,4)] -> [(1,2,3,4)]
sage: g = G([(1,3),(2,4)]); g(1,3)(2,4)
sage: phi(g)(1,3)(2,4)
sage: images = ((4,3,2,1),)
sage: phi = PermutationGroupMorphism_im_gens(G, G, images)
sage: g = G([(1,2,3,4)]); g(1,2,3,4)
sage: phi(g)(1,4,3,2)>>> from sage.all import *>>> G = CyclicPermutationGroup(Integer(4))>>> H = DihedralGroup(Integer(4))>>> phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())); phi
Permutation group morphism:
From: Cyclic group of order 4 as a permutation group
To:
Dihedral group of order 8 as a permutation group
Defn: [(1,2,3,4)] -> [(1,2,3,4)](continues on next page)

27.6. Permutation group homomorphisms

569

Groups, Release 10.4

(continued from previous page)>>> g = G([(Integer(1),Integer(3)),(Integer(2),Integer(4))]); g(1,3)(2,4)>>> phi(g)(1,3)(2,4)>>> images = ((Integer(4),Integer(3),Integer(2),Integer(1)),)>>> phi = PermutationGroupMorphism_im_gens(G, G, images)>>> g = G([(Integer(1),Integer(2),Integer(3),Integer(4))]); g(1,2,3,4)>>> phi(g)(1,4,3,2)

AUTHORS:• David Joyner (2006-02)
sage.groups.perm_gps.permgroup_morphism.is_PermutationGroupMorphism(f)Return True if the argument f is a PermutationGroupMorphism.
EXAMPLES:
sage: from sage.groups.perm_gps.permgroup_morphism import is_
˓→PermutationGroupMorphism
sage: G = CyclicPermutationGroup(4)sage: H = DihedralGroup(4)sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
sage: is_PermutationGroupMorphism(phi)doctest:warning...
DeprecationWarning: The function is_PermutationGroupMorphism is deprecated;
use isinstance(..., PermutationGroupMorphism) instead.
See https://github.com/sagemath/sage/issues/38103 for details.
True>>> from sage.all import *>>> from sage.groups.perm_gps.permgroup_morphism import is_
˓→PermutationGroupMorphism>>> G = CyclicPermutationGroup(Integer(4))>>> H = DihedralGroup(Integer(4))>>> phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))>>> is_PermutationGroupMorphism(phi)doctest:warning...
DeprecationWarning: The function is_PermutationGroupMorphism is deprecated;
use isinstance(..., PermutationGroupMorphism) instead.
See https://github.com/sagemath/sage/issues/38103 for details.
True

27.7 Rubik’s cube group functions
Note: “Rubiks cube” is trademarked. We shall omit the trademark symbol below for simplicity.
NOTATION:
𝐵 denotes a clockwise quarter turn of the back face, 𝐷 denotes a clockwise quarter turn of the down face, and similarly
for 𝐹 (front), 𝐿 (left), 𝑅 (right), and 𝑈 (up). Products of moves are read right to left, so for example, 𝑅 · 𝑈 means move
𝑈 first and then 𝑅.
570

Chapter 27. Permutation Groups

Groups, Release 10.4

See CubeGroup.parse() for all possible input notations.
The “Singmaster notation”:• moves: 𝑈, 𝐷, 𝑅, 𝐿, 𝐹, 𝐵 as in the diagram below,• corners: 𝑥𝑦𝑧 means the facet is on face 𝑥 (in 𝑅, 𝐹, 𝐿, 𝑈, 𝐷, 𝐵) and the clockwise rotation of the corner sends
𝑥−𝑦−𝑧• edges: 𝑥𝑦 means the facet is on face 𝑥 and a flip of the edge sends 𝑥 − 𝑦.
sage: rubik = CubeGroup()
sage: rubik.display2d("")┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.display2d("")┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘AUTHORS:• David Joyner (2006-10-21): first version• David Joyner (2007-05): changed faces, added legal and solve• David Joyner(2007-06): added plotting functions• David Joyner (2007, 2008): colors corrected, “solve” rewritten (again),typos fixed.
• Robert Miller (2007, 2008): editing, cleaned up display2d• Robert Bradshaw (2007, 2008): RubiksCube object, 3d plotting.
• David Joyner (2007-09): rewrote docstring for CubeGroup’s “solve”.
• Robert Bradshaw (2007-09): Versatile parse function for all input types.
• Robert Bradshaw (2007-11): Cleanup.
27.7. Rubik’s cube group functions

571

Groups, Release 10.4

REFERENCES:• Cameron, P., Permutation Groups. New York: Cambridge University Press, 1999.
• Wielandt, H., Finite Permutation Groups. New York: Academic Press, 1964.
• Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996.
• Joyner, D., Adventures in Group Theory, Johns Hopkins Univ Press, 2002.
class sage.groups.perm_gps.cubegroup.CubeGroupBases: PermutationGroup_genericA python class to help compute Rubik’s cube group actions.
Note: This group is also available via groups.permutation.RubiksCube().
EXAMPLES:
If G denotes the cube group then it may be regarded as a subgroup of SymmetricGroup(48), where the 48
facets are labeled as follows.
sage: rubik = CubeGroup()
sage: rubik.display2d("")┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.display2d("")┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘
sage: rubik
The Rubik s cube group with generators R,L,F,B,U,D in SymmetricGroup(48).

572

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> rubik
The Rubik s cube group with generators R,L,F,B,U,D in SymmetricGroup(48).

B()
Return the generator 𝐵 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.B()(1,14,48,27)(2,12,47,29)(3,9,46,32)(33,35,40,38)(34,37,39,36)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.B()(1,14,48,27)(2,12,47,29)(3,9,46,32)(33,35,40,38)(34,37,39,36)

D()
Return the generator 𝐷 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.D()(14,22,30,38)(15,23,31,39)(16,24,32,40)(41,43,48,46)(42,45,47,44)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.D()(14,22,30,38)(15,23,31,39)(16,24,32,40)(41,43,48,46)(42,45,47,44)

F()
Return the generator 𝐹 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.F()(6,25,43,16)(7,28,42,13)(8,30,41,11)(17,19,24,22)(18,21,23,20)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.F()(6,25,43,16)(7,28,42,13)(8,30,41,11)(17,19,24,22)(18,21,23,20)

L()
Return the generator 𝐿 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.L()(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)

27.7. Rubik’s cube group functions

573

Groups, Release 10.4>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.L()(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)R()
Return the generator 𝑅 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.R()(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.R()(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)

U()
Return the generator 𝑈 in Singmaster notation.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.U()(1,3,8,6)(2,5,7,4)(9,33,25,17)(10,34,26,18)(11,35,27,19)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.U()(1,3,8,6)(2,5,7,4)(9,33,25,17)(10,34,26,18)(11,35,27,19)

display2d(mv)Print the 2d representation of self.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.display2d("R")┌──────────────┐
│ 1
2
38 │
│ 4
top 36 ││ 6
733 │┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 17
18
3 │ 2729 32 │ 48 34 35 ││ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
8 │ 2528 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
19 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘>>> from sage.all import *>>> rubik = CubeGroup()(continues on next page)

574

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> rubik.display2d("R")┌──────────────┐
│ 1
2
38 │
│ 4
top 36 ││ 6
733 │┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 17
18
3 │ 2729 32 │ 48 34 35 ││ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
8 │ 2528 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
19 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘

faces(mv)
Return the dictionary of faces created by the effect of the move mv, which is a string of the form 𝑋 𝑎 *𝑌 𝑏 *...,
where 𝑋, 𝑌, . . . are in {𝑅, 𝐿, 𝐹, 𝐵, 𝑈, 𝐷} and 𝑎, 𝑏, . . . are integers. We call this ordering of the faces the“BDFLRU, L2R, T2B ordering”.
EXAMPLES:
sage: rubik = CubeGroup()>>> from sage.all import *>>> rubik = CubeGroup()

Here is the dictionary of the solved state:sage: sorted(rubik.faces("").items())[( back , [[33, 34, 35], [36, 0, 37], [38, 39, 40]]),( down , [[41, 42, 43], [44, 0, 45], [46, 47, 48]]),( front , [[17, 18, 19], [20, 0, 21], [22, 23, 24]]),( left , [[9, 10, 11], [12, 0, 13], [14, 15, 16]]),( right , [[25, 26, 27], [28, 0, 29], [30, 31, 32]]),( up , [[1, 2, 3], [4, 0, 5], [6, 7, 8]])]>>> from sage.all import *>>> sorted(rubik.faces("").items())[( back , [[33, 34, 35], [36, 0, 37], [38, 39, 40]]),( down , [[41, 42, 43], [44, 0, 45], [46, 47, 48]]),( front , [[17, 18, 19], [20, 0, 21], [22, 23, 24]]),( left , [[9, 10, 11], [12, 0, 13], [14, 15, 16]]),( right , [[25, 26, 27], [28, 0, 29], [30, 31, 32]]),( up , [[1, 2, 3], [4, 0, 5], [6, 7, 8]])]

Now the dictionary of the state obtained after making the move 𝑅 followed by 𝐿:
sage: sorted(rubik.faces("R*U").items())[( back , [[48, 26, 27], [45, 0, 37], [43, 39, 40]]),( down , [[41, 42, 11], [44, 0, 21], [46, 47, 24]]),( front , [[9, 10, 8], [20, 0, 7], [22, 23, 6]]),( left , [[33, 34, 35], [12, 0, 13], [14, 15, 16]]),( right , [[19, 29, 32], [18, 0, 31], [17, 28, 30]]),( up , [[3, 5, 38], [2, 0, 36], [1, 4, 25]])]27.7. Rubik’s cube group functions

575

Groups, Release 10.4>>> from sage.all import *>>> sorted(rubik.faces("R*U").items())[( back , [[48, 26, 27], [45, 0, 37], [43, 39, 40]]),( down , [[41, 42, 11], [44, 0, 21], [46, 47, 24]]),( front , [[9, 10, 8], [20, 0, 7], [22, 23, 6]]),( left , [[33, 34, 35], [12, 0, 13], [14, 15, 16]]),( right , [[19, 29, 32], [18, 0, 31], [17, 28, 30]]),( up , [[3, 5, 38], [2, 0, 36], [1, 4, 25]])]facets(g=None)
Return the set of facets on which the group acts. This function is a “constant”.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.facets() == list(range(1,49))
True>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.facets() == list(range(Integer(1),Integer(49)))
True

gen_names()
Return the names of the generators.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.gen_names()[ B , D , F , L , R ,U ]>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.gen_names()[ B , D , F , L , R , U ]legal(state, mode='quiet')
Return 1 (true) if the dictionary state (in the same format as returned by the faces method) represents alegal position (or state) of the Rubik’s cube or 0 (false) otherwise.
EXAMPLES:
sage: rubik = CubeGroup()
sage: r0 = rubik.faces("")
sage: r1 = { back : [[33, 34, 35], [36, 0, 37], [38, 39, 40]], down : [[41,␣˓→42, 43], [44, 0, 45], [46, 47, 48]], front : [[17, 18, 19], [20, 0, 21],␣
˓→[22, 23, 24]], left : [[9, 10, 11], [12, 0, 13], [14, 15, 16]], right :␣˓→[[25, 26, 27], [28, 0, 29], [30, 31, 32]], up : [[1, 2, 3], [4, 0, 5], [6,␣
˓→8, 7]]}sage: rubik.legal(r0)1
sage: rubik.legal(r0,"verbose")(1, ())
sage: rubik.legal(r1)0576

Chapter 27. Permutation Groups

Groups, Release 10.4>>> from sage.all import *>>> rubik = CubeGroup()>>> r0 = rubik.faces("")>>> r1 = { back : [[Integer(33), Integer(34), Integer(35)], [Integer(36),␣
˓→Integer(0), Integer(37)], [Integer(38), Integer(39), Integer(40)]],
down :␣
˓→[[Integer(41), Integer(42), Integer(43)], [Integer(44), Integer(0),␣
˓→Integer(45)], [Integer(46), Integer(47), Integer(48)]], front :␣˓→[[Integer(17), Integer(18), Integer(19)], [Integer(20), Integer(0),␣
˓→Integer(21)], [Integer(22), Integer(23), Integer(24)]], left : [[Integer(9),˓→ Integer(10), Integer(11)], [Integer(12), Integer(0), Integer(13)],␣
˓→[Integer(14), Integer(15), Integer(16)]], right : [[Integer(25),␣
˓→Integer(26), Integer(27)], [Integer(28), Integer(0), Integer(29)],␣
˓→[Integer(30), Integer(31), Integer(32)]], up : [[Integer(1), Integer(2),␣
˓→Integer(3)], [Integer(4), Integer(0), Integer(5)], [Integer(6), Integer(8),␣
˓→Integer(7)]]}>>> rubik.legal(r0)1>>> rubik.legal(r0,"verbose")(1, ())>>> rubik.legal(r1)0move(mv)
Return the group element and the reordered list of facets, as moved by the list mv (read left-to-right)
INPUT:• mv – A string of the form Xa*Yb*..., where X, Y, … are in R, L, F, B, U, D and a, b, … are integers.
EXAMPLES:
sage: rubik = CubeGroup()
sage: rubik.move("")[0]()sage: rubik.move("R")[0](3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)
sage: rubik.R()(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)>>> from sage.all import *>>> rubik = CubeGroup()>>> rubik.move("")[Integer(0)]()>>> rubik.move("R")[Integer(0)](3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)>>> rubik.R()(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)

parse(mv, check=True)
This function allows one to create the permutation group element from a variety of formats.
INPUT:• mv – Can one of the following:– list – list of facets (as returned by self.facets())– dict – list of faces (as returned by self.faces())– str – either cycle notation (passed to GAP) or a product of generators or Singmaster notation
27.7. Rubik’s cube group functions

577

Groups, Release 10.4

– perm_group element – returned as an element of self
• check – check if the input is valid
EXAMPLES:
sage: C = CubeGroup()
sage: C.parse(list(range(1,49)))()
sage: g = C.parse("L"); g(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)
sage: C.parse(str(g)) == gTruesage: facets = C.facets(g); facets[17, 2, 3, 20, 5, 22, 7, 8, 11, 13, 16, 10, 15, 9, 12, 14, 41, 18, 19, 44, 21,
˓→ 46, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 6, 36, 4, 38, 39, 1,␣
˓→40, 42, 43, 37, 45, 35, 47, 48]
sage: C.parse(facets)(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)
sage: C.parse(facets) == gTruesage: faces = C.faces("L"); faces{ back : [[33, 34, 6], [36, 0, 4], [38, 39, 1]],
down : [[40, 42, 43], [37, 0, 45], [35, 47, 48]],
front : [[41, 18, 19], [44, 0, 21], [46, 23, 24]],
left : [[11, 13, 16], [10, 0, 15], [9, 12, 14]],right : [[25, 26, 27], [28, 0, 29], [30, 31, 32]],
up : [[17, 2, 3], [20, 0, 5], [22, 7, 8]]}sage: C.parse(faces) == C.parse("L")
True
sage: C.parse("L R2") == C.parse("L^(-1)*R^2")
True
sage: C.parse("L R2")
(1,40,41,17)(3,43)(4,37,44,20)(5,45)(6,35,46,22)(8,48)(9,14,16,11)(10,12,15,
˓→13)(19,38)(21,36)(24,33)(25,32)(26,31)(27,30)(28,29)
sage: C.parse("L^4")()sage: C.parse("L^(-1)*R")(1,40,41,17)(3,38,43,19)(4,37,44,20)(5,36,45,21)(6,35,46,22)(8,33,48,24)(9,14,
˓→16,11)(10,12,15,13)(25,27,32,30)(26,29,31,28)>>> from sage.all import *>>> C = CubeGroup()>>> C.parse(list(range(Integer(1),Integer(49))))()>>> g = C.parse("L"); g(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)>>> C.parse(str(g)) == g
True>>> facets = C.facets(g); facets[17, 2, 3, 20, 5, 22, 7, 8, 11, 13, 16, 10, 15, 9, 12, 14, 41, 18, 19, 44, 21,
˓→ 46, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 6, 36, 4, 38, 39, 1,␣
˓→40, 42, 43, 37, 45, 35, 47, 48]>>> C.parse(facets)(1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12)>>> C.parse(facets) == g
True>>> faces = C.faces("L"); faces(continues on next page)

578

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page){ back : [[33, 34, 6], [36, 0, 4], [38, 39, 1]],
down : [[40, 42, 43], [37, 0, 45], [35, 47, 48]],
front : [[41, 18, 19], [44, 0, 21], [46, 23, 24]],
left : [[11, 13, 16], [10, 0, 15], [9, 12, 14]],right : [[25, 26, 27], [28, 0, 29], [30, 31, 32]],
up : [[17, 2, 3], [20, 0, 5], [22, 7, 8]]}>>> C.parse(faces) == C.parse("L")
True>>> C.parse("L R2") == C.parse("L^(-1)*R^2")
True>>> C.parse("L R2")
(1,40,41,17)(3,43)(4,37,44,20)(5,45)(6,35,46,22)(8,48)(9,14,16,11)(10,12,15,
˓→13)(19,38)(21,36)(24,33)(25,32)(26,31)(27,30)(28,29)>>> C.parse("L^4")()>>> C.parse("L^(-1)*R")(1,40,41,17)(3,38,43,19)(4,37,44,20)(5,36,45,21)(6,35,46,22)(8,33,48,24)(9,14,
˓→16,11)(10,12,15,13)(25,27,32,30)(26,29,31,28)

plot3d_cube(mv, title=True)
Displays 𝐹, 𝑈, 𝑅 faces of the cube after the given move mv. Mostly included for the purpose of drawing
pictures and checking moves.
INPUT:• mv – A string in the Singmaster notation• title – (Default: True) Display the title information
The first one below is “superflip+4 spot” (in 26q* moves) and the second one is the superflip (in 20f* moves).
Type show(P) to view them.
EXAMPLES:
sage: rubik = CubeGroup()
sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^
˓→3*U*L^3*R*D*R^3*L^3*D^2")# needs sage.plot
sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^
˓→3*F^2*D^3*R^2*U^3*F^2*D^3")# needs sage.plot>>> from sage.all import *>>> rubik = CubeGroup()>>> P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^
˓→3*R*D*R^3*L^3*D^2")# needs sage.plot>>> P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^
˓→3*F^2*D^3*R^2*U^3*F^2*D^3")# needs sage.plot

plot_cube(mv, title=True, colors=[(1, 0.63, 1), (1, 1, 0), (1, 0, 0), (0, 1, 0), (1, 0.6, 0.3), (0, 0, 1)])
Input the move mv, as a string in the Singmaster notation, and output the 2D plot of the cube in that state.
Type P.show() to display any of the plots below.
EXAMPLES:
sage: rubik = CubeGroup()
sage: P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title=False)
˓→needs sage.plot
sage: # (R^2U^2)^3 permutes 2 pairs of edges (uf,ub)(fr,br)#␣(continues on next page)

27.7. Rubik’s cube group functions

579

Groups, Release 10.4

(continued from previous page)

sage: P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^
˓→3*F^2*D^3*R^2*U^3*F^2*D^3")# needs sage.plot
sage: # the superflip (in 20f* moves)
sage: P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^
˓→3*R*D*R^3*L^3*D^2")# needs sage.plot
sage: # "superflip+4 spot" (in 26q* moves)>>> from sage.all import *>>> rubik = CubeGroup()>>> P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title=False)#␣˓→needs sage.plot>>> # (R^2U^2)^3 permutes 2 pairs of edges (uf,ub)(fr,br)>>> P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^
˓→2*D^3*R^2*U^3*F^2*D^3")# needs sage.plot>>> # the superflip (in 20f* moves)>>> P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^
˓→3*R*D*R^3*L^3*D^2")# needs sage.plot>>> # "superflip+4 spot" (in 26q* moves)repr2d(mv)Displays a 2D map of the Rubik’s cube after the move mv has been made. Nothing is returned.
EXAMPLES:
sage: rubik = CubeGroup()
sage: print(rubik.repr2d(""))┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘>>> from sage.all import *>>> rubik = CubeGroup()>>> print(rubik.repr2d(""))┌──────────────┐
│ 1
2
3 │
│ 4
top
5 │
│ 6
7
8 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 1718
19 │ 25
26 27 │ 33 34 35 ││ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 ││ 14 15 16 │ 2223
24 │ 30
31 32 │ 38 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
43 │
│ 44 bottom 45 │
│ 46
47
48 │
└──────────────┘580

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: print(rubik.repr2d("R"))┌──────────────┐
│ 1
2
38 │
│ 4
top 36 ││ 6
733 │┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 17
18
3 │ 2729 32 │ 48 34 35 ││ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
8 │ 2528 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
19 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘>>> from sage.all import *>>> print(rubik.repr2d("R"))┌──────────────┐
│ 1
2
38 │
│ 4
top 36 ││ 6
733 │┌────────────┼──────────────┼─────────────┬────────────┐│ 9 10 11 │ 17
18
3 │ 2729 32 │ 48 34 35 ││ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
8 │ 2528 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
19 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘You can see the right face has been rotated but not the left face.
solve(state, algorithm='default')
Solve the cube in the state, given as a dictionary as in legal. See the solve method of the RubiksCube
class for more details.
This may use GAP’s EpimorphismFromFreeGroup and PreImagesRepresentative as explained below, if ‘gap’ is passed in as the algorithm.
This algorithm
1. constructs the free group on 6 generators then computes a reasonable set of relations which they satisfy
2. computes a homomorphism from the cube group to this free group quotient
3. takes the cube position, regarded as a group element, and maps it over to the free group quotient
4. using those relations and tricks from combinatorial group theory (stabilizer chains), solves the “wordproblem” for that element.
5. uses python string parsing to rewrite that in cube notation.
The Rubik’s cube group has about 4.3 × 1019 elements, so this process is time-consuming. See https://www.gap-system.org/Doc/Examples/rubik.html for an interesting discussion of some GAP code analyzing
the Rubik’s cube.
EXAMPLES:

27.7. Rubik’s cube group functions

581

Groups, Release 10.4

sage: rubik = CubeGroup()
sage: state = rubik.faces("R")
sage: rubik.solve(state)Rsage: state = rubik.faces("R*U")
sage: rubik.solve(state, algorithm= gap )R*U>>> from sage.all import *>>> rubik = CubeGroup()>>> state = rubik.faces("R")>>> rubik.solve(state)R>>> state = rubik.faces("R*U")>>> rubik.solve(state, algorithm= gap )R*U# long time

# long time

You can also check this another (but similar) way using the word_problem method (eg, G = rubik.group();g = G(“(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)”); g.word_problem([b,d,f,l,r,u]),though the output will be less intuitive).
class sage.groups.perm_gps.cubegroup.RubiksCube(state=None, history=[], colors=[(1, 0.63, 1),(1, 1, 0), (1, 0, 0), (0, 1, 0), (1, 0.6, 0.3), (0, 0,
1)])
Bases: SageObject
The Rubik’s cube (in a given state).
EXAMPLES:
sage: C = RubiksCube().move("R U R ")sage: C.show3d()
˓→needs sage.plot#␣>>> from sage.all import *>>> C = RubiksCube().move("R U R ")>>> C.show3d()
˓→needs sage.plot#␣

sage: C = RubiksCube("R*L"); C┌──────────────┐
│ 17
2
38 │
│ 20
top 36 │
│ 22
7
33 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 11 13 16 │ 41
18
3 │ 2729 32 │ 48 34
6 ││ 10 left 15 │ 44 front 5 │ 26 right 31 │ 45 rear 4 ││ 9 12 14 │ 46
23
8 │ 2528 30 │ 43 39
1 │└────────────┼──────────────┼─────────────┴────────────┘
│ 40
42
19 │
│ 37 bottom 21 │
│ 35
47
24 │
└──────────────┘
sage: C.show()˓→needs sage.plot
sage: C.solve(algorithm= gap ) # long time#␣(continues on next page)

582

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

L*R
sage: C == RubiksCube("L*R")
True>>> from sage.all import *>>> C = RubiksCube("R*L"); C┌──────────────┐
│ 17
2
38 │
│ 20
top 36 │
│ 22
7
33 │
┌────────────┼──────────────┼─────────────┬────────────┐│ 11 13 16 │ 41
18
3 │ 2729 32 │ 48 34
6 ││ 10 left 15 │ 44 front 5 │ 26 right 31 │ 45 rear 4 ││ 9 12 14 │ 46
23
8 │ 2528 30 │ 43 39
1 │└────────────┼──────────────┼─────────────┴────────────┘
│ 40
42
19 │
│ 37 bottom 21 │
│ 35
47
24 │
└──────────────┘>>> C.show()˓→needs sage.plot>>> C.solve(algorithm= gap ) # long time
L*R>>> C == RubiksCube("L*R")
True

#␣

cubie(size, gap, x, y, z, colors, stickers=True)
Return the cubie at (𝑥, 𝑦, 𝑧).
INPUT:• size – The size of the cubie• gap – The gap between cubies• x, y, z – The position of the cubie• colors – The list of colors• stickers – (Default True) Boolean to display stickers
EXAMPLES:
sage: C = RubiksCube("R*U")
sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3)
˓→needs sage.plot
Graphics3d Object#␣>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.cubie(RealNumber( 0.15 ), RealNumber( 0.025 ), Integer(0),Integer(0),˓→Integer(0), C.colors*Integer(3))# needs sage.
˓→plotGraphics3d Object

facets()Return the facets of self.
EXAMPLES:
27.7. Rubik’s cube group functions

583

Groups, Release 10.4

sage: C = RubiksCube("R*U")
sage: C.facets()[3, 5, 38, 2, 36, 1, 4, 25, 33, 34, 35, 12, 13, 14, 15, 16, 9, 10,
8, 20, 7, 22, 23, 6, 19, 29, 32, 18, 31, 17, 28, 30, 48, 26, 27,
45, 37, 43, 39, 40, 41, 42, 11, 44, 21, 46, 47, 24]>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.facets()[3, 5, 38, 2, 36, 1, 4, 25, 33, 34, 35, 12, 13, 14, 15, 16, 9, 10,
8, 20, 7, 22, 23, 6, 19, 29, 32, 18, 31, 17, 28, 30, 48, 26, 27,
45, 37, 43, 39, 40, 41, 42, 11, 44, 21, 46, 47, 24]

move(g)Move the Rubik’s cube by g.
EXAMPLES:
sage: RubiksCube().move("R*U") == RubiksCube("R*U")
True>>> from sage.all import *>>> RubiksCube().move("R*U") == RubiksCube("R*U")
Trueplot()
Return a plot of self.
EXAMPLES:
sage: C = RubiksCube("R*U")
sage: C.plot()
˓→needs sage.plot
Graphics object consisting of 55 graphics primitives>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.plot()
˓→needs sage.plot
Graphics object consisting of 55 graphics primitives#␣#␣

plot3d(stickers=True)
Return a 3D plot of self.
EXAMPLES:
sage: C = RubiksCube("R*U")
sage: C.plot3d()
˓→needs sage.plot
Graphics3d Object>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.plot3d()
˓→needs sage.plot
Graphics3d Object

584

#␣

#␣

Chapter 27. Permutation Groups

Groups, Release 10.4

scramble(moves=30)
Scramble the Rubik’s cube.
EXAMPLES:
sage: C = RubiksCube()sage: C.scramble() # random┌──────────────┐
│ 3
5
38 │
│ 2
top 36 ││ 1
425 │┌────────────┼──────────────┼─────────────┬────────────┐│ 33 34 35 │ 9
10
8 │ 1929 32 │ 48 26 27 ││ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
6 │ 1728 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
11 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘>>> from sage.all import *>>> C = RubiksCube()>>> C.scramble() # random┌──────────────┐
│ 3
5
38 │
│ 2
top 36 ││ 1
425 │┌────────────┼──────────────┼─────────────┬────────────┐│ 33 34 35 │ 9
10
8 │ 1929 32 │ 48 26 27 ││ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 ││ 14 15 16 │ 22
23
6 │ 1728 30 │ 43 39 40 │└────────────┼──────────────┼─────────────┴────────────┘
│ 41
42
11 │
│ 44 bottom 21 │
│ 46
47
24 │
└──────────────┘show()Show a plot of self.
EXAMPLES:
sage: C = RubiksCube("R*U")
sage: C.show()˓→needs sage.plot>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.show()˓→needs sage.plot#␣#␣

show3d()Show a 3D plot of self.
EXAMPLES:

27.7. Rubik’s cube group functions

585

Groups, Release 10.4

sage: C = RubiksCube("R*U")
sage: C.show3d()
˓→needs sage.plot#␣>>> from sage.all import *>>> C = RubiksCube("R*U")>>> C.show3d()
˓→needs sage.plot#␣solve(algorithm='hybrid', timeout=15)
Solve the Rubik’s cube.
INPUT:• algorithm – must be one of the following:– hybrid – try kociemba for timeout seconds, then dietz– kociemba – Use Dik T. Winter’s program (reasonable speed, few moves)– dietz – Use Eric Dietz’s cubex program (fast but lots of moves)– optimal – Use Michael Reid’s optimal program (may take a long time)– gap – Use GAP word solution (can be slow)
Any choice other than gap requires the optional package rubiks. Otherwise, the gap algorithm is used.
EXAMPLES:
sage: C = RubiksCube("R U F L B D")
sage: C.solve()# optional - rubiks
R U F L B D>>> from sage.all import *>>> C = RubiksCube("R U F L B D")>>> C.solve()# optional - rubiks
R U F L B D

Dietz’s program is much faster, but may give highly non-optimal solutions:sage: s = C.solve( dietz ); s
# optional - rubiks"U L L U L U L U D L L D L D L D L D L U L D L
˓→L D L D
U L U L B L B L U L U L F L F L F L F
˓→B L BL B L B F L F F B L F B D D L D B B L D
˓→F L D F "sage: C2 = RubiksCube(s) # optional - rubiks
sage: C == C2# optional - rubiks
True>>> from sage.all import *>>> s = C.solve( dietz ); s
# optional - rubiks"U L L U L U L U D L L D L D L D L D L U L D L
˓→L D L D
U L U L B L B L U L U L F L F L F L F
˓→B L BL B L B F L F F B L F B D D L D B B L D
˓→F L D F ">>> C2 = RubiksCube(s) # optional - rubiks>>> C == C2# optional - rubiks
True

586

U L B U L U B␣L D L D D L D ␣
B U U L B D F

U L B U L U B␣L D L D D L D ␣
B U U L B D F

Chapter 27. Permutation Groups

Groups, Release 10.4

undo()
Undo the last move of the Rubik’s cube.
EXAMPLES:
sage: C = RubiksCube()sage: D = C.move("R*U")
sage: D.undo() == C
True>>> from sage.all import *>>> C = RubiksCube()>>> D = C.move("R*U")>>> D.undo() == C
Truesage.groups.perm_gps.cubegroup.color_of_square(facet, colors=['lpurple', 'yellow', 'red', 'green','orange', 'blue'])
Return the color the facet has in the solved state.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import color_of_square
sage: color_of_square(41)blue>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import color_of_square>>> color_of_square(Integer(41))
bluesage.groups.perm_gps.cubegroup.create_poly(face, color)
Create the polygon given by face with color color.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import create_poly, red
sage: create_poly( ur , red)
˓→needs sage.plot
Graphics object consisting of 1 graphics primitive>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import create_poly, red>>> create_poly( ur , red)
˓→needs sage.plot
Graphics object consisting of 1 graphics primitive#␣#␣

sage.groups.perm_gps.cubegroup.cubie_centers(label)
Return the cubie center list element given by label.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import cubie_centers
sage: cubie_centers(3)[0, 2, 2]

27.7. Rubik’s cube group functions

587

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import cubie_centers>>> cubie_centers(Integer(3))[0, 2, 2]

sage.groups.perm_gps.cubegroup.cubie_colors(label, state0)
Return the color of the cubie given by label at state0.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import cubie_colors
sage: G = CubeGroup()
sage: g = G.parse("R*U")
sage: cubie_colors(3, G.facets(g))[(1, 1, 1), (1, 0.63, 1), (1, 0.6, 0.3)]>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import cubie_colors>>> G = CubeGroup()>>> g = G.parse("R*U")>>> cubie_colors(Integer(3), G.facets(g))[(1, 1, 1), (1, 0.63, 1), (1, 0.6, 0.3)]

sage.groups.perm_gps.cubegroup.cubie_faces()
This provides a map from the 6 faces of the 27 cubies to the 48 facets of the larger cube.
-1,-1,-1 is left, top, front
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import cubie_faces
sage: sorted(cubie_faces().items())[((-1, -1, -1), [6, 17, 11, 0, 0, 0]),((-1, -1, 0), [4, 0, 10, 0, 0, 0]),((-1, -1, 1), [1, 0, 9, 0, 35, 0]),((-1, 0, -1), [0, 20, 13, 0, 0, 0]),((-1, 0, 0), [0, 0, -5, 0, 0, 0]),((-1, 0, 1), [0, 0, 12, 0, 37, 0]),((-1, 1, -1), [0, 22, 16, 41, 0, 0]),((-1, 1, 0), [0, 0, 15, 44, 0, 0]),((-1, 1, 1), [0, 0, 14, 46, 40, 0]),((0, -1, -1), [7, 18, 0, 0, 0, 0]),((0, -1, 0), [-6, 0, 0, 0, 0, 0]),((0, -1, 1), [2, 0, 0, 0, 34, 0]),((0, 0, -1), [0, -4, 0, 0, 0, 0]),((0, 0, 0), [0, 0, 0, 0, 0, 0]),((0, 0, 1), [0, 0, 0, 0, -2, 0]),((0, 1, -1), [0, 23, 0, 42, 0, 0]),((0, 1, 0), [0, 0, 0, -1, 0, 0]),((0, 1, 1), [0, 0, 0, 47, 39, 0]),((1, -1, -1), [8, 19, 0, 0, 0, 25]),((1, -1, 0), [5, 0, 0, 0, 0, 26]),((1, -1, 1), [3, 0, 0, 0, 33, 27]),((1, 0, -1), [0, 21, 0, 0, 0, 28]),((1, 0, 0), [0, 0, 0, 0, 0, -3]),((1, 0, 1), [0, 0, 0, 0, 36, 29]),((1, 1, -1), [0, 24, 0, 43, 0, 30]),(continues on next page)

588

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)((1, 1, 0), [0, 0, 0, 45, 0, 31]),((1, 1, 1), [0, 0, 0, 48, 38, 32])]>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import cubie_faces>>> sorted(cubie_faces().items())[((-1, -1, -1), [6, 17, 11, 0, 0, 0]),((-1, -1, 0), [4, 0, 10, 0, 0, 0]),((-1, -1, 1), [1, 0, 9, 0, 35, 0]),((-1, 0, -1), [0, 20, 13, 0, 0, 0]),((-1, 0, 0), [0, 0, -5, 0, 0, 0]),((-1, 0, 1), [0, 0, 12, 0, 37, 0]),((-1, 1, -1), [0, 22, 16, 41, 0, 0]),((-1, 1, 0), [0, 0, 15, 44, 0, 0]),((-1, 1, 1), [0, 0, 14, 46, 40, 0]),((0, -1, -1), [7, 18, 0, 0, 0, 0]),((0, -1, 0), [-6, 0, 0, 0, 0, 0]),((0, -1, 1), [2, 0, 0, 0, 34, 0]),((0, 0, -1), [0, -4, 0, 0, 0, 0]),((0, 0, 0), [0, 0, 0, 0, 0, 0]),((0, 0, 1), [0, 0, 0, 0, -2, 0]),((0, 1, -1), [0, 23, 0, 42, 0, 0]),((0, 1, 0), [0, 0, 0, -1, 0, 0]),((0, 1, 1), [0, 0, 0, 47, 39, 0]),((1, -1, -1), [8, 19, 0, 0, 0, 25]),((1, -1, 0), [5, 0, 0, 0, 0, 26]),((1, -1, 1), [3, 0, 0, 0, 33, 27]),((1, 0, -1), [0, 21, 0, 0, 0, 28]),((1, 0, 0), [0, 0, 0, 0, 0, -3]),((1, 0, 1), [0, 0, 0, 0, 36, 29]),((1, 1, -1), [0, 24, 0, 43, 0, 30]),((1, 1, 0), [0, 0, 0, 45, 0, 31]),((1, 1, 1), [0, 0, 0, 48, 38, 32])]

sage.groups.perm_gps.cubegroup.index2singmaster(facet)
Translate index used (eg, 43) to Singmaster facet notation (eg, fdr).
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import index2singmastersage: index2singmaster(41)dlf>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import index2singmaster>>> index2singmaster(Integer(41))
dlf

sage.groups.perm_gps.cubegroup.inv_list(lst)
Input a list of ints 1, . . . , 𝑚 (in any order), outputs inverse perm.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import inv_list
sage: L = [2,3,1](continues on next page)

27.7. Rubik’s cube group functions

589

Groups, Release 10.4

(continued from previous page)

sage: inv_list(L)[3, 1, 2]>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import inv_list>>> L = [Integer(2),Integer(3),Integer(1)]>>> inv_list(L)[3, 1, 2]

sage.groups.perm_gps.cubegroup.plot3d_cubie(cnt, clrs)
Plot the front, up and right face of a cubie centered at cnt and rgbcolors given by clrs (in the order FUR).
Type P.show() to view.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import plot3d_cubie, blue, red, green
sage: clrF = blue; clrU = red; clrR = green
sage: P = plot3d_cubie([1/2,1/2,1/2],[clrF,clrU,clrR])#␣˓→needs sage.plot>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import plot3d_cubie, blue, red, green>>> clrF = blue; clrU = red; clrR = green>>> P = plot3d_cubie([Integer(1)/Integer(2),Integer(1)/Integer(2),Integer(1)/˓→Integer(2)],[clrF,clrU,clrR])# needs sage.plot

sage.groups.perm_gps.cubegroup.polygon_plot3d(points, tilt=30, turn=30, **kwargs)
Plot a polygon viewed from an angle determined by tilt, turn, and vertices points.
Warning: The ordering of the points is important to get “correct” and if you add several of these plots together,
the one added first is also drawn first (ie, addition of Graphics objects is not commutative).
The following example produced a green-colored square with vertices at the points indicated.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import polygon_plot3d,green
sage: P = polygon_plot3d([[1,3,1],[2,3,1],[2,3,2],[1,3,2],[1,3,1]],
˓→needs sage.plot....:
rgbcolor=green)#␣>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import polygon_plot3d,green>>> P = polygon_plot3d([[Integer(1),Integer(3),Integer(1)],[Integer(2),Integer(3),˓→Integer(1)],[Integer(2),Integer(3),Integer(2)],[Integer(1),Integer(3),˓→Integer(2)],[Integer(1),Integer(3),Integer(1)]],# needs sage.plot...
rgbcolor=green)

sage.groups.perm_gps.cubegroup.rotation_list(tilt, turn)
Return a list [sin(𝜃), sin(𝜑), cos(𝜃), cos(𝜑)] of rotations where 𝜃 is tilt and 𝜑 is turn.
EXAMPLES:

590

Chapter 27. Permutation Groups

Groups, Release 10.4

sage: from sage.groups.perm_gps.cubegroup import rotation_list
sage: rotation_list(30, 45)[0.49999999999999994, 0.7071067811865475, 0.8660254037844387, 0.7071067811865476]>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import rotation_list>>> rotation_list(Integer(30), Integer(45))[0.49999999999999994, 0.7071067811865475, 0.8660254037844387, 0.7071067811865476]

sage.groups.perm_gps.cubegroup.xproj(x, y, z, r)
Return the 𝑥-projection of (𝑥, 𝑦, 𝑧) rotated by 𝑟.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import rotation_list, xproj
sage: rot = rotation_list(30, 45)
sage: xproj(1,2,3,rot)
0.6123724356957945>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import rotation_list, xproj>>> rot = rotation_list(Integer(30), Integer(45))>>> xproj(Integer(1),Integer(2),Integer(3),rot)
0.6123724356957945

sage.groups.perm_gps.cubegroup.yproj(x, y, z, r)
Return the 𝑦-projection of (𝑥, 𝑦, 𝑧) rotated by 𝑟.
EXAMPLES:
sage: from sage.groups.perm_gps.cubegroup import rotation_list, yproj
sage: rot = rotation_list(30, 45)
sage: yproj(1,2,3,rot)
1.378497416975604>>> from sage.all import *>>> from sage.groups.perm_gps.cubegroup import rotation_list, yproj>>> rot = rotation_list(Integer(30), Integer(45))>>> yproj(Integer(1),Integer(2),Integer(3),rot)
1.378497416975604

27.8 Conjugacy Classes Of The Symmetric GroupAUTHORS:• Vincent Delecroix, Travis Scrimshaw (2014-11-23)
class sage.groups.perm_gps.symgp_conjugacy_class.PermutationsConjugacyClass(P,part)
Bases: SymmetricGroupConjugacyClassMixin, ConjugacyClassA conjugacy class of the permutations of 𝑛.
INPUT:• P – the permutations of 𝑛
27.8. Conjugacy Classes Of The Symmetric Group

591

Groups, Release 10.4

• part – a partition or an element of P
set()
The set of all elements in the conjugacy class self.
EXAMPLES:
sage: G = Permutations(3)sage: g = G([2, 1, 3])
sage: C = G.conjugacy_class(g)˓→needs sage.combinat
sage: S = [[1, 3, 2], [2, 1, 3], [3, 2, 1]]
sage: C.set() == Set(G(x) for x in S)
˓→needs sage.combinat
True

#␣

#␣

>>> from sage.all import *>>> G = Permutations(Integer(3))>>> g = G([Integer(2), Integer(1), Integer(3)])>>> C = G.conjugacy_class(g)˓→needs sage.combinat>>> S = [[Integer(1), Integer(3), Integer(2)], [Integer(2), Integer(1),␣
˓→Integer(3)], [Integer(3), Integer(2), Integer(1)]]>>> C.set() == Set(G(x) for x in S)
˓→needs sage.combinat
True

#␣

#␣

class sage.groups.perm_gps.symgp_conjugacy_class.SymmetricGroupConjugacyClass(group,part)
Bases: SymmetricGroupConjugacyClassMixin, ConjugacyClassGAP
A conjugacy class of the symmetric group.
INPUT:• group – the symmetric group• part – a partition or an element of groupset()
The set of all elements in the conjugacy class self.
EXAMPLES:
sage: G = SymmetricGroup(3)sage: g = G((1,2))
sage: C = G.conjugacy_class(g)˓→needs sage.combinat
sage: S = [(2,3), (1,2), (1,3)]
sage: C.set() == Set(G(x) for x in S)
˓→needs sage.combinat
True

#␣

#␣

>>> from sage.all import *>>> G = SymmetricGroup(Integer(3))>>> g = G((Integer(1),Integer(2)))>>> C = G.conjugacy_class(g)˓→needs sage.combinat>>> S = [(Integer(2),Integer(3)), (Integer(1),Integer(2)), (Integer(1),#␣(continues on next page)

592

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)

Integer(3))]>>> C.set() == Set(G(x) for x in S)
˓→needs sage.combinat
True
˓→

#␣

class sage.groups.perm_gps.symgp_conjugacy_class.SymmetricGroupConjugacyClassMixin(domain,part)
Bases: object
Mixin class which contains methods for conjugacy classes of the symmetric group.
partition()
Return the partition of self.
EXAMPLES:
sage: G = SymmetricGroup(5)sage: g = G([(1,2), (3,4,5)])
sage: C = G.conjugacy_class(g)˓→needs sage.combinat#␣>>> from sage.all import *>>> G = SymmetricGroup(Integer(5))>>> g = G([(Integer(1),Integer(2)), (Integer(3),Integer(4),Integer(5))])>>> C = G.conjugacy_class(g)˓→needs sage.combinat#␣sage.groups.perm_gps.symgp_conjugacy_class.conjugacy_class_iterator(part, S=None)
Return an iterator over the conjugacy class associated to the partition part.
The elements are given as a list of tuples, each tuple being a cycle.
INPUT:• part – partition• S – (default: {1, 2, . . . , 𝑛}, where 𝑛 is the size of part) a set
OUTPUT: an iterator over the conjugacy class consisting of all permutations of the set S whose cycle type is part
EXAMPLES:
sage: from sage.groups.perm_gps.symgp_conjugacy_class import conjugacy_class_˓→iterator# needs sage.combinat
sage: for p in conjugacy_class_iterator([2,2]): print(p)˓→needs sage.combinat[(1, 2), (3, 4)][(1, 4), (2, 3)][(1, 3), (2, 4)]>>> from sage.all import *>>> from sage.groups.perm_gps.symgp_conjugacy_class import conjugacy_class_˓→iterator# needs sage.combinat>>> for p in conjugacy_class_iterator([Integer(2),Integer(2)]): print(p)˓→# needs sage.combinat[(1, 2), (3, 4)]#␣␣(continues on next page)

27.8. Conjugacy Classes Of The Symmetric Group

593

Groups, Release 10.4

(continued from previous page)[(1, 4), (2, 3)][(1, 3), (2, 4)]

In order to get permutations, one just has to wrap:
sage: S = SymmetricGroup(5)sage: for p in conjugacy_class_iterator([3,2]): print(S(p))˓→needs sage.combinat(1,3)(2,4,5)(1,3)(2,5,4)(1,2)(3,4,5)(1,2)(3,5,4)...
(1,4)(2,3,5)(1,4)(2,5,3)#␣>>> from sage.all import *>>> S = SymmetricGroup(Integer(5))>>> for p in conjugacy_class_iterator([Integer(3),Integer(2)]): print(S(p))˓→# needs sage.combinat(1,3)(2,4,5)(1,3)(2,5,4)(1,2)(3,4,5)(1,2)(3,5,4)...
(1,4)(2,3,5)(1,4)(2,5,3)

␣Check that the number of elements is the number of elements in the conjugacy class:sage: s = lambda p: sum(1 for _ in conjugacy_class_iterator(p))
sage: all(s(p) == p.conjugacy_class_size() for p in Partitions(5))˓→needs sage.combinat
True

#␣

>>> from sage.all import *>>> s = lambda p: sum(Integer(1) for _ in conjugacy_class_iterator(p))>>> all(s(p) == p.conjugacy_class_size() for p in Partitions(Integer(5)))˓→# needs sage.combinat
True␣

It is also possible to specify any underlying set:sage: it = conjugacy_class_iterator([2,2,2],
˓→needs sage.combinat
sage: sorted(flatten(next(it)))˓→needs sage.combinat[ a , b , c , d , e , f ]sage: all(len(x) == 2 for x in next(it))˓→needs sage.combinat
Trueabcdef )

#␣
#␣

#␣

>>> from sage.all import *>>> it = conjugacy_class_iterator([Integer(2),Integer(2),Integer(2)],˓→# needs sage.combinat

abcdef )␣(continues on next page)

594

Chapter 27. Permutation Groups

Groups, Release 10.4

(continued from previous page)>>> sorted(flatten(next(it)))˓→needs sage.combinat[ a , b , c , d , e , f ]>>> all(len(x) == Integer(2) for x in next(it))˓→# needs sage.combinat
True

#␣

␣

sage.groups.perm_gps.symgp_conjugacy_class.default_representative(part, G)
Construct the default representative for the conjugacy class of cycle type part of a symmetric group G.
Let 𝜆 be a partition of 𝑛. We pick a representative by(1, 2, . . . , 𝜆1 )(𝜆1 + 1, . . . , 𝜆1 + 𝜆2 )(𝜆1 + 𝜆2 + · · · + 𝜆ℓ−1 , . . . , 𝑛),where ℓ is the length (or number of parts) of 𝜆.
INPUT:• part – partition• G – a symmetric group
EXAMPLES:
sage: from sage.groups.perm_gps.symgp_conjugacy_class import default_
˓→representative# needs sage.combinat
sage: S = SymmetricGroup(4)sage: for p in Partitions(4):˓→needs sage.combinat....:
print(default_representative(p, S))(1,2,3,4)(1,2,3)(1,2)(3,4)
(1,2)
()

#␣

>>> from sage.all import *>>> from sage.groups.perm_gps.symgp_conjugacy_class import default_representative␣˓→# needs sage.combinat>>> S = SymmetricGroup(Integer(4))>>> for p in Partitions(Integer(4)):␣˓→# needs sage.combinat...
print(default_representative(p, S))(1,2,3,4)(1,2,3)(1,2)(3,4)
(1,2)
()

27.8. Conjugacy Classes Of The Symmetric Group

595

Groups, Release 10.4

596

Chapter 27. Permutation Groups

CHAPTERTWENTYEIGHTMATRIX AND AFFINE GROUPS

28.1 Library of Interesting Groups
Type groups.matrix.<tab> to access examples of groups implemented as permutation groups.

28.2 Base classes for Matrix Groups
AUTHORS:• William Stein: initial version• David Joyner (2006-03-15): degree, base_ring, _contains_, list, random, order methods; examples• William Stein (2006-12): rewrite• David Joyner (2007-12): Added invariant_generators (with Martin Albrecht and Simon King)• David Joyner (2008-08): Added module_composition_factors (interface to GAP’s MeatAxe implementation) and
as_permutation_group (returns isomorphic PermutationGroup).
• Simon King (2010-05): Improve invariant_generators by using GAP for the construction of the Reynolds operator
in Singular.
• Sebastian Oehms (2018-07): Add subgroup() and ambient() see Issue #25894
class sage.groups.matrix_gps.matrix_group.MatrixGroup_base
Bases: Group
Base class for all matrix groups.
This base class just holds the base ring, but not the degree. So it can be a base for affine groups where the natural
matrix is larger than the degree of the affine group. Makes no assumption about the group except that its elements
have a matrix() method.
ambient()
Return the ambient group of a subgroup.
OUTPUT:
A group containing self. If self has not been defined as a subgroup, we just return self.
EXAMPLES:

597

Groups, Release 10.4

sage: G = GL(2, QQ)
sage: m = matrix(QQ, 2, 2, [[3, 0], [~5,1]])
sage: S = G.subgroup([m])
sage: S.ambient() is G
True>>> from sage.all import *>>> G = GL(Integer(2), QQ)>>> m = matrix(QQ, Integer(2), Integer(2), [[Integer(3), Integer(0)], [~˓→Integer(5),Integer(1)]])>>> S = G.subgroup([m])>>> S.ambient() is G
True

as_matrix_group()
Return a new matrix group from the generators.
This will throw away any extra structure (encoded in a derived class) that a group of special matrices has.
EXAMPLES:
sage: G = SU(4, GF(5))˓→needs sage.rings.finite_rings
sage: G.as_matrix_group()
˓→needs sage.libs.gap sage.rings.finite_rings
Matrix group over Finite Field in a of size 5^2 with 2 generators (
[
a
0
0
0] [
1
0 4*a + 30][0 2*a + 3
0
0] [
1
0
0
0]
[
0
0 4*a + 10] [0 2*a + 4
0
1]
[
0
0
0
3*a], [
0 3*a + 1
0
0]
)

#␣
#␣

sage: # needs sage.libs.gap
sage: G = GO(3, GF(5))
sage: G.as_matrix_group()
Matrix group over Finite Field of size 5 with 2 generators ([2 0 0] [0 1 0]
[0 3 0] [1 4 4]
[0 0 1], [0 2 1])>>> from sage.all import *>>> G = SU(Integer(4), GF(Integer(5)))˓→# needs sage.rings.finite_rings>>> G.as_matrix_group()
˓→needs sage.libs.gap sage.rings.finite_rings
Matrix group over Finite Field in a of size 5^2 with 2 generators (
[
a
0
0
0] [
1
0 4*a + 30][0 2*a + 3
0
0] [
1
0
0
0]
[
0
0 4*a + 10] [0 2*a + 4
0
1]
[
0
0
0
3*a], [
0 3*a + 1
0
0]
)

␣
#␣

>>> # needs sage.libs.gap>>> G = GO(Integer(3), GF(Integer(5)))>>> G.as_matrix_group()
Matrix group over Finite Field of size 5 with 2 generators ((continues on next page)

598

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[2 0 0] [0 1 0]
[0 3 0] [1 4 4]
[0 0 1], [0 2 1])

natural_representation(base_ring=None)
Return the natural representation of self over base_ring.
INPUT:• base_ring – (optional) the base ring; the default is the base ring of self
EXAMPLES:
sage: G = groups.matrix.SL(6, 3)
sage: V = G.natural_representation()sage: V
Natural representation of Special Linear Group of degree 6
over Finite Field of size 3
sage: e = prod(G.gens())
sage: e[2 0 0 0 0 1]
[2 0 0 0 0 0]
[0 2 0 0 0 0]
[0 0 2 0 0 0]
[0 0 0 2 0 0]
[0 0 0 0 2 0]
sage: v = V.an_element()
sage: v
2*e[0] + 2*e[1]sage: e * v
e[0] + e[1] + e[2]>>> from sage.all import *>>> G = groups.matrix.SL(Integer(6), Integer(3))>>> V = G.natural_representation()>>> V
Natural representation of Special Linear Group of degree 6
over Finite Field of size 3>>> e = prod(G.gens())>>> e[2 0 0 0 0 1]
[2 0 0 0 0 0]
[0 2 0 0 0 0]
[0 0 2 0 0 0]
[0 0 0 2 0 0]
[0 0 0 0 2 0]>>> v = V.an_element()>>> v
2*e[0] + 2*e[1]>>> e * v
e[0] + e[1] + e[2]sign_representation(base_ring=None)
Return the sign representation of self over base_ring.
INPUT:

28.2. Base classes for Matrix Groups599

Groups, Release 10.4

• base_ring – (optional) the base ring; the default is the base ring of self
EXAMPLES:
sage: G = GL(2, QQ)
sage: V = G.sign_representation()sage: e = G.an_element()
sage: e[1 0]
[0 1]
sage: m2 = V.an_element()
sage: m2
2*B[ v ]sage: m2*e
2*B[ v ]sage: m2*e*e
2*B[ v ]sage: W = WeylGroup(["A", 1, 1])
sage: W.sign_representation()
Sign representation of
Weyl Group of type [ A , 1, 1] (as a matrix group acting on the root space)over Rational Field
sage: G = GL(4, 2)
sage: G.sign_representation() == G.trivial_representation()
True>>> from sage.all import *>>> G = GL(Integer(2), QQ)>>> V = G.sign_representation()>>> e = G.an_element()
>>> e
[1 0]
[0 1]
>>> m2 = V.an_element()>>> m2
2*B[ v ]>>> m2*e
2*B[ v ]>>> m2*e*e
2*B[ v ]>>> W = WeylGroup(["A", Integer(1), Integer(1)])>>> W.sign_representation()
Sign representation of
Weyl Group of type [ A , 1, 1] (as a matrix group acting on the root space)over Rational Field>>> G = GL(Integer(4), Integer(2))>>> G.sign_representation() == G.trivial_representation()
Truesubgroup(generators, check=True)
Return the subgroup generated by the given generators.
INPUT:• generators – a list/tuple/iterable of group elements of self
600

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• check – boolean (default: True); whether to check that each matrix is invertible
OUTPUT: the subgroup generated by generators as an instance of FinitelyGeneratedMatrixGroup_gap
EXAMPLES:
sage: # needs sage.libs.gap sage.rings.number_fieldsage: UCF = UniversalCyclotomicField()sage: G = GL(3, UCF)
sage: e3 = UCF.gen(3); e5 = UCF.gen(5)sage: m = matrix(UCF, 3,3, [[e3, 1, 0], [0, e5, 7],[4, 3, 2]])sage: S = G.subgroup([m]); S
Subgroup with 1 generators (
[E(3)
1
0]
[
0 E(5)
7][4
3
2]) of General Linear Group of degree 3 over Universal Cyclotomic Field
sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3)sage: G = GL(3, CF3)
sage: e3 = CF3.gen()sage: m = matrix(CF3, 3,3, [[e3, 1, 0], [0, ~e3, 7],[4, 3, 2]])sage: S = G.subgroup([m]); S
Subgroup with 1 generators (
[
zeta3
1
0]
[
0 -zeta3 - 1
7]
[
4
3
2]
) of General Linear Group of degree 3 over Cyclotomic Field of order 3 and␣
˓→degree 2>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> UCF = UniversalCyclotomicField()>>> G = GL(Integer(3), UCF)>>> e3 = UCF.gen(Integer(3)); e5 = UCF.gen(Integer(5))>>> m = matrix(UCF, Integer(3),Integer(3), [[e3, Integer(1), Integer(0)],␣
˓→[Integer(0), e5, Integer(7)],[Integer(4), Integer(3), Integer(2)]])>>> S = G.subgroup([m]); S
Subgroup with 1 generators (
[E(3)
1
0]
[
0 E(5)
7][4
3
2]) of General Linear Group of degree 3 over Universal Cyclotomic Field>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3))>>> G = GL(Integer(3), CF3)>>> e3 = CF3.gen()>>> m = matrix(CF3, Integer(3),Integer(3), [[e3, Integer(1), Integer(0)],␣
˓→[Integer(0), ~e3, Integer(7)],[Integer(4), Integer(3), Integer(2)]])>>> S = G.subgroup([m]); S
Subgroup with 1 generators (
[
zeta3
1
0]
[
0 -zeta3 - 1
7]
[
4
3
2]
) of General Linear Group of degree 3 over Cyclotomic Field of order 3 and␣
˓→degree 2

28.2. Base classes for Matrix Groups

601

Groups, Release 10.4class sage.groups.matrix_gps.matrix_group.MatrixGroup_generic(degree, base_ring,
category=None)
Bases: MatrixGroup_base
Base class for matrix groups over generic base rings.
You should not use this class directly. Instead, use one of the more specialized derived classes.
INPUT:• degree – integer; the degree (matrix size) of the matrix group• base_ring – ring; the base ring of the matrices
Element
alias of MatrixGroupElement_generic
degree()Return the degree of this matrix group.
OUTPUT: integer; the size (number of rows equals number of columns) of the matrices
EXAMPLES:
sage: SU(5,5).degree()
˓→needs sage.rings.finite_rings
5#␣>>> from sage.all import *>>> SU(Integer(5),Integer(5)).degree()˓→# needs sage.rings.finite_rings5␣

is_trivial()
Return True if this group is the trivial group.
A group is trivial, if it consists only of the identity element, that is, if all its generators are the identity.
EXAMPLES:
sage: MatrixGroup([identity_matrix(3)]).is_trivial()
True
sage: SL(2, ZZ).is_trivial()
False
sage: CoxeterGroup([ B ,3], implementation="matrix").is_trivial()
False>>> from sage.all import *>>> MatrixGroup([identity_matrix(Integer(3))]).is_trivial()
True>>> SL(Integer(2), ZZ).is_trivial()
False>>> CoxeterGroup([ B ,Integer(3)], implementation="matrix").is_trivial()
False

matrix_space()
Return the matrix space corresponding to this matrix group.
This is a matrix space over the field of definition of this matrix group.
EXAMPLES:
602

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

sage: F = GF(5); MS = MatrixSpace(F, 2, 2)
sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])sage: G.matrix_space()
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5
sage: G.matrix_space() is MS
True>>> from sage.all import *>>> F = GF(Integer(5)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> G = MatrixGroup([MS(Integer(1)), MS([Integer(1),Integer(2),Integer(3),˓→Integer(4)])])>>> G.matrix_space()
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5>>> G.matrix_space() is MS
Truesage.groups.matrix_gps.matrix_group.is_MatrixGroup(x)Test whether x is a matrix group.
EXAMPLES:
sage: from sage.groups.matrix_gps.matrix_group import is_MatrixGroupsage: is_MatrixGroup(MatrixSpace(QQ, 3))doctest:warning...
DeprecationWarning: the function is_MatrixGroup is deprecated;
use isinstance(..., MatrixGroup_base) instead
See https://github.com/sagemath/sage/issues/37898 for details.
False
sage: is_MatrixGroup(Mat(QQ, 3))
False
sage: is_MatrixGroup(GL(2, ZZ))
True
sage: is_MatrixGroup(MatrixGroup([matrix(2, [1,1,0,1])]))
True>>> from sage.all import *>>> from sage.groups.matrix_gps.matrix_group import is_MatrixGroup>>> is_MatrixGroup(MatrixSpace(QQ, Integer(3)))
doctest:warning...
DeprecationWarning: the function is_MatrixGroup is deprecated;
use isinstance(..., MatrixGroup_base) instead
See https://github.com/sagemath/sage/issues/37898 for details.
False>>> is_MatrixGroup(Mat(QQ, Integer(3)))
False>>> is_MatrixGroup(GL(Integer(2), ZZ))
True>>> is_MatrixGroup(MatrixGroup([matrix(Integer(2), [Integer(1),Integer(1),˓→Integer(0),Integer(1)])]))
True

28.2. Base classes for Matrix Groups603

Groups, Release 10.4

28.3 Matrix group over a ring that GAP understands
class sage.groups.matrix_gps.matrix_group_gap.MatrixGroup_gap(degree, base_ring,libgap_group,
ambient=None,
category=None)
Bases: GroupMixinLibGAP, MatrixGroup_generic, ParentLibGAP
Base class for matrix groups that implements GAP interface.
INPUT:• degree – integer; the degree (matrix size) of the matrix group• base_ring – ring; the base ring of the matrices• libgap_group – the defining libgap group• ambient – a derived class of ParentLibGAP or None (default); the ambient class if libgap_grouphas been defined as a subgroup
Element
alias of MatrixGroupElement_gap
structure_description(G, latex=False)
Return a string that tries to describe the structure of G.
This methods wraps GAP’s StructureDescription method.
For full details, including the form of the returned string and the algorithm to build it, see GAP’s documentation.
INPUT:• latex – a boolean (default: False); if True, return a LaTeX formatted string
OUTPUT: string
Warning: From GAP’s documentation: The string returned by StructureDescription is not
an isomorphism invariant: non-isomorphic groups can have the same string value, and two isomorphic
groups in different representations can produce different strings.
EXAMPLES:
sage: # needs sage.groups
sage: G = CyclicPermutationGroup(6)sage: G.structure_description()C6
sage: G.structure_description(latex=True)
C_{6}sage: G2 = G.direct_product(G, maps=False)
sage: LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}>>> from sage.all import *>>> # needs sage.groups>>> G = CyclicPermutationGroup(Integer(6))>>> G.structure_description()(continues on next page)

604

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)C6>>> G.structure_description(latex=True)
C_{6}>>> G2 = G.direct_product(G, maps=False)>>> LatexExpr(G2.structure_description(latex=True))
C_{6} \times C_{6}This method is mainly intended for small groups or groups with few normal subgroups. Even then there aresome surprises:
sage: D3 = DihedralGroup(3)˓→# needs sage.groups
sage: D3.structure_description()˓→# needs sage.groups
S3>>> from sage.all import *>>> D3 = DihedralGroup(Integer(3))˓→# needs sage.groups>>> D3.structure_description()
˓→# needs sage.groups
S3

␣
␣

␣

We use the Sage notation for the degree of dihedral groups:
sage: D4 = DihedralGroup(4)˓→# needs sage.groups
sage: D4.structure_description()˓→# needs sage.groups
D4>>> from sage.all import *>>> D4 = DihedralGroup(Integer(4))˓→# needs sage.groups>>> D4.structure_description()
˓→# needs sage.groups
D4

␣
␣

␣

Works for finitely presented groups (Issue #17573):
sage: F.<x, y> = FreeGroup()˓→# needs sage.groups
sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]˓→# needs sage.groups
sage: G.structure_description()˓→# needs sage.groups
C7

␣
␣
␣

>>> from sage.all import *>>> F = FreeGroup(names=( x , y ,)); (x, y,) = F._first_ngens(2)# needs sage.
˓→groups>>> G = F / [x**Integer(2)*y**-Integer(1), x**Integer(3)*y**Integer(2),␣
˓→x*y*x**-Integer(1)*y**-Integer(1)]# needs␣
˓→sage.groups>>> G.structure_description()(continues on next page)

28.3. Matrix group over a ring that GAP understands

605

Groups, Release 10.4

(continued from previous page)# needs sage.groups
C7˓→

And matrix groups (Issue #17573):
sage: groups.matrix.GL(4,2).structure_description()˓→# needs sage.libs.gap sage.modules
A8␣>>> from sage.all import *>>> groups.matrix.GL(Integer(4),Integer(2)).structure_description()˓→# needs sage.libs.gap sage.modules
A8␣

subgroup(generators, check=True)
Return the subgroup generated by the given generators.
INPUT:• generators – a list/tuple/iterable of group elements of self
• check – boolean (default: True). Whether to check that each matrix is invertible
OUTPUT: The subgroup generated by generators as an instance of FinitelyGeneratedMatrixGroup_gap
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: UCF = UniversalCyclotomicField()sage: G = GL(3, UCF)
sage: e3 = UCF.gen(3); e5 = UCF.gen(5)sage: m = matrix(UCF, 3,3, [[e3, 1, 0], [0, e5, 7],[4, 3, 2]])sage: S = G.subgroup([m]); S
Subgroup with 1 generators (
[E(3)
1
0]
[
0 E(5)
7][4
3
2]) of General Linear Group of degree 3 over Universal Cyclotomic Field
sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3)sage: G = GL(3, CF3)
sage: e3 = CF3.gen()sage: m = matrix(CF3, 3,3, [[e3, 1, 0], [0, ~e3, 7],[4, 3, 2]])sage: S = G.subgroup([m]); S
Subgroup with 1 generators (
[
zeta3
1
0]
[
0 -zeta3 - 1
7]
[
4
3
2]
) of General Linear Group of degree 3 over Cyclotomic Field of order 3 and␣
˓→degree 2>>> from sage.all import *>>> # needs sage.rings.number_field>>> UCF = UniversalCyclotomicField()>>> G = GL(Integer(3), UCF)
(continues on next page)

606

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> e3 = UCF.gen(Integer(3)); e5 = UCF.gen(Integer(5))>>> m = matrix(UCF, Integer(3),Integer(3), [[e3, Integer(1), Integer(0)],␣
˓→[Integer(0), e5, Integer(7)],[Integer(4), Integer(3), Integer(2)]])>>> S = G.subgroup([m]); S
Subgroup with 1 generators (
[E(3)
1
0]
[
0 E(5)
7][4
3
2]) of General Linear Group of degree 3 over Universal Cyclotomic Field>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3))>>> G = GL(Integer(3), CF3)>>> e3 = CF3.gen()>>> m = matrix(CF3, Integer(3),Integer(3), [[e3, Integer(1), Integer(0)],␣
˓→[Integer(0), ~e3, Integer(7)],[Integer(4), Integer(3), Integer(2)]])>>> S = G.subgroup([m]); S
Subgroup with 1 generators (
[
zeta3
1
0]
[
0 -zeta3 - 1
7]
[
4
3
2]
) of General Linear Group of degree 3 over Cyclotomic Field of order 3 and␣
˓→degree 2

28.4 Matrix Group Elements
EXAMPLES:
sage: F = GF(3); MS = MatrixSpace(F, 2, 2)
sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])]
sage: G = MatrixGroup(gens); G
Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1] )sage: g = G([[1,1], [0,1]])
sage: h = G([[1,2], [0,1]])
sage: g*h
[1 0]
[0 1]
>>> from sage.all import *>>> F = GF(Integer(3)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> gens = [MS([[Integer(1),Integer(0)], [Integer(0),Integer(1)]]), MS([[Integer(1),˓→Integer(1)], [Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens); G
Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1] )>>> g = G([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])>>> h = G([[Integer(1),Integer(2)], [Integer(0),Integer(1)]])>>> g*h
[1 0]
[0 1]

28.4. Matrix Group Elements

607

Groups, Release 10.4

You cannot add two matrices, since this is not a group operation. You can coerce matrices back to the matrix space andadd them there:
sage: g + h
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for +:Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1]) andMatrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1])sage: g.matrix() + h.matrix()
[2 0]
[0 2]
>>> from sage.all import *>>> g + h
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for +:Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1]) andMatrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1])>>> g.matrix() + h.matrix()
[2 0]
[0 2]

Similarly, you cannot multiply group elements by scalars but you can do it with the underlying matrices:sage: 2*g
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Integer Ring
and Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1] )>>> from sage.all import *>>> Integer(2)*gTraceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Integer Ring
and Matrix group over Finite Field of size 3 with 2 generators ([1 0] [1 1][0 1], [0 1] )AUTHORS:
608

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• David Joyner (2006-05): initial version David Joyner• David Joyner (2006-05): various modifications to address William Stein’s TODO’s.
• William Stein (2006-12-09): many revisions.
• Volker Braun (2013-1) port to new Parent, libGAP.
• Travis Scrimshaw (2016-01): reworks class hierarchy in order to cythonize
class sage.groups.matrix_gps.group_element.MatrixGroupElement_generic
Bases: MultiplicativeGroupElement
Element of a matrix group over a generic ring.
The group elements are implemented as Sage matrices.
INPUT:• M – a matrix• parent – the parent• check – bool (default: True); if True, then do some type checking• convert – bool (default: True); if True, then convert M to the right matrix space
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], base_ring=ZZ)
˓→needs sage.graphs
sage: g = W.an_element(); g˓→needs sage.graphs[ 0 0 -1]
[ 1 0 -1]
[ 0 1 -1]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], base_ring=ZZ)
˓→# needs sage.graphs>>> g = W.an_element(); g˓→needs sage.graphs[ 0 0 -1]
[ 1 0 -1]
[ 0 1 -1]

#␣
#␣

␣
#␣

inverse()Return the inverse group element.
OUTPUT: a matrix group element
EXAMPLES:
sage: # needs sage.combinat sage.libs.gap
sage: W = CoxeterGroup([ A ,3], base_ring=ZZ)
sage: g = W.an_element()
sage: ~g[-1 1 0][-1 0 1][-1 0 0]sage: g * ~g == W.one()
True(continues on next page)

28.4. Matrix Group Elements609

Groups, Release 10.4

(continued from previous page)

sage: ~g * g == W.one()True
sage: # needs sage.combinat sage.libs.gap sage.rings.number_fieldsage: W = CoxeterGroup([ B ,3])
sage: W.base_ring()
Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?
sage: g = W.an_element()
sage: ~g[-1 1 0][-1 0 a][-a 0 1]>>> from sage.all import *>>> # needs sage.combinat sage.libs.gap>>> W = CoxeterGroup([ A ,Integer(3)], base_ring=ZZ)>>> g = W.an_element()>>> ~g[-1 1 0][-1 0 1][-1 0 0]>>> g * ~g == W.one()True>>> ~g * g == W.one()True>>> # needs sage.combinat sage.libs.gap sage.rings.number_field>>> W = CoxeterGroup([ B ,Integer(3)])>>> W.base_ring()
Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?
>>> g = W.an_element()>>> ~g[-1 1 0][-1 0 a][-a 0 1]

is_one()Return whether self is the identity of the group.
EXAMPLES:
sage: # needs sage.graphs
sage: W = CoxeterGroup([ A ,3])
sage: g = W.gen(0)sage: g.is_one()False
sage: W.an_element().is_one()False
sage: W.one().is_one()True>>> from sage.all import *>>> # needs sage.graphs>>> W = CoxeterGroup([ A ,Integer(3)])>>> g = W.gen(Integer(0))>>> g.is_one()(continues on next page)

610

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

False>>> W.an_element().is_one()
False>>> W.one().is_one()Truelist()
Return list representation of this matrix.
EXAMPLES:
sage: # needs sage.combinat sage.libs.gap
sage: W = CoxeterGroup([ A ,3], base_ring=ZZ)
sage: g = W.gen(0)sage: g[-1 1 0][ 0 1 0][ 0 0 1]
sage: g.list()[[-1, 1, 0], [0, 1, 0], [0, 0, 1]]>>> from sage.all import *>>> # needs sage.combinat sage.libs.gap>>> W = CoxeterGroup([ A ,Integer(3)], base_ring=ZZ)>>> g = W.gen(Integer(0))>>> g[-1 1 0][ 0 1 0][ 0 0 1]>>> g.list()[[-1, 1, 0], [0, 1, 0], [0, 0, 1]]

matrix()
Obtain the usual matrix (as an element of a matrix space) associated to this matrix group element.
One reason to compute the associated matrix is that matrices support a huge range of functionality.
EXAMPLES:
sage: # needs sage.combinat sage.libs.gap
sage: W = CoxeterGroup([ A ,3], base_ring=ZZ)
sage: g = W.gen(0)sage: g.matrix()[-1 1 0][ 0 1 0][ 0 0 1]
sage: parent(g.matrix())
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> # needs sage.combinat sage.libs.gap>>> W = CoxeterGroup([ A ,Integer(3)], base_ring=ZZ)>>> g = W.gen(Integer(0))>>> g.matrix()[-1 1 0][ 0 1 0](continues on next page)

28.4. Matrix Group Elements

611

Groups, Release 10.4

(continued from previous page)[ 0 0 1]>>> parent(g.matrix())
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring

Matrices have extra functionality that matrix group elements do not have:sage: g.matrix().charpoly( t )˓→needs sage.combinat sage.libs.gap
t^3 - t^2 - t + 1#␣>>> from sage.all import *>>> g.matrix().charpoly( t )˓→needs sage.combinat sage.libs.gap
t^3 - t^2 - t + 1#␣sage.groups.matrix_gps.group_element.is_MatrixGroupElement(x)Test whether x is a matrix group element.
INPUT:• x – anything
OUTPUT: boolean
EXAMPLES:
sage: from sage.groups.matrix_gps.group_element import is_MatrixGroupElement
sage: is_MatrixGroupElement( helloooo )Falsesage: G = GL(2,3)
sage: is_MatrixGroupElement(G.an_element())
True>>> from sage.all import *>>> from sage.groups.matrix_gps.group_element import is_MatrixGroupElement>>> is_MatrixGroupElement( helloooo )False>>> G = GL(Integer(2),Integer(3))>>> is_MatrixGroupElement(G.an_element())
True

28.5 Matrix group elements implemented in GAPclass sage.groups.matrix_gps.group_element_gap.MatrixGroupElement_gap
Bases: ElementLibGAP
Element of a matrix group over a generic ring.
The group elements are implemented as wrappers around libGAP matrices.
INPUT:• M – a matrix

612

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• parent – the parent• check – bool (default: True); if True, do some type checking• convert – bool (default: True); if True, convert M to the right matrix spacelist()
Return list representation of this matrix.
EXAMPLES:
sage: F = GF(3); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: g = G.0
sage: g[1 0]
[0 1]
sage: g.list()[[1, 0], [0, 1]]>>> from sage.all import *>>> F = GF(Integer(3)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(1),Integer(0)],[Integer(0),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> g = G.gen(0)
>>> g
[1 0]
[0 1]
>>> g.list()[[1, 0], [0, 1]]

matrix()
Obtain the usual matrix (as an element of a matrix space) associated to this matrix group element.
EXAMPLES:
sage: F = GF(3); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)sage: m = G.gen(0).matrix(); m
[1 0]
[0 1]
sage: m.parent()
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3
sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,
˓→2])])
sage: g = G.0
sage: g.matrix()
[1 1]
[0 1]
sage: parent(g.matrix())
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7>>> from sage.all import *>>> F = GF(Integer(3)); MS = MatrixSpace(F,Integer(2),Integer(2))(continues on next page)

28.5. Matrix group elements implemented in GAP

613

Groups, Release 10.4

(continued from previous page)>>> gens = [MS([[Integer(1),Integer(0)],[Integer(0),Integer(1)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> m = G.gen(Integer(0)).matrix(); m
[1 0]
[0 1]
>>> m.parent()
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3>>> k = GF(Integer(7)); G = MatrixGroup([matrix(k,Integer(2),[Integer(1),˓→Integer(1),Integer(0),Integer(1)]), matrix(k,Integer(2),[Integer(1),˓→Integer(0),Integer(0),Integer(2)])])>>> g = G.gen(0)>>> g.matrix()
[1 1]
[0 1]
>>> parent(g.matrix())
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7

Matrices have extra functionality that matrix group elements do not have:sage: g.matrix().charpoly( t )t^2 + 5*t + 1>>> from sage.all import *>>> g.matrix().charpoly( t )t^2 + 5*t + 1

multiplicative_order()Return the order of this group element, which is the smallest positive integer 𝑛 such that 𝑔 𝑛 = 1, or +Infinity
if no such integer exists.
EXAMPLES:
sage: k = GF(7)sage: G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]); G
Matrix group over Finite Field of size 7 with 2 generators ([1 1] [1 0][0 1], [0 2])sage: G.order()21
sage: G.gen(0).multiplicative_order(), G.gen(1).multiplicative_order()(7, 3)>>> from sage.all import *>>> k = GF(Integer(7))>>> G = MatrixGroup([matrix(k,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)]), matrix(k,Integer(2),[Integer(1),Integer(0),Integer(0),˓→Integer(2)])]); G
Matrix group over Finite Field of size 7 with 2 generators ([1 1] [1 0][0 1], [0 2])>>> G.order()21(continues on next page)

614

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> G.gen(Integer(0)).multiplicative_order(), G.gen(Integer(1)).
˓→multiplicative_order()(7, 3)

order is just an alias for multiplicative_order:
sage: G.gen(0).order(), G.gen(1).order()(7, 3)
sage: k = QQ
sage: G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]); G
Matrix group over Rational Field with 2 generators ([1 1] [1 0][0 1], [0 2])sage: G.order()+Infinity
sage: G.gen(0).order(), G.gen(1).order()(+Infinity, +Infinity)
sage: gl = GL(2, ZZ); gl
General Linear Group of degree 2 over Integer Ringsage: g = gl.gen(2); g
[1 1]
[0 1]
sage: g.order()+Infinity>>> from sage.all import *>>> G.gen(Integer(0)).order(), G.gen(Integer(1)).order()(7, 3)>>> k = QQ>>> G = MatrixGroup([matrix(k,Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)]), matrix(k,Integer(2),[Integer(1),Integer(0),Integer(0),˓→Integer(2)])]); G
Matrix group over Rational Field with 2 generators ([1 1] [1 0][0 1], [0 2])>>> G.order()+Infinity>>> G.gen(Integer(0)).order(), G.gen(Integer(1)).order()(+Infinity, +Infinity)>>> gl = GL(Integer(2), ZZ); gl
General Linear Group of degree 2 over Integer Ring>>> g = gl.gen(Integer(2)); g
[1 1]
[0 1]
>>> g.order()+Infinity

word_problem(gens=None)
Solve the word problem.
This method writes the group element as a product of the elements of the list gens, or the standard generators
28.5. Matrix group elements implemented in GAP

615

Groups, Release 10.4of the parent of self if gens is None.
INPUT:• gens – a list/tuple/iterable of elements (or objects that can be converted to group elements), or None(default); by default, the generators of the parent group are used
OUTPUT:
A factorization object that contains information about the order of factors and the exponents. A ValueError is raised if the group element cannot be written as a word in gens.
ALGORITHM:
Use GAP, which has optimized algorithms for solving the word problem (the GAP functions EpimorphismFromFreeGroup and PreImagesRepresentative).
EXAMPLES:
sage: G = GL(2,5); G
General Linear Group of degree 2 over Finite Field of size 5
sage: G.gens()([2 0] [4 1][0 1], [4 0])sage: G(1).word_problem([G.gen(0)])
1sage: type(_)<class sage.structure.factorization.Factorization >sage: g = G([0,4,1,4])
sage: g.word_problem()([4 1][4 0])^-1>>> from sage.all import *>>> G = GL(Integer(2),Integer(5)); G
General Linear Group of degree 2 over Finite Field of size 5>>> G.gens()([2 0] [4 1][0 1], [4 0])>>> G(Integer(1)).word_problem([G.gen(Integer(0))])1>>> type(_)<class sage.structure.factorization.Factorization >>>> g = G([Integer(0),Integer(4),Integer(1),Integer(4)])>>> g.word_problem()([4 1][4 0])^-1

Next we construct a more complicated element of the group from the generators:
sage: s,t = G.0, G.1
sage: a = (s * t * s); b = a.word_problem(); b([2 0][0 1]) *(continues on next page)

616

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)([4 1][4 0]) *([2 0][0 1])
sage: flatten(b)
[
[2 0]
[4 1]
[2 0]
[0 1], 1, [4 0], 1, [0 1], 1]
sage: b.prod() == a
True>>> from sage.all import *>>> s,t = G.gen(0), G.gen(1)>>> a = (s * t * s); b = a.word_problem(); b([2 0][0 1]) *([4 1][4 0]) *([2 0][0 1])>>> flatten(b)
[
[2 0]
[4 1]
[2 0]
[0 1], 1, [4 0], 1, [0 1], 1]>>> b.prod() == aTrue

We solve the word problem using some different generators:
sage: s = G([2,0,0,1]); t = G([1,1,0,1]); u = G([0,-1,1,0])
sage: a.word_problem([s,t,u])([2 0][0 1])^-1 *([1 1][0 1])^-1 *([0 4][1 0]) *([2 0][0 1])^-1>>> from sage.all import *>>> s = G([Integer(2),Integer(0),Integer(0),Integer(1)]); t = G([Integer(1),˓→Integer(1),Integer(0),Integer(1)]); u = G([Integer(0),-Integer(1),˓→Integer(1),Integer(0)])>>> a.word_problem([s,t,u])([2 0][0 1])^-1 *([1 1][0 1])^-1 *([0 4][1 0]) *([2 0][0 1])^-1

We try some elements that don’t actually generate the group:
28.5. Matrix group elements implemented in GAP

617

Groups, Release 10.4

sage: a.word_problem([t,u])Traceback (most recent call last):...
ValueError: word problem has no solution>>> from sage.all import *>>> a.word_problem([t,u])Traceback (most recent call last):...
ValueError: word problem has no solution

AUTHORS:• David Joyner and William Stein• David Loeffler (2010): fixed some bugs
• Volker Braun (2013): LibGAP

28.6 Finitely Generated Matrix Groups
This class is designed for computing with matrix groups defined by a finite set of generating matrices.
EXAMPLES:
sage: F = GF(3)sage: gens = [matrix(F, 2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]
sage: G = MatrixGroup(gens)sage: G.conjugacy_classes_representatives()
˓→needs sage.libs.gap([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0])#␣

>>> from sage.all import *>>> F = GF(Integer(3))>>> gens = [matrix(F, Integer(2), [Integer(1),Integer(0), -Integer(1),Integer(1)]),␣
˓→matrix(F, Integer(2), [Integer(1),Integer(1),Integer(0),Integer(1)])]>>> G = MatrixGroup(gens)>>> G.conjugacy_classes_representatives()#␣˓→needs sage.libs.gap([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0])

The finitely generated matrix groups can also be constructed as subgroups of matrix groups:
sage: SL2Z = SL(2, ZZ)
sage: S, T = SL2Z.gens()
sage: SL2Z.subgroup([T^2])
Subgroup with 1 generators (
[1 2]
[0 1]
) of Special Linear Group of degree 2 over Integer Ring

618

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4>>> from sage.all import *>>> SL2Z = SL(Integer(2), ZZ)>>> S, T = SL2Z.gens()>>> SL2Z.subgroup([T**Integer(2)])
Subgroup with 1 generators (
[1 2]
[0 1]
) of Special Linear Group of degree 2 over Integer Ring

AUTHORS:• William Stein: initial version• David Joyner (2006-03-15): degree, base_ring, _contains_, list, random, order methods; examples• William Stein (2006-12): rewrite• David Joyner (2007-12): Added invariant_generators (with Martin Albrecht and Simon King)• David Joyner (2008-08): Added module_composition_factors (interface to GAP’s MeatAxe implementation) and
as_permutation_group (returns isomorphic PermutationGroup).
• Simon King (2010-05): Improve invariant_generators by using GAP for the construction of the Reynolds operator
in Singular.
• Volker Braun (2013-1) port to new Parent, libGAP.
• Sebastian Oehms (2018-07): Added _permutation_group_element_ (Issue #25706)• Sebastian Oehms (2019-01): Revision of Issue #25706 (Issue #26903 and Issue #27143).

class sage.groups.matrix_gps.finitely_generated.FinitelyGeneratedMatrixGroup_generic(degree,
base_rin
generator_matrices,
category=No
Bases: MatrixGroup_genericgen(i)
Return the 𝑖-th generator.
OUTPUT: the 𝑖-th generator of the group
EXAMPLES:
sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
sage: G.gen(0)
[1 0]
[2 1]
sage: G.gen(0).matrix() == h1.matrix()
True

28.6. Finitely Generated Matrix Groups619

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.libs.gap>>> H = GL(Integer(2), GF(Integer(3)))>>> h1, h2 = H([[Integer(1),Integer(0)], [Integer(2),Integer(1)]]),␣
˓→H([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])>>> G = H.subgroup([h1, h2])>>> G.gen(Integer(0))
[1 0]
[2 1]
>>> G.gen(Integer(0)).matrix() == h1.matrix()Truegens()
Return the generators of the matrix group.
EXAMPLES:
sage: F = GF(3); MS = MatrixSpace(F, 2, 2)
sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])]
sage: G = MatrixGroup(gens)sage: gens[0] in G
True
sage: gens = G.gens()
sage: gens[0] in G
True
sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])]
sage: F = GF(5); MS = MatrixSpace(F, 2, 2)
sage: G = MatrixGroup([MS(1), MS([1,2, 3,4])])sage: G
Matrix group over Finite Field of size 5 with 2 generators ([1 0] [1 2][0 1], [3 4])sage: G.gens()([1 0] [1 2][0 1], [3 4])>>> from sage.all import *>>> F = GF(Integer(3)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> gens = [MS([[Integer(1),Integer(0)], [Integer(0),Integer(1)]]),␣
˓→MS([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])]>>> G = MatrixGroup(gens)>>> gens[Integer(0)] in G
True>>> gens = G.gens()>>> gens[Integer(0)] in G
True>>> gens = [MS([[Integer(1),Integer(0)], [Integer(0),Integer(1)]]),␣
˓→MS([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])]>>> F = GF(Integer(5)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> G = MatrixGroup([MS(Integer(1)), MS([Integer(1),Integer(2), Integer(3),˓→Integer(4)])])>>> G(continues on next page)

620

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)Matrix group over Finite Field of size 5 with 2 generators ([1 0] [1 2][0 1], [3 4])>>> G.gens()([1 0] [1 2][0 1], [3 4])ngens()
Return the number of generators.
OUTPUT: integer; the number of generators
EXAMPLES:
sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
sage: G.ngens()2>>> from sage.all import *>>> # needs sage.libs.gap>>> H = GL(Integer(2), GF(Integer(3)))>>> h1, h2 = H([[Integer(1),Integer(0)], [Integer(2),Integer(1)]]),␣
˓→H([[Integer(1),Integer(1)], [Integer(0),Integer(1)]])>>> G = H.subgroup([h1, h2])>>> G.ngens()
2

sage.groups.matrix_gps.finitely_generated.MatrixGroup(*gens, **kwds)
Return the matrix group with given generators.
INPUT:• *gens – matrices, or a single list/tuple/iterable of matrices, or a matrix group• check – boolean keyword argument (default: True); whether to check that each matrix is invertible
EXAMPLES:
sage: F = GF(5)sage: gens = [matrix(F, 2, [1,2, -1,1]), matrix(F,2, [1,1, 0,1])]
sage: G = MatrixGroup(gens); G
Matrix group over Finite Field of size 5 with 2 generators ([1 2] [1 1][4 1], [0 1])>>> from sage.all import *>>> F = GF(Integer(5))>>> gens = [matrix(F, Integer(2), [Integer(1),Integer(2), -Integer(1),˓→Integer(1)]), matrix(F,Integer(2), [Integer(1),Integer(1), Integer(0),˓→Integer(1)])](continues on next page)

28.6. Finitely Generated Matrix Groups

621

Groups, Release 10.4

(continued from previous page)>>> G = MatrixGroup(gens); G
Matrix group over Finite Field of size 5 with 2 generators ([1 2] [1 1][4 1], [0 1])

In the second example, the generators are a matrix over , a matrix over a finite field, and the integer 2. Sage
determines that they both canonically map to matrices over the finite field, so creates that matrix group there:
sage: gens = [matrix(2, [1,2, -1,1]), matrix(GF(7), 2, [1,1, 0,1]), 2]
sage: G = MatrixGroup(gens); G
Matrix group over Finite Field of size 7 with 3 generators ([1 2] [1 1] [2 0][6 1], [0 1], [0 2])>>> from sage.all import *>>> gens = [matrix(Integer(2), [Integer(1),Integer(2), -Integer(1),Integer(1)]),␣
˓→matrix(GF(Integer(7)), Integer(2), [Integer(1),Integer(1), Integer(0),˓→Integer(1)]), Integer(2)]>>> G = MatrixGroup(gens); G
Matrix group over Finite Field of size 7 with 3 generators ([1 2] [1 1] [2 0][6 1], [0 1], [0 2])Each generator must be invertible:
sage: G = MatrixGroup([matrix(ZZ, 2, [1,2,3,4])])
Traceback (most recent call last):...
ValueError: each generator must be an invertible matrix
sage: F = GF(5); MS = MatrixSpace(F, 2, 2)
sage: MatrixGroup([MS.0])
Traceback (most recent call last):...
ValueError: each generator must be an invertible matrix
sage: MatrixGroup([MS.0], check=False) # works formally but is mathematical␣
˓→nonsense
Matrix group over Finite Field of size 5 with 1 generators (
[1 0]
[0 0]
)
>>> from sage.all import *>>> G = MatrixGroup([matrix(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3),˓→Integer(4)])])
Traceback (most recent call last):...
ValueError: each generator must be an invertible matrix>>> F = GF(Integer(5)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> MatrixGroup([MS.gen(0)])
Traceback (most recent call last):...
(continues on next page)

622

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

ValueError: each generator must be an invertible matrix>>> MatrixGroup([MS.gen(0)], check=False) # works formally but is mathematical␣
˓→nonsense
Matrix group over Finite Field of size 5 with 1 generators (
[1 0]
[0 0]
)

Some groups are not supported, or do not have much functionality implemented:
sage: G = SL(0, QQ)
Traceback (most recent call last):...
ValueError: the degree must be at least 1
sage: SL2C = SL(2, CC); SL2C
Special Linear Group of degree 2 over Complex Field with 53 bits of precision
sage: SL2C.gens()
Traceback (most recent call last):...
AttributeError: LinearMatrixGroup_generic_with_category object has no attribute
˓→ gens ...
>>> from sage.all import *>>> G = SL(Integer(0), QQ)
Traceback (most recent call last):...
ValueError: the degree must be at least 1>>> SL2C = SL(Integer(2), CC); SL2C
Special Linear Group of degree 2 over Complex Field with 53 bits of precision>>> SL2C.gens()
Traceback (most recent call last):...
AttributeError: LinearMatrixGroup_generic_with_category object has no attribute
˓→ gens ...

sage.groups.matrix_gps.finitely_generated.QuaternionMatrixGroupGF3()
The quaternion group as a set of 2 × 2 matrices over F3 .
OUTPUT:
A matrix group consisting of 2 × 2 matrices with elements from the finite field of order 3. The group is thequaternion group, the nonabelian group of order 8 that is not isomorphic to the group of symmetries of a square(the dihedral group 𝐷4 ).
Note: This group is most easily available via groups.matrix.QuaternionGF3().
EXAMPLES:
The generators are the matrix representations of the elements commonly called 𝐼 and 𝐽, while 𝐾 is the product of
𝐼 and 𝐽.
sage: from sage.groups.matrix_gps.finitely_generated import␣
˓→QuaternionMatrixGroupGF3(continues on next page)

28.6. Finitely Generated Matrix Groups623

Groups, Release 10.4

(continued from previous page)

sage: # needs sage.libs.gap
sage: Q = QuaternionMatrixGroupGF3()
sage: Q.order()8sage: aye = Q.gens()[0]; aye
[1 1]
[1 2]
sage: jay = Q.gens()[1]; jay
[2 1]
[1 1]
sage: kay = aye*jay; kay
[0 2]
[1 0]
>>> from sage.all import *>>> from sage.groups.matrix_gps.finitely_generated import QuaternionMatrixGroupGF3>>> # needs sage.libs.gap>>> Q = QuaternionMatrixGroupGF3()>>> Q.order()8>>> aye = Q.gens()[Integer(0)]; aye
[1 1]
[1 2]
>>> jay = Q.gens()[Integer(1)]; jay
[2 1]
[1 1]
>>> kay = aye*jay; kay
[0 2]
[1 0]

sage.groups.matrix_gps.finitely_generated.normalize_square_matrices(matrices)
Find a common space for all matrices.
OUTPUT: a list of matrices, all elements of the same matrix space
EXAMPLES:
sage: from sage.groups.matrix_gps.finitely_generated import normalize_square_
˓→matrices
sage: m1 = [[1,2], [3,4]]
sage: m2 = [2, 3, 4, 5]
sage: m3 = matrix(QQ, [[1/2,1/3], [1/4,1/5]])
sage: m4 = MatrixGroup(m3).gen(0)sage: normalize_square_matrices([m1, m2, m3, m4])[
[1 2] [2 3] [1/2 1/3] [1/2 1/3]
[3 4], [4 5], [1/4 1/5], [1/4 1/5]]>>> from sage.all import *>>> from sage.groups.matrix_gps.finitely_generated import normalize_square_
˓→matrices>>> m1 = [[Integer(1),Integer(2)], [Integer(3),Integer(4)]]>>> m2 = [Integer(2), Integer(3), Integer(4), Integer(5)](continues on next page)

624

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> m3 = matrix(QQ, [[Integer(1)/Integer(2),Integer(1)/Integer(3)], [Integer(1)/˓→Integer(4),Integer(1)/Integer(5)]])>>> m4 = MatrixGroup(m3).gen(Integer(0))>>> normalize_square_matrices([m1, m2, m3, m4])[
[1 2] [2 3] [1/2 1/3] [1/2 1/3]
[3 4], [4 5], [1/4 1/5], [1/4 1/5]]

28.7 Finitely Generated Matrix Groups with GAPclass sage.groups.matrix_gps.finitely_generated_gap.FinitelyGeneratedMatrixGroup_gap(degree,
base_rinlibgap_grou
ambient=Non
category=No
Bases: MatrixGroup_gap
Matrix group generated by a finite number of matrices.
EXAMPLES:
sage: m1 = matrix(GF(11), [[1,2],[3,4]])
sage: m2 = matrix(GF(11), [[1,3],[10,0]])
sage: G = MatrixGroup(m1, m2); G
Matrix group over Finite Field of size 11 with 2 generators ([1 2] [ 1 3]
[3 4], [10 0])
sage: type(G)<class sage.groups.matrix_gps.finitely_generated_gap.
˓→FinitelyGeneratedMatrixGroup_gap_with_category >sage: TestSuite(G).run()>>> from sage.all import *>>> m1 = matrix(GF(Integer(11)), [[Integer(1),Integer(2)],[Integer(3),˓→Integer(4)]])>>> m2 = matrix(GF(Integer(11)), [[Integer(1),Integer(3)],[Integer(10),
˓→Integer(0)]])>>> G = MatrixGroup(m1, m2); G
Matrix group over Finite Field of size 11 with 2 generators ([1 2] [ 1 3]
[3 4], [10 0])>>> type(G)<class sage.groups.matrix_gps.finitely_generated_gap.
(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

625

Groups, Release 10.4

(continued from previous page)

FinitelyGeneratedMatrixGroup_gap_with_category >>>> TestSuite(G).run()˓→

as_permutation_group(algorithm=None, seed=None)
Return a permutation group representation for the group.
In most cases occurring in practice, this is a permutation group of minimal degree (the degree being determined from orbits under the group action). When these orbits are hard to compute, the procedure can betime-consuming and the degree may not be minimal.
INPUT:• algorithm – None or smaller ; in the latter case, try harder to find a permutation representationof small degree• seed – None or an integer specifying the seed to fix results depending on pseudo-random-numbers;
here it makes sense to be used with respect to the smaller option, since GAP produces random
output in that context
OUTPUT:
A permutation group isomorphic to self. The algorithm= smaller option tries to return an isomorphic group of low degree, but is not guaranteed to find the smallest one and must not even differ from theone obtained without the option. In that case repeating the invocation may help (see the example below).
EXAMPLES:
sage: MS = MatrixSpace(GF(2), 5, 5)
sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]])
sage: G = MatrixGroup([A])
sage: G.as_permutation_group().order()2>>> from sage.all import *>>> MS = MatrixSpace(GF(Integer(2)), Integer(5), Integer(5))>>> A = MS([[Integer(0),Integer(0),Integer(0),Integer(0),Integer(1)],
˓→[Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)],[Integer(0),˓→Integer(0),Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),˓→Integer(0),Integer(0),Integer(0)],[Integer(1),Integer(0),Integer(0),˓→Integer(0),Integer(0)]])>>> G = MatrixGroup([A])>>> G.as_permutation_group().order()2

A finite subgroup of 𝐺𝐿(12, ) as a permutation group:sage: imf = libgap.function_factory( ImfMatrixGroup )sage: GG = imf( 12, 3 )sage: G = MatrixGroup(GG.GeneratorsOfGroup())
sage: G.cardinality()
21499084800
sage: P = G.as_permutation_group()
sage: Psmaller = G.as_permutation_group(algorithm="smaller", seed=6)
sage: P.cardinality()
21499084800
sage: P.degree()144
sage: Psmaller.cardinality()(continues on next page)

626

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)21499084800
sage: Psmaller.degree() <= P.degree()True>>> from sage.all import *>>> imf = libgap.function_factory( ImfMatrixGroup )>>> GG = imf( Integer(12), Integer(3) )>>> G = MatrixGroup(GG.GeneratorsOfGroup())>>> G.cardinality()
21499084800>>> P = G.as_permutation_group()>>> Psmaller = G.as_permutation_group(algorithm="smaller", seed=Integer(6))>>> P.cardinality()
21499084800>>> P.degree()144>>> Psmaller.cardinality()
21499084800>>> Psmaller.degree() <= P.degree()
True

Note: In this case, the “smaller” option returned an isomorphic group of lower degree. The above example
used GAP’s library of irreducible maximal finite (“imf”) integer matrix groups to construct the MatrixGroup 𝐺 over F7 . The section “Irreducible Maximal Finite Integral Matrix Groups” in the GAP reference
manual has more details.

Note: Concerning the option algorithm= smaller you should note the following from GAP documentation: “The methods used might involve the use of random elements and the permutation representation(or even the degree of the representation) is not guaranteed to be the same for different calls of SmallerDegreePermutationRepresentation.”
To obtain a reproducible result the optional argument seed may be used as in the example above.
invariant_generators()
Return invariant ring generators.
Computes generators for the polynomial ring 𝐹 [𝑥1 , . . . , 𝑥𝑛 ]𝐺 , where 𝐺 in 𝐺𝐿(𝑛, 𝐹 ) is a finite matrix group.
In the “good characteristic” case the polynomials returned form a minimal generating set for the algebra of
𝐺-invariant polynomials. In the “bad” case, the polynomials returned are primary and secondary invariants,
forming a not necessarily minimal generating set for the algebra of 𝐺-invariant polynomials.
ALGORITHM:
Wraps Singular’s invariant_algebra_reynolds and invariant_ring in finvar.lib.
EXAMPLES:
sage: F = GF(7); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]sage: G = MatrixGroup(gens)sage: G.invariant_generators()
˓→needs sage.libs.singular[x1^7*x2 - x1*x2^7,#␣(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

627

Groups, Release 10.4

(continued from previous page)x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12,
x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18]
sage: q = 4; a = 2
sage: MS = MatrixSpace(QQ, 2, 2)
sage: gen1 = [[1/a, (q-1)/a], [1/a, -1/a]]
sage: gen2 = [[1,0], [0,-1]]; gen3 = [[-1,0], [0,1]]
sage: G = MatrixGroup([MS(gen1), MS(gen2), MS(gen3)])sage: G.cardinality()
12
sage: G.invariant_generators()
˓→needs sage.libs.singular[x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6]#␣

sage: # needs sage.rings.number_fieldsage: F = CyclotomicField(8)sage: z = F.gen()sage: a = z+1/z
sage: b = z^2
sage: MS = MatrixSpace(F,2,2)
sage: g1 = MS([[1/a, 1/a], [1/a, -1/a]])sage: g2 = MS([[-b, 0], [0, b]])sage: G = MatrixGroup([g1,g2])
sage: G.invariant_generators()
˓→needs sage.libs.singular[x1^4 + 2*x1^2*x2^2 + x2^4,
x1^5*x2 - x1*x2^5,
x1^8 + 28/9*x1^6*x2^2 + 70/9*x1^4*x2^4 + 28/9*x1^2*x2^6 + x2^8]#␣>>> from sage.all import *>>> F = GF(Integer(7)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(0),Integer(1)],[-Integer(1),Integer(0)]]),
˓→MS([[Integer(1),Integer(1)],[Integer(2),Integer(3)]])]>>> G = MatrixGroup(gens)>>> G.invariant_generators()#␣˓→needs sage.libs.singular[x1^7*x2 - x1*x2^7,
x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12,
x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18]>>> q = Integer(4); a = Integer(2)>>> MS = MatrixSpace(QQ, Integer(2), Integer(2))>>> gen1 = [[Integer(1)/a, (q-Integer(1))/a], [Integer(1)/a, -Integer(1)/a]]>>> gen2 = [[Integer(1),Integer(0)], [Integer(0),-Integer(1)]]; gen3 = [[˓→Integer(1),Integer(0)], [Integer(0),Integer(1)]]>>> G = MatrixGroup([MS(gen1), MS(gen2), MS(gen3)])>>> G.cardinality()
12>>> G.invariant_generators()#␣˓→needs sage.libs.singular[x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6]>>> # needs sage.rings.number_field>>> F = CyclotomicField(Integer(8))>>> z = F.gen()>>> a = z+Integer(1)/z(continues on next page)

628

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> b = z**Integer(2)>>> MS = MatrixSpace(F,Integer(2),Integer(2))>>> g1 = MS([[Integer(1)/a, Integer(1)/a], [Integer(1)/a, -Integer(1)/a]])>>> g2 = MS([[-b, Integer(0)], [Integer(0), b]])>>> G = MatrixGroup([g1,g2])>>> G.invariant_generators()#␣˓→needs sage.libs.singular[x1^4 + 2*x1^2*x2^2 + x2^4,
x1^5*x2 - x1*x2^5,
x1^8 + 28/9*x1^6*x2^2 + 70/9*x1^4*x2^4 + 28/9*x1^2*x2^6 + x2^8]

AUTHORS:• David Joyner, Simon King and Martin Albrecht.
REFERENCES:• Singular reference manual• [Stu1993]• S. King, “Minimal Generating Sets of non-modular invariant rings of finite groups”, arXiv
math/0703035.
invariants_of_degree(deg, chi=None, R=None)
Return the (relative) invariants of given degree for this group.
For this group, compute the invariants of degree deg with respect to the group character chi. The method
is to project each possible monomial of degree deg via the Reynolds operator. Note that if the polynomial
ring R is specified it’s base ring may be extended if the resulting invariant is defined over a bigger field.
INPUT:• degree – a positive integer• chi – (default: trivial character) a linear group character of this group• R – (optional) a polynomial ring
OUTPUT: list of polynomials
EXAMPLES:
sage: # needs sage.groups sage.rings.number_fieldsage: Gr = MatrixGroup(SymmetricGroup(2))
sage: sorted(Gr.invariants_of_degree(3))[x0^2*x1 + x0*x1^2, x0^3 + x1^3]
sage: R.<x,y> = QQ[]
sage: sorted(Gr.invariants_of_degree(4, R=R))[x^2*y^2, x^3*y + x*y^3, x^4 + y^4]>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> Gr = MatrixGroup(SymmetricGroup(Integer(2)))>>> sorted(Gr.invariants_of_degree(Integer(3)))[x0^2*x1 + x0*x1^2, x0^3 + x1^3]>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> sorted(Gr.invariants_of_degree(Integer(4), R=R))[x^2*y^2, x^3*y + x*y^3, x^4 + y^4]

28.7. Finitely Generated Matrix Groups with GAP

629

Groups, Release 10.4

sage: # needs sage.groups sage.rings.number_fieldsage: R.<x,y,z> = QQ[]
sage: Gr = MatrixGroup(DihedralGroup(3))
sage: ct = Gr.character_table()sage: chi = Gr.character(ct[0])sage: all(f(*(g.matrix()*vector(R.gens()))) == chi(g)*f....: for f in Gr.invariants_of_degree(3, R=R, chi=chi) for g in Gr)
True>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> R = QQ[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> Gr = MatrixGroup(DihedralGroup(Integer(3)))>>> ct = Gr.character_table()>>> chi = Gr.character(ct[Integer(0)])>>> all(f(*(g.matrix()*vector(R.gens()))) == chi(g)*f... for f in Gr.invariants_of_degree(Integer(3), R=R, chi=chi) for g in Gr)
True
sage: i = GF(7)(3)
sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])sage: G.invariants_of_degree(25)˓→needs sage.rings.number_field[]#␣>>> from sage.all import *>>> i = GF(Integer(7))(Integer(3))>>> G = MatrixGroup([[i**Integer(3),Integer(0),Integer(0),-i**Integer(3)],˓→[i**Integer(2),Integer(0),Integer(0),-i**Integer(2)]])>>> G.invariants_of_degree(Integer(25))˓→# needs sage.rings.number_field[]␣

sage: # needs sage.groups
sage: G = MatrixGroup(SymmetricGroup(5))
sage: R = QQ[ x,y ]sage: G.invariants_of_degree(3, R=R)
Traceback (most recent call last):...
TypeError: number of variables in polynomial ring must match size of matrices>>> from sage.all import *>>> # needs sage.groups>>> G = MatrixGroup(SymmetricGroup(Integer(5)))>>> R = QQ[ x,y ]>>> G.invariants_of_degree(Integer(3), R=R)
Traceback (most recent call last):...
TypeError: number of variables in polynomial ring must match size of matrices
sage: # needs sage.groups sage.rings.number_fieldsage: K.<i> = CyclotomicField(4)sage: G = MatrixGroup(CyclicPermutationGroup(3))
sage: chi = G.character(G.character_table()[1])sage: R.<x,y,z> = K[](continues on next page)

630

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

sage: sorted(G.invariants_of_degree(2, R=R, chi=chi))[x*y + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*x*z+ (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y*z,x^2 + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y^2+ (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*z^2]>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> K = CyclotomicField(Integer(4), names=( i ,)); (i,) = K._first_ngens(1)>>> G = MatrixGroup(CyclicPermutationGroup(Integer(3)))>>> chi = G.character(G.character_table()[Integer(1)])>>> R = K[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> sorted(G.invariants_of_degree(Integer(2), R=R, chi=chi))[x*y + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*x*z+ (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y*z,x^2 + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y^2+ (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*z^2]
sage: # needs sage.groups sage.rings.number_fieldsage: S3 = MatrixGroup(SymmetricGroup(3))
sage: chi = S3.character(S3.character_table()[0])sage: sorted(S3.invariants_of_degree(5, chi=chi))[x0^3*x1^2 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 + x0^2*x2^3 - x1^2*x2^3,
x0^4*x1 - x0*x1^4 - x0^4*x2 + x1^4*x2 + x0*x2^4 - x1*x2^4]>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> S3 = MatrixGroup(SymmetricGroup(Integer(3)))>>> chi = S3.character(S3.character_table()[Integer(0)])>>> sorted(S3.invariants_of_degree(Integer(5), chi=chi))[x0^3*x1^2 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 + x0^2*x2^3 - x1^2*x2^3,
x0^4*x1 - x0*x1^4 - x0^4*x2 + x1^4*x2 + x0*x2^4 - x1*x2^4]

module_composition_factors(algorithm=None)
Return a list of triples consisting of [base field, dimension, irreducibility], for each of the Meataxe composition
factors modules. The algorithm="verbose" option returns more information, but in Meataxe notation.
EXAMPLES:
sage: F = GF(3); MS = MatrixSpace(F,4,4)
sage: M = MS(0)sage: M[0,1] = 1; M[1,2] = 1; M[2,3] = 1; M[3,0] = 1
sage: G = MatrixGroup([M])
sage: G.module_composition_factors()[(Finite Field of size 3, 1, True),(Finite Field of size 3, 1, True),(Finite Field of size 3, 2, True)]sage: F = GF(7); MS = MatrixSpace(F,2,2)
sage: gens = [MS([[0,1],[-1,0]]), MS([[1,1],[2,3]])]sage: G = MatrixGroup(gens)sage: G.module_composition_factors()[(Finite Field of size 7, 2, True)]>>> from sage.all import *>>> F = GF(Integer(3)); MS = MatrixSpace(F,Integer(4),Integer(4))(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

631

Groups, Release 10.4

(continued from previous page)>>> M = MS(Integer(0))>>> M[Integer(0),Integer(1)] = Integer(1); M[Integer(1),Integer(2)] =␣
˓→Integer(1); M[Integer(2),Integer(3)] = Integer(1); M[Integer(3),Integer(0)]␣
˓→= Integer(1)>>> G = MatrixGroup([M])>>> G.module_composition_factors()[(Finite Field of size 3, 1, True),(Finite Field of size 3, 1, True),(Finite Field of size 3, 2, True)]>>> F = GF(Integer(7)); MS = MatrixSpace(F,Integer(2),Integer(2))>>> gens = [MS([[Integer(0),Integer(1)],[-Integer(1),Integer(0)]]),␣
˓→MS([[Integer(1),Integer(1)],[Integer(2),Integer(3)]])]>>> G = MatrixGroup(gens)>>> G.module_composition_factors()[(Finite Field of size 7, 2, True)]Type G.module_composition_factors(algorithm= verbose ) to get a more verbose version.
For more on MeatAxe notation, see GAP: chap69.
molien_series(chi=None, return_series=True, prec=20, variable='t')Compute the Molien series of this finite group with respect to the character chi.
It can be returned either as a rational function in one variable or a power series in one variable. The base fieldmust be a finite field, the rationals, or a cyclotomic field.
Note that the base field characteristic cannot divide the group order (i.e., the non-modular case).
ALGORITHM:
For a finite group 𝐺 in characteristic zero we construct the Molien series as
1 ∑︁
𝜒(𝑔)
,
|𝐺|
det(𝐼 − 𝑡𝑔)𝑔∈𝐺

where 𝐼 is the identity matrix and 𝑡 an indeterminate.
For characteristic 𝑝 not dividing the order of 𝐺, let 𝑘 be the base field and 𝑁 the order of 𝐺. Define 𝜆 as aprimitive 𝑁 -th root of unity over 𝑘 and 𝜔 as a primitive 𝑁 -th root of unity over . For each 𝑔 ∈ 𝐺 define𝑘𝑖 (𝑔) to be the positive integer such that 𝑒𝑖 = 𝜆𝑘𝑖 (𝑔) for each eigenvalue 𝑒𝑖 of 𝑔. Then the Molien series iscomputed as
1 ∑︁
𝜒(𝑔)
∏︀𝑛
,
|𝐺|
(1
− 𝑡𝜔 𝑘𝑖 (𝑔) )𝑖=1𝑔∈𝐺where 𝑡 is an indeterminant. [Dec1998]
INPUT:• chi – (default: trivial character) a linear group character of this group• return_series – boolean (default: True) if True, then returns the Molien series as a power series,
False as a rational function• prec – integer (default: 20); power series default precision (possibly infinite, in which case it is computed lazily)• variable – string (default: t ); variable name for the Molien series

632

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

OUTPUT: single variable rational function or power series with integer coefficients
EXAMPLES:
sage: MatrixGroup(matrix(QQ,2,2,[1,1,0,1])).molien_series()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups
sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series()
˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: characteristic cannot divide group order#␣>>> from sage.all import *>>> MatrixGroup(matrix(QQ,Integer(2),Integer(2),[Integer(1),Integer(1),˓→Integer(0),Integer(1)])).molien_series()
Traceback (most recent call last):...
NotImplementedError: only implemented for finite groups>>> MatrixGroup(matrix(GF(Integer(3)),Integer(2),Integer(2),[Integer(1),˓→Integer(1),Integer(0),Integer(1)])).molien_series()# needs␣
˓→sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: characteristic cannot divide group order

Tetrahedral Group:sage: # needs sage.rings.number_fieldsage: K.<i> = CyclotomicField(4)sage: Tetra = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
sage: Tetra.molien_series(prec=30)
1 + t^8 + 2*t^12 + t^16 + 2*t^20 + 3*t^24 + 2*t^28 + O(t^30)
sage: mol = Tetra.molien_series(return_series=False); mol(t^8 - t^4 + 1)/(t^16 - t^12 - t^4 + 1)
sage: mol.parent()
Fraction Field of Univariate Polynomial Ring in t over Integer Ringsage: chi = Tetra.character(Tetra.character_table()[1])sage: Tetra.molien_series(chi, prec=30, variable= u )u^6 + u^14 + 2*u^18 + u^22 + 2*u^26 + 3*u^30 + 2*u^34 + O(u^36)
sage: chi = Tetra.character(Tetra.character_table()[2])sage: Tetra.molien_series(chi)t^10 + t^14 + t^18 + 2*t^22 + 2*t^26 + O(t^30)>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(4), names=( i ,)); (i,) = K._first_ngens(1)>>> Tetra = MatrixGroup([(-Integer(1)+i)/Integer(2),(-Integer(1)+i)/
˓→Integer(2), (Integer(1)+i)/Integer(2),(-Integer(1)-i)/Integer(2)],␣
˓→[Integer(0),i, -i,Integer(0)])>>> Tetra.molien_series(prec=Integer(30))
1 + t^8 + 2*t^12 + t^16 + 2*t^20 + 3*t^24 + 2*t^28 + O(t^30)>>> mol = Tetra.molien_series(return_series=False); mol(t^8 - t^4 + 1)/(t^16 - t^12 - t^4 + 1)>>> mol.parent()
Fraction Field of Univariate Polynomial Ring in t over Integer Ring>>> chi = Tetra.character(Tetra.character_table()[Integer(1)])(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

633

Groups, Release 10.4

(continued from previous page)>>> Tetra.molien_series(chi, prec=Integer(30), variable= u )u^6 + u^14 + 2*u^18 + u^22 + 2*u^26 + 3*u^30 + 2*u^34 + O(u^36)>>> chi = Tetra.character(Tetra.character_table()[Integer(2)])>>> Tetra.molien_series(chi)t^10 + t^14 + t^18 + 2*t^22 + 2*t^26 + O(t^30)
sage: # needs sage.groups sage.rings.number_fieldsage: S3 = MatrixGroup(SymmetricGroup(3))
sage: mol = S3.molien_series(prec=10); mol
1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^˓→10)
sage: mol.parent()
Power Series Ring in t over Integer Ringsage: mol = S3.molien_series(prec=oo); mol
1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + O(t^7)
sage: mol.parent()
Lazy Taylor Series Ring in t over Integer Ring>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> S3 = MatrixGroup(SymmetricGroup(Integer(3)))>>> mol = S3.molien_series(prec=Integer(10)); mol
1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^˓→10)>>> mol.parent()
Power Series Ring in t over Integer Ring>>> mol = S3.molien_series(prec=oo); mol
1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + O(t^7)>>> mol.parent()
Lazy Taylor Series Ring in t over Integer Ring

Octahedral Group:sage: # needs sage.rings.number_fieldsage: K.<v> = CyclotomicField(8)sage: a = v - v^3 # sqrt(2)sage: i = v^2
sage: Octa = MatrixGroup([(-1+i)/2, (-1+i)/2, (1+i)/2, (-1-i)/2],
˓→needs sage.symbolic....:[(1+i)/a, 0, 0, (1-i)/a])sage: Octa.molien_series(prec=30)
˓→needs sage.symbolic
1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30)>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(8), names=( v ,)); (v,) = K._first_ngens(1)>>> a = v - v**Integer(3) # sqrt(2)>>> i = v**Integer(2)>>> Octa = MatrixGroup([(-Integer(1)+i)/Integer(2), (-Integer(1)+i)/
˓→Integer(2),(Integer(1)+i)/Integer(2), (-Integer(1)-i)/Integer(2)],˓→# needs sage.symbolic...
[(Integer(1)+i)/a, Integer(0), Integer(0),␣
˓→(Integer(1)-i)/a])>>> Octa.molien_series(prec=Integer(30))˓→# needs sage.symbolic

#␣

#␣

␣

␣

(continues on next page)

634

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30)

Icosahedral Group:sage: # needs sage.rings.number_fieldsage: K.<v> = CyclotomicField(10)sage: z5 = v^2
sage: i = z5^5sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5)sage: Ico = MatrixGroup([[z5^3,0, 0,z5^2],....:[0,1, -1,0],....:[(z5^4-z5)/a, (z5^2-z5^3)/a,....:(z5^2-z5^3)/a, -(z5^4-z5)/a]])sage: Ico.molien_series(prec=40)
1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40)>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(10), names=( v ,)); (v,) = K._first_ngens(1)>>> z5 = v**Integer(2)>>> i = z5**Integer(5)>>> a = Integer(2)*z5**Integer(3) + Integer(2)*z5**Integer(2) + Integer(1)˓→#sqrt(5)>>> Ico = MatrixGroup([[z5**Integer(3),Integer(0), Integer(0),z5**Integer(2)],...
[Integer(0),Integer(1), -Integer(1),Integer(0)],...
[(z5**Integer(4)-z5)/a, (z5**Integer(2)˓→z5**Integer(3))/a,...
(z5**Integer(2)-z5**Integer(3))/a, -(z5**Integer(4)˓→z5)/a]])>>> Ico.molien_series(prec=Integer(40))
1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40)
sage: # needs sage.groups sage.rings.number_fieldsage: G = MatrixGroup(CyclicPermutationGroup(3))
sage: chi = G.character(G.character_table()[1])sage: G.molien_series(chi, prec=10)
t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 9*t^6+ 12*t^7 + 15*t^8 + 18*t^9 + 22*t^10 + O(t^11)>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> G = MatrixGroup(CyclicPermutationGroup(Integer(3)))>>> chi = G.character(G.character_table()[Integer(1)])>>> G.molien_series(chi, prec=Integer(10))
t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 9*t^6+ 12*t^7 + 15*t^8 + 18*t^9 + 22*t^10 + O(t^11)
sage: # needs sage.groups sage.rings.number_fieldsage: K = GF(5)sage: S = MatrixGroup(SymmetricGroup(4))
sage: G = MatrixGroup([matrix(K, 4, 4,....:[K(y) for u in m.list() for y in u])....:
for m in S.gens()])
sage: G.molien_series(return_series=False)
1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1)

28.7. Finitely Generated Matrix Groups with GAP

635

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> K = GF(Integer(5))>>> S = MatrixGroup(SymmetricGroup(Integer(4)))>>> G = MatrixGroup([matrix(K, Integer(4), Integer(4),...
[K(y) for u in m.list() for y in u])...
for m in S.gens()])>>> G.molien_series(return_series=False)
1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1)
sage: # needs sage.rings.number_fieldsage: i = GF(7)(3)
sage: G = MatrixGroup([[i^3,0, 0,-i^3], [i^2,0, 0,-i^2]])sage: chi = G.character(G.character_table()[4])sage: G.molien_series(chi)3*t^5 + 6*t^11 + 9*t^17 + 12*t^23 + O(t^25)>>> from sage.all import *>>> # needs sage.rings.number_field>>> i = GF(Integer(7))(Integer(3))>>> G = MatrixGroup([[i**Integer(3),Integer(0), Integer(0),-i**Integer(3)],␣
˓→[i**Integer(2),Integer(0), Integer(0),-i**Integer(2)]])>>> chi = G.character(G.character_table()[Integer(4)])>>> G.molien_series(chi)3*t^5 + 6*t^11 + 9*t^17 + 12*t^23 + O(t^25)

reynolds_operator(poly, chi=None)
Compute the Reynolds operator of this finite group 𝐺.
This is the projection from a polynomial ring to the ring of relative invariants [Stu1993]. If possible, theinvariant is returned defined over the base field of the given polynomial poly, otherwise, it is returned overthe compositum of the fields involved in the computation. Only implemented for absolute fields.
ALGORITHM:
Let 𝐾[𝑥] be a polynomial ring and 𝜒 a linear character for 𝐺. Let
be the ring of invariants of 𝐺 relative to 𝜒. Then the Reynolds operator is a map 𝑅 from 𝐾[𝑥] into 𝐾[𝑥]𝐺𝜒
defined by
INPUT:• poly – a polynomial• chi – (default: trivial character) a linear group character of this group
OUTPUT: an invariant polynomial relative to 𝜒
AUTHORS:
Rebecca Lauren Miller and Ben Hutz
EXAMPLES:
sage: S3 = MatrixGroup(SymmetricGroup(3))
sage: R.<x,y,z> = QQ[]
sage: f = x*y*z^3sage: S3.reynolds_operator(f)˓→needs sage.rings.number_field
1/3*x^3*y*z + 1/3*x*y^3*z + 1/3*x*y*z^3

636

#␣

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4>>> from sage.all import *>>> S3 = MatrixGroup(SymmetricGroup(Integer(3)))>>> R = QQ[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> f = x*y*z**Integer(3)>>> S3.reynolds_operator(f)˓→needs sage.rings.number_field
1/3*x^3*y*z + 1/3*x*y^3*z + 1/3*x*y*z^3#␣

sage: # needs sage.groups sage.rings.number_fieldsage: G = MatrixGroup(CyclicPermutationGroup(4))
sage: chi = G.character(G.character_table()[3])sage: K.<v> = CyclotomicField(4)sage: R.<x,y,z,w> = K[]
sage: G.reynolds_operator(x, chi)
1/4*x + (1/4*v)*y - 1/4*z + (-1/4*v)*w
sage: chi = G.character(G.character_table()[2])sage: R.<x,y,z,w> = QQ[]
sage: G.reynolds_operator(x*y, chi)
1/4*x*y + (-1/4*zeta4)*y*z + (1/4*zeta4)*x*w - 1/4*z*w>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> G = MatrixGroup(CyclicPermutationGroup(Integer(4)))>>> chi = G.character(G.character_table()[Integer(3)])>>> K = CyclotomicField(Integer(4), names=( v ,)); (v,) = K._first_ngens(1)>>> R = K[ x, y, z, w ]; (x, y, z, w,) = R._first_ngens(4)>>> G.reynolds_operator(x, chi)
1/4*x + (1/4*v)*y - 1/4*z + (-1/4*v)*w>>> chi = G.character(G.character_table()[Integer(2)])>>> R = QQ[ x, y, z, w ]; (x, y, z, w,) = R._first_ngens(4)>>> G.reynolds_operator(x*y, chi)
1/4*x*y + (-1/4*zeta4)*y*z + (1/4*zeta4)*x*w - 1/4*z*w
sage: # needs sage.groups sage.rings.number_fieldsage: K.<i> = CyclotomicField(4)sage: G = MatrixGroup(CyclicPermutationGroup(3))
sage: chi = G.character(G.character_table()[1])sage: R.<x,y,z> = K[]
sage: G.reynolds_operator(x*y^5, chi)
1/3*x*y^5 + (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*x^5*z+ (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*y*z^5sage: R.<x,y,z> = QQbar[]
sage: G.reynolds_operator(x*y^5, chi)
1/3*x*y^5 + (-0.1666666666666667? + 0.2886751345948129?*I)*x^5*z+ (-0.1666666666666667? - 0.2886751345948129?*I)*y*z^5>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> K = CyclotomicField(Integer(4), names=( i ,)); (i,) = K._first_ngens(1)>>> G = MatrixGroup(CyclicPermutationGroup(Integer(3)))>>> chi = G.character(G.character_table()[Integer(1)])>>> R = K[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> G.reynolds_operator(x*y**Integer(5), chi)
1/3*x*y^5 + (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*x^5*z+ (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*y*z^5>>> R = QQbar[ x, y, z ]; (x, y, z,) = R._first_ngens(3)(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

637

Groups, Release 10.4

(continued from previous page)>>> G.reynolds_operator(x*y**Integer(5), chi)
1/3*x*y^5 + (-0.1666666666666667? + 0.2886751345948129?*I)*x^5*z+ (-0.1666666666666667? - 0.2886751345948129?*I)*y*z^5sage: # needs sage.rings.number_fieldsage: K.<i> = CyclotomicField(4)sage: Tetra = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
sage: chi = Tetra.character(Tetra.character_table()[4])sage: L.<v> = QuadraticField(-3)
sage: R.<x,y> = L[]sage: Tetra.reynolds_operator(x^4)
0sage: Tetra.reynolds_operator(x^4, chi)
1/4*x^4 + (1/2*v)*x^2*y^2 + 1/4*y^4sage: R.<x>=L[]
sage: LL.<w> = L.extension(x^2 + v)
sage: R.<x,y> = LL[]
sage: Tetra.reynolds_operator(x^4, chi)Traceback (most recent call last):...
NotImplementedError: only implemented for absolute fields>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(4), names=( i ,)); (i,) = K._first_ngens(1)>>> Tetra = MatrixGroup([(-Integer(1)+i)/Integer(2),(-Integer(1)+i)/
˓→Integer(2), (Integer(1)+i)/Integer(2),(-Integer(1)-i)/Integer(2)],␣
˓→[Integer(0),i, -i,Integer(0)])>>> chi = Tetra.character(Tetra.character_table()[Integer(4)])>>> L = QuadraticField(-Integer(3), names=( v ,)); (v,) = L._first_ngens(1)>>> R = L[ x, y ]; (x, y,) = R._first_ngens(2)>>> Tetra.reynolds_operator(x**Integer(4))
0>>> Tetra.reynolds_operator(x**Integer(4), chi)
1/4*x^4 + (1/2*v)*x^2*y^2 + 1/4*y^4>>> R = L[ x ]; (x,) = R._first_ngens(1)>>> LL = L.extension(x**Integer(2) + v, names=( w ,)); (w,) = LL._first_
˓→ngens(1)>>> R = LL[ x, y ]; (x, y,) = R._first_ngens(2)>>> Tetra.reynolds_operator(x**Integer(4), chi)Traceback (most recent call last):...
NotImplementedError: only implemented for absolute fields
sage: # needs sage.groups sage.rings.number_fieldsage: G = MatrixGroup(DihedralGroup(4))
sage: chi = G.character(G.character_table()[1])sage: R.<x,y> = QQ[]
sage: f = x^4
sage: G.reynolds_operator(f, chi)Traceback (most recent call last):...
TypeError: number of variables in polynomial must match size of matrices
sage: R.<x,y,z,w> = QQ[]
sage: f = x^3*ysage: G.reynolds_operator(f, chi)(continues on next page)

638

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

1/8*x^3*y - 1/8*x*y^3 + 1/8*y^3*z - 1/8*y*z^3 - 1/8*x^3*w + 1/8*z^3*w +1/8*x*w^3 - 1/8*z*w^3>>> from sage.all import *>>> # needs sage.groups sage.rings.number_field>>> G = MatrixGroup(DihedralGroup(Integer(4)))>>> chi = G.character(G.character_table()[Integer(1)])>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> f = x**Integer(4)>>> G.reynolds_operator(f, chi)Traceback (most recent call last):...
TypeError: number of variables in polynomial must match size of matrices>>> R = QQ[ x, y, z, w ]; (x, y, z, w,) = R._first_ngens(4)>>> f = x**Integer(3)*y>>> G.reynolds_operator(f, chi)
1/8*x^3*y - 1/8*x*y^3 + 1/8*y^3*z - 1/8*y*z^3 - 1/8*x^3*w + 1/8*z^3*w +1/8*x*w^3 - 1/8*z*w^3

Characteristic 𝑝 > 0 examples:sage: G = MatrixGroup([[0,1, 1,0]])
sage: R.<w,x> = GF(2)[]sage: G.reynolds_operator(x)Traceback (most recent call last):...
NotImplementedError: not implemented when characteristic divides group order>>> from sage.all import *>>> G = MatrixGroup([[Integer(0),Integer(1), Integer(1),Integer(0)]])>>> R = GF(Integer(2))[ w, x ]; (w, x,) = R._first_ngens(2)>>> G.reynolds_operator(x)Traceback (most recent call last):...
NotImplementedError: not implemented when characteristic divides group ordersage: i = GF(7)(3)
sage: G = MatrixGroup([[i^3,0, 0,-i^3], [i^2,0, 0,-i^2]])sage: chi = G.character(G.character_table()[4])#␣˓→needs sage.rings.number_fieldsage: R.<w,x> = GF(7)[]sage: f = w^5*x + x^6
sage: G.reynolds_operator(f, chi)#␣˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: nontrivial characters not implemented for characteristic␣˓→> 0
sage: G.reynolds_operator(f)x^6>>> from sage.all import *>>> i = GF(Integer(7))(Integer(3))>>> G = MatrixGroup([[i**Integer(3),Integer(0), Integer(0),-i**Integer(3)],␣
˓→[i**Integer(2),Integer(0), Integer(0),-i**Integer(2)]])(continues on next page)

28.7. Finitely Generated Matrix Groups with GAP

639

Groups, Release 10.4

(continued from previous page)>>> chi = G.character(G.character_table()[Integer(4)])␣˓→# needs sage.rings.number_field>>> R = GF(Integer(7))[ w, x ]; (w, x,) = R._first_ngens(2)>>> f = w**Integer(5)*x + x**Integer(6)>>> G.reynolds_operator(f, chi)#␣˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: nontrivial characters not implemented for characteristic␣˓→> 0>>> G.reynolds_operator(f)x^6sage: # needs sage.rings.finite_rings
sage: K = GF(3^2, t )sage: G = MatrixGroup([matrix(K, 2, 2, [0,K.gen(), 1,0])])sage: R.<x,y> = GF(3)[]sage: G.reynolds_operator(x^8)-x^8 - y^8>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(2), t )>>> G = MatrixGroup([matrix(K, Integer(2), Integer(2), [Integer(0),K.gen(),␣˓→Integer(1),Integer(0)])])>>> R = GF(Integer(3))[ x, y ]; (x, y,) = R._first_ngens(2)>>> G.reynolds_operator(x**Integer(8))-x^8 - y^8sage: # needs sage.rings.finite_rings
sage: K = GF(3^2, t )sage: G = MatrixGroup([matrix(GF(3), 2, 2, [0,1, 1,0])])sage: R.<x,y> = K[]
sage: f = -K.gen()*x
sage: G.reynolds_operator(f)t*x + t*y>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> K = GF(Integer(3)**Integer(2), t )>>> G = MatrixGroup([matrix(GF(Integer(3)), Integer(2), Integer(2),␣
˓→[Integer(0),Integer(1), Integer(1),Integer(0)])])>>> R = K[ x, y ]; (x, y,) = R._first_ngens(2)>>> f = -K.gen()*x>>> G.reynolds_operator(f)t*x + t*y640

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

28.8 Homomorphisms Between Matrix Groups
Deprecated May, 2018; use sage.groups.libgap_morphism instead.
sage.groups.matrix_gps.morphism.to_libgap(x)Helper to convert x to a LibGAP matrix or matrix group element.
Deprecated; use the x.gap() method or libgap(x) instead.
EXAMPLES:
sage: from sage.groups.matrix_gps.morphism import to_libgap
sage: to_libgap(GL(2,3).gen(0))
doctest:...: DeprecationWarning: this function is deprecated.
Use x.gap() or libgap(x) instead.
See https://github.com/sagemath/sage/issues/25444 for details.
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]sage: to_libgap(matrix(QQ, [[1,2],[3,4]]))[ [ 1, 2 ], [ 3, 4 ] ]>>> from sage.all import *>>> from sage.groups.matrix_gps.morphism import to_libgap>>> to_libgap(GL(Integer(2),Integer(3)).gen(Integer(0)))
doctest:...: DeprecationWarning: this function is deprecated.
Use x.gap() or libgap(x) instead.
See https://github.com/sagemath/sage/issues/25444 for details.
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]>>> to_libgap(matrix(QQ, [[Integer(1),Integer(2)],[Integer(3),Integer(4)]]))[ [ 1, 2 ], [ 3, 4 ] ]28.9 Matrix Group Homsets
AUTHORS:• William Stein (2006-05-07): initial version• Volker Braun (2013-1) port to new Parent, libGAP
sage.groups.matrix_gps.homset.is_MatrixGroupHomset(x)Test whether x is a matrix group homset.
EXAMPLES:
sage: from sage.groups.matrix_gps.homset import is_MatrixGroupHomset
sage: is_MatrixGroupHomset(4)doctest:...: DeprecationWarning:
Importing MatrixGroupHomset from here is deprecated; please use"from sage.groups.libgap_morphism import GroupHomset_libgap as MatrixGroupHomset"␣
˓→instead.
See https://github.com/sagemath/sage/issues/25444 for details.
False
sage: F = GF(5)sage: gens = [matrix(F,2,[1,2, -1, 1]), matrix(F,2, [1,1, 0,1])]
sage: G = MatrixGroup(gens)sage: from sage.groups.matrix_gps.homset import MatrixGroupHomset(continues on next page)

28.8. Homomorphisms Between Matrix Groups

641

Groups, Release 10.4

(continued from previous page)

sage: M = MatrixGroupHomset(G, G)
sage: is_MatrixGroupHomset(M)True>>> from sage.all import *>>> from sage.groups.matrix_gps.homset import is_MatrixGroupHomset>>> is_MatrixGroupHomset(Integer(4))
doctest:...: DeprecationWarning:
Importing MatrixGroupHomset from here is deprecated; please use"from sage.groups.libgap_morphism import GroupHomset_libgap as MatrixGroupHomset"␣
˓→instead.
See https://github.com/sagemath/sage/issues/25444 for details.
False>>> F = GF(Integer(5))>>> gens = [matrix(F,Integer(2),[Integer(1),Integer(2), -Integer(1), Integer(1)]),
˓→ matrix(F,Integer(2), [Integer(1),Integer(1), Integer(0),Integer(1)])]>>> G = MatrixGroup(gens)>>> from sage.groups.matrix_gps.homset import MatrixGroupHomset>>> M = MatrixGroupHomset(G, G)>>> is_MatrixGroupHomset(M)True

28.10 Binary Dihedral Groups
AUTHORS:• Travis Scrimshaw (2016-02): initial version
class sage.groups.matrix_gps.binary_dihedral.BinaryDihedralGroup(n)Bases: UniqueRepresentation, FinitelyGeneratedMatrixGroup_gap
The binary dihedral group 𝐵𝐷𝑛 of order 4𝑛.
Let 𝑛 be a positive integer. The binary dihedral group 𝐵𝐷𝑛 is a finite group of order 4𝑛, and can be considered as
the matrix group generated by
(︂
)︂
(︂
)︂
𝜁
0
0 𝜁4
𝑔1 = 2𝑛
,
𝑔
=
,
2
−1
𝜁4 0
0 𝜁2𝑛
where 𝜁𝑘 = 𝑒2𝜋𝑖/𝑘 is the primitive 𝑘-th root of unity. Furthermore, 𝐵𝐷𝑛 admits the following presentation (notethat there is a typo in [Sun2010]):
𝐵𝐷𝑛 = ⟨𝑥, 𝑦, 𝑧|𝑥2 = 𝑦 2 = 𝑧 𝑛 = 𝑥𝑦𝑧⟩.
(The 𝑥, 𝑦 and 𝑧 in this presentations correspond to the 𝑔2 , 𝑔2 𝑔1−1 and 𝑔1 in the matrix group avatar.)
REFERENCES:• [Dol2009]• [Sun2010]• Wikipedia article Dicyclic_group#Binary_dihedral_group

642

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

cardinality()
Return the order of self, which is 4𝑛.
EXAMPLES:
sage: G = groups.matrix.BinaryDihedral(3)sage: G.order()12>>> from sage.all import *>>> G = groups.matrix.BinaryDihedral(Integer(3))>>> G.order()12order()
Return the order of self, which is 4𝑛.
EXAMPLES:
sage: G = groups.matrix.BinaryDihedral(3)sage: G.order()12>>> from sage.all import *>>> G = groups.matrix.BinaryDihedral(Integer(3))>>> G.order()12

28.11 Coxeter Groups As Matrix Groups
This implements a general Coxeter group as a matrix group by using the reflection representation.
AUTHORS:• Travis Scrimshaw (2013-08-28): Initial version
class sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup(coxeter_matrix,
base_ring, index_set)
Bases: UniqueRepresentation, FinitelyGeneratedMatrixGroup_genericA Coxeter group represented as a matrix group.
Let (𝑊, 𝑆) be a Coxeter system. We construct a vector space 𝑉 over R with a basis of {𝛼𝑠 }𝑠∈𝑆 and inner product(︂)︂𝜋𝐵(𝛼𝑠 , 𝛼𝑡 ) = − cos
𝑚𝑠𝑡where we have 𝐵(𝛼𝑠 , 𝛼𝑡 ) = −1 if 𝑚𝑠𝑡 = ∞. Next we define a representation 𝜎𝑠 : 𝑉 → 𝑉 by
𝜎𝑠 𝜆 = 𝜆 − 2𝐵(𝛼𝑠 , 𝜆)𝛼𝑠 .
This representation is faithful so we can represent the Coxeter group 𝑊 by the set of matrices 𝜎𝑠 acting on 𝑉 .
INPUT:• data – a Coxeter matrix or graph or a Cartan type28.11. Coxeter Groups As Matrix Groups643

Groups, Release 10.4

• base_ring – (default: the universal cyclotomic field or a number field) the base ring which contains allvalues cos(𝜋/𝑚𝑖𝑗 ) where (𝑚𝑖𝑗 )𝑖𝑗 is the Coxeter matrix• index_set – (optional) an indexing set for the generators
For finite Coxeter groups, the default base ring is taken to be

or a quadratic number field when possible.

For more on creating Coxeter groups, see CoxeterGroup().
Todo: Currently the label ∞ is implemented as −1 in the Coxeter matrix.
EXAMPLES:
We can create Coxeter groups from Coxeter matrices:sage: # needs sage.libs.gap sage.rings.number_fieldsage: W = CoxeterGroup([[1, 6, 3], [6, 1, 10], [3, 10, 1]]); W
Coxeter group over Universal Cyclotomic Field with Coxeter matrix:[ 1 6 3]
[ 6 1 10]
[ 3 10 1]
sage: W.gens()([-1 -E(12)^7 + E(12)^11
1]
[
0
1
0]
[
0
0
1],
[
1
[-E(12)^7 + E(12)^11
[
0
[
[
[
)

1
0
0
1
1 E(20) - E(20)^9

0
-1
0

0]
E(20) - E(20)^9]
1],
0]
0]
-1]

sage: m = matrix([[1,3,3,3], [3,1,3,2], [3,3,1,2], [3,2,2,1]])
sage: W = CoxeterGroup(m)sage: W.gens()([-1 1 1 1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]
[ 0 1 0 0] [ 1 -1 1 0] [ 0 1 0 0] [ 0 1 0 0]
[ 0 0 1 0] [ 0 0 1 0] [ 1 1 -1 0] [ 0 0 1 0]
[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 1 0 0 -1])
sage: a,b,c,d = W.gens()
sage: (a*b*c)^3[ 5 1 -5 7][ 5 0 -4 5][ 4 1 -4 4][ 0 0 0 1]
sage: (a*b)^3[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: b*d == d*b
True(continues on next page)

644

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

sage: a*c*a == c*a*c
True>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> W = CoxeterGroup([[Integer(1), Integer(6), Integer(3)], [Integer(6),␣
˓→Integer(1), Integer(10)], [Integer(3), Integer(10), Integer(1)]]); W
Coxeter group over Universal Cyclotomic Field with Coxeter matrix:[ 1 6 3]
[ 6 1 10]
[ 3 10 1]>>> W.gens()([-1 -E(12)^7 + E(12)^11
1]
[
0
1
0]
[
0
0
1],
<BLANKLINE>[1
00][-E(12)^7 + E(12)^11-1
E(20) - E(20)^9]
[
0
0
1],
<BLANKLINE>
[
1
0
0]
[
0
1
0]
[
1 E(20) - E(20)^9-1])>>> m = matrix([[Integer(1),Integer(3),Integer(3),Integer(3)], [Integer(3),˓→Integer(1),Integer(3),Integer(2)], [Integer(3),Integer(3),Integer(1),˓→Integer(2)], [Integer(3),Integer(2),Integer(2),Integer(1)]])>>> W = CoxeterGroup(m)>>> W.gens()([-1 1 1 1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]
[ 0 1 0 0] [ 1 -1 1 0] [ 0 1 0 0] [ 0 1 0 0]
[ 0 0 1 0] [ 0 0 1 0] [ 1 1 -1 0] [ 0 0 1 0]
[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 1 0 0 -1])>>> a,b,c,d = W.gens()>>> (a*b*c)**Integer(3)[ 5 1 -5 7][ 5 0 -4 5][ 4 1 -4 4][ 0 0 0 1]>>> (a*b)**Integer(3)[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> b*d == d*b
True>>> a*c*a == c*a*c
True

We can create the matrix representation over different base rings and with different index sets. Note that the basering must contain all 2 * cos(𝜋/𝑚𝑖𝑗 ) where (𝑚𝑖𝑗 )𝑖𝑗 is the Coxeter matrix:

28.11. Coxeter Groups As Matrix Groups

645Groups, Release 10.4

sage: W = CoxeterGroup(m, base_ring=RR, index_set=[ a , b , c , d ])sage: W.base_ring()
Real Field with 53 bits of precision
sage: W.index_set()( a , b , c , d )sage: CoxeterGroup(m, base_ring=ZZ)
Coxeter group over Integer Ring with Coxeter matrix:[1 3 3 3][3 1 3 2][3 3 1 2][3 2 2 1]
sage: CoxeterGroup([[1,4],[4,1]], base_ring=QQ)
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: unable to convert sqrt(2) to a rational#␣>>> from sage.all import *>>> W = CoxeterGroup(m, base_ring=RR, index_set=[ a , b , c , d ])>>> W.base_ring()
Real Field with 53 bits of precision>>> W.index_set()( a , b , c , d )>>> CoxeterGroup(m, base_ring=ZZ)
Coxeter group over Integer Ring with Coxeter matrix:[1 3 3 3][3 1 3 2][3 3 1 2][3 2 2 1]>>> CoxeterGroup([[Integer(1),Integer(4)],[Integer(4),Integer(1)]], base_ring=QQ)␣
˓→# needs sage.symbolic
Traceback (most recent call last):...
TypeError: unable to convert sqrt(2) to a rational

Using the well-known conversion between Coxeter matrices and Coxeter graphs, we can input a Coxeter graph.
Following the standard convention, edges with no label (i.e. labelled by None) are treated as 3:
sage: # needs sage.libs.gap sage.rings.number_fieldsage: G = Graph([(0,3,None), (1,3,15), (2,3,7), (0,1,3)])
sage: W = CoxeterGroup(G); W
Coxeter group over Universal Cyclotomic Field with Coxeter matrix:[ 1 3 2 3]
[ 3 1 2 15][ 2 2 1 7]
[ 3 15 7 1]
sage: G2 = W.coxeter_diagram()
sage: CoxeterGroup(G2) is W
True>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> G = Graph([(Integer(0),Integer(3),None), (Integer(1),Integer(3),Integer(15)),␣
˓→(Integer(2),Integer(3),Integer(7)), (Integer(0),Integer(1),Integer(3))])>>> W = CoxeterGroup(G); W(continues on next page)

646

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

Coxeter group over Universal Cyclotomic Field with Coxeter matrix:[ 1 3 2 3]
[ 3 1 2 15][ 2 2 1 7]
[ 3 15 7 1]>>> G2 = W.coxeter_diagram()>>> CoxeterGroup(G2) is W
True

Because there currently is no class for∪ {∞}, labels of ∞ are given by −1 in the Coxeter matrix:

sage: # needs sage.libs.gap sage.rings.number_fieldsage: G = Graph([(0,1,None), (1,2,4), (0,2,oo)])sage: W = CoxeterGroup(G)sage: W.coxeter_matrix()[ 1 3 -1]
[ 3 1 4][-1 4 1]>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> G = Graph([(Integer(0),Integer(1),None), (Integer(1),Integer(2),Integer(4)),␣
˓→(Integer(0),Integer(2),oo)])>>> W = CoxeterGroup(G)>>> W.coxeter_matrix()[ 1 3 -1]
[ 3 1 4][-1 4 1]

We can also create Coxeter groups from Cartan types using the implementation keyword:
sage: W = CoxeterGroup([ D ,5], implementation="reflection"); W
Finite Coxeter group over Integer Ring with Coxeter matrix:[1 3 2 2 2]
[3 1 3 2 2]
[2 3 1 3 3]
[2 2 3 1 2]
[2 2 3 2 1]
sage: W = CoxeterGroup([ H ,3], implementation="reflection"); W#␣˓→needs sage.libs.gap sage.rings.number_field
Finite Coxeter group overNumber Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?
with Coxeter matrix:[1 3 2][3 1 5][2 5 1]>>> from sage.all import *>>> W = CoxeterGroup([ D ,Integer(5)], implementation="reflection"); W
Finite Coxeter group over Integer Ring with Coxeter matrix:[1 3 2 2 2]
[3 1 3 2 2]
[2 3 1 3 3]
[2 2 3 1 2]
[2 2 3 2 1]>>> W = CoxeterGroup([ H ,Integer(3)], implementation="reflection"); W␣(continues on next page)

28.11. Coxeter Groups As Matrix Groups

647

Groups, Release 10.4

(continued from previous page)# needs sage.libs.gap sage.rings.number_field
Finite Coxeter group overNumber Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?
with Coxeter matrix:[1 3 2][3 1 5][2 5 1]˓→class Element
Bases: MatrixGroupElement_genericA Coxeter group element.
action_on_root_indices(i, side='left')
Return the action on the set of roots.
The roots are ordered as in the output of the method roots().
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: w = W.w0
sage: w.action_on_root_indices(0)11>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> w = W.w0>>> w.action_on_root_indices(Integer(0))
11canonical_matrix()
Return the matrix of self in the canonical faithful representation, which is self as a matrix.
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: a,b,c = W.gens()
sage: elt = a*b*c
sage: elt.canonical_matrix()[ 0 0 -1]
[ 1 0 -1]
[ 0 1 -1]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> a,b,c = W.gens()>>> elt = a*b*c>>> elt.canonical_matrix()[ 0 0 -1]
[ 1 0 -1]
[ 0 1 -1]

descents(side='right', index_set=None, positive=False)
Return the descents of self, as a list of elements of the index_set.
INPUT:
648

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• index_set – (default: all of them) a subset (as a list or iterable) of the nodes of the Dynkin
diagram• side – (default: right ) left or right• positive – (default: False) boolean
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: a,b,c = W.gens()
sage: elt = b*a*c
sage: elt.descents()[1, 3]
sage: elt.descents(positive=True)[2]
sage: elt.descents(index_set=[1,2])[1]
sage: elt.descents(side= left )[2]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> a,b,c = W.gens()>>> elt = b*a*c>>> elt.descents()[1, 3]>>> elt.descents(positive=True)[2]>>> elt.descents(index_set=[Integer(1),Integer(2)])[1]>>> elt.descents(side= left )[2]

first_descent(side='right', index_set=None, positive=False)
Return the first left (resp. right) descent of self, as ane element of index_set, or None if there isnone.
See descents() for a description of the options.
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: a,b,c = W.gens()
sage: elt = b*a*c
sage: elt.first_descent()
1
sage: elt.first_descent(side= left )2>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> a,b,c = W.gens()>>> elt = b*a*c>>> elt.first_descent()
1>>> elt.first_descent(side= left )2

has_right_descent(i)Return whether i is a right descent of self.
28.11. Coxeter Groups As Matrix Groups649

Groups, Release 10.4

A Coxeter system (𝑊,∑︀ 𝑆) has a root system defined as {𝑤(𝛼𝑠 )}𝑤∈𝑊 and we define the positive (resp.
negative) roots 𝛼 = 𝑠∈𝑆 𝑐𝑠 𝛼𝑠 by all 𝑐𝑠 ≥ 0 (resp. 𝑐𝑠 ≤ 0). In particular, we note that if ℓ(𝑤𝑠) > ℓ(𝑤)then 𝑤(𝛼𝑠 ) > 0 and if ℓ(𝑤𝑠) < ℓ(𝑤) then 𝑤(𝛼𝑠 ) < 0. Thus 𝑖 ∈ 𝐼 is a right descent if 𝑤(𝛼𝑠𝑖 ) < 0 or
equivalently if the matrix representing 𝑤 has all entries of the 𝑖-th column being non-positive.
INPUT:• i – an element in the index set
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: a,b,c = W.gens()
sage: elt = b*a*c
sage: [elt.has_right_descent(i) for i in [1, 2, 3]][True, False, True]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> a,b,c = W.gens()>>> elt = b*a*c>>> [elt.has_right_descent(i) for i in [Integer(1), Integer(2),␣
˓→Integer(3)]][True, False, True]bilinear_form()
Return the bilinear form associated to self.
Given a Coxeter group 𝐺 with Coxeter matrix 𝑀 = (𝑚𝑖𝑗 )𝑖𝑗 , the associated bilinear form 𝐴 = (𝑎𝑖𝑗 )𝑖𝑗 isgiven by(︂)︂𝜋𝑎𝑖𝑗 = − cos.
𝑚𝑖𝑗
If 𝐴 is positive definite, then 𝐺 is of finite type (and so the associated Coxeter group is a finite group). If 𝐴
is positive semidefinite, then 𝐺 is affine type.
EXAMPLES:
sage: W = CoxeterGroup([ D ,4])
sage: W.bilinear_form()
˓→needs sage.symbolic[
1 -1/20
0][-1/2
1 -1/2 -1/2][
0 -1/21
0][
0 -1/20
1]#␣>>> from sage.all import *>>> W = CoxeterGroup([ D ,Integer(4)])>>> W.bilinear_form()
˓→needs sage.symbolic[
1 -1/20
0][-1/2
1 -1/2 -1/2][
0 -1/21
0][
0 -1/20
1]#␣canonical_representation()
Return the canonical faithful representation of self, which is self.
EXAMPLES:
650

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

sage: W = CoxeterGroup([[1,3],[3,1]])
sage: W.canonical_representation() is W
True>>> from sage.all import *>>> W = CoxeterGroup([[Integer(1),Integer(3)],[Integer(3),Integer(1)]])>>> W.canonical_representation() is W
True

coxeter_matrix()
Return the Coxeter matrix of self.
EXAMPLES:
sage: W = CoxeterGroup([[1,3],[3,1]])
sage: W.coxeter_matrix()
[1 3]
[3 1]
sage: W = CoxeterGroup([ H ,3])
˓→needs sage.libs.gap sage.rings.number_fieldsage: W.coxeter_matrix()
˓→needs sage.libs.gap sage.rings.number_field[1 3 2][3 1 5][2 5 1]#␣#␣>>> from sage.all import *>>> W = CoxeterGroup([[Integer(1),Integer(3)],[Integer(3),Integer(1)]])>>> W.coxeter_matrix()
[1 3]
[3 1]
>>> W = CoxeterGroup([ H ,Integer(3)])˓→# needs sage.libs.gap sage.rings.number_field>>> W.coxeter_matrix()
˓→needs sage.libs.gap sage.rings.number_field[1 3 2][3 1 5][2 5 1]␣#␣

fundamental_weight(i)Return the fundamental weight with index i.
See also:
fundamental_weights()
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation= reflection )sage: W.fundamental_weight(1)˓→needs sage.symbolic(3/2, 1, 1/2)

#␣>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation= reflection )>>> W.fundamental_weight(Integer(1))␣(continues on next page)

28.11. Coxeter Groups As Matrix Groups651

Groups, Release 10.4

(continued from previous page)# needs sage.symbolic(3/2, 1, 1/2)
˓→

fundamental_weights()
Return the fundamental weights for self.
This is the dual basis to the basis of simple roots.
The base ring must be a field.
See also:
fundamental_weight()
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation= reflection )sage: W.fundamental_weights()
˓→needs sage.symbolic
Finite family {1: (3/2, 1, 1/2), 2: (1, 2, 1), 3: (1/2, 1, 3/2)}#␣>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation= reflection )>>> W.fundamental_weights()
˓→needs sage.symbolic
Finite family {1: (3/2, 1, 1/2), 2: (1, 2, 1), 3: (1/2, 1, 3/2)}#␣

is_commutative()
Return whether self is commutative.
EXAMPLES:
sage: CoxeterGroup([ A , 2]).is_commutative()
False
sage: W = CoxeterGroup([ I ,2])
sage: W.is_commutative()
True>>> from sage.all import *>>> CoxeterGroup([ A , Integer(2)]).is_commutative()
False>>> W = CoxeterGroup([ I ,Integer(2)])>>> W.is_commutative()
True

is_finite()
Return True if this group is finite.
EXAMPLES:
sage: # needs sage.libs.gap sage.rings.number_fieldsage: [l for l in range(2, 9) if....: CoxeterGroup([[1,3,2],[3,1,l],[2,l,1]]).is_finite()][2, 3, 4, 5]
sage: [l for l in range(2, 9) if....: CoxeterGroup([[1,3,2,2],[3,1,l,2],[2,l,1,3],[2,2,3,1]]).is_finite()][2, 3, 4](continues on next page)

652

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

sage: [l for l in range(2, 9) if....: CoxeterGroup([[1,3,2,2,2], [3,1,3,3,2], [2,3,1,2,2],....:[2,3,2,1,l], [2,2,2,l,1]]).is_finite()][2, 3]
sage: [l for l in range(2, 9) if....: CoxeterGroup([[1,3,2,2,2], [3,1,2,3,3], [2,2,1,l,2],....:[2,3,l,1,2], [2,3,2,2,1]]).is_finite()][2, 3]
sage: [l for l in range(2, 9) if....: CoxeterGroup([[1,3,2,2,2,2], [3,1,l,2,2,2], [2,l,1,3,l,2],....:[2,2,3,1,2,2], [2,2,l,2,1,3], [2,2,2,2,3,1]]).is_
˓→finite()][2, 3]>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> [l for l in range(Integer(2), Integer(9)) if... CoxeterGroup([[Integer(1),Integer(3),Integer(2)],[Integer(3),Integer(1),˓→l],[Integer(2),l,Integer(1)]]).is_finite()][2, 3, 4, 5]>>> [l for l in range(Integer(2), Integer(9)) if... CoxeterGroup([[Integer(1),Integer(3),Integer(2),Integer(2)],[Integer(3),˓→Integer(1),l,Integer(2)],[Integer(2),l,Integer(1),Integer(3)],[Integer(2),˓→Integer(2),Integer(3),Integer(1)]]).is_finite()][2, 3, 4]>>> [l for l in range(Integer(2), Integer(9)) if... CoxeterGroup([[Integer(1),Integer(3),Integer(2),Integer(2),Integer(2)],␣
˓→[Integer(3),Integer(1),Integer(3),Integer(3),Integer(2)], [Integer(2),˓→Integer(3),Integer(1),Integer(2),Integer(2)],...
[Integer(2),Integer(3),Integer(2),Integer(1),l],␣
˓→[Integer(2),Integer(2),Integer(2),l,Integer(1)]]).is_finite()][2, 3]>>> [l for l in range(Integer(2), Integer(9)) if... CoxeterGroup([[Integer(1),Integer(3),Integer(2),Integer(2),Integer(2)],␣
˓→[Integer(3),Integer(1),Integer(2),Integer(3),Integer(3)], [Integer(2),˓→Integer(2),Integer(1),l,Integer(2)],...
[Integer(2),Integer(3),l,Integer(1),Integer(2)],␣
˓→[Integer(2),Integer(3),Integer(2),Integer(2),Integer(1)]]).is_finite()][2, 3]>>> [l for l in range(Integer(2), Integer(9)) if... CoxeterGroup([[Integer(1),Integer(3),Integer(2),Integer(2),Integer(2),˓→Integer(2)], [Integer(3),Integer(1),l,Integer(2),Integer(2),Integer(2)],␣
˓→[Integer(2),l,Integer(1),Integer(3),l,Integer(2)],...
[Integer(2),Integer(2),Integer(3),Integer(1),Integer(2),˓→Integer(2)], [Integer(2),Integer(2),l,Integer(2),Integer(1),Integer(3)],␣
˓→[Integer(2),Integer(2),Integer(2),Integer(2),Integer(3),Integer(1)]]).is_
˓→finite()][2, 3]

order()
Return the order of self.
If the Coxeter group is finite, this uses an iterator.
EXAMPLES:

28.11. Coxeter Groups As Matrix Groups653

Groups, Release 10.4

sage: # needs sage.rings.number_fieldsage: W = CoxeterGroup([[1,3],[3,1]])
sage: W.order()6sage: W = CoxeterGroup([[1,-1],[-1,1]])
˓→needs sage.libs.gap
sage: W.order()˓→needs sage.libs.gap+Infinity#␣#␣>>> from sage.all import *>>> # needs sage.rings.number_field>>> W = CoxeterGroup([[Integer(1),Integer(3)],[Integer(3),Integer(1)]])>>> W.order()6>>> W = CoxeterGroup([[Integer(1),-Integer(1)],[-Integer(1),Integer(1)]])␣˓→# needs sage.libs.gap>>> W.order()#␣˓→needs sage.libs.gap+Infinity

positive_roots()
Return the positive roots.
These are roots in the Coxeter sense, that all have the same norm. They are given by their coefficients in thebase of simple roots, also taken to have all the same norm.
See also:
reflections()
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation= reflection )sage: W.positive_roots()((1, 0, 0), (1, 1, 0), (0, 1, 0), (1, 1, 1), (0, 1, 1), (0, 0, 1))
sage: # needs sage.libs.gap sage.rings.number_fieldsage: W = CoxeterGroup([ I ,5], implementation= reflection )sage: W.positive_roots()((1, 0),(-E(5)^2 - E(5)^3, 1),(-E(5)^2 - E(5)^3, -E(5)^2 - E(5)^3),(1, -E(5)^2 - E(5)^3),(0, 1))>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation= reflection )>>> W.positive_roots()((1, 0, 0), (1, 1, 0), (0, 1, 0), (1, 1, 1), (0, 1, 1), (0, 0, 1))>>> # needs sage.libs.gap sage.rings.number_field>>> W = CoxeterGroup([ I ,Integer(5)], implementation= reflection )>>> W.positive_roots()((1, 0),(-E(5)^2 - E(5)^3, 1),(-E(5)^2 - E(5)^3, -E(5)^2 - E(5)^3),(continues on next page)

654

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)(1, -E(5)^2 - E(5)^3),(0, 1))

reflections()
Return the set of reflections.
The order is the one given by positive_roots().
EXAMPLES:
sage: W = CoxeterGroup([ A ,2], implementation= reflection )sage: list(W.reflections())[[-1 1] [ 0 -1] [ 1 0]
[ 0 1], [-1 0], [ 1 -1]]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(2)], implementation= reflection )>>> list(W.reflections())[[-1 1] [ 0 -1] [ 1 0]
[ 0 1], [-1 0], [ 1 -1]]

roots()
Return the roots.
These are roots in the Coxeter sense, that all have the same norm. They are given by their coefficients in thebase of simple roots, also taken to have all the same norm.
The positive roots are listed first, then the negative roots in the same order. The order is the one given byroots().
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation= reflection )sage: W.roots()((1, 0, 0),(1, 1, 0),(0, 1, 0),(1, 1, 1),(0, 1, 1),(0, 0, 1),(-1, 0, 0),(-1, -1, 0),(0, -1, 0),(-1, -1, -1),
(0, -1, -1),
(0, 0, -1))
sage: # needs sage.libs.gap sage.rings.number_fieldsage: W = CoxeterGroup([ I ,5], implementation= reflection )sage: len(W.roots())
10

28.11. Coxeter Groups As Matrix Groups655

Groups, Release 10.4>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation= reflection )>>> W.roots()((1, 0, 0),(1, 1, 0),(0, 1, 0),(1, 1, 1),(0, 1, 1),(0, 0, 1),(-1, 0, 0),(-1, -1, 0),(0, -1, 0),(-1, -1, -1),
(0, -1, -1),
(0, 0, -1))>>> # needs sage.libs.gap sage.rings.number_field>>> W = CoxeterGroup([ I ,Integer(5)], implementation= reflection )>>> len(W.roots())
10

simple_reflection(i)Return the simple reflection 𝑠𝑖 .
INPUT:• i – an element from the index set
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation="reflection")sage: W.simple_reflection(1)[-1 1 0][ 0 1 0][ 0 0 1]
sage: W.simple_reflection(2)[ 1 0 0][ 1 -1 1][ 0 0 1]
sage: W.simple_reflection(3)[ 1 0 0][ 0 1 0][ 0 1 -1]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation="reflection")>>> W.simple_reflection(Integer(1))[-1 1 0][ 0 1 0][ 0 0 1]>>> W.simple_reflection(Integer(2))[ 1 0 0][ 1 -1 1][ 0 0 1]>>> W.simple_reflection(Integer(3))[ 1 0 0][ 0 1 0][ 0 1 -1]

656

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

simple_root_index(i)Return the index of the simple root 𝛼𝑖 .
This is the position of 𝛼𝑖 in the list of all roots as given be roots().
EXAMPLES:
sage: W = CoxeterGroup([ A ,3], implementation= reflection )sage: [W.simple_root_index(i) for i in W.index_set()][0, 2, 5]>>> from sage.all import *>>> W = CoxeterGroup([ A ,Integer(3)], implementation= reflection )>>> [W.simple_root_index(i) for i in W.index_set()][0, 2, 5]28.12 Linear Groups
EXAMPLES:
sage: GL(4, QQ)
General Linear Group of degree 4 over Rational Field
sage: GL(1, ZZ)
General Linear Group of degree 1 over Integer Ringsage: GL(100, RR)
General Linear Group of degree 100 over Real Field with 53 bits of precision
sage: GL(3, GF(49, a ))˓→needs sage.rings.finite_rings
General Linear Group of degree 3 over Finite Field in a of size 7^2#␣

sage: SL(2, ZZ)
Special Linear Group of degree 2 over Integer Ringsage: G = SL(2, GF(3)); G
Special Linear Group of degree 2 over Finite Field of size 3
sage: # needs sage.libs.gap
sage: G.is_finite()True
sage: G.conjugacy_classes_representatives()([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0])sage: G = SL(6, GF(5))
sage: G.gens()([2 0 0 0 0 0] [4 0 0 0 0 1]
[0 3 0 0 0 0] [4 0 0 0 0 0]
[0 0 1 0 0 0] [0 4 0 0 0 0]
[0 0 0 1 0 0] [0 0 4 0 0 0]
[0 0 0 0 1 0] [0 0 0 4 0 0]
[0 0 0 0 0 1], [0 0 0 0 4 0])28.12. Linear Groups

657

Groups, Release 10.4>>> from sage.all import *>>> GL(Integer(4), QQ)
General Linear Group of degree 4 over Rational Field>>> GL(Integer(1), ZZ)
General Linear Group of degree 1 over Integer Ring>>> GL(Integer(100), RR)
General Linear Group of degree 100 over Real Field with 53 bits of precision>>> GL(Integer(3), GF(Integer(49), a ))˓→
# needs sage.rings.finite_rings
General Linear Group of degree 3 over Finite Field in a of size 7^2␣>>> SL(Integer(2), ZZ)
Special Linear Group of degree 2 over Integer Ring>>> G = SL(Integer(2), GF(Integer(3))); G
Special Linear Group of degree 2 over Finite Field of size 3>>> # needs sage.libs.gap>>> G.is_finite()
True>>> G.conjugacy_classes_representatives()([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0])>>> G = SL(Integer(6), GF(Integer(5)))>>> G.gens()([2 0 0 0 0 0] [4 0 0 0 0 1]
[0 3 0 0 0 0] [4 0 0 0 0 0]
[0 0 1 0 0 0] [0 4 0 0 0 0]
[0 0 0 1 0 0] [0 0 4 0 0 0]
[0 0 0 0 1 0] [0 0 0 4 0 0]
[0 0 0 0 0 1], [0 0 0 0 4 0])

AUTHORS:• William Stein: initial version• David Joyner: degree, base_ring, random, order methods; examples• David Joyner (2006-05): added center, more examples, renamed random attributes, bug fixes.
• William Stein (2006-12): total rewrite• Volker Braun (2013-1) port to new Parent, libGAP, extreme refactoring.
REFERENCES: See [KL1990] and [Car1972].
sage.groups.matrix_gps.linear.GL(n, R, var='a')Return the general linear group.
The general linear group 𝐺𝐿(𝑑, 𝑅) consists of all 𝑑 × 𝑑 matrices that are invertible over the ring 𝑅.
Note: This group is also available via groups.matrix.GL().
INPUT:• n – a positive integer.

658

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• R – ring or an integer. If an integer is specified, the corresponding finite field is used.
• var – variable used to represent generator of the finite field, if needed.
EXAMPLES:
sage: G = GL(6, GF(5))
sage: G.base_ring()
Finite Field of size 5
sage: G.category()
Category of finite groups
sage: # needs sage.libs.gap
sage: G.order()11064475422000000000000000
sage: TestSuite(G).run()sage: G = GL(6, QQ)
sage: G.category()
Category of infinite groups
sage: # needs sage.libs.gap
sage: TestSuite(G).run()>>> from sage.all import *>>> G = GL(Integer(6), GF(Integer(5)))>>> G.base_ring()
Finite Field of size 5>>> G.category()
Category of finite groups>>> # needs sage.libs.gap>>> G.order()11064475422000000000000000>>> TestSuite(G).run()>>> G = GL(Integer(6), QQ)>>> G.category()
Category of infinite groups>>> # needs sage.libs.gap>>> TestSuite(G).run()

Here is the Cayley graph of (relatively small) finite General Linear Group:sage: # needs sage.graphs sage.libs.gap
sage: g = GL(2,3)
sage: d = g.cayley_graph(); dDigraph on 48 vertices
sage: d.plot(color_by_label=True, vertex_size=0.03,
˓→needs sage.plot....:
vertex_labels=False)
Graphics object consisting of 144 graphics primitives
sage: d.plot3d(color_by_label=True)
˓→needs sage.plot
Graphics3d Object

28.12. Linear Groups# long time#␣# long time

#␣

659

Groups, Release 10.4>>> from sage.all import *>>> # needs sage.graphs sage.libs.gap>>> g = GL(Integer(2),Integer(3))>>> d = g.cayley_graph(); dDigraph on 48 vertices>>> d.plot(color_by_label=True, vertex_size=RealNumber( 0.03 ),˓→# needs sage.plot...
vertex_labels=False)
Graphics object consisting of 144 graphics primitives>>> d.plot3d(color_by_label=True)# long time
˓→needs sage.plot
Graphics3d Object# long time␣#␣

sage: # needs sage.libs.gap
sage: F = GF(3); MS = MatrixSpace(F, 2, 2)
sage: gens = [MS([[2,0], [0,1]]), MS([[2,1], [2,0]])]sage: G = MatrixGroup(gens)sage: G.order()48
sage: G.cardinality()
48
sage: H = GL(2,F)
sage: H.order()48
sage: H == G
True
sage: H.gens() == G.gens()True
sage: H.as_matrix_group() == H
True
sage: H.gens()([2 0] [2 1][0 1], [2 0])>>> from sage.all import *>>> # needs sage.libs.gap>>> F = GF(Integer(3)); MS = MatrixSpace(F, Integer(2), Integer(2))>>> gens = [MS([[Integer(2),Integer(0)], [Integer(0),Integer(1)]]),␣
˓→MS([[Integer(2),Integer(1)], [Integer(2),Integer(0)]])]>>> G = MatrixGroup(gens)>>> G.order()48>>> G.cardinality()48>>> H = GL(Integer(2),F)>>> H.order()48>>> H == G
True>>> H.gens() == G.gens()True>>> H.as_matrix_group() == H
True>>> H.gens()((continues on next page)

660

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[2 0] [2 1][0 1], [2 0])class sage.groups.matrix_gps.linear.LinearMatrixGroup_generic(degree, base_ring,
special, sage_name,latex_string,
category=None,invariant_form=None)
Bases: NamedMatrixGroup_genericcardinality()
Return the order of self.
EXAMPLES:
sage: G = SL(3, GF(5))
sage: G.order()372000>>> from sage.all import *>>> G = SL(Integer(3), GF(Integer(5)))>>> G.order()372000The order computation also works over the base rings /𝑛 :sage: GL(4, Integers(15)).order()2815842631680000000
sage: SL(4, Integers(15)).order()351980328960000000
sage: G = GL(2, Integers(6))
sage: G.order() == len(list(G))
Truesage: H = SL(2, Integers(6))
sage: H.order() == len(list(H))
True>>> from sage.all import *>>> GL(Integer(4), Integers(Integer(15))).order()2815842631680000000>>> SL(Integer(4), Integers(Integer(15))).order()351980328960000000>>> G = GL(Integer(2), Integers(Integer(6)))>>> G.order() == len(list(G))
True>>> H = SL(Integer(2), Integers(Integer(6)))>>> H.order() == len(list(H))
True

28.12. Linear Groups

661

Groups, Release 10.4

Arbitrary base rings are currently not fully supported:
sage: R.<x> = PolynomialRing(GF(7))
sage: S = R.quotient(x^2 + 5)
sage: GL(2, S).order()Traceback (most recent call last):...
NotImplementedError: order computation of linear groups not fully supported␣˓→for arbitrary base rings>>> from sage.all import *>>> R = PolynomialRing(GF(Integer(7)), names=( x ,)); (x,) = R._first_ngens(1)>>> S = R.quotient(x**Integer(2) + Integer(5))>>> GL(Integer(2), S).order()Traceback (most recent call last):...
NotImplementedError: order computation of linear groups not fully supported␣˓→for arbitrary base rings

order()
Return the order of self.
EXAMPLES:
sage: G = SL(3, GF(5))
sage: G.order()372000>>> from sage.all import *>>> G = SL(Integer(3), GF(Integer(5)))>>> G.order()372000The order computation also works over the base rings /𝑛 :sage: GL(4, Integers(15)).order()2815842631680000000
sage: SL(4, Integers(15)).order()351980328960000000
sage: G = GL(2, Integers(6))
sage: G.order() == len(list(G))
Truesage: H = SL(2, Integers(6))
sage: H.order() == len(list(H))
True>>> from sage.all import *>>> GL(Integer(4), Integers(Integer(15))).order()2815842631680000000>>> SL(Integer(4), Integers(Integer(15))).order()351980328960000000>>> G = GL(Integer(2), Integers(Integer(6)))(continues on next page)

662

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> G.order() == len(list(G))
True>>> H = SL(Integer(2), Integers(Integer(6)))>>> H.order() == len(list(H))
True

Arbitrary base rings are currently not fully supported:
sage: R.<x> = PolynomialRing(GF(7))
sage: S = R.quotient(x^2 + 5)
sage: GL(2, S).order()Traceback (most recent call last):...
NotImplementedError: order computation of linear groups not fully supported␣˓→for arbitrary base rings>>> from sage.all import *>>> R = PolynomialRing(GF(Integer(7)), names=( x ,)); (x,) = R._first_ngens(1)>>> S = R.quotient(x**Integer(2) + Integer(5))>>> GL(Integer(2), S).order()Traceback (most recent call last):...
NotImplementedError: order computation of linear groups not fully supported␣˓→for arbitrary base rings

sage.groups.matrix_gps.linear.SL(n, R, var='a')Return the special linear group.
The special linear group 𝑆𝐿(𝑑, 𝑅) consists of all 𝑑 × 𝑑 matrices that are invertible over the ring 𝑅 with determinantone.
Note: This group is also available via groups.matrix.SL().
INPUT:• n – positive integer• R – ring or integer; if an integer is specified, the corresponding finite field is used
• var – variable used to represent generator of the finite field, if needed
EXAMPLES:
sage: SL(3, GF(2))
Special Linear Group of degree 3 over Finite Field of size 2
sage: G = SL(15, GF(7)); G
Special Linear Group of degree 15 over Finite Field of size 7
sage: G.category()
Category of finite groups

sage: # needs sage.libs.gap
sage: G.order()195671259569814696201521906242958634112401800718204947891606736963871306673788236339351996634365
sage: len(G.gens())
2(continues on next page)

28.12. Linear Groups663

Groups, Release 10.4

(continued from previous page)

sage: G = SL(2, ZZ); G
Special Linear Group of degree 2 over Integer Ringsage: G.category()
Category of infinite groups
sage: G.gens()([ 0 1] [1 1][-1 0], [0 1])>>> from sage.all import *>>> SL(Integer(3), GF(Integer(2)))
Special Linear Group of degree 3 over Finite Field of size 2>>> G = SL(Integer(15), GF(Integer(7))); G
Special Linear Group of degree 15 over Finite Field of size 7>>> G.category()
Category of finite groups>>> # needs sage.libs.gap>>> G.order()195671259569814696201521906242958634112401800718204947891606736963871306673788236339351996634365>>> len(G.gens())
2>>> G = SL(Integer(2), ZZ); G
Special Linear Group of degree 2 over Integer Ring>>> G.category()
Category of infinite groups>>> G.gens()([ 0 1] [1 1][-1 0], [0 1])

Next we compute generators for SL3 ( )sage: G = SL(3, ZZ); G
Special Linear Group of degree 3 over Integer Ringsage: # needs sage.libs.gap
sage: G.gens()([0 1 0] [ 0 1 0] [1 1 0]
[0 0 1] [-1 0 0] [0 1 0]
[1 0 0], [ 0 0 1], [0 0 1])
sage: TestSuite(G).run()>>> from sage.all import *>>> G = SL(Integer(3), ZZ); G
Special Linear Group of degree 3 over Integer Ring>>> # needs sage.libs.gap>>> G.gens()((continues on next page)

664

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[0 1 0] [ 0 1 0] [1 1 0]
[0 0 1] [-1 0 0] [0 1 0]
[1 0 0], [ 0 0 1], [0 0 1])>>> TestSuite(G).run()

28.13 Linear Groups with GAPclass sage.groups.matrix_gps.linear_gap.LinearMatrixGroup_gap(degree, base_ring,
special, sage_name,latex_string,
gap_command_string,
category=None)
Bases: NamedMatrixGroup_gap, LinearMatrixGroup_generic, FinitelyGeneratedMatrixGroup_gap
The general or special linear group in GAP.

28.14 Orthogonal Linear Groups
The general orthogonal group 𝐺𝑂(𝑛, 𝑅) consists of all 𝑛 × 𝑛 matrices over the ring 𝑅 preserving an 𝑛-ary positive
definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs to be
specified to disambiguate. The special orthogonal group is the normal subgroup of matrices of determinant one.
In characteristics different from 2, a quadratic form is equivalent to a bilinear symmetric form. Furthermore, over the real
numbers a positive definite quadratic form is equivalent to the diagonal quadratic form, equivalent to the bilinear symmetricform defined by the identity matrix. Hence, the orthogonal group 𝐺𝑂(𝑛, R) is the group of orthogonal matrices in theusual sense.
In the case of a finite field and if the degree 𝑛 is even, then there are two inequivalent quadratic forms and a third parametere must be specified to disambiguate these two possibilities. The index of 𝑆𝑂(𝑒, 𝑑, 𝑞) in 𝐺𝑂(𝑒, 𝑑, 𝑞) is 2 if 𝑞 is odd, but𝑆𝑂(𝑒, 𝑑, 𝑞) = 𝐺𝑂(𝑒, 𝑑, 𝑞) if 𝑞 is even.)
Warning: GAP and Sage use different notations:• GAP notation: The optional e comes first, that is, GO([e,] d, q), SO([e,] d, q).
• Sage notation: The optional e comes last, the standard Python convention: GO(d, GF(q), e=0), SO(d,GF(q), e=0).
EXAMPLES:
sage: GO(3,7)
General Orthogonal Group of degree 3 over Finite Field of size 7
sage: G = SO(4, GF(7), 1); G
Special Orthogonal Group of degree 4 and form parameter 1
over Finite Field of size 7
sage: # needs sage.libs.gap(continues on next page)

28.13. Linear Groups with GAP

665

Groups, Release 10.4

(continued from previous page)

sage: G.random_element()[4 3 5 2][6 6 4 0][0 4 6 0][4 4 5 1]# random>>> from sage.all import *>>> GO(Integer(3),Integer(7))
General Orthogonal Group of degree 3 over Finite Field of size 7>>> G = SO(Integer(4), GF(Integer(7)), Integer(1)); G
Special Orthogonal Group of degree 4 and form parameter 1
over Finite Field of size 7>>> # needs sage.libs.gap>>> G.random_element()# random[4 3 5 2][6 6 4 0][0 4 6 0][4 4 5 1]

AUTHORS:• David Joyner (2006-03): initial version• David Joyner (2006-05): added examples, _latex_, __str__, gens, as_matrix_group• William Stein (2006-12-09): rewrite• Volker Braun (2013-1) port to new Parent, libGAP, extreme refactoring.
• Sebastian Oehms (2018-8) add invariant_form() (as alias), _OG, option for user defined invariant bilinear
form, and bug-fix in cmd-string for calling GAP (see Issue #26028)
sage.groups.matrix_gps.orthogonal.GO(n, R, e=0, var='a', invariant_form=None)
Return the general orthogonal group.
The general orthogonal group 𝐺𝑂(𝑛, 𝑅) consists of all 𝑛 × 𝑛 matrices over the ring 𝑅 preserving an 𝑛-ary positive
definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs
to be specified to disambiguate.
In the case of a finite field and if the degree 𝑛 is even, then there are two inequivalent quadratic forms and a thirdparameter e must be specified to disambiguate these two possibilities.
Note: This group is also available via groups.matrix.GO().
INPUT:• n – integer; the degree• R – ring or an integer; if an integer is specified, the corresponding finite field is used
• e – +1 or -1, and ignored by default; only relevant for finite fields and if the degree is even: a parameter that
distinguishes inequivalent invariant forms• var – (default: a ) variable used to represent generator of the finite field, if needed

666

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• invariant_form – (optional) instances being accepted by the matrix-constructor which define a 𝑛 × 𝑛square matrix over R describing the symmetric form to be kept invariant by the orthogonal group; the form
is checked to be non-degenerate and symmetric but not to be positive definite
OUTPUT: the general orthogonal group of given degree, base ring, and choice of invariant form
EXAMPLES:
sage: GO(3, GF(7))
General Orthogonal Group of degree 3 over Finite Field of size 7
sage: # needs sage.libs.gap
sage: GO(3, GF(7)).order()672
sage: GO(3, GF(7)).gens()([3 0 0] [0 1 0]
[0 5 0] [1 6 6]
[0 0 1], [0 2 1])>>> from sage.all import *>>> GO(Integer(3), GF(Integer(7)))
General Orthogonal Group of degree 3 over Finite Field of size 7>>> # needs sage.libs.gap>>> GO(Integer(3), GF(Integer(7))).order()672>>> GO(Integer(3), GF(Integer(7))).gens()([3 0 0] [0 1 0]
[0 5 0] [1 6 6]
[0 0 1], [0 2 1])

Using the invariant_form option:
sage: m = matrix(QQ, 3, 3, [[0, 1, 0], [1, 0, 0], [0, 0, 3]])sage: GO3 = GO(3, QQ)
sage: GO3m = GO(3, QQ, invariant_form=m)
sage: GO3 == GO3m
False
sage: GO3.invariant_form()[1 0 0][0 1 0][0 0 1]
sage: GO3m.invariant_form()[0 1 0][1 0 0][0 0 3]sage: pm = Permutation([2,3,1]).to_matrix()
sage: g = GO3(pm); g in GO3; g
True[0 0 1][1 0 0][0 1 0]sage: GO3m(pm)Traceback (most recent call last):(continues on next page)

28.14. Orthogonal Linear Groups

667

Groups, Release 10.4

(continued from previous page)...
TypeError: matrix must be orthogonal with respect to the symmetric form
[0 1 0][1 0 0][0 0 3]sage: GO(3,3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]])
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP
sage: 5 + 5
10
sage: R.<x> = ZZ[]
sage: GO(2, R, invariant_form=[[x,0], [0,1]])
General Orthogonal Group of degree 2 over
Univariate Polynomial Ring in x over Integer Ring with respect to symmetric form
[x 0]
[0 1]
>>> from sage.all import *>>> m = matrix(QQ, Integer(3), Integer(3), [[Integer(0), Integer(1), Integer(0)],␣
˓→[Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(0), Integer(3)]])>>> GO3 = GO(Integer(3), QQ)>>> GO3m = GO(Integer(3), QQ, invariant_form=m)>>> GO3 == GO3m
False>>> GO3.invariant_form()[1 0 0][0 1 0][0 0 1]>>> GO3m.invariant_form()[0 1 0][1 0 0][0 0 3]>>> pm = Permutation([Integer(2),Integer(3),Integer(1)]).to_matrix()>>> g = GO3(pm); g in GO3; g
True[0 0 1][1 0 0][0 1 0]>>> GO3m(pm)Traceback (most recent call last):...
TypeError: matrix must be orthogonal with respect to the symmetric form
[0 1 0][1 0 0][0 0 3]>>> GO(Integer(3),Integer(3), invariant_form=[[Integer(1),Integer(0),Integer(0)],␣
˓→[Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP>>> Integer(5) + Integer(5)10>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)(continues on next page)

668

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> GO(Integer(2), R, invariant_form=[[x,Integer(0)], [Integer(0),Integer(1)]])
General Orthogonal Group of degree 2 over
Univariate Polynomial Ring in x over Integer Ring with respect to symmetric form
[x 0]
[0 1]

class sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_generic(degree,
base_ring,
special,sage_name,latex_string,
category=None,invariant_form=None)
Bases: NamedMatrixGroup_generic
General Orthogonal Group over arbitrary rings.
EXAMPLES:
sage: G = GO(3, GF(7)); G
General Orthogonal Group of degree 3 over Finite Field of size 7
sage: latex(G)\text{GO}_{3}(\Bold{F}_{7})sage: G = SO(3, GF(5)); G
Special Orthogonal Group of degree 3 over Finite Field of size 5
sage: latex(G)\text{SO}_{3}(\Bold{F}_{5})sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3); e3 = CF3.gen()sage: m = matrix(CF3, 3,3, [[1,e3,0],[e3,2,0],[0,0,1]])
sage: G = SO(3, CF3, invariant_form=m)
sage: latex(G)\text{SO}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to non positive definite␣˓→symmetric form }\left(\begin{array}{rrr}1 & \zeta_{3} & 0 \\\zeta_{3} & 2 & 0 \\0 & 0 & 1\end{array}\right)>>> from sage.all import *>>> G = GO(Integer(3), GF(Integer(7))); G
General Orthogonal Group of degree 3 over Finite Field of size 7>>> latex(G)\text{GO}_{3}(\Bold{F}_{7})>>> G = SO(Integer(3), GF(Integer(5))); G
Special Orthogonal Group of degree 3 over Finite Field of size 5>>> latex(G)\text{SO}_{3}(\Bold{F}_{5})>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen()(continues on next page)

28.14. Orthogonal Linear Groups669

Groups, Release 10.4

(continued from previous page)>>> m = matrix(CF3, Integer(3),Integer(3), [[Integer(1),e3,Integer(0)],[e3,˓→Integer(2),Integer(0)],[Integer(0),Integer(0),Integer(1)]])>>> G = SO(Integer(3), CF3, invariant_form=m)>>> latex(G)\text{SO}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to non positive definite␣˓→symmetric form }\left(\begin{array}{rrr}1 & \zeta_{3} & 0 \\\zeta_{3} & 2 & 0 \\0 & 0 & 1\end{array}\right)

invariant_bilinear_form()
Return the symmetric bilinear form preserved by self.
OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.libs.gap
sage: GO(2,3,+1).invariant_bilinear_form()
[0 1]
[1 0]
sage: GO(2,3,-1).invariant_bilinear_form()
[2 1]
[1 1]
sage: G = GO(4, QQ)
sage: G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3))
sage: GO3m.invariant_bilinear_form()[1 0 0][0 2 0][0 0 3]>>> from sage.all import *>>> # needs sage.libs.gap>>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form()
[0 1]
[1 0]
>>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form()
[2 1]
[1 1]
>>> G = GO(Integer(4), QQ)>>> G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),˓→Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),˓→Integer(3)))>>> GO3m.invariant_bilinear_form()[1 0 0][0 2 0](continues on next page)

670

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[0 0 3]

invariant_form()
Return the symmetric bilinear form preserved by self.
OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.libs.gap
sage: GO(2,3,+1).invariant_bilinear_form()
[0 1]
[1 0]
sage: GO(2,3,-1).invariant_bilinear_form()
[2 1]
[1 1]
sage: G = GO(4, QQ)
sage: G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3))
sage: GO3m.invariant_bilinear_form()[1 0 0][0 2 0][0 0 3]>>> from sage.all import *>>> # needs sage.libs.gap>>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form()
[0 1]
[1 0]
>>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form()
[2 1]
[1 1]
>>> G = GO(Integer(4), QQ)>>> G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),˓→Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),˓→Integer(3)))>>> GO3m.invariant_bilinear_form()[1 0 0][0 2 0][0 0 3]

invariant_quadratic_form()
Return the symmetric bilinear form preserved by self.
OUTPUT: a matrix
EXAMPLES:

28.14. Orthogonal Linear Groups

671

Groups, Release 10.4

sage: # needs sage.libs.gap
sage: GO(2,3,+1).invariant_bilinear_form()
[0 1]
[1 0]
sage: GO(2,3,-1).invariant_bilinear_form()
[2 1]
[1 1]
sage: G = GO(4, QQ)
sage: G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: GO3m = GO(3, QQ, invariant_form=(1,0,0, 0,2,0, 0,0,3))
sage: GO3m.invariant_bilinear_form()[1 0 0][0 2 0][0 0 3]>>> from sage.all import *>>> # needs sage.libs.gap>>> GO(Integer(2),Integer(3),+Integer(1)).invariant_bilinear_form()
[0 1]
[1 0]
>>> GO(Integer(2),Integer(3),-Integer(1)).invariant_bilinear_form()
[2 1]
[1 1]
>>> G = GO(Integer(4), QQ)>>> G.invariant_bilinear_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> GO3m = GO(Integer(3), QQ, invariant_form=(Integer(1),Integer(0),˓→Integer(0), Integer(0),Integer(2),Integer(0), Integer(0),Integer(0),˓→Integer(3)))>>> GO3m.invariant_bilinear_form()[1 0 0][0 2 0][0 0 3]sage.groups.matrix_gps.orthogonal.SO(n, R, e=None, var='a', invariant_form=None)
Return the special orthogonal group.
The special orthogonal group 𝐺𝑂(𝑛, 𝑅) consists of all 𝑛 × 𝑛 matrices with determinant one over the ring 𝑅
preserving an 𝑛-ary positive definite quadratic form. In cases where there are multiple non-isomorphic quadratic
forms, additional data needs to be specified to disambiguate.
Note: This group is also available via groups.matrix.SO().
INPUT:• n – integer; the degree• R – ring or an integer; if an integer is specified, the corresponding finite field is used
• e – +1 or -1, and ignored by default; only relevant for finite fields and if the degree is even: a parameter that672

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

distinguishes inequivalent invariant forms• var – (default: a ) variable used to represent generator of the finite field, if needed• invariant_form – (optional) instances being accepted by the matrix-constructor which define a 𝑛 × 𝑛square matrix over R describing the symmetric form to be kept invariant by the orthogonal group; the form
is checked to be non-degenerate and symmetric but not to be positive definite
OUTPUT: the special orthogonal group of given degree, base ring, and choice of invariant form
EXAMPLES:
sage: G = SO(3,GF(5)); G
Special Orthogonal Group of degree 3 over Finite Field of size 5
sage: # needs sage.libs.gap
sage: G = SO(3,GF(5))
sage: G.gens()([2 0 0] [3 2 3] [1 4 4]
[0 3 0] [0 2 0] [4 0 0]
[0 0 1], [0 3 1], [2 0 4])
sage: G.as_matrix_group()
Matrix group over Finite Field of size 5 with 3 generators ([2 0 0] [3 2 3] [1 4 4]
[0 3 0] [0 2 0] [4 0 0]
[0 0 1], [0 3 1], [2 0 4])>>> from sage.all import *>>> G = SO(Integer(3),GF(Integer(5))); G
Special Orthogonal Group of degree 3 over Finite Field of size 5>>> # needs sage.libs.gap>>> G = SO(Integer(3),GF(Integer(5)))>>> G.gens()([2 0 0] [3 2 3] [1 4 4]
[0 3 0] [0 2 0] [4 0 0]
[0 0 1], [0 3 1], [2 0 4])>>> G.as_matrix_group()
Matrix group over Finite Field of size 5 with 3 generators ([2 0 0] [3 2 3] [1 4 4]
[0 3 0] [0 2 0] [4 0 0]
[0 0 1], [0 3 1], [2 0 4])

Using the invariant_form option:
sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3); e3 = CF3.gen()sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3,2,0], [0,0,1]])
sage: SO3 = SO(3, CF3)
sage: SO3m = SO(3, CF3, invariant_form=m)
sage: SO3 == SO3m
False
sage: SO3.invariant_form()(continues on next page)

28.14. Orthogonal Linear Groups673

Groups, Release 10.4

(continued from previous page)[1 0 0][0 1 0][0 0 1]
sage: SO3m.invariant_form()[
1 zeta30][zeta3
2
0]
[
0
0
1]
sage: pm = Permutation([2,3,1]).to_matrix()
sage: g = SO3(pm); g in SO3; g
True[0 0 1][1 0 0][0 1 0]sage: SO3m(pm)Traceback (most recent call last):...
TypeError: matrix must be orthogonal with respect to the symmetric form[
1 zeta30][zeta3
2
0]
[
0
0
1]
sage: SO(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]])Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP
sage: 5+5
10>>> from sage.all import *>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen()>>> m = matrix(CF3, Integer(3), Integer(3), [[Integer(1),e3,Integer(0)], [e3,˓→Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])>>> SO3 = SO(Integer(3), CF3)>>> SO3m = SO(Integer(3), CF3, invariant_form=m)>>> SO3 == SO3m
False>>> SO3.invariant_form()[1 0 0][0 1 0][0 0 1]>>> SO3m.invariant_form()[
1 zeta30][zeta3
2
0]
[
0
0
1]
>>> pm = Permutation([Integer(2),Integer(3),Integer(1)]).to_matrix()>>> g = SO3(pm); g in SO3; g
True[0 0 1][1 0 0][0 1 0]>>> SO3m(pm)Traceback (most recent call last):...
TypeError: matrix must be orthogonal with respect to the symmetric form[
1 zeta30](continues on next page)

674

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[zeta3
[
0

2
0

0]
1]

>>> SO(Integer(3), Integer(5), invariant_form=[[Integer(1),Integer(0),Integer(0)],˓→ [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(3)]])
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP>>> Integer(5)+Integer(5)10sage.groups.matrix_gps.orthogonal.normalize_args_e(degree, ring, e)Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields.
INPUT:• degree – integer; the degree of the affine group, that is, the dimension of the affine space the group is actingon• ring – a ring; the base ring of the affine space• e – integer, one of +1, 0, −1. Only relevant for finite fields and if the degree is even. A parameter that
distinguishes inequivalent invariant forms.
OUTPUT: the integer e with values required by GAP

28.15 Orthogonal Linear Groups with GAPclass sage.groups.matrix_gps.orthogonal_gap.OrthogonalMatrixGroup_gap(degree,
base_ring,
special,sage_name,latex_string,
gap_command_string,
category=None)
Bases: OrthogonalMatrixGroup_generic, NamedMatrixGroup_gap, FinitelyGeneratedMatrixGroup_gap
The general or special orthogonal group in GAP.
invariant_bilinear_form()
Return the symmetric bilinear form preserved by the orthogonal group.
OUTPUT:
A matrix 𝑀 such that, for every group element 𝑔, the identity 𝑔𝑚𝑔 𝑇 = 𝑚 holds. In characteristic different
from two, this uniquely determines the orthogonal group.
EXAMPLES:
sage: G = GO(4, GF(7), -1)
sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0](continues on next page)

28.15. Orthogonal Linear Groups with GAP

675

Groups, Release 10.4

(continued from previous page)[0 0 2 0][0 0 0 2]
sage: G = GO(4, GF(7), +1)
sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 6 0][0 0 0 2]
sage: G = SO(4, GF(7), -1)
sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]>>> from sage.all import *>>> G = GO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]>>> G = GO(Integer(4), GF(Integer(7)), +Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 6 0][0 0 0 2]>>> G = SO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]

invariant_form()
Return the symmetric bilinear form preserved by the orthogonal group.
OUTPUT:
A matrix 𝑀 such that, for every group element 𝑔, the identity 𝑔𝑚𝑔 𝑇 = 𝑚 holds. In characteristic different
from two, this uniquely determines the orthogonal group.
EXAMPLES:
sage: G = GO(4, GF(7), -1)
sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]
sage: G = GO(4, GF(7), +1)(continues on next page)

676

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 6 0][0 0 0 2]
sage: G = SO(4, GF(7), -1)
sage: G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]>>> from sage.all import *>>> G = GO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]>>> G = GO(Integer(4), GF(Integer(7)), +Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 6 0][0 0 0 2]>>> G = SO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_bilinear_form()[0 1 0 0][1 0 0 0][0 0 2 0][0 0 0 2]

invariant_quadratic_form()
Return the quadratic form preserved by the orthogonal group.
OUTPUT:
The matrix 𝑄 defining “orthogonal” as follows. The matrix determines a quadratic form 𝑞 on the naturalvector space 𝑉 , on which 𝐺 acts, by 𝑞(𝑣) = 𝑣𝑄𝑣 𝑡 . A matrix 𝑀 is an element of the orthogonal group if
𝑞(𝑣) = 𝑞(𝑣𝑀 ) for all 𝑣 ∈ 𝑉 .
EXAMPLES:
sage: G = GO(4, GF(7), -1)
sage: G.invariant_quadratic_form()[0 1 0 0][0 0 0 0][0 0 1 0][0 0 0 1]
sage: G = GO(4, GF(7), +1)
sage: G.invariant_quadratic_form()[0 1 0 0][0 0 0 0](continues on next page)

28.15. Orthogonal Linear Groups with GAP

677

Groups, Release 10.4

(continued from previous page)[0 0 3 0][0 0 0 1]
sage: G = GO(4, QQ)
sage: G.invariant_quadratic_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: G = SO(4, GF(7), -1)
sage: G.invariant_quadratic_form()[0 1 0 0][0 0 0 0][0 0 1 0][0 0 0 1]>>> from sage.all import *>>> G = GO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_quadratic_form()[0 1 0 0][0 0 0 0][0 0 1 0][0 0 0 1]>>> G = GO(Integer(4), GF(Integer(7)), +Integer(1))>>> G.invariant_quadratic_form()[0 1 0 0][0 0 0 0][0 0 3 0][0 0 0 1]>>> G = GO(Integer(4), QQ)>>> G.invariant_quadratic_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> G = SO(Integer(4), GF(Integer(7)), -Integer(1))>>> G.invariant_quadratic_form()[0 1 0 0][0 0 0 0][0 0 1 0][0 0 0 1]

678

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

28.16 Groups of isometries
Let 𝑀 = 𝑛 or 𝑛 , 𝑏 : 𝑀 × 𝑀 → a bilinear form and 𝑓 : 𝑀 → 𝑀 a linear map. We say that 𝑓 is an isometry if for
all elements 𝑥, 𝑦 of 𝑀 we have that 𝑏(𝑥, 𝑦) = 𝑏(𝑓 (𝑥), 𝑓 (𝑦)). A group of isometries is a subgroup of 𝐺𝐿(𝑀 ) consistingof isometries.
EXAMPLES:
sage: L = IntegralLattice("D4")
˓→needs sage.graphs
sage: O = L.orthogonal_group(); O˓→needs sage.graphs
Group of isometries with 3 generators ([0 0 0 1] [ 1 1 0 0] [ 1 0 0 0]
[0 1 0 0] [ 0 0 1 0] [-1 -1 -1 -1][0 0 1 0] [ 0 1 0 1] [ 0 0 1 0]
[1 0 0 0], [ 0 -1 -1 0], [ 0 0 0 1])>>> from sage.all import *>>> L = IntegralLattice("D4")
˓→needs sage.graphs>>> O = L.orthogonal_group(); O˓→needs sage.graphs
Group of isometries with 3 generators ([0 0 0 1] [ 1 1 0 0] [ 1 0 0 0]
[0 1 0 0] [ 0 0 1 0] [-1 -1 -1 -1][0 0 1 0] [ 0 1 0 1] [ 0 0 1 0]
[1 0 0 0], [ 0 -1 -1 0], [ 0 0 0 1]
)

#␣
#␣

#␣
#␣

Basic functionality is provided by GAP:
sage: O.cardinality()
˓→needs sage.graphs1152
sage: len(O.conjugacy_classes_representatives())
˓→needs sage.graphs
25>>> from sage.all import *>>> O.cardinality()
˓→needs sage.graphs
1152>>> len(O.conjugacy_classes_representatives())
˓→needs sage.graphs
25

#␣

#␣

#␣

#␣

AUTHORS:• Simon Brandhorst (2018-02): First createdclass sage.groups.matrix_gps.isometries.GroupActionOnQuotientModule(MatrixGroup,
quotient_module,
is_left=False)
Bases: Action
28.16. Groups of isometries

679

Groups, Release 10.4

Matrix group action on a quotient module from the right.
INPUT:• MatrixGroup – the group acting GroupOfIsometries• submodule – an invariant quotient module• is_left – boolean (default: False)
EXAMPLES:
sage: from sage.groups.matrix_gps.isometries import GroupOfIsometries
sage: S = span(ZZ,[[0,1]])
sage: Q = S/(6*S)
sage: g = Matrix(QQ,2,[1,0,0,-1])
sage: G = GroupOfIsometries(2, ZZ, [g], invariant_bilinear_form=matrix.
˓→identity(2), invariant_quotient_module=Q)
sage: g = G.an_element()
sage: x = Q.an_element()
sage: x*g
(5)
sage: (x*g).parent()
Finitely generated module V/W over Integer Ring with invariants (6)>>> from sage.all import *>>> from sage.groups.matrix_gps.isometries import GroupOfIsometries>>> S = span(ZZ,[[Integer(0),Integer(1)]])>>> Q = S/(Integer(6)*S)>>> g = Matrix(QQ,Integer(2),[Integer(1),Integer(0),Integer(0),-Integer(1)])>>> G = GroupOfIsometries(Integer(2), ZZ, [g], invariant_bilinear_form=matrix.
˓→identity(Integer(2)), invariant_quotient_module=Q)>>> g = G.an_element()>>> x = Q.an_element()>>> x*g(5)>>> (x*g).parent()
Finitely generated module V/W over Integer Ring with invariants (6)class sage.groups.matrix_gps.isometries.GroupActionOnSubmodule(MatrixGroup,
submodule,
is_left=False)
Bases: Action
Matrix group action on a submodule from the right.
INPUT:• MatrixGroup – an instance of GroupOfIsometries• submodule – an invariant submodule• is_left – bool (default: False)
EXAMPLES:
sage: from sage.groups.matrix_gps.isometries import GroupOfIsometries
sage: S = span(ZZ, [[0,1]])
sage: g = Matrix(QQ, 2, [1,0,0,-1])
sage: G = GroupOfIsometries(2, ZZ, [g],....:invariant_bilinear_form=matrix.identity(2),(continues on next page)

680

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)....:
invariant_submodule=S)
sage: g = G.an_element()
sage: x = S.an_element()
sage: x*g(0, -1)
sage: (x*g).parent()
Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1]>>> from sage.all import *>>> from sage.groups.matrix_gps.isometries import GroupOfIsometries>>> S = span(ZZ, [[Integer(0),Integer(1)]])>>> g = Matrix(QQ, Integer(2), [Integer(1),Integer(0),Integer(0),-Integer(1)])>>> G = GroupOfIsometries(Integer(2), ZZ, [g],...
invariant_bilinear_form=matrix.identity(Integer(2)),...
invariant_submodule=S)>>> g = G.an_element()>>> x = S.an_element()>>> x*g(0, -1)>>> (x*g).parent()
Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1]

class sage.groups.matrix_gps.isometries.GroupOfIsometries(degree, base_ring, gens,invariant_bilinear_form,
category=None, check=True,
invariant_submodule=None,invariant_quotient_module=None)
Bases: FinitelyGeneratedMatrixGroup_gap
A base class for Orthogonal matrix groups with a gap backend.
Main difference to OrthogonalMatrixGroup_gap is that we can specify generators and a bilinear form.
Following GAP, the group action is from the right.
INPUT:• degree – integer, the degree (matrix size) of the matrix• base_ring – ring, the base ring of the matrices• gens – a list of matrices over the base ring• invariant_bilinear_form – a symmetric matrix• category – (default: None) a category of groups• check – bool (default: True) check if the generators preserve the bilinear form
• invariant_submodule – a submodule preserved by the group action (default: None) registers an action
on this submodule• invariant_quotient_module – a quotient module preserved by the group action (default: None)
registers an action on this quotient module
EXAMPLES:

28.16. Groups of isometries

681

Groups, Release 10.4

sage: from sage.groups.matrix_gps.isometries import GroupOfIsometries
sage: bil = Matrix(ZZ, 2, [3,2,2,3])
sage: gens = [-Matrix(ZZ, 2, [0,1,1,0])]
sage: O = GroupOfIsometries(2, ZZ, gens, bil)sage: OGroup of isometries with 1 generator ([ 0 -1][-1 0])
sage: O.order()2>>> from sage.all import *>>> from sage.groups.matrix_gps.isometries import GroupOfIsometries>>> bil = Matrix(ZZ, Integer(2), [Integer(3),Integer(2),Integer(2),Integer(3)])>>> gens = [-Matrix(ZZ, Integer(2), [Integer(0),Integer(1),Integer(1),˓→Integer(0)])]>>> O = GroupOfIsometries(Integer(2), ZZ, gens, bil)>>> O
Group of isometries with 1 generator ([ 0 -1][-1 0])>>> O.order()2Infinite groups are O.K. too:sage: bil = Matrix(ZZ,4,[0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0])
sage: f = Matrix(ZZ,4,[0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1, 1, 1, 1])
sage: O = GroupOfIsometries(2, ZZ, [f], bil)sage: O.cardinality()+Infinity>>> from sage.all import *>>> bil = Matrix(ZZ,Integer(4),[Integer(0), Integer(1), Integer(1), Integer(1),␣
˓→Integer(1), Integer(0), Integer(1), Integer(1), Integer(1), Integer(1),␣
˓→Integer(0), Integer(1), Integer(1), Integer(1), Integer(1), Integer(0)])>>> f = Matrix(ZZ,Integer(4),[Integer(0), Integer(1), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(1), -Integer(1), Integer(1), Integer(1), Integer(1)])>>> O = GroupOfIsometries(Integer(2), ZZ, [f], bil)>>> O.cardinality()+Infinity

invariant_bilinear_form()
Return the symmetric bilinear form preserved by the orthogonal group.
OUTPUT: the matrix defining the bilinear form
EXAMPLES:
sage: from sage.groups.matrix_gps.isometries import GroupOfIsometries
sage: bil = Matrix(ZZ,2,[3,2,2,3])
sage: gens = [-Matrix(ZZ,2,[0,1,1,0])]
sage: O = GroupOfIsometries(2,ZZ,gens,bil)
sage: O.invariant_bilinear_form()(continues on next page)682

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

[3 2]
[2 3]
>>> from sage.all import *>>> from sage.groups.matrix_gps.isometries import GroupOfIsometries>>> bil = Matrix(ZZ,Integer(2),[Integer(3),Integer(2),Integer(2),Integer(3)])>>> gens = [-Matrix(ZZ,Integer(2),[Integer(0),Integer(1),Integer(1),˓→Integer(0)])]>>> O = GroupOfIsometries(Integer(2),ZZ,gens,bil)>>> O.invariant_bilinear_form()
[3 2]
[2 3]

28.17 Symplectic Linear Groups
EXAMPLES:
sage: G = Sp(4, GF(7)); G
Symplectic Group of degree 4 over Finite Field of size 7
sage: # needs sage.libs.gap
sage: g = prod(G.gens()); g[3 0 3 0][1 0 0 0][0 1 0 1][0 2 0 0]
sage: m = g.matrix()
sage: m * G.invariant_form() * m.transpose() == G.invariant_form()True
sage: G.order()276595200>>> from sage.all import *>>> G = Sp(Integer(4), GF(Integer(7))); G
Symplectic Group of degree 4 over Finite Field of size 7>>> # needs sage.libs.gap>>> g = prod(G.gens()); g[3 0 3 0][1 0 0 0][0 1 0 1][0 2 0 0]>>> m = g.matrix()>>> m * G.invariant_form() * m.transpose() == G.invariant_form()
True>>> G.order()276595200

AUTHORS:• David Joyner (2006-03): initial version, modified from special_linear (by W. Stein)• Volker Braun (2013-1) port to new Parent, libGAP, extreme refactoring.

28.17. Symplectic Linear Groups683

Groups, Release 10.4

• Sebastian Oehms (2018-8) add option for user defined invariant bilinear form and bug-fix in invariant_form() (see Issue #26028)
sage.groups.matrix_gps.symplectic.Sp(n, R, var='a', invariant_form=None)
Return the symplectic group.
The special linear group 𝐺𝐿(𝑑, 𝑅) consists of all 𝑑×𝑑 matrices that are invertible over the ring 𝑅 with determinantone.
Note: This group is also available via groups.matrix.Sp().
INPUT:• n – a positive integer• R – ring or an integer; if an integer is specified, the corresponding finite field is used
• var – (default: a ) variable used to represent generator of the finite field, if needed• invariant_form – (optional) instances being accepted by the matrix-constructor which define a 𝑛 × 𝑛square matrix over R describing the alternating form to be kept invariant by the symplectic group
EXAMPLES:
sage: Sp(4, 5)
Symplectic Group of degree 4 over Finite Field of size 5
sage: Sp(4, IntegerModRing(15))
Symplectic Group of degree 4 over Ring of integers modulo 15
sage: Sp(3, GF(7))
Traceback (most recent call last):...
ValueError: the degree must be even>>> from sage.all import *>>> Sp(Integer(4), Integer(5))
Symplectic Group of degree 4 over Finite Field of size 5>>> Sp(Integer(4), IntegerModRing(Integer(15)))
Symplectic Group of degree 4 over Ring of integers modulo 15>>> Sp(Integer(3), GF(Integer(7)))
Traceback (most recent call last):...
ValueError: the degree must be even

Using the invariant_form option:
sage: m = matrix(QQ, 4,4, [[0, 0, 1, 0], [0, 0, 0, 2], [-1, 0, 0, 0], [0, -2, 0,␣
˓→0]])
sage: Sp4m = Sp(4, QQ, invariant_form=m)
sage: Sp4 = Sp(4, QQ)
sage: Sp4 == Sp4m
False
sage: Sp4.invariant_form()[ 0 0 0 1]
[ 0 0 1 0]
(continues on next page)

684

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[ 0 -1 0 0][-1 0 0 0]
sage: Sp4m.invariant_form()[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]
sage: pm = Permutation([2,1,4,3]).to_matrix()
sage: g = Sp4(pm); g in Sp4; g
True[0 1 0 0][1 0 0 0][0 0 0 1][0 0 1 0]
sage: Sp4m(pm)Traceback (most recent call last):...
TypeError: matrix must be symplectic with respect to the alternating form
[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]
sage: Sp(4,3, invariant_form=[[0,0,0,1],[0,0,1,0],[0,2,0,0], [2,0,0,0]])Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP>>> from sage.all import *>>> m = matrix(QQ, Integer(4),Integer(4), [[Integer(0), Integer(0), Integer(1),␣
˓→Integer(0)], [Integer(0), Integer(0), Integer(0), Integer(2)], [-Integer(1),␣
˓→Integer(0), Integer(0), Integer(0)], [Integer(0), -Integer(2), Integer(0),␣
˓→Integer(0)]])>>> Sp4m = Sp(Integer(4), QQ, invariant_form=m)>>> Sp4 = Sp(Integer(4), QQ)>>> Sp4 == Sp4m
False>>> Sp4.invariant_form()[ 0 0 0 1]
[ 0 0 1 0]
[ 0 -1 0 0][-1 0 0 0]>>> Sp4m.invariant_form()[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]>>> pm = Permutation([Integer(2),Integer(1),Integer(4),Integer(3)]).to_matrix()>>> g = Sp4(pm); g in Sp4; g
True[0 1 0 0][1 0 0 0][0 0 0 1][0 0 1 0]>>> Sp4m(pm)Traceback (most recent call last):(continues on next page)

28.17. Symplectic Linear Groups

685

Groups, Release 10.4

(continued from previous page)...
TypeError: matrix must be symplectic with respect to the alternating form
[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]>>> Sp(Integer(4),Integer(3), invariant_form=[[Integer(0),Integer(0),Integer(0),˓→Integer(1)],[Integer(0),Integer(0),Integer(1),Integer(0)],[Integer(0),˓→Integer(2),Integer(0),Integer(0)], [Integer(2),Integer(0),Integer(0),˓→Integer(0)]])Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAPclass sage.groups.matrix_gps.symplectic.SymplecticMatrixGroup_generic(degree,
base_ring,
special,sage_name,latex_string,
category=None,invariant_form=None)
Bases: NamedMatrixGroup_generic
Symplectic Group over arbitrary rings.
EXAMPLES:
sage: Sp43 = Sp(4,3); Sp43
Symplectic Group of degree 4 over Finite Field of size 3
sage: latex(Sp43)\text{Sp}_{4}(\Bold{F}_{3})sage: Sp4m = Sp(4, QQ, invariant_form=(0, 0, 1, 0, 0, 0, 0, 2,....:-1, 0, 0, 0, 0, -2, 0, 0)); Sp4m
Symplectic Group of degree 4 over Rational Field
with respect to alternating bilinear form
[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]
sage: latex(Sp4m)\text{Sp}_{4}(\Bold{Q})\text{ with respect to alternating bilinear form}\left(\˓→begin{array}{rrrr}
0 & 0 & 1 & 0 \\0 & 0 & 0 & 2 \\-1 & 0 & 0 & 0 \\0 & -2 & 0 & 0\end{array}\right)>>> from sage.all import *>>> Sp43 = Sp(Integer(4),Integer(3)); Sp43
Symplectic Group of degree 4 over Finite Field of size 3>>> latex(Sp43)(continues on next page)

686

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)\text{Sp}_{4}(\Bold{F}_{3})>>> Sp4m = Sp(Integer(4), QQ, invariant_form=(Integer(0), Integer(0), Integer(1),␣
˓→Integer(0),Integer(0), Integer(0), Integer(0), Integer(2),...
-Integer(1), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), -Integer(2), Integer(0), Integer(0))); Sp4m
Symplectic Group of degree 4 over Rational Field
with respect to alternating bilinear form
[ 0 0 1 0]
[ 0 0 0 2][-1 0 0 0]
[ 0 -2 0 0]>>> latex(Sp4m)\text{Sp}_{4}(\Bold{Q})\text{ with respect to alternating bilinear form}\left(\˓→begin{array}{rrrr}
0 & 0 & 1 & 0 \\0 & 0 & 0 & 2 \\-1 & 0 & 0 & 0 \\0 & -2 & 0 & 0\end{array}\right)

invariant_form()
Return the quadratic form preserved by the symplectic group.
OUTPUT: a matrix
EXAMPLES:
sage: Sp(4, QQ).invariant_form()[ 0 0 0 1]
[ 0 0 1 0]
[ 0 -1 0 0][-1 0 0 0]>>> from sage.all import *>>> Sp(Integer(4), QQ).invariant_form()[ 0 0 0 1]
[ 0 0 1 0]
[ 0 -1 0 0][-1 0 0 0]28.18 Symplectic Linear Groups with GAPclass sage.groups.matrix_gps.symplectic_gap.SymplecticMatrixGroup_gap(degree,
base_ring,
special,sage_name,latex_string,
gap_command_string,
category=None)
Bases: SymplecticMatrixGroup_generic, NamedMatrixGroup_gap, FinitelyGeneratedMatrixGroup_gap
28.18. Symplectic Linear Groups with GAP

687

Groups, Release 10.4

Symplectic group in GAP.
EXAMPLES:
sage: Sp(2,4)˓→needs sage.rings.finite_rings
Symplectic Group of degree 2 over Finite Field in a of size 2^2#␣

sage: latex(Sp(4,5))\text{Sp}_{4}(\Bold{F}_{5})>>> from sage.all import *>>> Sp(Integer(2),Integer(4))˓→# needs sage.rings.finite_rings
Symplectic Group of degree 2 over Finite Field in a of size 2^2␣>>> latex(Sp(Integer(4),Integer(5)))\text{Sp}_{4}(\Bold{F}_{5})invariant_form()
Return the quadratic form preserved by the symplectic group.
OUTPUT: a matrix
EXAMPLES:
sage: Sp(4, GF(3)).invariant_form()[0 0 0 1][0 0 1 0][0 2 0 0][2 0 0 0]>>> from sage.all import *>>> Sp(Integer(4), GF(Integer(3))).invariant_form()[0 0 0 1][0 0 1 0][0 2 0 0][2 0 0 0]28.19 Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞)
These are 𝑛 × 𝑛 unitary matrices with entries in 𝐺𝐹 (𝑞 2 ).
EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: G = SU(3,5)
sage: G.order()˓→needs sage.libs.gap
378000sage: G
Special Unitary Group of degree 3 over Finite Field in a of size 5^2sage: G.gens()
˓→needs sage.libs.gap
(

#␣

#␣

(continues on next page)

688

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[a00] [4*a[
0 2*a + 2
0] [ 4[003*a], [ 1)sage: G.base_ring()
Finite Field in a of size 5^2

4
4
0

1]
0]
0]

>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> G = SU(Integer(3),Integer(5))>>> G.order()˓→needs sage.libs.gap
378000>>> G
Special Unitary Group of degree 3 over Finite Field in a of size 5^2>>> G.gens()
˓→needs sage.libs.gap([a00] [4*a4
1][0 2*a + 2
0] [ 440][003*a], [ 100])>>> G.base_ring()
Finite Field in a of size 5^2#␣#␣

AUTHORS:• David Joyner (2006-03): initial version, modified from special_linear (by W. Stein)• David Joyner (2006-05): minor additions (examples, _latex_, __str__, gens)• William Stein (2006-12): rewrite• Volker Braun (2013-1) port to new Parent, libGAP, extreme refactoring.
• Sebastian Oehms (2018-8) add _UG, invariant_form(), option for user defined invariant bilinear form, andbug-fix in _check_matrix (see Issue #26028)
sage.groups.matrix_gps.unitary.GU(n, R, var='a', invariant_form=None)
Return the general unitary group.
The general unitary group 𝐺𝑈 (𝑑, 𝑅) consists of all 𝑑 × 𝑑 matrices that preserve a nondegenerate sesquilinear form
over the ring 𝑅.
Note: For a finite field, the matrices that preserve a sesquilinear form over F𝑞 live over F𝑞2 . So GU(n,q) for aprime power 𝑞 constructs the matrix group over the base ring GF(q^2).

Note: This group is also available via groups.matrix.GU().
INPUT:• n – a positive integer• R – ring or an integer; if an integer is specified, the corresponding finite field is used
• var – (default: a ) variable used to represent generator of the finite field, if needed

28.19. Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞)

689

Groups, Release 10.4

• invariant_form – (optional) instances being accepted by the matrix-constructor which define a 𝑛 × 𝑛square matrix over 𝑅 describing the hermitian form to be kept invariant by the unitary group; the form ischecked to be non-degenerate and hermitian but not to be positive definite
OUTPUT: the general unitary group
EXAMPLES:
sage: G = GU(3, 7); G˓→needs sage.rings.finite_rings
General Unitary Group of degree 3 over Finite Field in a of size 7^2sage: G.gens()
˓→needs sage.libs.gap sage.rings.finite_rings([ a00] [6*a61][ 0
10] [ 6
60][ 0
0 5*a], [ 100])sage: GU(2, QQ)
General Unitary Group of degree 2 over Rational Field#␣

sage: G = GU(3, 5, var= beta )˓→needs sage.rings.finite_rings
sage: G.base_ring()
˓→needs sage.rings.finite_rings
Finite Field in beta of size 5^2sage: G.gens()
˓→needs sage.libs.gap sage.rings.finite_rings([ beta00] [4*beta
4
1]
[
0
1
0] [
4
4
0]
[
0
0 3*beta], [
1
0
0]
)

#␣
#␣

#␣

>>> from sage.all import *>>> G = GU(Integer(3), Integer(7)); G˓→# needs sage.rings.finite_rings
General Unitary Group of degree 3 over Finite Field in a of size 7^2>>> G.gens()
˓→needs sage.libs.gap sage.rings.finite_rings([ a00] [6*a61][ 0
10] [ 6
60][ 0
0 5*a], [ 100])>>> GU(Integer(2), QQ)
General Unitary Group of degree 2 over Rational Field>>> G = GU(Integer(3), Integer(5), var= beta )˓→# needs sage.rings.finite_rings>>> G.base_ring()
˓→needs sage.rings.finite_rings
Finite Field in beta of size 5^2>>> G.gens()
˓→needs sage.libs.gap sage.rings.finite_rings([ beta00] [4*beta
4
1]
[
0
1
0] [
4
4
0]

#␣

␣

#␣

␣
#␣

#␣

(continues on next page)

690

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[)

00 3*beta], [

1

0

0]

Using the invariant_form option:
sage: # needs sage.libs.gap sage.rings.number_fieldsage: UCF = UniversalCyclotomicField(); e5 = UCF.gen(5)sage: m = matrix(UCF, 3, 3, [[1,e5,0], [e5.conjugate(),2,0], [0,0,1]])
sage: G = GU(3, UCF)
sage: Gm = GU(3, UCF, invariant_form=m)
sage: G == Gm
False
sage: G.invariant_form()[1 0 0][0 1 0][0 0 1]
sage: Gm.invariant_form()
[
1
E(5)
0]
[E(5)^4
2
0]
[
0
0
1]
sage: pm = Permutation((1,2,3)).to_matrix()
sage: g = G(pm); g in G; g
˓→needs sage.combinat
True[0 0 1][1 0 0][0 1 0]sage: Gm(pm)˓→needs sage.combinat
Traceback (most recent call last):...
TypeError: matrix must be unitary with respect to the hermitian form
[
1
E(5)
0]
[E(5)^4
2
0]
[
0
0
1]
sage: GU(3, 3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]])
˓→needs sage.libs.pari
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP

#␣

#␣

#␣

sage: GU(2, QQ, invariant_form=[[1,0], [2,0]])Traceback (most recent call last):...
ValueError: invariant_form must be non-degenerate>>> from sage.all import *>>> # needs sage.libs.gap sage.rings.number_field>>> UCF = UniversalCyclotomicField(); e5 = UCF.gen(Integer(5))>>> m = matrix(UCF, Integer(3), Integer(3), [[Integer(1),e5,Integer(0)], [e5.
˓→conjugate(),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])>>> G = GU(Integer(3), UCF)>>> Gm = GU(Integer(3), UCF, invariant_form=m)>>> G == Gm
False(continues on next page)

28.19. Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞)

691

Groups, Release 10.4

(continued from previous page)>>> G.invariant_form()[1 0 0][0 1 0][0 0 1]>>> Gm.invariant_form()
[
1
E(5)
0]
[E(5)^4
2
0]
[
0
0
1]
>>> pm = Permutation((Integer(1),Integer(2),Integer(3))).to_matrix()>>> g = G(pm); g in G; g
˓→needs sage.combinat
True[0 0 1][1 0 0][0 1 0]>>> Gm(pm)˓→needs sage.combinat
Traceback (most recent call last):...
TypeError: matrix must be unitary with respect to the hermitian form
[
1
E(5)
0]
[E(5)^4
2
0]
[
0
0
1]

#␣

#␣

>>> GU(Integer(3), Integer(3), invariant_form=[[Integer(1),Integer(0),Integer(0)],˓→ [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])␣˓→# needs sage.libs.pari
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP>>> GU(Integer(2), QQ, invariant_form=[[Integer(1),Integer(0)], [Integer(2),˓→Integer(0)]])Traceback (most recent call last):...
ValueError: invariant_form must be non-degenerate

sage.groups.matrix_gps.unitary.SU(n, R, var='a', invariant_form=None)
The special unitary group 𝑆𝑈 (𝑑, 𝑅) consists of all 𝑑 × 𝑑 matrices that preserve a nondegenerate sesquilinear form
over the ring 𝑅 and have determinant 1.
Note: For a finite field the matrices that preserve a sesquilinear form over F𝑞 live over F𝑞2 . So SU(n,q) for aprime power 𝑞 constructs the matrix group over the base ring GF(q^2).

Note: This group is also available via groups.matrix.SU().
INPUT:• n – a positive integer• R – ring or an integer; if an integer is specified, the corresponding finite field is used
• var – (default: a ) variable used to represent generator of the finite field, if needed• invariant_form – (optional) instances being accepted by the matrix-constructor which define a 𝑛 × 𝑛
692

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

square matrix over R describing the hermitian form to be kept invariant by the unitary group; the form ischecked to be non-degenerate and hermitian but not to be positive definite
OUTPUT: the special unitary group
EXAMPLES:
sage: SU(3,5)˓→needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2sage: SU(3, GF(5))˓→needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2sage: SU(3, QQ)
Special Unitary Group of degree 3 over Rational Field#␣#␣>>> from sage.all import *>>> SU(Integer(3),Integer(5))˓→# needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2>>> SU(Integer(3), GF(Integer(5)))˓→# needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2>>> SU(Integer(3), QQ)
Special Unitary Group of degree 3 over Rational Field␣␣

Using the invariant_form option:
sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3); e3 = CF3.gen()sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]])
sage: G = SU(3, CF3)
sage: Gm = SU(3, CF3, invariant_form=m)
sage: G == Gm
False
sage: G.invariant_form()[1 0 0][0 1 0][0 0 1]
sage: Gm.invariant_form()
[
1
zeta3
0]
[-zeta3 - 1
2
0]
[
0
0
1]
sage: pm = Permutation((1,2,3)).to_matrix()
sage: G(pm)˓→needs sage.combinat[0 0 1][1 0 0][0 1 0]sage: Gm(pm)˓→needs sage.combinat
Traceback (most recent call last):...
TypeError: matrix must be unitary with respect to the hermitian form
[
1
zeta3
0]
[-zeta3 - 1
2
0]
[
0
0
1]

#␣

#␣

(continues on next page)

28.19. Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞)693

Groups, Release 10.4

(continued from previous page)

sage: SU(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]])
˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAP#␣>>> from sage.all import *>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen()>>> m = matrix(CF3, Integer(3), Integer(3), [[Integer(1),e3,Integer(0)], [e3.
˓→conjugate(),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])>>> G = SU(Integer(3), CF3)>>> Gm = SU(Integer(3), CF3, invariant_form=m)>>> G == Gm
False>>> G.invariant_form()[1 0 0][0 1 0][0 0 1]>>> Gm.invariant_form()
[
1
zeta3
0]
[-zeta3 - 1
2
0]
[
0
0
1]
>>> pm = Permutation((Integer(1),Integer(2),Integer(3))).to_matrix()>>> G(pm)#␣˓→needs sage.combinat[0 0 1][1 0 0][0 1 0]>>> Gm(pm)#␣˓→needs sage.combinat
Traceback (most recent call last):...
TypeError: matrix must be unitary with respect to the hermitian form
[
1
zeta3
0]
[-zeta3 - 1
2
0]
[
0
0
1]
>>> SU(Integer(3), Integer(5), invariant_form=[[Integer(1),Integer(0),Integer(0)],˓→ [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(3)]])␣˓→# needs sage.rings.finite_rings
Traceback (most recent call last):...
NotImplementedError: invariant_form for finite groups is fixed by GAPclass sage.groups.matrix_gps.unitary.UnitaryMatrixGroup_generic(degree, base_ring,
special, sage_name,latex_string,
category=None, invariant_form=None)
Bases: NamedMatrixGroup_generic
General Unitary Group over arbitrary rings.
EXAMPLES:

694

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

sage: G = GU(3, GF(7)); G˓→needs sage.rings.finite_rings
General Unitary Group of degree 3 over Finite Field in a of size 7^2sage: latex(G)˓→needs sage.rings.finite_rings\text{GU}_{3}(\Bold{F}_{7^{2}})#␣sage: G = SU(3, GF(5)); G˓→needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2sage: latex(G)˓→needs sage.rings.finite_rings\text{SU}_{3}(\Bold{F}_{5^{2}})

#␣

#␣

#␣

sage: # needs sage.rings.number_fieldsage: CF3 = CyclotomicField(3); e3 = CF3.gen()sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]])
sage: G = SU(3, CF3, invariant_form=m)
sage: latex(G)\text{SU}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to positive definite␣˓→hermitian form }\left(\begin{array}{rrr}1 & \zeta_{3} & 0 \\-\zeta_{3} - 1 & 2 & 0 \\0 & 0 & 1\end{array}\right)>>> from sage.all import *>>> G = GU(Integer(3), GF(Integer(7))); G˓→# needs sage.rings.finite_rings
General Unitary Group of degree 3 over Finite Field in a of size 7^2>>> latex(G)˓→needs sage.rings.finite_rings\text{GU}_{3}(\Bold{F}_{7^{2}})>>> G = SU(Integer(3), GF(Integer(5))); G˓→# needs sage.rings.finite_rings
Special Unitary Group of degree 3 over Finite Field in a of size 5^2>>> latex(G)˓→needs sage.rings.finite_rings\text{SU}_{3}(\Bold{F}_{5^{2}})

␣

#␣

␣

#␣

>>> # needs sage.rings.number_field>>> CF3 = CyclotomicField(Integer(3)); e3 = CF3.gen()>>> m = matrix(CF3, Integer(3), Integer(3), [[Integer(1),e3,Integer(0)], [e3.
˓→conjugate(),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(1)]])>>> G = SU(Integer(3), CF3, invariant_form=m)>>> latex(G)\text{SU}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to positive definite␣˓→hermitian form }\left(\begin{array}{rrr}1 & \zeta_{3} & 0 \\-\zeta_{3} - 1 & 2 & 0 \\0 & 0 & 1\end{array}\right)

invariant_form()
Return the hermitian form preserved by the unitary group.
OUTPUT: a square matrix describing the bilinear form
28.19. Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞)695

Groups, Release 10.4

EXAMPLES:
sage: SU4 = SU(4, QQ)
sage: SU4.invariant_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> from sage.all import *>>> SU4 = SU(Integer(4), QQ)>>> SU4.invariant_form()[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]

sage.groups.matrix_gps.unitary.finite_field_sqrt(ring)
Helper function.
OUTPUT: integer 𝑞 such that ring is the finite field with 𝑞 2 elements
EXAMPLES:
sage: from sage.groups.matrix_gps.unitary import finite_field_sqrt
sage: finite_field_sqrt(GF(4, a ))˓→needs sage.rings.finite_rings2#␣>>> from sage.all import *>>> from sage.groups.matrix_gps.unitary import finite_field_sqrt>>> finite_field_sqrt(GF(Integer(4), a ))˓→
# needs sage.rings.finite_rings2␣

28.20 Unitary Groups 𝐺𝑈 (𝑛, 𝑞) and 𝑆𝑈 (𝑛, 𝑞) with GAPclass sage.groups.matrix_gps.unitary_gap.UnitaryMatrixGroup_gap(degree, base_ring,
special, sage_name,latex_string,
gap_command_string,
category=None)
Bases: UnitaryMatrixGroup_generic, NamedMatrixGroup_gap, FinitelyGeneratedMatrixGroup_gap
The general or special unitary group in GAP.
invariant_form()
Return the hermitian form preserved by the unitary group.
OUTPUT: a square matrix describing the bilinear form
EXAMPLES:

696

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

sage: G32 = GU(3,2)
sage: G32.invariant_form()[0 0 1][0 1 0][1 0 0]>>> from sage.all import *>>> G32 = GU(Integer(3),Integer(2))>>> G32.invariant_form()[0 0 1][0 1 0][1 0 0]28.21 Heisenberg GroupAUTHORS:• Hilder Vitor Lima Pereira (2017-08): initial version
class sage.groups.matrix_gps.heisenberg.HeisenbergGroup(n=1, R=0)
Bases: UniqueRepresentation, FinitelyGeneratedMatrixGroup_gap
The Heisenberg group of degree 𝑛.
Let 𝑅 be a ring, and let 𝑛 be a positive integer. The Heisenberg group of degree 𝑛 over 𝑅 is a multiplicative groupwhose elements are matrices with the following form:⎛⎞
1 𝑥𝑇 𝑧⎝0 𝐼𝑛 𝑦 ⎠ ,0 0 1
where 𝑥 and 𝑦 are column vectors in 𝑅𝑛 , 𝑧 is a scalar in 𝑅, and 𝐼𝑛 is the identity matrix of size 𝑛.
INPUT:• n – the degree of the Heisenberg group• R – (default: ) the ring 𝑅 or a positive integer as a shorthand for the ring /𝑅
EXAMPLES:
sage: H = groups.matrix.Heisenberg(); H
Heisenberg group of degree 1 over Integer Ringsage: H.gens()([1 1 0] [1 0 0] [1 0 1]
[0 1 0] [0 1 1] [0 1 0]
[0 0 1], [0 0 1], [0 0 1])
sage: X, Y, Z = H.gens()
sage: Z * X * Y**-1[ 1 1 0][ 0 1 -1]
[ 0 0 1]
sage: X * Y * X**-1 * Y**-1 == Z
True(continues on next page)

28.21. Heisenberg Group

697

Groups, Release 10.4

(continued from previous page)

sage: H = groups.matrix.Heisenberg(R=5); H
Heisenberg group of degree 1 over Ring of integers modulo 5
sage: H = groups.matrix.Heisenberg(n=3, R=13); H
Heisenberg group of degree 3 over Ring of integers modulo 13>>> from sage.all import *>>> H = groups.matrix.Heisenberg(); H
Heisenberg group of degree 1 over Integer Ring>>> H.gens()([1 1 0] [1 0 0] [1 0 1]
[0 1 0] [0 1 1] [0 1 0]
[0 0 1], [0 0 1], [0 0 1])>>> X, Y, Z = H.gens()>>> Z * X * Y**-Integer(1)[ 1 1 0][ 0 1 -1]
[ 0 0 1]>>> X * Y * X**-Integer(1) * Y**-Integer(1) == Z
True>>> H = groups.matrix.Heisenberg(R=Integer(5)); H
Heisenberg group of degree 1 over Ring of integers modulo 5>>> H = groups.matrix.Heisenberg(n=Integer(3), R=Integer(13)); H
Heisenberg group of degree 3 over Ring of integers modulo 13

REFERENCES:• Wikipedia article Heisenberg_groupcardinality()
Return the order of self.
EXAMPLES:
sage: H = groups.matrix.Heisenberg()
sage: H.order()+Infinity
sage: H = groups.matrix.Heisenberg(n=4)
sage: H.order()+Infinity
sage: H = groups.matrix.Heisenberg(R=3)
sage: H.order()27
sage: H = groups.matrix.Heisenberg(n=2, R=3)
sage: H.order()243
sage: H = groups.matrix.Heisenberg(n=2, R=GF(4))
sage: H.order()1024>>> from sage.all import *>>> H = groups.matrix.Heisenberg()>>> H.order()+Infinity>>> H = groups.matrix.Heisenberg(n=Integer(4))(continues on next page)

698

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)>>> H.order()+Infinity>>> H = groups.matrix.Heisenberg(R=Integer(3))>>> H.order()27>>> H = groups.matrix.Heisenberg(n=Integer(2), R=Integer(3))>>> H.order()243>>> H = groups.matrix.Heisenberg(n=Integer(2), R=GF(Integer(4)))>>> H.order()1024

center()Return the center of self.
This is the subgroup generated by the 𝑧, the matrix with a 1 in the upper right corner and along the diagonal.
EXAMPLES:
sage: H = groups.matrix.Heisenberg(2)sage: H.center()
Subgroup with 1 generators ([1 0 0 1][0 1 0 0][0 0 1 0][0 0 0 1]) of Heisenberg group of degree 2 over Integer Ringsage: H = groups.matrix.Heisenberg(3, 4)
sage: H.center()
Subgroup with 1 generators ([1 0 0 0 1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
) of Heisenberg group of degree 3 over Ring of integers modulo 4>>> from sage.all import *>>> H = groups.matrix.Heisenberg(Integer(2))>>> H.center()
Subgroup with 1 generators ([1 0 0 1][0 1 0 0][0 0 1 0][0 0 0 1]) of Heisenberg group of degree 2 over Integer Ring>>> H = groups.matrix.Heisenberg(Integer(3), Integer(4))>>> H.center()
Subgroup with 1 generators ([1 0 0 0 1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
) of Heisenberg group of degree 3 over Ring of integers modulo 428.21. Heisenberg Group

699

Groups, Release 10.4

order()
Return the order of self.
EXAMPLES:
sage: H = groups.matrix.Heisenberg()
sage: H.order()+Infinity
sage: H = groups.matrix.Heisenberg(n=4)
sage: H.order()+Infinity
sage: H = groups.matrix.Heisenberg(R=3)
sage: H.order()27
sage: H = groups.matrix.Heisenberg(n=2, R=3)
sage: H.order()243
sage: H = groups.matrix.Heisenberg(n=2, R=GF(4))
sage: H.order()1024>>> from sage.all import *>>> H = groups.matrix.Heisenberg()>>> H.order()+Infinity>>> H = groups.matrix.Heisenberg(n=Integer(4))>>> H.order()+Infinity>>> H = groups.matrix.Heisenberg(R=Integer(3))>>> H.order()27>>> H = groups.matrix.Heisenberg(n=Integer(2), R=Integer(3))>>> H.order()243>>> H = groups.matrix.Heisenberg(n=Integer(2), R=GF(Integer(4)))>>> H.order()1024

28.22 Affine Groups
AUTHORS:• Volker Braun: initial version
class sage.groups.affine_gps.affine_group.AffineGroup(degree, ring)
Bases: UniqueRepresentation, GroupAn affine group.
The affine group Aff(𝐴) (or general affine group) of an affine space 𝐴 is the group of all invertible affine transformations from the space into itself.
If we let 𝐴𝑉 be the affine space of a vector space 𝑉 (essentially, forgetting what is the origin) then the affine group
Aff(𝐴𝑉 ) is the group generated by the general linear group 𝐺𝐿(𝑉 ) together with the translations. Recall thatthe group of translations acting on 𝐴𝑉 is just 𝑉 itself. The general linear and translation subgroups do not quite

700

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

commute, and in fact generate the semidirect product
Aff(𝐴𝑉 ) = 𝐺𝐿(𝑉 ) n 𝑉.
As such, the group elements can be represented by pairs (𝐴, 𝑏) of a matrix and a vector. This pair then represents
the transformation𝑥 ↦→ 𝐴𝑥 + 𝑏.
We can also represent affine transformations as linear transformations by considering dim(𝑉 ) + 1 dimensional
space. We take the affine transformation (𝐴, 𝑏) to
(︂
)︂
𝐴 𝑏
0 1
and lifting 𝑥 = (𝑥1 , . . . , 𝑥𝑛 ) to (𝑥1 , . . . , 𝑥𝑛 , 1). Here the (𝑛 + 1)-th component is always 1, so the linear representations acts on the affine hyperplane 𝑥𝑛+1 = 1 as affine transformations which can be seen directly from thematrix multiplication.
INPUT:
Something that defines an affine space. For example• An affine space itself:– A – affine space• A vector space:– V – a vector space• Degree and base ring:– degree – An integer. The degree of the affine group, that is, the dimension of the affine space thegroup is acting on.
– ring – A ring or an integer. The base ring of the affine space. If an integer is given, it must be a prime
power and the corresponding finite field is constructed.
– var – (default: a ) Keyword argument to specify the finite field generator name in the case where
ring is a prime power.
EXAMPLES:
sage: F = AffineGroup(3, QQ); F
Affine Group of degree 3 over Rational Field
sage: F(matrix(QQ,[[1,2,3],[4,5,6],[7,8,0]]), vector(QQ,[10,11,12]))[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]
sage: F([[1,2,3],[4,5,6],[7,8,0]], [10,11,12])[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]
sage: F([1,2,3,4,5,6,7,8,0], [10,11,12])[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]28.22. Affine Groups

701

Groups, Release 10.4>>> from sage.all import *>>> F = AffineGroup(Integer(3), QQ); F
Affine Group of degree 3 over Rational Field>>> F(matrix(QQ,[[Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5),˓→Integer(6)],[Integer(7),Integer(8),Integer(0)]]), vector(QQ,[Integer(10),
˓→Integer(11),Integer(12)]))[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]>>> F([[Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5),Integer(6)],
˓→[Integer(7),Integer(8),Integer(0)]], [Integer(10),Integer(11),Integer(12)])[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]>>> F([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]Instead of specifying the complete matrix/vector information, you can also create special group elements:
sage: F.linear([1,2,3,4,5,6,7,8,0])[1 2 3][0]
x |-> [4 5 6] x + [0][7 8 0][0]sage: F.translation([1,2,3])[1 0 0][1]
x |-> [0 1 0] x + [2][0 0 1][3]>>> from sage.all import *>>> F.linear([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)])[1 2 3][0]
x |-> [4 5 6] x + [0][7 8 0][0]>>> F.translation([Integer(1),Integer(2),Integer(3)])[1 0 0][1]
x |-> [0 1 0] x + [2][0 0 1][3]

Some additional ways to create affine groups:
sage: A = AffineSpace(2, GF(4, a )); A˓→needs sage.rings.finite_rings
Affine Space of dimension 2 over Finite Field in a of size 2^2
sage: G = AffineGroup(A); G˓→needs sage.rings.finite_rings
Affine Group of degree 2 over Finite Field in a of size 2^2
sage: G is AffineGroup(2,4) # shorthand˓→needs sage.rings.finite_rings
True

#␣

#␣

#␣

sage: V = ZZ^3; V
Ambient free module of rank 3 over the principal ideal domain Integer Ringsage: AffineGroup(V)(continues on next page)702

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)

Affine Group of degree 3 over Integer Ring>>> from sage.all import *>>> A = AffineSpace(Integer(2), GF(Integer(4), a )); A˓→# needs sage.rings.finite_rings
Affine Space of dimension 2 over Finite Field in a of size 2^2>>> G = AffineGroup(A); G˓→needs sage.rings.finite_rings
Affine Group of degree 2 over Finite Field in a of size 2^2>>> G is AffineGroup(Integer(2),Integer(4)) # shorthand˓→# needs sage.rings.finite_rings
True

␣

#␣

␣

>>> V = ZZ**Integer(3); V
Ambient free module of rank 3 over the principal ideal domain Integer Ring>>> AffineGroup(V)Affine Group of degree 3 over Integer Ring

REFERENCES:• Wikipedia article Affine_group
Element
alias of AffineGroupElement
cardinality()
Return the cardinality of self.
EXAMPLES:
sage: # needs sage.libs.gap
sage: AffineGroup(6, GF(5)).cardinality()
172882428468750000000000000000
sage: AffineGroup(6, ZZ).cardinality()+Infinity>>> from sage.all import *>>> # needs sage.libs.gap>>> AffineGroup(Integer(6), GF(Integer(5))).cardinality()
172882428468750000000000000000>>> AffineGroup(Integer(6), ZZ).cardinality()+Infinity

degree()Return the dimension of the affine space.
OUTPUT: integer
EXAMPLES:
sage: G = AffineGroup(6, GF(5))
sage: g = G.an_element()
sage: G.degree()6
sage: G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree()True

28.22. Affine Groups703

Groups, Release 10.4>>> from sage.all import *>>> G = AffineGroup(Integer(6), GF(Integer(5)))>>> g = G.an_element()>>> G.degree()6>>> G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree()Truelinear(A)Construct the general linear transformation by A.
INPUT:• A – anything that determines a matrix
OUTPUT: The affine group element 𝑥 ↦→ 𝐴𝑥
EXAMPLES:
sage: G = AffineGroup(3, GF(5))
sage: G.linear([1,2,3,4,5,6,7,8,0])[1 2 3][0]
x |-> [4 0 1] x + [0][2 3 0][0]>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(5)))>>> G.linear([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(6),Integer(7),Integer(8),Integer(0)])[1 2 3][0]
x |-> [4 0 1] x + [0][2 3 0][0]linear_space()
Return the space of the affine transformations represented as linear transformations.
We can represent affine transformations 𝐴𝑥 + 𝑏 as linear transformations by
(︂
)︂
𝐴 𝑏
0 1
and lifting 𝑥 = (𝑥1 , . . . , 𝑥𝑛 ) to (𝑥1 , . . . , 𝑥𝑛 , 1).
See also:• sage.groups.affine_gps.group_element.AffineGroupElement.matrix()
EXAMPLES:
sage: G = AffineGroup(3, GF(5))
sage: G.linear_space()
Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 5>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(5)))>>> G.linear_space()
Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 5704

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

matrix_space()
Return the space of matrices representing the general linear transformations.
OUTPUT: the parent of the matrices 𝐴 defining the affine group element 𝐴𝑥 + 𝑏
EXAMPLES:
sage: G = AffineGroup(3, GF(5))
sage: G.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(5)))>>> G.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5

random_element()
Return a random element of this group.
EXAMPLES:
sage: # needs sage.libs.gap
sage: G = AffineGroup(4, GF(3))
sage: G.random_element() # random[2 0 1 2][1][2 1 1 2][2]
x |-> [1 0 2 2] x + [2][1 1 1 1][2]
sage: G.random_element() in G
True>>> from sage.all import *>>> # needs sage.libs.gap>>> G = AffineGroup(Integer(4), GF(Integer(3)))>>> G.random_element() # random[2 0 1 2][1][2 1 1 2][2]
x |-> [1 0 2 2] x + [2][1 1 1 1][2]>>> G.random_element() in G
True

reflection(v)Construct the Householder reflection.
A Householder reflection (transformation) is the affine transformation corresponding to an elementary reflection at the hyperplane perpendicular to 𝑣.
INPUT:• v – a vector, or something that determines a vector
OUTPUT:
The affine group element that is just the Householder transformation (a.k.a. Householder reflection, elementary reflection) at the hyperplane perpendicular to 𝑣.
EXAMPLES:

28.22. Affine Groups

705

Groups, Release 10.4

sage: G = AffineGroup(3, QQ)
sage: G.reflection([1,0,0])[-1 0 0][0]
x |-> [ 0 1 0] x + [0][ 0 0 1][0]
sage: G.reflection([3,4,-5])[ 16/25 -12/25
3/5][0]x |-> [-12/25
9/25
4/5] x + [0]
[
3/5
4/5
0]
[0]
>>> from sage.all import *>>> G = AffineGroup(Integer(3), QQ)>>> G.reflection([Integer(1),Integer(0),Integer(0)])[-1 0 0][0]
x |-> [ 0 1 0] x + [0][ 0 0 1][0]>>> G.reflection([Integer(3),Integer(4),-Integer(5)])[ 16/25 -12/25
3/5][0]x |-> [-12/25
9/25
4/5] x + [0]
[
3/5
4/5
0]
[0]

some_elements()
Return some elements.
EXAMPLES:
sage: # needs sage.libs.gap
sage: G = AffineGroup(4,5)
sage: G.some_elements()[[2 0 0 0][1][0 1 0 0][0]
x |-> [0 0 1 0] x + [0][0 0 0 1][0],[2 0 0 0][0][0 1 0 0][0]
x |-> [0 0 1 0] x + [0][0 0 0 1][0],[2 0 0 0][...][0 1 0 0][...]
x |-> [0 0 1 0] x + [...][0 0 0 1][...]]
sage: all(v.parent() is G for v in G.some_elements())
Truesage: G = AffineGroup(2,QQ)
sage: G.some_elements()
[
[1 0]
[1]
x |-> [0 1] x + [0],...]>>> from sage.all import *>>> # needs sage.libs.gap>>> G = AffineGroup(Integer(4),Integer(5))>>> G.some_elements()[[2 0 0 0][1][0 1 0 0][0]
x |-> [0 0 1 0] x + [0](continues on next page)

706

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[0 0 0 1][0],[2 0 0 0][0][0 1 0 0][0]
x |-> [0 0 1 0] x + [0][0 0 0 1][0],[2 0 0 0][...][0 1 0 0][...]
x |-> [0 0 1 0] x + [...][0 0 0 1][...]]>>> all(v.parent() is G for v in G.some_elements())
True>>> G = AffineGroup(Integer(2),QQ)>>> G.some_elements()
[
[1 0]
[1]
x |-> [0 1] x + [0],...]translation(b)Construct the translation by b.
INPUT:• b – anything that determines a vector
OUTPUT: The affine group element 𝑥 ↦→ 𝑥 + 𝑏
EXAMPLES:
sage: G = AffineGroup(3, GF(5))
sage: G.translation([1,4,8])[1 0 0][1]
x |-> [0 1 0] x + [4][0 0 1][3]>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(5)))>>> G.translation([Integer(1),Integer(4),Integer(8)])[1 0 0][1]
x |-> [0 1 0] x + [4][0 0 1][3]vector_space()
Return the vector space of the underlying affine space.
EXAMPLES:
sage: G = AffineGroup(3, GF(5))
sage: G.vector_space()
Vector space of dimension 3 over Finite Field of size 5>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(5)))>>> G.vector_space()
Vector space of dimension 3 over Finite Field of size 528.22. Affine Groups

707

Groups, Release 10.4

28.23 Euclidean Groups
AUTHORS:• Volker Braun: initial version
class sage.groups.affine_gps.euclidean_group.EuclideanGroup(degree, ring)
Bases: AffineGroupA Euclidean group.
The Euclidean group 𝐸(𝐴) (or general affine group) of an affine space 𝐴 is the group of all invertible affine transformations from the space into itself preserving the Euclidean metric.
If we let 𝐴𝑉 be the affine space of a vector space 𝑉 (essentially, forgetting what is the origin) then the Euclideangroup 𝐸(𝐴𝑉 ) is the group generated by the general linear group 𝑆𝑂(𝑉 ) together with the translations. Recall thatthe group of translations acting on 𝐴𝑉 is just 𝑉 itself. The general linear and translation subgroups do not quite
commute, and in fact generate the semidirect product
𝐸(𝐴𝑉 ) = 𝑆𝑂(𝑉 ) n 𝑉.
As such, the group elements can be represented by pairs (𝐴, 𝑏) of a matrix and a vector. This pair then represents
the transformation𝑥 ↦→ 𝐴𝑥 + 𝑏.
We can also represent this as a linear transformation in dim(𝑉 ) + 1 dimensional space as
(︂
)︂
𝐴 𝑏
0 1
and lifting 𝑥 = (𝑥1 , . . . , 𝑥𝑛 ) to (𝑥1 , . . . , 𝑥𝑛 , 1).
See also:• AffineGroupINPUT:
Something that defines an affine space. For example• An affine space itself:– A – affine space• A vector space:– V – a vector space• Degree and base ring:– degree – An integer. The degree of the affine group, that is, the dimension of the affine space thegroup is acting on.
– ring – A ring or an integer. The base ring of the affine space. If an integer is given, it must be a prime
power and the corresponding finite field is constructed.
– var – (default: a ) Keyword argument to specify the finite field generator name in the case where
ring is a prime power.
EXAMPLES:

708

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

sage: E3 = EuclideanGroup(3, QQ); E3
Euclidean Group of degree 3 over Rational Field
sage: E3(matrix(QQ,[(6/7, -2/7, 3/7), (-2/7, 3/7, 6/7), (3/7, 6/7, -2/7)]),␣
˓→vector(QQ,[10,11,12]))[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]
sage: E3([[6/7, -2/7, 3/7], [-2/7, 3/7, 6/7], [3/7, 6/7, -2/7]], [10,11,12])[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]
sage: E3([6/7, -2/7, 3/7, -2/7, 3/7, 6/7, 3/7, 6/7, -2/7], [10,11,12])[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]>>> from sage.all import *>>> E3 = EuclideanGroup(Integer(3), QQ); E3
Euclidean Group of degree 3 over Rational Field>>> E3(matrix(QQ,[(Integer(6)/Integer(7), -Integer(2)/Integer(7), Integer(3)/˓→Integer(7)), (-Integer(2)/Integer(7), Integer(3)/Integer(7), Integer(6)/˓→Integer(7)), (Integer(3)/Integer(7), Integer(6)/Integer(7), -Integer(2)/˓→Integer(7))]), vector(QQ,[Integer(10),Integer(11),Integer(12)]))[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]>>> E3([[Integer(6)/Integer(7), -Integer(2)/Integer(7), Integer(3)/Integer(7)], [˓→Integer(2)/Integer(7), Integer(3)/Integer(7), Integer(6)/Integer(7)],␣
˓→[Integer(3)/Integer(7), Integer(6)/Integer(7), -Integer(2)/Integer(7)]],␣
˓→[Integer(10),Integer(11),Integer(12)])[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]>>> E3([Integer(6)/Integer(7), -Integer(2)/Integer(7), Integer(3)/Integer(7), ˓→Integer(2)/Integer(7), Integer(3)/Integer(7), Integer(6)/Integer(7), Integer(3)/˓→Integer(7), Integer(6)/Integer(7), -Integer(2)/Integer(7)], [Integer(10),
˓→Integer(11),Integer(12)])[ 6/7 -2/7 3/7]
[10]
x |-> [-2/7 3/7 6/7] x + [11][ 3/7 6/7 -2/7][12]Instead of specifying the complete matrix/vector information, you can also create special group elements:
sage: E3.linear([6/7, -2/7, 3/7, -2/7, 3/7, 6/7, 3/7, 6/7, -2/7])[ 6/7 -2/7 3/7]
[0]
x |-> [-2/7 3/7 6/7] x + [0][ 3/7 6/7 -2/7][0]
sage: E3.reflection([4,5,6])[ 45/77 -40/77 -48/77][0]x |-> [-40/77 27/77 -60/77] x + [0][-48/77 -60/77
5/77]
[0]
sage: E3.translation([1,2,3])[1 0 0][1]
x |-> [0 1 0] x + [2][0 0 1][3]

28.23. Euclidean Groups709

Groups, Release 10.4>>> from sage.all import *>>> E3.linear([Integer(6)/Integer(7), -Integer(2)/Integer(7), Integer(3)/˓→Integer(7), -Integer(2)/Integer(7), Integer(3)/Integer(7), Integer(6)/˓→Integer(7), Integer(3)/Integer(7), Integer(6)/Integer(7), -Integer(2)/˓→Integer(7)])[ 6/7 -2/7 3/7]
[0]
x |-> [-2/7 3/7 6/7] x + [0][ 3/7 6/7 -2/7][0]>>> E3.reflection([Integer(4),Integer(5),Integer(6)])[ 45/77 -40/77 -48/77][0]x |-> [-40/77 27/77 -60/77] x + [0][-48/77 -60/77
5/77]
[0]
>>> E3.translation([Integer(1),Integer(2),Integer(3)])[1 0 0][1]
x |-> [0 1 0] x + [2][0 0 1][3]

Some additional ways to create Euclidean groups:
sage: A = AffineSpace(2, GF(4, a )); A˓→needs sage.rings.finite_rings
Affine Space of dimension 2 over Finite Field in a of size 2^2
sage: G = EuclideanGroup(A); G˓→needs sage.rings.finite_rings
Euclidean Group of degree 2 over Finite Field in a of size 2^2
sage: G is EuclideanGroup(2,4) # shorthand˓→needs sage.rings.finite_rings
True

#␣

#␣

#␣

sage: V = ZZ^3; V
Ambient free module of rank 3 over the principal ideal domain Integer Ringsage: EuclideanGroup(V)Euclidean Group of degree 3 over Integer Ringsage: EuclideanGroup(2, QQ)
Euclidean Group of degree 2 over Rational Field>>> from sage.all import *>>> A = AffineSpace(Integer(2), GF(Integer(4), a )); A˓→# needs sage.rings.finite_rings
Affine Space of dimension 2 over Finite Field in a of size 2^2>>> G = EuclideanGroup(A); G˓→needs sage.rings.finite_rings
Euclidean Group of degree 2 over Finite Field in a of size 2^2>>> G is EuclideanGroup(Integer(2),Integer(4)) # shorthand˓→# needs sage.rings.finite_rings
True

␣

#␣

␣

>>> V = ZZ**Integer(3); V
Ambient free module of rank 3 over the principal ideal domain Integer Ring>>> EuclideanGroup(V)Euclidean Group of degree 3 over Integer Ring>>> EuclideanGroup(Integer(2), QQ)
Euclidean Group of degree 2 over Rational Field

REFERENCES:

710

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

• Wikipedia article Euclidean_grouprandom_element()
Return a random element of this group.
EXAMPLES:
sage: G = EuclideanGroup(4, GF(3))
sage: G.random_element() # random[2 1 2 1][1][1 2 2 1][0]
x |-> [2 2 2 2] x + [1][1 1 2 2][2]sage: G.random_element() in G
True>>> from sage.all import *>>> G = EuclideanGroup(Integer(4), GF(Integer(3)))>>> G.random_element() # random[2 1 2 1][1][1 2 2 1][0]
x |-> [2 2 2 2] x + [1][1 1 2 2][2]>>> G.random_element() in G
True

28.24 Elements of Affine Groups
The class in this module is used to represent the elements of AffineGroup() and its subgroups.
EXAMPLES:
sage: F = AffineGroup(3, QQ)
sage: F([1,2,3,4,5,6,7,8,0], [10,11,12])[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]
sage: G = AffineGroup(2, ZZ)
sage: g = G([[1,1],[0,1]], [1,0])
sage: h = G([[1,2],[0,1]], [0,1])
sage: g*h
[1 3]
[2]x |-> [0 1] x + [1]sage: h*g
[1 3]
[1]x |-> [0 1] x + [1]sage: g*h != h*g
True>>> from sage.all import *>>> F = AffineGroup(Integer(3), QQ)>>> F([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),Integer(7),˓→Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])[1 2 3][10](continues on next page)

28.24. Elements of Affine Groups711

Groups, Release 10.4

(continued from previous page)x |-> [4 5 6] x + [11]
[7 8 0][12]>>> G = AffineGroup(Integer(2), ZZ)>>> g = G([[Integer(1),Integer(1)],[Integer(0),Integer(1)]], [Integer(1),Integer(0)])>>> h = G([[Integer(1),Integer(2)],[Integer(0),Integer(1)]], [Integer(0),Integer(1)])>>> g*h[1 3][2]x |-> [0 1] x + [1]>>> h*g[1 3][1]x |-> [0 1] x + [1]>>> g*h != h*g
True

AUTHORS:• Volker Braunclass sage.groups.affine_gps.group_element.AffineGroupElement(parent, A, b=0,
convert=True,
check=True)
Bases: MultiplicativeGroupElement
An affine group element.
INPUT:• A – an invertible matrix, or something defining a matrix if convert==True• b – a vector, or something defining a vector if convert==True (default: 0, defining the zero vector)• parent – the parent affine group• convert – bool (default: True); whether to convert A into the correct matrix space and b into the correct
vector space• check – bool (default: True); whether to do some checks or just accept the input as valid
As a special case, A can be a matrix obtained from matrix(), that is, one row and one column larger. In thatcase, the group element defining that matrix is reconstructed.
OUTPUT: The affine group element 𝑥 ↦→ 𝐴𝑥 + 𝑏
EXAMPLES:
sage: G = AffineGroup(2, GF(3))
sage: # needs sage.libs.gap
sage: g = G.random_element()
sage: type(g)<class sage.groups.affine_gps.affine_group.AffineGroup_with_category.element_
˓→class >sage: G(g.matrix()) == gTruesage: G(2)
[2 0]
[0]
x |-> [0 2] x + [0]712Chapter 28. Matrix and Affine Groups

Groups, Release 10.4>>> from sage.all import *>>> G = AffineGroup(Integer(2), GF(Integer(3)))>>> # needs sage.libs.gap>>> g = G.random_element()>>> type(g)<class sage.groups.affine_gps.affine_group.AffineGroup_with_category.element_
˓→class >>>> G(g.matrix()) == g
True>>> G(Integer(2))
[2 0]
[0]
x |-> [0 2] x + [0]Conversion from a matrix and a matrix group element:
sage: M = Matrix(4, 4, [0, 0, -1, 1, 0, -1, 0, 1, -1, 0, 0, 1, 0, 0, 0, 1])
sage: A = AffineGroup(3, ZZ)
sage: A(M)[ 0 0 -1]
[1]
x |-> [ 0 -1 0] x + [1][-1 0 0][1]
sage: G = MatrixGroup([M])
sage: A(G.0)[ 0 0 -1]
[1]
x |-> [ 0 -1 0] x + [1][-1 0 0][1]>>> from sage.all import *>>> M = Matrix(Integer(4), Integer(4), [Integer(0), Integer(0), -Integer(1),␣
˓→Integer(1), Integer(0), -Integer(1), Integer(0), Integer(1), -Integer(1),␣
˓→Integer(0), Integer(0), Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1)])>>> A = AffineGroup(Integer(3), ZZ)>>> A(M)[ 0 0 -1]
[1]
x |-> [ 0 -1 0] x + [1][-1 0 0][1]>>> G = MatrixGroup([M])>>> A(G.gen(0))[ 0 0 -1]
[1]
x |-> [ 0 -1 0] x + [1][-1 0 0]
[1]

A()
Return the general linear part of an affine group element.
OUTPUT: The matrix 𝐴 of the affine group element 𝐴𝑥 + 𝑏
EXAMPLES:
sage: G = AffineGroup(3, QQ)
sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12])
sage: g.A()[1 2 3][4 5 6][7 8 0]28.24. Elements of Affine Groups713

Groups, Release 10.4>>> from sage.all import *>>> G = AffineGroup(Integer(3), QQ)>>> g = G([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])>>> g.A()[1 2 3][4 5 6][7 8 0]b()
Return the translation part of an affine group element.
OUTPUT: The vector 𝑏 of the affine group element 𝐴𝑥 + 𝑏
EXAMPLES:
sage: G = AffineGroup(3, QQ)
sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12])
sage: g.b()(10, 11, 12)>>> from sage.all import *>>> G = AffineGroup(Integer(3), QQ)>>> g = G([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])>>> g.b()(10, 11, 12)list()
Return list representation of self.
EXAMPLES:
sage: F = AffineGroup(3, QQ)
sage: g = F([1,2,3,4,5,6,7,8,0], [10,11,12])
sage: g
[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]
sage: g.matrix()[ 1 2 3|10][ 4 5 6|11][ 7 8 0|12][--------+--][ 0 0 0| 1]
sage: g.list()[[1, 2, 3, 10], [4, 5, 6, 11], [7, 8, 0, 12], [0, 0, 0, 1]]>>> from sage.all import *>>> F = AffineGroup(Integer(3), QQ)>>> g = F([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])>>> g[1 2 3][10]
x |-> [4 5 6] x + [11]
[7 8 0][12]>>> g.matrix()(continues on next page)714

Chapter 28. Matrix and Affine Groups

Groups, Release 10.4

(continued from previous page)[ 1 2 3|10][ 4 5 6|11][ 7 8 0|12][--------+--][ 0 0 0| 1]>>> g.list()[[1, 2, 3, 10], [4, 5, 6, 11], [7, 8, 0, 12], [0, 0, 0, 1]]

matrix()Return the standard matrix representation of self.
See also:• AffineGroup.linear_space()
EXAMPLES:
sage: G = AffineGroup(3, GF(7))
sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12])
sage: g
[1 2 3][3]
x |-> [4 5 6] x + [4][0 1 0][5]
sage: g.matrix()[1 2 3|3][4 5 6|4][0 1 0|5][-----+-][0 0 0|1]
sage: parent(g.matrix())
Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 7
sage: g.matrix() == matrix(g)True>>> from sage.all import *>>> G = AffineGroup(Integer(3), GF(Integer(7)))>>> g = G([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7),Integer(8),Integer(0)], [Integer(10),Integer(11),Integer(12)])>>> g[1 2 3][3]
x |-> [4 5 6] x + [4][0 1 0][5]>>> g.matrix()[1 2 3|3][4 5 6|4][0 1 0|5][-----+-][0 0 0|1]>>> parent(g.matrix())
Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 7>>> g.matrix() == matrix(g)TrueComposition of affine group elements equals multiplication of the matrices:

28.24. Elements of Affine Groups

715Groups, Release 10.4

sage: # needs sage.libs.gap
sage: g1 = G.random_element()
sage: g2 = G.random_element()
sage: g1.matrix() * g2.matrix() == (g1*g2).matrix()True>>> from sage.all import *>>> # needs sage.libs.gap>>> g1 = G.random_element()>>> g2 = G.random_element()>>> g1.matrix() * g2.matrix() == (g1*g2).matrix()
True

716

Chapter 28. Matrix and Affine Groups

CHAPTERTWENTYNINE

LIE GROUPS

29.1 Nilpotent Lie groups
AUTHORS:• Eero Hakavuori (2018-09-25): initial version of nilpotent Lie groups
class sage.groups.lie_gps.nilpotent_lie_group.NilpotentLieGroup(L, name, **kwds)
Bases: Group, DifferentiableManifold
A nilpotent Lie group.
INPUT:• L – the Lie algebra of the Lie group; must be a finite dimensional nilpotent Lie algebra with basis over a
topological field, e.g. or R
• name – a string; name (symbol) given to the Lie group
Two types of exponential coordinates are defined on any nilpotent Lie group using the basis of the Lie algebra, seechart_exp1() and chart_exp2().
EXAMPLES:
Creation of a nilpotent Lie group:sage: L = lie_algebras.Heisenberg(QQ, 1)
sage: G = L.lie_group(); G
Lie group G of Heisenberg algebra of rank 1 over Rational Field>>> from sage.all import *>>> L = lie_algebras.Heisenberg(QQ, Integer(1))>>> G = L.lie_group(); G
Lie group G of Heisenberg algebra of rank 1 over Rational Field

Giving a different name to the group:sage: L.lie_group( H )Lie group H of Heisenberg algebra of rank 1 over Rational Field>>> from sage.all import *>>> L.lie_group( H )Lie group H of Heisenberg algebra of rank 1 over Rational Field

Elements can be created using the exponential map:

717

Groups, Release 10.4

sage: p,q,z = L.basis()
sage: g = G.exp(p); g
exp(p1)
sage: h = G.exp(q); hexp(q1)>>> from sage.all import *>>> p,q,z = L.basis()>>> g = G.exp(p); g
exp(p1)>>> h = G.exp(q); hexp(q1)

Lie group multiplication has the usual product syntax:
sage: k = g*h; kexp(p1 + q1 + 1/2*z)>>> from sage.all import *>>> k = g*h; kexp(p1 + q1 + 1/2*z)

The identity element is given by one():sage: e = G.one(); eexp(0)
sage: e*k == k and k*e == kTrue>>> from sage.all import *>>> e = G.one(); eexp(0)>>> e*k == k and k*e == kTrue

The default coordinate system is exponential coordinates of the first kind:sage: G.default_chart() == G.chart_exp1()
True
sage: G.chart_exp1()
Chart (G, (x_0, x_1, x_2))>>> from sage.all import *>>> G.default_chart() == G.chart_exp1()
True>>> G.chart_exp1()
Chart (G, (x_0, x_1, x_2))

Changing the default coordinates to exponential coordinates of the second kind will change how elements are
printed:sage: G.set_default_chart(G.chart_exp2())
sage: kexp(z)exp(q1)exp(p1)sage: G.set_default_chart(G.chart_exp1())(continues on next page)

718

Chapter 29. Lie Groups

Groups, Release 10.4

(continued from previous page)

sage: kexp(p1 + q1 + 1/2*z)>>> from sage.all import *>>> G.set_default_chart(G.chart_exp2())>>> k
exp(z)exp(q1)exp(p1)>>> G.set_default_chart(G.chart_exp1())>>> k
exp(p1 + q1 + 1/2*z)

The frames of left- or right-invariant vector fields are created using left_invariant_frame() andright_invariant_frame():sage: X = G.left_invariant_frame(); X
Vector frame (G, (X_0,X_1,X_2))
sage: X[0]Vector field X_0 on the Lie group G of Heisenberg algebra of rank 1 over Rational␣
˓→Field>>> from sage.all import *>>> X = G.left_invariant_frame(); X
Vector frame (G, (X_0,X_1,X_2))>>> X[Integer(0)]Vector field X_0 on the Lie group G of Heisenberg algebra of rank 1 over Rational␣
˓→Field

A vector field can be displayed with respect to a coordinate frame:
sage: exp1_frame = G.chart_exp1().frame()
sage: exp2_frame = G.chart_exp2().frame()
sage: X[0].display(exp1_frame)
X_0 = ∂/∂x_0 - 1/2*x_1 ∂/∂x_2
sage: X[0].display(exp2_frame)
X_0 = ∂/∂y_0
sage: X[1].display(exp1_frame)
X_1 = ∂/∂x_1 + 1/2*x_0 ∂/∂x_2
sage: X[1].display(exp2_frame)
X_1 = ∂/∂y_1 + x_0 ∂/∂y_2>>> from sage.all import *>>> exp1_frame = G.chart_exp1().frame()>>> exp2_frame = G.chart_exp2().frame()>>> X[Integer(0)].display(exp1_frame)
X_0 = ∂/∂x_0 - 1/2*x_1 ∂/∂x_2>>> X[Integer(0)].display(exp2_frame)
X_0 = ∂/∂y_0>>> X[Integer(1)].display(exp1_frame)
X_1 = ∂/∂x_1 + 1/2*x_0 ∂/∂x_2>>> X[Integer(1)].display(exp2_frame)
X_1 = ∂/∂y_1 + x_0 ∂/∂y_2

Defining a left translation by a generic point:

29.1. Nilpotent Lie groups719

Groups, Release 10.4

sage: g = G.point([var( a ), var( b ), var( c )]); gexp(a*p1 + b*q1 + c*z)
sage: L_g = G.left_translation(g); L_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over Rational␣
˓→Field
sage: L_g.display()
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, -1/2*b*x_0 + 1/2*a*x_1 + c + x_2)
(x_0, x_1, x_2) ↦ (y_0, y_1, y_2) = (a + x_0, b + x_1,
1/2*a*b + 1/2*(2*a + x_0)*x_1 + c + x_2)
(y_0, y_1, y_2) ↦ (x_0, x_1, x_2) = (a + y_0, b + y_1,
-1/2*b*y_0 + 1/2*(a - y_0)*y_1 + c + y_2)
(y_0, y_1, y_2) ↦ (a + y_0, b + y_1, 1/2*a*b + a*y_1 + c + y_2)>>> from sage.all import *>>> g = G.point([var( a ), var( b ), var( c )]); gexp(a*p1 + b*q1 + c*z)>>> L_g = G.left_translation(g); L_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over Rational␣
˓→Field>>> L_g.display()
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, -1/2*b*x_0 + 1/2*a*x_1 + c + x_2)
(x_0, x_1, x_2) ↦ (y_0, y_1, y_2) = (a + x_0, b + x_1,
1/2*a*b + 1/2*(2*a + x_0)*x_1 + c + x_2)
(y_0, y_1, y_2) ↦ (x_0, x_1, x_2) = (a + y_0, b + y_1,
-1/2*b*y_0 + 1/2*(a - y_0)*y_1 + c + y_2)
(y_0, y_1, y_2) ↦ (a + y_0, b + y_1, 1/2*a*b + a*y_1 + c + y_2)

Verifying the left-invariance of the left-invariant frame:
sage: x = G(G.chart_exp1()[:])
sage: L_g.differential(x)(X[0].at(x)) == X[0].at(L_g(x))
Truesage: L_g.differential(x)(X[1].at(x)) == X[1].at(L_g(x))
Truesage: L_g.differential(x)(X[2].at(x)) == X[2].at(L_g(x))
True>>> from sage.all import *>>> x = G(G.chart_exp1()[:])>>> L_g.differential(x)(X[Integer(0)].at(x)) == X[Integer(0)].at(L_g(x))
True>>> L_g.differential(x)(X[Integer(1)].at(x)) == X[Integer(1)].at(L_g(x))
True>>> L_g.differential(x)(X[Integer(2)].at(x)) == X[Integer(2)].at(L_g(x))
True

An element of the Lie algebra can be extended to a left or right invariant vector field:
sage: X_L = G.left_invariant_extension(p + 3*q); X_L
Vector field p1 + 3*q1 on the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: X_L.display(exp1_frame)
p1 + 3*q1 = ∂/∂x_0 + 3 ∂/∂x_1 + (3/2*x_0 - 1/2*x_1) ∂/∂x_2
sage: X_R = G.right_invariant_extension(p + 3*q)
(continues on next page)

720

Chapter 29. Lie Groups

Groups, Release 10.4

(continued from previous page)

sage: X_R.display(exp1_frame)
p1 + 3*q1 = ∂/∂x_0 + 3 ∂/∂x_1 + (-3/2*x_0 + 1/2*x_1) ∂/∂x_2>>> from sage.all import *>>> X_L = G.left_invariant_extension(p + Integer(3)*q); X_L
Vector field p1 + 3*q1 on the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> X_L.display(exp1_frame)
p1 + 3*q1 = ∂/∂x_0 + 3 ∂/∂x_1 + (3/2*x_0 - 1/2*x_1) ∂/∂x_2>>> X_R = G.right_invariant_extension(p + Integer(3)*q)>>> X_R.display(exp1_frame)
p1 + 3*q1 = ∂/∂x_0 + 3 ∂/∂x_1 + (-3/2*x_0 + 1/2*x_1) ∂/∂x_2

The nilpotency step of the Lie group is the nilpotency step of its algebra. Nilpotency for Lie groups means thatgroup commutators that are longer than the nilpotency step vanish:
sage: G.step()2
sage: g = G.exp(p); h = G.exp(q)sage: c = g*h*~g*~h; cexp(z)
sage: g*c*~g*~cexp(0)>>> from sage.all import *>>> G.step()2>>> g = G.exp(p); h = G.exp(q)>>> c = g*h*~g*~h; cexp(z)>>> g*c*~g*~cexp(0)

class Element(parent, **kwds)
Bases: ManifoldPoint, MultiplicativeGroupElement
A base class for an element of a Lie group.
EXAMPLES:
Elements of the group are printed in the default exponential coordinates:sage: L.<X,Y,Z> = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: g = G.exp(2*X + 3*Z); g
exp(2*X + 3*Z)
sage: h = G.point([ var( a ), var( b ), 0]); hexp(a*X + b*Y)
sage: G.set_default_chart(G.chart_exp2())
sage: gexp(3*Z)exp(2*X)
sage: hexp(1/2*a*b*Z)exp(b*Y)exp(a*X)>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2), names=( X ,Y ,Z ,));␣

(continues on next page)

29.1. Nilpotent Lie groups

721

Groups, Release 10.4

(continued from previous page)(X, Y, Z,) = L._first_ngens(3)>>> G = L.lie_group()>>> g = G.exp(Integer(2)*X + Integer(3)*Z); g
exp(2*X + 3*Z)>>> h = G.point([ var( a ), var( b ), Integer(0)]); hexp(a*X + b*Y)>>> G.set_default_chart(G.chart_exp2())>>> g
exp(3*Z)exp(2*X)>>> hexp(1/2*a*b*Z)exp(b*Y)exp(a*X)
˓→

Multiplication of two elements uses the usual product syntax:
sage: G.exp(Y)*G.exp(X)
exp(Y)exp(X)sage: G.exp(X)*G.exp(Y)
exp(Z)exp(Y)exp(X)sage: G.set_default_chart(G.chart_exp1())
sage: G.exp(X)*G.exp(Y)
exp(X + Y + 1/2*Z)>>> from sage.all import *>>> G.exp(Y)*G.exp(X)
exp(Y)exp(X)>>> G.exp(X)*G.exp(Y)
exp(Z)exp(Y)exp(X)>>> G.set_default_chart(G.chart_exp1())>>> G.exp(X)*G.exp(Y)
exp(X + Y + 1/2*Z)

adjoint(g)Return the adjoint map as an automorphism of the Lie algebra of self.
INPUT:• g – an element of self
For a Lie group element 𝑔, the adjoint map Ad𝑔 is the map on the Lie algebra g given by the differential of
the conjugation by 𝑔 at the identity.
If the Lie algebra of self does not admit symbolic coefficients, the adjoint is not in general defined for
abstract points.
EXAMPLES:
An example of an adjoint map:
sage: L = LieAlgebra(QQ, 2, step=3)
sage: G = L.lie_group()
sage: g = G.exp(L.basis().list()[0]); g
exp(X_1)
sage: Ad_g = G.adjoint(g); Ad_g
Lie algebra endomorphism of Free Nilpotent Lie algebra on 5
generators (X_1, X_2, X_12, X_112, X_122) over Rational Field
Defn: X_1 |--> X_1
X_2 |--> X_2 + X_12 + 1/2*X_112
X_12 |--> X_12 + X_112(continues on next page)722

Chapter 29. Lie Groups

Groups, Release 10.4

(continued from previous page)

X_112 |--> X_112
X_122 |--> X_122>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(3))>>> G = L.lie_group()>>> g = G.exp(L.basis().list()[Integer(0)]); g
exp(X_1)>>> Ad_g = G.adjoint(g); Ad_g
Lie algebra endomorphism of Free Nilpotent Lie algebra on 5
generators (X_1, X_2, X_12, X_112, X_122) over Rational Field
Defn: X_1 |--> X_1
X_2 |--> X_2 + X_12 + 1/2*X_112
X_12 |--> X_12 + X_112
X_112 |--> X_112
X_122 |--> X_122

Usually the adjoint map of a symbolic point is not defined:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: g = G.point([var( a ), var( b ), var( c )]); gexp(a*X_1 + b*X_2 + c*X_12)
sage: G.adjoint(g)Traceback (most recent call last):...
TypeError: unable to convert -b to a rational>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> g = G.point([var( a ), var( b ), var( c )]); gexp(a*X_1 + b*X_2 + c*X_12)>>> G.adjoint(g)Traceback (most recent call last):...
TypeError: unable to convert -b to a rational

However, if the adjoint map is independent from the symbolic terms, the map is still well defined:
sage: g = G.point([0, 0, var( a )]); gexp(a*X_12)
sage: G.adjoint(g)Lie algebra endomorphism of Free Nilpotent Lie algebra on 3 generators (X_1,␣
˓→X_2, X_12) over Rational Field
Defn: X_1 |--> X_1
X_2 |--> X_2
X_12 |--> X_12>>> from sage.all import *>>> g = G.point([Integer(0), Integer(0), var( a )]); gexp(a*X_12)>>> G.adjoint(g)Lie algebra endomorphism of Free Nilpotent Lie algebra on 3 generators (X_1,␣
˓→X_2, X_12) over Rational Field(continues on next page)

29.1. Nilpotent Lie groups723

Groups, Release 10.4

(continued from previous page)

Defn: X_1 |--> X_1
X_2 |--> X_2
X_12 |--> X_12

chart_exp1()
Return the chart of exponential coordinates of the first kind.
Exponential coordinates of the first kind areexp(𝑥1 𝑋1 + · · · + 𝑥𝑛 𝑋𝑛 ) ↦→ (𝑥1 , . . . , 𝑥𝑛 ).
EXAMPLES:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: G.chart_exp1()
Chart (G, (x_1, x_2, x_12))>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> G.chart_exp1()
Chart (G, (x_1, x_2, x_12))

chart_exp2()
Return the chart of exponential coordinates of the second kind.
Exponential coordinates of the second kind areexp(𝑥𝑛 𝑋𝑛 ) · · · exp(𝑥1 𝑋1 ) ↦→ (𝑥1 , . . . , 𝑥𝑛 ).
EXAMPLES:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: G.chart_exp2()
Chart (G, (y_1, y_2, y_12))>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> G.chart_exp2()
Chart (G, (y_1, y_2, y_12))

conjugation(g)Return the conjugation by g as an automorphism of self.
The conjugation by 𝑔 on a Lie group 𝐺 is the map
𝐺 → 𝐺,ℎ ↦→ 𝑔ℎ𝑔 −1 .

INPUT:• g – an element of self
EXAMPLES:
A generic conjugation in the Heisenberg group:
724

Chapter 29. Lie Groups

Groups, Release 10.4

sage: H = lie_algebras.Heisenberg(QQ, 1)
sage: p,q,z = H.basis()
sage: G = H.lie_group()
sage: g = G.point([var( a ), var( b ), var( c )])sage: C_g = G.conjugation(g); C_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: C_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0, x_1, -b*x_0 + a*x_1 + x_2)>>> from sage.all import *>>> H = lie_algebras.Heisenberg(QQ, Integer(1))>>> p,q,z = H.basis()>>> G = H.lie_group()>>> g = G.point([var( a ), var( b ), var( c )])>>> C_g = G.conjugation(g); C_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> C_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0, x_1, -b*x_0 + a*x_1 + x_2)

exp(X)
Return the group element 𝑒𝑥𝑝(𝑋).
INPUT:• X – an element of the Lie algebra of self
EXAMPLES:
sage: L.<X,Y,Z> = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: G.exp(X)
exp(X)
sage: G.exp(Y)
exp(Y)
sage: G.exp(X + Y)
exp(X + Y)>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2), names=( X ,˓→(X, Y, Z,) = L._first_ngens(3)>>> G = L.lie_group()>>> G.exp(X)
exp(X)>>> G.exp(Y)
exp(Y)>>> G.exp(X + Y)
exp(X + Y)Y ,Z ,));␣

gens()
Return a tuple of elements whose one-parameter subgroups generate the Lie group.
EXAMPLES:

29.1. Nilpotent Lie groups

725

Groups, Release 10.4

sage: L = lie_algebras.Heisenberg(QQ, 1)
sage: G = L.lie_group()
sage: G.gens()(exp(p1), exp(q1), exp(z))>>> from sage.all import *>>> L = lie_algebras.Heisenberg(QQ, Integer(1))>>> G = L.lie_group()>>> G.gens()(exp(p1), exp(q1), exp(z))

left_invariant_extension(X, name=None)
Return the left-invariant vector field that has the value X at the identity.
INPUT:• X – an element of the Lie algebra of self
• name – (optional) a string to use as a name for the vector field; if nothing is given, the name of the vector
X is used
EXAMPLES:A left-invariant extension in the Heisenberg group:sage: L = lie_algebras.Heisenberg(QQ, 1)
sage: p, q, z = L.basis()
sage: H = L.lie_group( H )sage: X = H.left_invariant_extension(p); X
Vector field p1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: X.display(H.chart_exp1().frame())
p1 = ∂/∂x_0 - 1/2*x_1 ∂/∂x_2>>> from sage.all import *>>> L = lie_algebras.Heisenberg(QQ, Integer(1))>>> p, q, z = L.basis()>>> H = L.lie_group( H )>>> X = H.left_invariant_extension(p); X
Vector field p1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> X.display(H.chart_exp1().frame())
p1 = ∂/∂x_0 - 1/2*x_1 ∂/∂x_2

Default vs. custom naming for the invariant vector field:
sage: Y = H.left_invariant_extension(p + q); Y
Vector field p1 + q1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: Z = H.left_invariant_extension(p + q, Z ); Z
Vector field Z on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> from sage.all import *>>> Y = H.left_invariant_extension(p + q); Y
Vector field p1 + q1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field(continues on next page)

726

Chapter 29. Lie Groups

Groups, Release 10.4

(continued from previous page)>>> Z = H.left_invariant_extension(p + q, Z ); Z
Vector field Z on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field

left_invariant_frame(**kwds)
Return the frame of left-invariant vector fields of self.
The labeling of the frame and the dual frame can be customized using keyword parameters as
described in sage.manifolds.differentiable.manifold.DifferentiableManifold.
vector_frame().
EXAMPLES:
The default left-invariant frame:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: livf = G.left_invariant_frame(); livf
Vector frame (G, (X_1,X_2,X_12))
sage: coord_frame = G.chart_exp1().frame()
sage: livf[0].display(coord_frame)
X_1 = ∂/∂x_1 - 1/2*x_2 ∂/∂x_12
sage: livf[1].display(coord_frame)
X_2 = ∂/∂x_2 + 1/2*x_1 ∂/∂x_12
sage: livf[2].display(coord_frame)
X_12 = ∂/∂x_12>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> livf = G.left_invariant_frame(); livf
Vector frame (G, (X_1,X_2,X_12))>>> coord_frame = G.chart_exp1().frame()>>> livf[Integer(0)].display(coord_frame)
X_1 = ∂/∂x_1 - 1/2*x_2 ∂/∂x_12>>> livf[Integer(1)].display(coord_frame)
X_2 = ∂/∂x_2 + 1/2*x_1 ∂/∂x_12>>> livf[Integer(2)].display(coord_frame)
X_12 = ∂/∂x_12

Examples of custom labeling for the frame:
sage: G.left_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))
sage: G.left_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))
sage: G.left_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))>>> from sage.all import *>>> G.left_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))>>> G.left_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))>>> G.left_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))

29.1. Nilpotent Lie groups

727

Groups, Release 10.4

left_translation(g)Return the left translation by g as an automorphism of self.
The left translation by 𝑔 on a Lie group 𝐺 is the map
𝐺 → 𝐺,ℎ ↦→ 𝑔ℎ.

INPUT:• g – an element of self
EXAMPLES:A left translation in the Heisenberg group:sage: H = lie_algebras.Heisenberg(QQ, 1)
sage: p,q,z = H.basis()
sage: G = H.lie_group()
sage: g = G.exp(p)sage: L_g = G.left_translation(g); L_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: L_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0 + 1, x_1, 1/2*x_1 + x_2)>>> from sage.all import *>>> H = lie_algebras.Heisenberg(QQ, Integer(1))>>> p,q,z = H.basis()>>> G = H.lie_group()>>> g = G.exp(p)>>> L_g = G.left_translation(g); L_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> L_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0 + 1, x_1, 1/2*x_1 + x_2)

Left translation by a generic element:
sage: h = G.point([var( a ), var( b ), var( c )])sage: L_h = G.left_translation(h)sage: L_h.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, -1/2*b*x_0 + 1/2*a*x_1 + c + x_2)>>> from sage.all import *>>> h = G.point([var( a ), var( b ), var( c )])>>> L_h = G.left_translation(h)>>> L_h.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, -1/2*b*x_0 + 1/2*a*x_1 + c + x_2)

lie_algebra()
Return the Lie algebra of self.
EXAMPLES:

728

Chapter 29. Lie Groups

Groups, Release 10.4

sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: G.lie_algebra() == L
True>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> G.lie_algebra() == L
Truelivf(**kwds)
Return the frame of left-invariant vector fields of self.
The labeling of the frame and the dual frame can be customized using keyword parameters as
described in sage.manifolds.differentiable.manifold.DifferentiableManifold.
vector_frame().
EXAMPLES:
The default left-invariant frame:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: livf = G.left_invariant_frame(); livf
Vector frame (G, (X_1,X_2,X_12))
sage: coord_frame = G.chart_exp1().frame()
sage: livf[0].display(coord_frame)
X_1 = ∂/∂x_1 - 1/2*x_2 ∂/∂x_12
sage: livf[1].display(coord_frame)
X_2 = ∂/∂x_2 + 1/2*x_1 ∂/∂x_12
sage: livf[2].display(coord_frame)
X_12 = ∂/∂x_12>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> livf = G.left_invariant_frame(); livf
Vector frame (G, (X_1,X_2,X_12))>>> coord_frame = G.chart_exp1().frame()>>> livf[Integer(0)].display(coord_frame)
X_1 = ∂/∂x_1 - 1/2*x_2 ∂/∂x_12>>> livf[Integer(1)].display(coord_frame)
X_2 = ∂/∂x_2 + 1/2*x_1 ∂/∂x_12>>> livf[Integer(2)].display(coord_frame)
X_12 = ∂/∂x_12

Examples of custom labeling for the frame:
sage: G.left_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))
sage: G.left_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))
sage: G.left_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))

29.1. Nilpotent Lie groups729

Groups, Release 10.4>>> from sage.all import *>>> G.left_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))>>> G.left_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))>>> G.left_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))log(x)
Return the logarithm of the element x of self.
INPUT:• x – an element of self
The logarithm is by definition the inverse of exp().
If the Lie algebra of self does not admit symbolic coefficients, the logarithm is not defined for abstract, i.e.
symbolic, points.
EXAMPLES:
The logarithm is the inverse of the exponential:
sage: L.<X,Y,Z> = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: G.log(G.exp(X)) == X
True
sage: G.log(G.exp(X)*G.exp(Y))
X + Y + 1/2*Z>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2), names=( X ,˓→(X, Y, Z,) = L._first_ngens(3)>>> G = L.lie_group()>>> G.log(G.exp(X)) == X
True>>> G.log(G.exp(X)*G.exp(Y))
X + Y + 1/2*ZY ,Z ,));␣

The logarithm is not defined for abstract (symbolic) points:
sage: g = G.point([var( a ), 1, 2]); gexp(a*X + Y + 2*Z)
sage: G.log(g)Traceback (most recent call last):...
TypeError: unable to convert a to a rational>>> from sage.all import *>>> g = G.point([var( a ), Integer(1), Integer(2)]); gexp(a*X + Y + 2*Z)>>> G.log(g)Traceback (most recent call last):...
TypeError: unable to convert a to a rational

one()
Return the identity element of self.
730

Chapter 29. Lie Groups

Groups, Release 10.4

EXAMPLES:
sage: L = LieAlgebra(QQ, 2, step=4)
sage: G = L.lie_group()
sage: G.one()exp(0)>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(4))>>> G = L.lie_group()>>> G.one()exp(0)

right_invariant_extension(X, name=None)
Return the right-invariant vector field that has the value X at the identity.
INPUT:• X – an element of the Lie algebra of self
• name – (optional) a string to use as a name for the vector field; if nothing is given, the name of the vector
X is used
EXAMPLES:
A right-invariant extension in the Heisenberg group:sage: L = lie_algebras.Heisenberg(QQ, 1)
sage: p, q, z = L.basis()
sage: H = L.lie_group( H )sage: X = H.right_invariant_extension(p); X
Vector field p1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: X.display(H.chart_exp1().frame())
p1 = ∂/∂x_0 + 1/2*x_1 ∂/∂x_2>>> from sage.all import *>>> L = lie_algebras.Heisenberg(QQ, Integer(1))>>> p, q, z = L.basis()>>> H = L.lie_group( H )>>> X = H.right_invariant_extension(p); X
Vector field p1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> X.display(H.chart_exp1().frame())
p1 = ∂/∂x_0 + 1/2*x_1 ∂/∂x_2

Default vs. custom naming for the invariant vector field:
sage: Y = H.right_invariant_extension(p + q); Y
Vector field p1 + q1 on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: Z = H.right_invariant_extension(p + q, Z ); Z
Vector field Z on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> from sage.all import *>>> Y = H.right_invariant_extension(p + q); Y
Vector field p1 + q1 on the Lie group H of Heisenberg algebra of rank 1 over␣(continues on next page)

29.1. Nilpotent Lie groups731

Groups, Release 10.4

(continued from previous page)

Rational Field>>> Z = H.right_invariant_extension(p + q, Z ); Z
Vector field Z on the Lie group H of Heisenberg algebra of rank 1 over␣˓→Rational Field˓→right_invariant_frame(**kwds)
Return the frame of right-invariant vector fields of self.
The labeling of the frame and the dual frame can be customized using keyword parameters as
described in sage.manifolds.differentiable.manifold.DifferentiableManifold.
vector_frame().
EXAMPLES:
The default right-invariant frame:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: rivf = G.right_invariant_frame(); rivf
Vector frame (G, (XR_1,XR_2,XR_12))
sage: coord_frame = G.chart_exp1().frame()
sage: rivf[0].display(coord_frame)
XR_1 = ∂/∂x_1 + 1/2*x_2 ∂/∂x_12
sage: rivf[1].display(coord_frame)
XR_2 = ∂/∂x_2 - 1/2*x_1 ∂/∂x_12
sage: rivf[2].display(coord_frame)
XR_12 = ∂/∂x_12>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> rivf = G.right_invariant_frame(); rivf
Vector frame (G, (XR_1,XR_2,XR_12))>>> coord_frame = G.chart_exp1().frame()>>> rivf[Integer(0)].display(coord_frame)
XR_1 = ∂/∂x_1 + 1/2*x_2 ∂/∂x_12>>> rivf[Integer(1)].display(coord_frame)
XR_2 = ∂/∂x_2 - 1/2*x_1 ∂/∂x_12>>> rivf[Integer(2)].display(coord_frame)
XR_12 = ∂/∂x_12

Examples of custom labeling for the frame:
sage: G.right_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))
sage: G.right_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))
sage: G.right_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))>>> from sage.all import *>>> G.right_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))>>> G.right_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))>>> G.right_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))

732

Chapter 29. Lie Groups

Groups, Release 10.4

right_translation(g)Return the right translation by g as an automorphism of self.
The right translation by 𝑔 on a Lie group 𝐺 is the map
𝐺 → 𝐺,ℎ ↦→ ℎ𝑔.

INPUT:• g – an element of self
EXAMPLES:
A right translation in the Heisenberg group:sage: H = lie_algebras.Heisenberg(QQ, 1)
sage: p,q,z = H.basis()
sage: G = H.lie_group()
sage: g = G.exp(p)sage: R_g = G.right_translation(g); R_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field
sage: R_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0 + 1, x_1, -1/2*x_1 + x_2)>>> from sage.all import *>>> H = lie_algebras.Heisenberg(QQ, Integer(1))>>> p,q,z = H.basis()>>> G = H.lie_group()>>> g = G.exp(p)>>> R_g = G.right_translation(g); R_g
Diffeomorphism of the Lie group G of Heisenberg algebra of rank 1 over␣˓→Rational Field>>> R_g.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (x_0 + 1, x_1, -1/2*x_1 + x_2)

Right translation by a generic element:
sage: h = G.point([var( a ), var( b ), var( c )])sage: R_h = G.right_translation(h)sage: R_h.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, 1/2*b*x_0 - 1/2*a*x_1 + c + x_2)>>> from sage.all import *>>> h = G.point([var( a ), var( b ), var( c )])>>> R_h = G.right_translation(h)>>> R_h.display(chart1=G.chart_exp1(), chart2=G.chart_exp1())
G → G(x_0, x_1, x_2) ↦ (a + x_0, b + x_1, 1/2*b*x_0 - 1/2*a*x_1 + c + x_2)

rivf(**kwds)
Return the frame of right-invariant vector fields of self.
The labeling of the frame and the dual frame can be customized using keyword parameters as
described in sage.manifolds.differentiable.manifold.DifferentiableManifold.
vector_frame().
29.1. Nilpotent Lie groups733

Groups, Release 10.4

EXAMPLES:
The default right-invariant frame:
sage: L = LieAlgebra(QQ, 2, step=2)
sage: G = L.lie_group()
sage: rivf = G.right_invariant_frame(); rivf
Vector frame (G, (XR_1,XR_2,XR_12))
sage: coord_frame = G.chart_exp1().frame()
sage: rivf[0].display(coord_frame)
XR_1 = ∂/∂x_1 + 1/2*x_2 ∂/∂x_12
sage: rivf[1].display(coord_frame)
XR_2 = ∂/∂x_2 - 1/2*x_1 ∂/∂x_12
sage: rivf[2].display(coord_frame)
XR_12 = ∂/∂x_12>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(2))>>> G = L.lie_group()>>> rivf = G.right_invariant_frame(); rivf
Vector frame (G, (XR_1,XR_2,XR_12))>>> coord_frame = G.chart_exp1().frame()>>> rivf[Integer(0)].display(coord_frame)
XR_1 = ∂/∂x_1 + 1/2*x_2 ∂/∂x_12>>> rivf[Integer(1)].display(coord_frame)
XR_2 = ∂/∂x_2 - 1/2*x_1 ∂/∂x_12>>> rivf[Integer(2)].display(coord_frame)
XR_12 = ∂/∂x_12

Examples of custom labeling for the frame:
sage: G.right_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))
sage: G.right_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))
sage: G.right_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))>>> from sage.all import *>>> G.right_invariant_frame(symbol= Y )Vector frame (G, (Y_1,Y_2,Y_12))>>> G.right_invariant_frame(symbol= Z , indices=None)
Vector frame (G, (Z_0,Z_1,Z_2))>>> G.right_invariant_frame(symbol= W , indices=( a , b , c ))Vector frame (G, (W_a,W_b,W_c))step()
Return the nilpotency step of self.
EXAMPLES:
sage: L = LieAlgebra(QQ, 2, step=4)
sage: G = L.lie_group()
sage: G.step()
4734

Chapter 29. Lie Groups

Groups, Release 10.4>>> from sage.all import *>>> L = LieAlgebra(QQ, Integer(2), step=Integer(4))>>> G = L.lie_group()>>> G.step()
4

29.1. Nilpotent Lie groups

735

Groups, Release 10.4

736

Chapter 29. Lie Groups

CHAPTERTHIRTYPARTITION REFINEMENT

30.1 Canonical augmentation
This module implements a general algorithm for generating isomorphism classes of objects. The class of objects inquestion must be some kind of structure which can be built up out of smaller objects by a process of augmentation, andfor which an automorphism is a permutation in 𝑆𝑛 for some 𝑛. This process consists of starting with a finite number of“seed objects” and building up to more complicated objects by a sequence of “augmentations.” It should be noted thatthe word “canonical” in the term canonical augmentation is used loosely. Given an object 𝑋, one must define a canonicalparent 𝑀 (𝑋), which is essentially an arbitrary choice.
The class of objects in question must satisfy the assumptions made in the module automorphism_group_canonical_label, in particular the three custom functions mentioned there must be implemented:
A. refine_and_return_invariant:Signature:
int refine_and_return_invariant(PartitionStack *PS, void *S, int*cells_to_refine_by, int ctrb_len)
B. compare_structures:
Signature:
int compare_structures(int *gamma_1, int *gamma_2, void *S1, void
*S2, int degree)
C. all_children_are_equivalent:
Signature:bint all_children_are_equivalent(PartitionStack *PS, void *S)
In the following functions there is frequently a mem_err input. This is a pointer to an integer which must be set to anonzero value in case of an allocation failure. Other functions have an int return value which serves the same purpose.
The idea is that if a memory error occurs, the canonical generator should still be able to iterate over the objects alreadygenerated before it terminates.
More details about these functions can be found in that module. In addition, several other functions must be implemented,
which will make use of the following:
ctypedef struct iterator:
void *data
void *(*next)(void *data, int *degree, int *mem_err)

The following functions must be implemented for each specific type of object to be generated. Each function following
which takes a mem_err variable as input should make use of this variable.

737

Groups, Release 10.4

D. generate_children:
Signature:
int generate_children(void *S, aut_gp_and_can_lab *group, iterator*it)This function receives a pointer to an iterator it. The iterator has two fields: data and next. The
function generate_children should set these two fields, returning 1 to indicate a memory error,
or 0 for no error.
The function that next points to takes data as an argument, and should return a (void *) pointerto the next object to be iterated. It also takes a pointer to an int, and must update that int to reflect thedegree of each generated object. The objects to be iterated over should satisfy the property that if 𝛾 isan automorphism of the parent object 𝑆, then for any two child objects 𝐶1 , 𝐶2 given by the iterator, it
is not the case that 𝛾(𝐶1 ) = 𝐶2 , where in the latter 𝛾 is appropriately extended if necessary to operate
on 𝐶1 and 𝐶2 . It is essential for this iterator to handle its own data. If the next function is called
and no suitable object is yielded, a NULL pointer indicates a termination of the iteration. At this point,
the data pointed to by the data variable should be cleared by the next function, because the iterator
struct itself will be deallocated.
The next function must check mem_err[0] before proceeding. If it is nonzero then the function
should deallocate the iterator right away and return NULL to end the iteration. This ensures that the
canonical augmentation software will finish iterating over the objects found before finishing, and themem_err attribute of the canonical_generator_data will reflect this.
The objects which the iterator generates can be thought of as augmentations, which the following function must turn into objects.
E. apply_augmentation:
Signature:void *apply_augmentation(void *parent, void *aug, void *child, int*degree, bint *mem_err)
This function takes the parent, applies the augmentation aug and returns a pointer to the corresponding child object (freeing aug if necessary). Should also update degree[0] to be the degree of the new
child.
F. free_object:
Signature:void free_object(void *child)This function is a simple deallocation function for children which are not canonically generated, andtherefore rejected in the canonical augmentation process. They should deallocate the contents ofchild.
G. free_iter_data:
Signature:void free_iter_data(void *data)
This function deallocates the data part of the iterator which is set up by generate_children.
H. free_aug:
Signature:void free_aug(void *aug)
This function frees an augmentation as generated by the iterator returned by generate_children.
738

Chapter 30. Partition Refinement

Groups, Release 10.4

I. canonical_parent:
Signature:void *canonical_parent(void *child, void *parent, int *permutation,
int *degree, bint *mem_err)
Apply the permutation to the child, determine an arbitrary but fixed parent, apply the inverseof permutation to that parent, and return the resulting object. Must also set the integer degree
points to the degree of the returned object.
Note: It is a good idea to try to implement an augmentation scheme where the degree of objects on each level of theaugmentation tree is constant. The iteration will be more efficient in this case, as the relevant work spaces will never need
to be reallocated. Otherwise, one should at least strive to iterate over augmentations in such a way that all children of thesame degree are given in the same segment of iteration.
EXAMPLES:
sage: import sage.groups.perm_gps.partn_ref.canonical_augmentation>>> from sage.all import *>>> import sage.groups.perm_gps.partn_ref.canonical_augmentation

REFERENCE:• [1] McKay, Brendan D. Isomorph-free exhaustive generation. J Algorithms, Vol. 26 (1998), pp. 306-324.

30.2 Data structures
This module implements basic data structures essential to the rest of the partn_ref module.
REFERENCES:[1] McKay, Brendan D. Practical Graph Isomorphism. Congressus Numerantium,
Vol. 30 (1981), pp. 45-87.
[2] Fredman, M. and Saks, M. The cell probe complexity of dynamic data
structures. Proceedings of the Twenty-First Annual ACM Symposium on Theory of Computing, pp.
345–354. May 1989.
[3] Seress, Akos. Permutation Group Algorithms. Cambridge University Press,
2003.
sage.groups.perm_gps.partn_ref.data_structures.OP_represent(n, merges, perm)
Demonstration and testing.
sage.groups.perm_gps.partn_ref.data_structures.PS_represent(partition, splits)
Demonstration and testing.
sage.groups.perm_gps.partn_ref.data_structures.SC_test_list_perms(L, n, limit, gap,
limit_complain,
test_contains)
Test that the permutation group generated by list perms in L of degree n is of the correct order, by comparing with
GAP. Don’t test if the group is of size greater than limit.

30.2. Data structures739

Groups, Release 10.4

30.3 Graph-theoretic partition backtrack functions
EXAMPLES:
sage: import sage.groups.perm_gps.partn_ref.refinement_graphs>>> from sage.all import *>>> import sage.groups.perm_gps.partn_ref.refinement_graphs

REFERENCE:• [1] McKay, Brendan D. Practical Graph Isomorphism. Congressus Numerantium, Vol. 30 (1981), pp. 45-87.
class sage.groups.perm_gps.partn_ref.refinement_graphs.GraphStruct
Bases: object
sage.groups.perm_gps.partn_ref.refinement_graphs.all_labeled_graphs(n)Return all labeled graphs on n vertices {0,1,…,n-1}.
Used in classifying isomorphism types (naive approach), and more importantly in benchmarking the search algorithm.
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import all_labeled_
˓→graphssage: st = sage.groups.perm_gps.partn_ref.refinement_graphs.search_tree
sage: Glist = {}sage: Giso = {}sage: for n in [1..5]: # long time (4s on sage.math, 2011)....: Glist[n] = all_labeled_graphs(n)....: Giso[n] = []....: for g in Glist[n]:....:a, b = st(g, [range(n)])....:
inn = False....:
for gi in Giso[n]:....:if b == gi:....:
inn = True....:
if not inn:....:
Giso[n].append(b)sage: for n in Giso: # long time....:
print("{} {}".format(n, len(Giso[n])))
1 1
2 2
3 4
4 11
5 34
>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import all_labeled_
˓→graphs>>> st = sage.groups.perm_gps.partn_ref.refinement_graphs.search_tree>>> Glist = {}>>> Giso = {}>>> for n in (ellipsis_range(Integer(1),Ellipsis,Integer(5))): # long time (4s␣˓→on sage.math, 2011)... Glist[n] = all_labeled_graphs(n)(continues on next page)

740

Chapter 30. Partition Refinement

Groups, Release 10.4

(continued from previous page)... Giso[n] = []... for g in Glist[n]:...
a, b = st(g, [range(n)])...
inn = False...
for gi in Giso[n]:...
if b == gi:...
inn = True...
if not inn:...
Giso[n].append(b)>>> for n in Giso: # long time...
print("{} {}".format(n, len(Giso[n])))
1 1
2 2
3 4
4 11
5 34

sage.groups.perm_gps.partn_ref.refinement_graphs.coarsest_equitable_refinement(G,partition,
directed)
Return the coarsest equitable refinement of partition for G.
This is a helper function for the graph function of the same name.
DOCTEST (More thorough testing in sage/graphs/graph.py):
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import coarsest_
˓→equitable_refinement
sage: from sage.graphs.base.sparse_graph import SparseGraphsage: coarsest_equitable_refinement(SparseGraph(7), [[0], [1,2,3,4], [5,6]], 0)[[0], [1, 2, 3, 4], [5, 6]]>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import coarsest_
˓→equitable_refinement>>> from sage.graphs.base.sparse_graph import SparseGraph>>> coarsest_equitable_refinement(SparseGraph(Integer(7)), [[Integer(0)],␣
˓→[Integer(1),Integer(2),Integer(3),Integer(4)], [Integer(5),Integer(6)]],␣
˓→Integer(0))[[0], [1, 2, 3, 4], [5, 6]]

sage.groups.perm_gps.partn_ref.refinement_graphs.generate_dense_graphs_edge_addition(n,loops,
G=Nonedepth=N
construct=F
indicate_mem
EXAMPLES:

30.3. Graph-theoretic partition backtrack functions

741

Groups, Release 10.4

sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import generate_dense_
˓→graphs_edge_addition>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import generate_dense_
˓→graphs_edge_addition
sage: for n in [0..6]:....:
print(generate_dense_graphs_edge_addition(n,1))
1
2
6
20
90
544
5096
>>> from sage.all import *>>> for n in (ellipsis_range(Integer(0),Ellipsis,Integer(6))):...
print(generate_dense_graphs_edge_addition(n,Integer(1)))
1
2
6
20
90
544
5096
sage: for n in [0..7]:....:
print(generate_dense_graphs_edge_addition(n,0))
1
1
2
4
11
34
156
1044
sage: generate_dense_graphs_edge_addition(8,0) # long time (about 14 seconds at␣˓→2.4 GHz)
12346>>> from sage.all import *>>> for n in (ellipsis_range(Integer(0),Ellipsis,Integer(7))):...
print(generate_dense_graphs_edge_addition(n,Integer(0)))
1
1
2
4
11
34
156
1044
>>> generate_dense_graphs_edge_addition(Integer(8),Integer(0)) # long time␣˓→(about 14 seconds at 2.4 GHz)
12346

742

Chapter 30. Partition Refinement

Groups, Release 10.4

sage.groups.perm_gps.partn_ref.refinement_graphs.generate_dense_graphs_vert_addition(n,base_G=
construct=F
indicate_mem
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import generate_dense_
˓→graphs_vert_addition>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import generate_dense_
˓→graphs_vert_addition
sage: for n in [0..7]:....:
generate_dense_graphs_vert_addition(n)
1
2
4
8
19
53
209
1253
sage: generate_dense_graphs_vert_addition(8) # long time13599>>> from sage.all import *>>> for n in (ellipsis_range(Integer(0),Ellipsis,Integer(7))):...
generate_dense_graphs_vert_addition(n)
1
2
4
8
19
53
209
1253
>>> generate_dense_graphs_vert_addition(Integer(8)) # long time13599

sage.groups.perm_gps.partn_ref.refinement_graphs.get_orbits(gens, n)Compute orbits given a list of generators of a permutation group, in list format.
This is a helper function for automorphism groups of graphs.
DOCTEST (More thorough testing in sage/graphs/graph.py):
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import get_orbits
sage: get_orbits([[1,2,3,0,4,5], [0,1,2,3,5,4]], 6)[[0, 1, 2, 3], [4, 5]]>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import get_orbits(continues on next page)30.3. Graph-theoretic partition backtrack functions

743

Groups, Release 10.4

(continued from previous page)>>> get_orbits([[Integer(1),Integer(2),Integer(3),Integer(0),Integer(4),˓→Integer(5)], [Integer(0),Integer(1),Integer(2),Integer(3),Integer(5),˓→Integer(4)]], Integer(6))[[0, 1, 2, 3], [4, 5]]

sage.groups.perm_gps.partn_ref.refinement_graphs.isomorphic(G1, G2, partn, ordering2,
dig, use_indicator_function,
sparse=False)
Test whether two graphs are isomorphic.
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import isomorphic
sage: G = Graph(2)sage: H = Graph(2)sage: isomorphic(G, H, [[0,1]], [0,1], 0, 1){0: 0, 1: 1}
sage: isomorphic(G, H, [[0,1]], [0,1], 0, 1){0: 0, 1: 1}
sage: isomorphic(G, H, [[0],[1]], [0,1], 0, 1){0: 0, 1: 1}
sage: isomorphic(G, H, [[0],[1]], [1,0], 0, 1){0: 1, 1: 0}
sage: G = Graph(3)sage: H = Graph(3)sage: isomorphic(G, H, [[0,1,2]], [0,1,2], 0, 1){0: 0, 1: 1, 2: 2}
sage: G.add_edge(0,1)
sage: isomorphic(G, H, [[0,1,2]], [0,1,2], 0, 1)
False
sage: H.add_edge(1,2)
sage: isomorphic(G, H, [[0,1,2]], [0,1,2], 0, 1){0: 1, 1: 2, 2: 0}>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import isomorphic>>> G = Graph(Integer(2))>>> H = Graph(Integer(2))>>> isomorphic(G, H, [[Integer(0),Integer(1)]], [Integer(0),Integer(1)],␣
˓→Integer(0), Integer(1)){0: 0, 1: 1}>>> isomorphic(G, H, [[Integer(0),Integer(1)]], [Integer(0),Integer(1)],␣
˓→Integer(0), Integer(1)){0: 0, 1: 1}>>> isomorphic(G, H, [[Integer(0)],[Integer(1)]], [Integer(0),Integer(1)],␣
˓→Integer(0), Integer(1)){0: 0, 1: 1}>>> isomorphic(G, H, [[Integer(0)],[Integer(1)]], [Integer(1),Integer(0)],␣
˓→Integer(0), Integer(1)){0: 1, 1: 0}>>> G = Graph(Integer(3))>>> H = Graph(Integer(3))(continues on next page)

744

Chapter 30. Partition Refinement

Groups, Release 10.4

(continued from previous page)>>> isomorphic(G, H, [[Integer(0),Integer(1),Integer(2)]], [Integer(0),Integer(1),˓→Integer(2)], Integer(0), Integer(1)){0: 0, 1: 1, 2: 2}>>> G.add_edge(Integer(0),Integer(1))>>> isomorphic(G, H, [[Integer(0),Integer(1),Integer(2)]], [Integer(0),Integer(1),˓→Integer(2)], Integer(0), Integer(1))
False>>> H.add_edge(Integer(1),Integer(2))>>> isomorphic(G, H, [[Integer(0),Integer(1),Integer(2)]], [Integer(0),Integer(1),˓→Integer(2)], Integer(0), Integer(1)){0: 1, 1: 2, 2: 0}

sage.groups.perm_gps.partn_ref.refinement_graphs.orbit_partition(gamma,
list_perm=False)
Assuming that G is a graph on vertices 0,1,…,n-1, and gamma is an element of SymmetricGroup(n), returns thepartition of the vertex set determined by the orbits of gamma, considered as action on the set 1,2,…,n where wetake 0 = n. In other words, returns the partition determined by a cyclic representation of gamma.
INPUT:• list_perm – if True, assumes gamma is a list representing the map 𝑖 ↦→ ``𝑔𝑎𝑚𝑚𝑎``[𝑖]
EXAMPLES:
sage: # needs sage.groups
sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import orbit_partition
sage: G = graphs.PetersenGraph()
sage: S = SymmetricGroup(10)sage: gamma = S( (10,1,2,3,4)(5,6,7)(8,9) )sage: orbit_partition(gamma)[[1, 2, 3, 4, 0], [5, 6, 7], [8, 9]]
sage: gamma = S( (10,5)(1,6)(2,7)(3,8)(4,9) )sage: orbit_partition(gamma)[[1, 6], [2, 7], [3, 8], [4, 9], [5, 0]]>>> from sage.all import *>>> # needs sage.groups>>> from sage.groups.perm_gps.partn_ref.refinement_graphs import orbit_partition>>> G = graphs.PetersenGraph()>>> S = SymmetricGroup(Integer(10))>>> gamma = S( (10,1,2,3,4)(5,6,7)(8,9) )>>> orbit_partition(gamma)[[1, 2, 3, 4, 0], [5, 6, 7], [8, 9]]>>> gamma = S( (10,5)(1,6)(2,7)(3,8)(4,9) )>>> orbit_partition(gamma)[[1, 6], [2, 7], [3, 8], [4, 9], [5, 0]]sage.groups.perm_gps.partn_ref.refinement_graphs.random_tests(num=10, n_max=60,
perms_per_graph=5)
Tests to make sure that C(gamma(G)) == C(G) for random permutations gamma and random graphs G, and thatisomorphic returns an isomorphism.
INPUT:• num – run tests for this many graphs• n_max – test graphs with at most this many vertices

30.3. Graph-theoretic partition backtrack functions

745

Groups, Release 10.4

• perms_per_graph – test each graph with this many random permutations
DISCUSSION:
This code generates num random graphs G on at most n_max vertices. The density of edges is chosen randomly
between 0 and 1.
For each graph G generated, we uniformly generate perms_per_graph random permutations and verify that the
canonical labels of G and the image of G under the generated permutation are equal, and that the isomorphic
function returns an isomorphism.
sage.groups.perm_gps.partn_ref.refinement_graphs.search_tree(G_in, partition, lab=True,
dig=False,
dict_rep=False,
certificate=False,verbosity=0, use_indicator_function=True,sparse=True, base=False,order=False)
Compute canonical labels and automorphism groups of graphs.
INPUT:• G_in – a Sage graph• partition – a list of lists representing a partition of the vertices• lab – if True, compute and return the canonical label in addition to the automorphism group• dig – set to True for digraphs and graphs with loops. If True, does not use optimizations based on Lemma
2.25 in [1] that are valid only for simple graphs.
• dict_rep – if True, return a dictionary with keys the vertices of the input graph G_in and values elementsof the set the permutation group acts on. (The point is that graphs are arbitrarily labelled, often 0..n-1, andpermutation groups always act on 1..n. This dictionary maps vertex labels (such as 0..n-1) to the domain of
the permutations.)• certificate – if True, return the permutation from G to its canonical label.
• verbosity – currently ignored• use_indicator_function – option to turn off indicator function (True is generally faster)• sparse – whether to use sparse or dense representation of the graph (ignored if G is already a CGraph see sage.graphs.base)• base – whether to return the first sequence of split vertices (used in computing the order of the group)• order – whether to return the order of the automorphism group
OUTPUT:
Depends on the options. If more than one thing is returned, they are in a tuple in the following order:• list of generators in list-permutation format – always• dict – if dict_rep• graph – if lab• dict – if certificate• list – if base• integer – if order746

Chapter 30. Partition Refinement

Groups, Release 10.4

EXAMPLES:
sage: st = sage.groups.perm_gps.partn_ref.refinement_graphs.search_tree
sage: from sage.graphs.base.dense_graph import DenseGraphsage: from sage.graphs.base.sparse_graph import SparseGraph>>> from sage.all import *>>> st = sage.groups.perm_gps.partn_ref.refinement_graphs.search_tree>>> from sage.graphs.base.dense_graph import DenseGraph>>> from sage.graphs.base.sparse_graph import SparseGraph

Graphs on zero vertices:sage: G = Graph()
sage: st(G, [[]], order=True)([], Graph on 0 vertices, 1)>>> from sage.all import *>>> G = Graph()>>> st(G, [[]], order=True)([], Graph on 0 vertices, 1)

Graphs on one vertex:
sage: G = Graph(1)sage: st(G, [[0]], order=True)([], Graph on 1 vertex, 1)>>> from sage.all import *>>> G = Graph(Integer(1))>>> st(G, [[Integer(0)]], order=True)([], Graph on 1 vertex, 1)

Graphs on two vertices:sage: G = Graph(2)sage: st(G, [[0,1]], order=True)([[1, 0]], Graph on 2 vertices, 2)
sage: st(G, [[0],[1]], order=True)([], Graph on 2 vertices, 1)
sage: G.add_edge(0,1)
sage: st(G, [[0,1]], order=True)([[1, 0]], Graph on 2 vertices, 2)
sage: st(G, [[0],[1]], order=True)([], Graph on 2 vertices, 1)>>> from sage.all import *>>> G = Graph(Integer(2))>>> st(G, [[Integer(0),Integer(1)]], order=True)([[1, 0]], Graph on 2 vertices, 2)>>> st(G, [[Integer(0)],[Integer(1)]], order=True)([], Graph on 2 vertices, 1)>>> G.add_edge(Integer(0),Integer(1))>>> st(G, [[Integer(0),Integer(1)]], order=True)([[1, 0]], Graph on 2 vertices, 2)>>> st(G, [[Integer(0)],[Integer(1)]], order=True)([], Graph on 2 vertices, 1)

30.3. Graph-theoretic partition backtrack functions

747

Groups, Release 10.4

Graphs on three vertices:sage: G = Graph(3)sage: st(G, [[0,1,2]], order=True)([[0, 2, 1], [1, 0, 2]], Graph on 3 vertices, 6)
sage: st(G, [[0],[1,2]], order=True)([[0, 2, 1]], Graph on 3 vertices, 2)
sage: st(G, [[0],[1],[2]], order=True)([], Graph on 3 vertices, 1)
sage: G.add_edge(0,1)
sage: st(G, [range(3)], order=True)([[1, 0, 2]], Graph on 3 vertices, 2)
sage: st(G, [[0],[1,2]], order=True)([], Graph on 3 vertices, 1)
sage: st(G, [[0,1],[2]], order=True)([[1, 0, 2]], Graph on 3 vertices, 2)>>> from sage.all import *>>> G = Graph(Integer(3))>>> st(G, [[Integer(0),Integer(1),Integer(2)]], order=True)([[0, 2, 1], [1, 0, 2]], Graph on 3 vertices, 6)>>> st(G, [[Integer(0)],[Integer(1),Integer(2)]], order=True)([[0, 2, 1]], Graph on 3 vertices, 2)>>> st(G, [[Integer(0)],[Integer(1)],[Integer(2)]], order=True)([], Graph on 3 vertices, 1)>>> G.add_edge(Integer(0),Integer(1))>>> st(G, [range(Integer(3))], order=True)([[1, 0, 2]], Graph on 3 vertices, 2)>>> st(G, [[Integer(0)],[Integer(1),Integer(2)]], order=True)([], Graph on 3 vertices, 1)>>> st(G, [[Integer(0),Integer(1)],[Integer(2)]], order=True)([[1, 0, 2]], Graph on 3 vertices, 2)

The Dodecahedron has automorphism group of size 120:sage: G = graphs.DodecahedralGraph()
sage: Pi = [range(20)]sage: st(G, Pi, order=True)[2]120>>> from sage.all import *>>> G = graphs.DodecahedralGraph()>>> Pi = [range(Integer(20))]>>> st(G, Pi, order=True)[Integer(2)]120

The three-cube has automorphism group of size 48:
sage: G = graphs.CubeGraph(3)sage: G.relabel()
sage: Pi = [G.vertices(sort=False)]
sage: st(G, Pi, order=True)[2]48>>> from sage.all import *>>> G = graphs.CubeGraph(Integer(3))>>> G.relabel()(continues on next page)

748

Chapter 30. Partition Refinement

Groups, Release 10.4

(continued from previous page)>>> Pi = [G.vertices(sort=False)]>>> st(G, Pi, order=True)[Integer(2)]48

We obtain the same output using different types of Sage graphs:
sage: G = graphs.DodecahedralGraph()
sage: GD = DenseGraph(20)sage: GS = SparseGraph(20)sage: for i,j,_ in G.edge_iterator():....: GD.add_arc(i,j); GD.add_arc(j,i)....: GS.add_arc(i,j); GS.add_arc(j,i)
sage: Pi = [range(20)]sage: a,b = st(G, Pi)
sage: asp,bsp = st(GS, Pi)
sage: ade,bde = st(GD, Pi)
sage: bsg = Graph()
sage: bdg = Graph()
sage: for i in range(20):....:for j in range(20):....:if bsp.has_arc(i,j):....:bsg.add_edge(i,j)....:
if bde.has_arc(i,j):....:bdg.add_edge(i,j)
sage: a, b.graph6_string()([[0, 19, 3, 2, 6, 5, 4, 17, 18, 11, 10, 9, 13, 12, 16, 15, 14, 7, 8, 1],[0, 1, 8, 9, 13, 14, 7, 6, 2, 3, 19, 18, 17, 4, 5, 15, 16, 12, 11, 10],
[1, 8, 9, 10, 11, 12, 13, 14, 7, 6, 2, 3, 4, 5, 15, 16, 17, 18, 19, 0]],S?[PG__OQ@?_?_?P?CO?_?AE?EC?Ac?@O )sage: a == asp
True
sage: a == ade
True
sage: b == bsg
True
sage: b == bdg
True>>> from sage.all import *>>> G = graphs.DodecahedralGraph()>>> GD = DenseGraph(Integer(20))>>> GS = SparseGraph(Integer(20))>>> for i,j,_ in G.edge_iterator():... GD.add_arc(i,j); GD.add_arc(j,i)... GS.add_arc(i,j); GS.add_arc(j,i)>>> Pi = [range(Integer(20))]>>> a,b = st(G, Pi)>>> asp,bsp = st(GS, Pi)>>> ade,bde = st(GD, Pi)>>> bsg = Graph()>>> bdg = Graph()>>> for i in range(Integer(20)):...
for j in range(Integer(20)):...
if bsp.has_arc(i,j):...
bsg.add_edge(i,j)...
if bde.has_arc(i,j):(continues on next page)30.3. Graph-theoretic partition backtrack functions

749

Groups, Release 10.4

(continued from previous page)...
bdg.add_edge(i,j)>>> a, b.graph6_string()([[0, 19, 3, 2, 6, 5, 4, 17, 18, 11, 10, 9, 13, 12, 16, 15, 14, 7, 8, 1],[0, 1, 8, 9, 13, 14, 7, 6, 2, 3, 19, 18, 17, 4, 5, 15, 16, 12, 11, 10],
[1, 8, 9, 10, 11, 12, 13, 14, 7, 6, 2, 3, 4, 5, 15, 16, 17, 18, 19, 0]],S?[PG__OQ@?_?_?P?CO?_?AE?EC?Ac?@O )>>> a == asp
True>>> a == ade
True>>> b == bsg
True>>> b == bdg
True

Cubes!:
sage: C = graphs.CubeGraph(1)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order2
sage: C = graphs.CubeGraph(2)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order8
sage: C = graphs.CubeGraph(3)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order48
sage: C = graphs.CubeGraph(4)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order384
sage: C = graphs.CubeGraph(5)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order3840
sage: C = graphs.CubeGraph(6)sage: gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order46080>>> from sage.all import *>>> C = graphs.CubeGraph(Integer(1))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order2>>> C = graphs.CubeGraph(Integer(2))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order8>>> C = graphs.CubeGraph(Integer(3))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order48>>> C = graphs.CubeGraph(Integer(4))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order384>>> C = graphs.CubeGraph(Integer(5))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order3840>>> C = graphs.CubeGraph(Integer(6))>>> gens, order = st(C, [C.vertices(sort=False)], lab=False, order=True); order46080

One can also turn off the indicator function (note: this will take longer):
750

Chapter 30. Partition Refinement

Groups, Release 10.4

sage: D1 = DiGraph({0:[2],2:[0],1:[1]}, loops=True)
sage: D2 = DiGraph({1:[2],2:[1],0:[0]}, loops=True)
sage: a,b = st(D1, [D1.vertices(sort=False)], dig=True, use_indicator_
˓→function=False)
sage: c,d = st(D2, [D2.vertices(sort=False)], dig=True, use_indicator_
˓→function=False)
sage: b==dTrue>>> from sage.all import *>>> D1 = DiGraph({Integer(0):[Integer(2)],Integer(2):[Integer(0)],˓→Integer(1):[Integer(1)]}, loops=True)>>> D2 = DiGraph({Integer(1):[Integer(2)],Integer(2):[Integer(1)],
˓→Integer(0):[Integer(0)]}, loops=True)>>> a,b = st(D1, [D1.vertices(sort=False)], dig=True, use_indicator_
˓→function=False)>>> c,d = st(D2, [D2.vertices(sort=False)], dig=True, use_indicator_
˓→function=False)>>> b==dTrueThis example is due to Chris Godsil:
sage: HS = graphs.HoffmanSingletonGraph()
sage: alqs = [Set(c) for c in (HS.complement()).cliques_maximum()]
sage: Y = Graph([alqs, lambda s,t: len(s.intersection(t))==0])
sage: Y0,Y1 = Y.connected_components_subgraphs()sage: st(Y0, [Y0.vertices(sort=False)])[1] == st(Y1, [Y1.vertices(sort=False)])[1]
True
sage: st(Y0, [Y0.vertices(sort=False)])[1] == st(HS, [HS.vertices(sort=False)])[1]
True
sage: st(HS, [HS.vertices(sort=False)])[1] == st(Y1, [Y1.vertices(sort=False)])[1]
True>>> from sage.all import *>>> HS = graphs.HoffmanSingletonGraph()>>> alqs = [Set(c) for c in (HS.complement()).cliques_maximum()]>>> Y = Graph([alqs, lambda s,t: len(s.intersection(t))==Integer(0)])>>> Y0,Y1 = Y.connected_components_subgraphs()>>> st(Y0, [Y0.vertices(sort=False)])[Integer(1)] == st(Y1, [Y1.
˓→vertices(sort=False)])[Integer(1)]True>>> st(Y0, [Y0.vertices(sort=False)])[Integer(1)] == st(HS, [HS.
˓→vertices(sort=False)])[Integer(1)]True>>> st(HS, [HS.vertices(sort=False)])[Integer(1)] == st(Y1, [Y1.
˓→vertices(sort=False)])[Integer(1)]True

Certain border cases need to be tested as well:sage: G = Graph( Fll^G )sage: a,b,c = st(G, [range(G.num_verts())], order=True); b
Graph on 7 vertices
sage: c48
sage: G = Graph(21)(continues on next page)30.3. Graph-theoretic partition backtrack functions

751

Groups, Release 10.4

(continued from previous page)

sage: st(G, [range(G.num_verts())], order=True)[2] == factorial(21)True
sage: G = Graph( ^????????????????????{??N??@w??FaGa?PCO@CP?AGa?_QO?Q@G?CcA??cc???
˓→?Bo????{????F_ )sage: perm = {3:15, 15:3}
sage: H = G.relabel(perm, inplace=False)
sage: st(G, [range(G.num_verts())])[1] == st(H, [range(H.num_verts())])[1]
True
sage: st(Graph( :Dkw ), [range(5)], lab=False, dig=True)[[4, 1, 2, 3, 0], [0, 2, 1, 3, 4]]>>> from sage.all import *>>> G = Graph( Fll^G )>>> a,b,c = st(G, [range(G.num_verts())], order=True); b
Graph on 7 vertices>>> c48>>> G = Graph(Integer(21))>>> st(G, [range(G.num_verts())], order=True)[Integer(2)] ==␣
˓→factorial(Integer(21))
True>>> G = Graph( ^????????????????????{??N??@w??FaGa?PCO@CP?AGa?_QO?Q@G?CcA??cc????
˓→Bo????{????F_ )>>> perm = {Integer(3):Integer(15), Integer(15):Integer(3)}>>> H = G.relabel(perm, inplace=False)>>> st(G, [range(G.num_verts())])[Integer(1)] == st(H, [range(H.num_
˓→verts())])[Integer(1)]True>>> st(Graph( :Dkw ), [range(Integer(5))], lab=False, dig=True)[[4, 1, 2, 3, 0], [0, 2, 1, 3, 4]]

30.4 Partition backtrack functions for lists – a simple example of using partn_ref
EXAMPLES:
sage: import sage.groups.perm_gps.partn_ref.refinement_lists>>> from sage.all import *>>> import sage.groups.perm_gps.partn_ref.refinement_lists

sage.groups.perm_gps.partn_ref.refinement_lists.is_isomorphic(self, other)
Return the bijection as a permutation if two lists are isomorphic, return False otherwise.
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_lists import is_isomorphic
sage: is_isomorphic([0,0,1],[1,0,0])[1, 2, 0]752

Chapter 30. Partition Refinement

Groups, Release 10.4>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_lists import is_isomorphic>>> is_isomorphic([Integer(0),Integer(0),Integer(1)],[Integer(1),Integer(0),˓→Integer(0)])[1, 2, 0]30.5 Partition backtrack functions for matrices
EXAMPLES:
sage: import sage.groups.perm_gps.partn_ref.refinement_matrices>>> from sage.all import *>>> import sage.groups.perm_gps.partn_ref.refinement_matrices

REFERENCE:• [1] McKay, Brendan D. Practical Graph Isomorphism. Congressus Numerantium, Vol. 30 (1981), pp. 45-87.
• [2] Leon, Jeffrey. Permutation Group Algorithms Based on Partitions, I: Theory and Algorithms. J. Symbolic
Computation, Vol. 12 (1991), pp. 533-583.
class sage.groups.perm_gps.partn_ref.refinement_matrices.MatrixStruct
Bases: object
automorphism_group()
Return a list of generators of the automorphism group, along with its order and a base for which the list ofgenerators is a strong generating set.
For more examples, see self.run().
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]]))
sage: M.automorphism_group()([[0, 2, 1]], 2, [1])>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct>>> M = MatrixStruct(matrix(GF(Integer(3)),[[Integer(0),Integer(1),˓→Integer(2)],[Integer(0),Integer(2),Integer(1)]]))>>> M.automorphism_group()([[0, 2, 1]], 2, [1])canonical_relabeling()
Return a canonical relabeling (in list permutation format).
For more examples, see self.run().
EXAMPLES:

30.5. Partition backtrack functions for matrices

753

Groups, Release 10.4

sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]]))
sage: M.canonical_relabeling()[0, 1, 2]>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct>>> M = MatrixStruct(matrix(GF(Integer(3)),[[Integer(0),Integer(1),˓→Integer(2)],[Integer(0),Integer(2),Integer(1)]]))>>> M.canonical_relabeling()[0, 1, 2]display()
Display the matrix, and associated data.
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct
sage: M = MatrixStruct(Matrix(GF(5), [[0,1,1,4,4],[0,4,4,1,1]]))
sage: M.display()[0 1 1 4 4]
[0 4 4 1 1]
01100
00011
1
00011
01100
4
>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct>>> M = MatrixStruct(Matrix(GF(Integer(5)), [[Integer(0),Integer(1),˓→Integer(1),Integer(4),Integer(4)],[Integer(0),Integer(4),Integer(4),˓→Integer(1),Integer(1)]]))>>> M.display()[0 1 1 4 4]
[0 4 4 1 1]
<BLANKLINE>
01100
00011
1
<BLANKLINE>
00011
01100
4

is_isomorphic(other)
Calculate whether self is isomorphic to other.
EXAMPLES:
754

Chapter 30. Partition Refinement

Groups, Release 10.4

sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct
sage: M = MatrixStruct(Matrix(GF(11), [[1,2,3,0,0,0],[0,0,0,1,2,3]]))sage: N = MatrixStruct(Matrix(GF(11), [[0,1,0,2,0,3],[1,0,2,0,3,0]]))sage: M.is_isomorphic(N)[0, 2, 4, 1, 3, 5]>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct>>> M = MatrixStruct(Matrix(GF(Integer(11)), [[Integer(1),Integer(2),˓→Integer(3),Integer(0),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(1),Integer(2),Integer(3)]]))>>> N = MatrixStruct(Matrix(GF(Integer(11)), [[Integer(0),Integer(1),˓→Integer(0),Integer(2),Integer(0),Integer(3)],[Integer(1),Integer(0),˓→Integer(2),Integer(0),Integer(3),Integer(0)]]))>>> M.is_isomorphic(N)[0, 2, 4, 1, 3, 5]

run(partition=None)
Perform the canonical labeling and automorphism group computation, storing results to self.
INPUT:• partition – an optional list of lists partition of the columns; default is the unit partition.
EXAMPLES:
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]]))
sage: M.run()sage: M.automorphism_group()([[0, 2, 1]], 2, [1])sage: M.canonical_relabeling()[0, 1, 2]
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1],[1,0,2],[1,2,0],[2,0,1],
˓→[2,1,0]]))sage: M.automorphism_group()[1] == 6
True
sage: M = MatrixStruct(matrix(GF(3),[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2]]))sage: M.automorphism_group()[1] == factorial(14)True>>> from sage.all import *>>> from sage.groups.perm_gps.partn_ref.refinement_matrices import␣
˓→MatrixStruct>>> M = MatrixStruct(matrix(GF(Integer(3)),[[Integer(0),Integer(1),˓→Integer(2)],[Integer(0),Integer(2),Integer(1)]]))>>> M.run()>>> M.automorphism_group()([[0, 2, 1]], 2, [1])>>> M.canonical_relabeling()(continues on next page)

30.5. Partition backtrack functions for matrices

755

Groups, Release 10.4

(continued from previous page)[0, 1, 2]>>> M = MatrixStruct(matrix(GF(Integer(3)),[[Integer(0),Integer(1),˓→Integer(2)],[Integer(0),Integer(2),Integer(1)],[Integer(1),Integer(0),˓→Integer(2)],[Integer(1),Integer(2),Integer(0)],[Integer(2),Integer(0),˓→Integer(1)],[Integer(2),Integer(1),Integer(0)]]))>>> M.automorphism_group()[Integer(1)] == Integer(6)True>>> M = MatrixStruct(matrix(GF(Integer(3)),[[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(0),Integer(0),Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(0),Integer(0),Integer(0),Integer(0),Integer(1),˓→Integer(2)]]))>>> M.automorphism_group()[Integer(1)] == factorial(Integer(14))
Truesage.groups.perm_gps.partn_ref.refinement_matrices.random_tests(n=10,
nrows_max=50,
ncols_max=50,
nsymbols_max=10,
perms_per_matrix=5,
density_range=(0.1,
0.9))
Test to make sure that C(gamma(M)) == C(M) for random permutations gamma and random matrices M, andthat M.is_isomorphic(gamma(M)) returns an isomorphism.
INPUT:• n – run tests on this many matrices• nrows_max – test matrices with at most this many rows
• ncols_max – test matrices with at most this many columns• perms_per_matrix – test each matrix with this many random permutations• nsymbols_max – maximum number of distinct symbols in the matrix
This code generates n random matrices M on at most ncols_max columns and at most nrows_max rows. The densityof entries in the basis is chosen randomly between 0 and 1.
For each matrix M generated, we uniformly generate perms_per_matrix random permutations and verify that the
canonical labels of M and the image of M under the generated permutation are equal, and that the isomorphism is
discovered by the double coset function.

756

Chapter 30. Partition Refinement

CHAPTERTHIRTYONE

INTERNALS

31.1 Base for Classical Matrix Groups
This module implements the base class for matrix groups that have various famous names, like the general linear group.
EXAMPLES:
sage: SL(2, ZZ)
Special Linear Group of degree 2 over Integer Ringsage: G = SL(2, GF(3)); G
Special Linear Group of degree 2 over Finite Field of size 3
sage: # needs sage.libs.gap
sage: G.is_finite()True
sage: G.conjugacy_classes_representatives()([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0])sage: G = SL(6, GF(5))
sage: G.gens()([2 0 0 0 0 0] [4 0 0 0 0 1]
[0 3 0 0 0 0] [4 0 0 0 0 0]
[0 0 1 0 0 0] [0 4 0 0 0 0]
[0 0 0 1 0 0] [0 0 4 0 0 0]
[0 0 0 0 1 0] [0 0 0 4 0 0]
[0 0 0 0 0 1], [0 0 0 0 4 0])>>> from sage.all import *>>> SL(Integer(2), ZZ)
Special Linear Group of degree 2 over Integer Ring>>> G = SL(Integer(2), GF(Integer(3))); G
Special Linear Group of degree 2 over Finite Field of size 3>>> # needs sage.libs.gap>>> G.is_finite()
True>>> G.conjugacy_classes_representatives()([1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2][0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0](continues on next page)757

Groups, Release 10.4

(continued from previous page))>>> G = SL(Integer(6), GF(Integer(5)))>>> G.gens()([2 0 0 0 0 0] [4 0 0 0 0 1]
[0 3 0 0 0 0] [4 0 0 0 0 0]
[0 0 1 0 0 0] [0 4 0 0 0 0]
[0 0 0 1 0 0] [0 0 4 0 0 0]
[0 0 0 0 1 0] [0 0 0 4 0 0]
[0 0 0 0 0 1], [0 0 0 0 4 0])class sage.groups.matrix_gps.named_group.NamedMatrixGroup_generic(degree, base_ring,
special,sage_name,latex_string,
category=None,invariant_form=None)
Bases: CachedRepresentation, MatrixGroup_generic
Base class for “named” matrix groups.
INPUT:• degree – integer; the degree (number of rows/columns of matrices)• base_ring – ring; the base ring of the matrices• special – boolean; whether the matrix group is special, that is, elements have determinant one• sage_name – string; the name of the group• latex_string – string; the latex representation• category – (optional) a subcategory of sage.categories.groups.Groups passed to the constructor of sage.groups.matrix_gps.matrix_group.MatrixGroup_generic• invariant_form – (optional) square-matrix of the given degree over the given base_ring describing abilinear form to be kept invariant by the group
EXAMPLES:
sage: G = GL(2, QQ)
sage: from sage.groups.matrix_gps.named_group import NamedMatrixGroup_genericsage: isinstance(G, NamedMatrixGroup_generic)True>>> from sage.all import *>>> G = GL(Integer(2), QQ)>>> from sage.groups.matrix_gps.named_group import NamedMatrixGroup_generic>>> isinstance(G, NamedMatrixGroup_generic)
True

See also:
See the examples for GU(), SU(), Sp(), etc. as well.
sage.groups.matrix_gps.named_group.normalize_args_invariant_form(R, d,invariant_form)
758

Chapter 31. Internals

Groups, Release 10.4

Normalize the input of a user defined invariant bilinear form for orthogonal, unitary and symplectic groups.
Further informations and examples can be found in the defining functions (GU(), SU(), Sp(), etc.) for unitary,
symplectic groups, etc.
INPUT:• R – instance of the integral domain which should become the base_ring of the classical group• d – integer giving the dimension of the module the classical group is operating on• invariant_form – (optional) instances being accepted by the matrix-constructor that define a 𝑑 × 𝑑square matrix over R describing the bilinear form to be kept invariant by the classical group
OUTPUT:
None if invariant_form was not specified (or None). A matrix if the normalization was possible; otherwise
an error is raised.
AUTHORS:• Sebastian Oehms (2018-8) (see Issue #26028)
sage.groups.matrix_gps.named_group.normalize_args_vectorspace(*args, **kwds)
Normalize the arguments that relate to a vector space.
INPUT:
Something that defines an affine space. For example• An affine space itself:– A – affine space• A vector space:– V – a vector space• Degree and base ring:– degree – integer. The degree of the affine group, that is, the dimension of the affine space the groupis acting on.
– ring – a ring or an integer. The base ring of the affine space. If an integer is given, it must be a prime
power and the corresponding finite field is constructed.
– var= a – optional keyword argument to specify the finite field generator name in the case where
ring is a prime power.
OUTPUT: a pair (degree, ring)31.2 Base for Classical Matrix Groups with GAPclass sage.groups.matrix_gps.named_group_gap.NamedMatrixGroup_gap(degree, base_ring,
special,sage_name,latex_string,
gap_command_string,
category=None)

31.2. Base for Classical Matrix Groups with GAP

759

Groups, Release 10.4

Bases: NamedMatrixGroup_generic, MatrixGroup_gap
Base class for “named” matrix groups using LibGAP.
INPUT:• degree – integer; the degree (number of rows/columns of matrices)• base_ring – ring; the base ring of the matrices• special – boolean; whether the matrix group is special, that is, elements have determinant one• latex_string – string; the latex representation• gap_command_string – string; the GAP command to construct the matrix group
EXAMPLES:
sage: G = GL(2, GF(3))
sage: from sage.groups.matrix_gps.named_group_gap import NamedMatrixGroup_gap
sage: isinstance(G, NamedMatrixGroup_gap)
True>>> from sage.all import *>>> G = GL(Integer(2), GF(Integer(3)))>>> from sage.groups.matrix_gps.named_group_gap import NamedMatrixGroup_gap>>> isinstance(G, NamedMatrixGroup_gap)
True

760

Chapter 31. Internals

CHAPTERTHIRTYTWO

INDICES AND TABLES• Index• Module Index• Search Page

761

Groups, Release 10.4

762

Chapter 32. Indices and Tables

BIBLIOGRAPHY[Cohen1] H. Cohen, Advanced topics in computational number theory, Springer, 2000.
[Cohen2] H. Cohen, A course in computational algebraic number theory, Springer, 1996.
[Rotman] J. Rotman, An introduction to the theory of groups, 4th ed, Springer, 1995.

763

Groups, Release 10.4

764

Bibliography

PYTHON MODULE INDEX

gsage.groups.indexed_free_group, 215
sage.groups.abelian_gps.abelian_aut, 345 sage.groups.kernel_subgroup, 277
sage.groups.libgap_group, 33
sage.groups.abelian_gps.abelian_group,sage.groups.libgap_mixin, 35
307
sage.groups.libgap_morphism, 9
sage.groups.abelian_gps.abelian_group_elsage.groups.libgap_wrapper, 19
ement, 370
sage.groups.lie_gps.nilposage.groups.abelian_gps.abelian_group_gap,
tent_lie_group, 717
332
sage.groups.matrix_gps.binary_dihesage.groups.abelian_gps.abelian_group_mordral, 642
phism, 376
sage.groups.matrix_gps.catalog,
597
sage.groups.abelian_gps.dual_abelian_group,sage.groups.matrix_gps.coxeter_group,359
sage.groups.abelian_gps.dual_abelian_group_el- 643
sage.groups.matrix_gps.finitely_generement, 374
ated, 618
sage.groups.abelian_gps.element_base,sage.groups.matrix_gps.finitely_gener366
ated_gap, 625
sage.groups.abelian_gps.values, 352
sage.groups.matrix_gps.group_element,
sage.groups.additive_abelian.addi607
tive_abelian_group, 379
sage.groups.matrix_gps.group_elesage.groups.additive_abelian.addiment_gap, 612
tive_abelian_wrapper, 386
sage.groups.matrix_gps.heisenberg,
697
sage.groups.affine_gps.affine_group, 700
sage.groups.matrix_gps.homset,
641
sage.groups.affine_gps.eusage.groups.matrix_gps.isometries, 679
clidean_group, 708
sage.groups.matrix_gps.linear, 657
sage.groups.affine_gps.group_element,
sage.groups.matrix_gps.linear_gap, 665
711
sage.groups.matrix_gps.matrix_group, 597
sage.groups.artin, 221
sage.groups.matrix_gps.masage.groups.braid, 145
trix_group_gap, 604
sage.groups.cactus_group, 241
sage.groups.matrix_gps.morphism, 641
sage.groups.class_function, 281
sage.groups.matrix_gps.named_group, 757
sage.groups.conjugacy_classes, 299
sage.groups.matrix_gps.named_group_gap,
sage.groups.cubic_braid, 193
759
sage.groups.finitely_presented, 101
sage.groups.matrix_gps.orthogonal, 665
sage.groups.finitely_presented_named,
sage.groups.matrix_gps.orthogonal_gap,
137675
sage.groups.free_group, 91
sage.groups.matrix_gps.symplectic, 683
sage.groups.generic, 63
sage.groups.matrix_gps.symplectic_gap,
sage.groups.group, 3687
sage.groups.group_exp, 253
sage.groups.matrix_gps.unitary, 688
sage.groups.group_semidirect_product,
sage.groups.matrix_gps.unitary_gap, 696
259
sage.groups.misc_gps.argument_groups,
sage.groups.groups_catalog, 1765

Groups, Release 10.4

395
sage.groups.misc_gps.imaginary_groups,404
sage.groups.misc_gps.misc_groups, 267
sage.groups.pari_group, 59
sage.groups.perm_gps.constructor, 407
sage.groups.perm_gps.cubegroup, 570
sage.groups.perm_gps.partn_ref.canonical_augmentation, 737
sage.groups.perm_gps.partn_ref.data_structures, 739
sage.groups.perm_gps.partn_ref.refinement_graphs, 740
sage.groups.perm_gps.partn_ref.refinement_lists, 752
sage.groups.perm_gps.partn_ref.refinement_matrices, 753
sage.groups.perm_gps.permgroup, 412
sage.groups.perm_gps.permgroup_element, 550
sage.groups.perm_gps.permgroup_morphism, 565
sage.groups.perm_gps.permgroup_named,
500
sage.groups.perm_gps.permutation_groups_catalog, 407
sage.groups.perm_gps.symgp_conjugacy_class, 591
sage.groups.raag, 233
sage.groups.semimonomial_transformations.semimonomial_transformation, 273
sage.groups.semimonomial_transformations.semimonomial_transformation_group, 269

766

Python Module Index

INDEXA

sage.groups.abelian_gps.abelian_group_gap),
335
A()(sage.groups.affine_gps.group_element.AffineAbelianGroupMap(classinGroupElement method), 713
sage.groups.abelian_gps.abelian_group_morabelian_alexander_matrix()
phism), 376(sage.groups.finitely_presented.FinitelyPreAbelianGroupMorphism(classinsentedGroup method), 105
sage.groups.abelian_gps.abelian_group_morabelian_invariants() (sage.groups.finitely_prephism), 376
sented.FinitelyPresentedGroup method), 106
AbelianGroupQuotient_gap(classinabelian_invariants()
sage.groups.abelian_gps.abelian_group_gap),(sage.groups.free_group.FreeGroup_class336
method), 97
AbelianGroupSubgroup_gap(classin
AbelianGroup (class in sage.groups.group), 3
sage.groups.abelian_gps.abelian_group_gap),
AbelianGroup()(inmodule338
sage.groups.abelian_gps.abelian_group), 310
AbelianGroupWithValues()(inmoduleAbelianGroup_class(classin
sage.groups.abelian_gps.values),354
sage.groups.abelian_gps.abelian_group), 311(classin
AbelianGroup_gap(classin AbelianGroupWithValues_classsage.groups.abelian_gps.values),
357
sage.groups.abelian_gps.abelian_group_gap),
AbelianGroupWithValuesElement (class in339
sage.groups.abelian_gps.values), 355
AbelianGroup_subgroup(classin
AbelianGroupWithValuesEmbedding(class in
sage.groups.abelian_gps.abelian_group), 327
sage.groups.abelian_gps.values),
356
AbelianGroupAutomorphism(classinabelianization_map() (sage.groups.finitely_presage.groups.abelian_gps.abelian_aut), 347
sented.FinitelyPresentedGroup method), 107
AbelianGroupAutomorphismGroup (class inabelianization_to_algebra()sage.groups.abelian_gps.abelian_aut), 349(sage.groups.finitely_presented.FinitelyPreAbelianGroupAutomorphismGroup_gap (classsentedGroup method), 107
in sage.groups.abelian_gps.abelian_aut), 349
absolute_length()(sage.groups.perm_gps.perAbelianGroupAutomorphismGroup_subgroupmgroup_element.SymmetricGroupElement(class in sage.groups.abelian_gps.abelian_aut),
method), 563
351
AbelianGroupElement(classin AbstractArgument (class in sage.groups.misc_gps.argument_groups), 396
sage.groups.abelian_gps.abelian_group_eleAbstractArgumentGroup(classinment), 371
sage.groups.misc_gps.argument_groups), 396
AbelianGroupElement_gap(classin
act_to_right() (sage.groups.group_semidirect_prodsage.groups.abelian_gps.abelian_group_gap),
uct.GroupSemidirectProduct method), 261
332(sage.groups.maAbelianGroupElement_polycyclic (class in action_on_root_indices()
trix_gps.coxeter_group.CoxeterMatrixGroup.Elesage.groups.abelian_gps.abelian_group_gap),
ment method), 648
334(sage.groups.class_funcAbelianGroupElementBase(classin adams_operation()tion.ClassFunction_gap method), 282
sage.groups.abelian_gps.element_base), 366(sage.groups.class_funcAbelianGroupGap(classin adams_operation()
767

Groups, Release 10.4

tion.ClassFunction_libgap method), 289
ambient_group()(sage.groups.perm_gps.perAdditiveAbelianGroup()(inmodmgroup.PermutationGroup_subgroup method),ule
sage.groups.additive_abelian.addi498
tive_abelian_group), 379
an_element() (sage.groups.artin.ArtinGroup method),
AdditiveAbelianGroup_class(class222
insage.groups.additive_abelian.addi- an_element() (sage.groups.braid.BraidGroup_classtive_abelian_group), 382
method), 183
AdditiveAbelianGroup_fixed_gens(class an_element() (sage.groups.conjugacy_classes.Conjuin
sage.groups.additive_abelian.addigacyClass method), 300
tive_abelian_group), 384
an_element()(sage.groups.group_exp.GroupAdditiveAbelianGroupElement(class
Exp_Class method), 256insage.groups.additive_abelian.addi- annular_khovanov_complex()
tive_abelian_group), 382(sage.groups.braid.Braid method), 151
AdditiveAbelianGroupWrapper(class annular_khovanov_homology()
insage.groups.additive_abelian.addi(sage.groups.braid.Braid method), 151
tive_abelian_wrapper), 386
ArgumentByElement(classin
AdditiveAbelianGroupWrapperElement
sage.groups.misc_gps.argument_groups), 396(class in sage.groups.additive_abelian.addi- ArgumentByElementGroup(classintive_abelian_wrapper), 393
sage.groups.misc_gps.argument_groups), 396
adjoint()(sage.groups.lie_gps.nilpo- ArgumentGroup (in module sage.groups.misc_gps.argutent_lie_group.NilpotentLieGroupmethod),ment_groups), 397
722
ArgumentGroupFactory(classinAffineGroup(classin
sage.groups.misc_gps.argument_groups), 397
sage.groups.affine_gps.affine_group), 700
ArtinGroup (class in sage.groups.artin), 221
AffineGroupElement(classin ArtinGroupElement (class in sage.groups.artin), 226
sage.groups.affine_gps.group_element), 712
as_AbelianGroup()(sage.groups.perm_gps.peralexander_matrix()(sage.groups.finitely_premgroup_named.CyclicPermutationGroupsented.FinitelyPresentedGroup method), 108
method), 509
alexander_polynomial() (sage.groups.braid.Braid as_classical_group()(sage.groups.cumethod), 149
bic_braid.CubicBraidGroup method), 201
algebra()(sage.groups.perm_gps.per- as_finitely_presented_group()
mgroup_named.SymmetricGroupmethod),(sage.groups.perm_gps.permgroup.Permuta539
tionGroup_generic method), 421
algebra_generators()(sage.groups.raag.Coho- as_matrix_group() (sage.groups.cubic_braid.CumologyRAAG method), 233
bicBraidGroup method), 203
AlgebraicGroup (class in sage.groups.group), 3
as_matrix_group()(sage.groups.matrix_gps.maall_labeled_graphs()(inmoduletrix_group.MatrixGroup_base method), 598
sage.groups.perm_gps.partn_ref.refineas_permutation() (sage.groups.abelian_gps.abelian_group_elment_graphs), 740
ement.AbelianGroupElement method), 371
all_subgroups() (sage.groups.abelian_gps.abelian_group_gap.Abelianas_permutation_group() (sage.groups.artin.ArtinGroup_gap method), 340
Group method), 223
AlternatingGroup(classin as_permutation_group()
sage.groups.perm_gps.permgroup_named),(sage.groups.braid.BraidGroup_class method),
501
183
AlternatingPresentation()(inmodule as_permutation_group()(sage.groups.cusage.groups.finitely_presented_named), 138
bic_braid.CubicBraidGroup method), 205
ambient()(sage.groups.kernel_subgroup.KernelSub- as_permutation_group()group method), 277(sage.groups.finitely_presented.FinitelyPreambient() (sage.groups.libgap_wrapper.ParentLibGAP
sentedGroup method), 110
method), 25
as_permutation_group()(sage.groups.maambient() (sage.groups.matrix_gps.matrix_group.Matrix_gps.finitely_generated_gap.FinitelyGenerattrixGroup_base method), 597
edMatrixGroup_gap method), 626
ambient_group() (sage.groups.abelian_gps.abelian_group.Abelianas_reflection_group()(sage.groups.cuGroup_subgroup method), 327
bic_braid.CubicBraidGroup method), 205
768

Index

Groups, Release 10.4

AssionGroupS() (in module sage.groups.cubic_braid), BraidGroup_class (class in sage.groups.braid), 179
193
bsgs() (in module sage.groups.generic), 66
AssionGroupU() (in module sage.groups.cubic_braid), burau_matrix() (sage.groups.braid.Braid method),
194
153
AssionS (sage.groups.cubic_braid.CubicBraidGroup.type burau_matrix()(sage.groups.cubic_braid.Cuattribute), 214
bicBraidElement method), 195
AssionU (sage.groups.cubic_braid.CubicBraidGroup.typeCattribute), 214aut() (sage.groups.abelian_gps.abelian_group_gap.Abelian-CactusGroup (class in sage.groups.cactus_group), 241
Group_gap method), 340
CactusGroup.Element (class in sage.groups.cacautomorphism_group()
tus_group), 242(sage.groups.abelian_gps.abelian_group_gap.AbelianCactusPresentation()(inmoduleGroup_gap method), 341
sage.groups.finitely_presented_named), 138
automorphism_group()
canonical_matrix() (sage.groups.matrix_gps.cox(sage.groups.perm_gps.partn_ref.refinement_maeter_group.CoxeterMatrixGroup.Element
trices.MatrixStruct method), 753
method), 648
canonical_relabeling()B(sage.groups.perm_gps.partn_ref.refinement_mab()(sage.groups.affine_gps.group_element.Affinetrices.MatrixStruct method), 753
GroupElement method), 714
canonical_representation() (sage.groups.maB()(sage.groups.perm_gps.cubegroup.CubeGroup
trix_gps.coxeter_group.CoxeterMatrixGroupmethod), 573
method), 650
base() (sage.groups.perm_gps.permgroup.Permutation- cardinality() (sage.groups.abelian_gps.abelian_group.AbelianGroup_generic method), 423
Group_class method), 312
base_ring() (sage.groups.abelian_gps.dual_abelian_group.Ducardinality() (sage.groups.affine_gps.affine_group.AffinealAbelianGroup_class method), 361
Group method), 703
base_ring()(sage.groups.perm_gps.per- cardinality()(sage.groups.artin.ArtinGroupmgroup_named.PermutationGroup_plg method),
method), 223
524
cardinality() (sage.groups.braid.BraidGroup_classbase_ring()(sage.groups.perm_gps.permethod), 183
mgroup_named.SuzukiGroup method), 537
cardinality() (sage.groups.conjugacy_classes.Conjubase_ring()(sage.groups.semimonomial_transgacyClassGAP method), 304
formations.semimonomial_transformacardinality() (sage.groups.cubic_braid.CubicBraidtion_group.SemimonomialTransformationGroup
Group method), 208
method), 271
cardinality() (sage.groups.finitely_presented.Finitebasis_from_generators()(in
modlyPresentedGroup method), 110
ulesage.groups.additive_abelian.addi- cardinality()(sage.groups.libgap_mixin.Grouptive_abelian_wrapper), 394
MixinLibGAP method), 35
bilinear_form() (sage.groups.cactus_group.Cactus- cardinality() (sage.groups.matrix_gps.binary_diheGroup method), 244
dral.BinaryDihedralGroup method), 642
bilinear_form()(sage.groups.matrix_gps.cox- cardinality()(sage.groups.matrix_gps.heiseneter_group.CoxeterMatrixGroup method), 650
berg.HeisenbergGroup method), 698
BinaryDihedralGroup (class in sage.groups.ma- cardinality() (sage.groups.matrix_gps.linear.Lineartrix_gps.binary_dihedral), 642
MatrixGroup_generic method), 661
BinaryDihedralPresentation() (in module cardinality()(sage.groups.pari_group.PariGroupsage.groups.finitely_presented_named), 138
method), 59
blocks_all() (sage.groups.perm_gps.permgroup.Per- cardinality()(sage.groups.perm_gps.permutationGroup_generic method), 424
mgroup_named.PrimitiveGroupsOfDegree
Braid (class in sage.groups.braid), 146
method), 529
braid() (sage.groups.cubic_braid.CubicBraidElement cardinality()(sage.groups.perm_gps.permethod), 195
mgroup_named.TransitiveGroupsOfDegree
braid_group() (sage.groups.cubic_braid.CubicBraidmethod), 549
Group method), 207
cardinality()(sage.groups.perm_gps.perBraidGroup() (in module sage.groups.braid), 178
mgroup.PermutationGroup_genericmethod),
Index

769

Groups, Release 10.4

425
cartan_type()(sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),540
center()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 36
center() (sage.groups.matrix_gps.heisenberg.HeisenbergGroup method), 699
center() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 426
central_character()(sage.groups.class_function.ClassFunction_gap method), 283
central_character()(sage.groups.class_function.ClassFunction_libgap method), 290
centralizer() (sage.groups.braid.Braid method), 155
centralizer()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 38
centralizer()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),426
centralizing_element()(sage.groups.cubic_braid.CubicBraidGroup method), 208
character() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 39
character() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 427
character_table()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 40
character_table()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),427
characteristic_varieties()(sage.groups.finitely_presented.FinitelyPresentedGroup method), 111
chart_exp1()(sage.groups.lie_gps.nilpotent_lie_group.NilpotentLieGroupmethod),724
chart_exp2()(sage.groups.lie_gps.nilpotent_lie_group.NilpotentLieGroupmethod),724
class_function() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 41
ClassFunction() (in module sage.groups.class_function), 281
ClassFunction_gap (class in sage.groups.class_function), 281
ClassFunction_libgap(classin
sage.groups.class_function), 289
classical_invariant_form() (sage.groups.cubic_braid.CubicBraidGroup method), 210
coarsest_equitable_refinement()(inmodule sage.groups.perm_gps.partn_ref.refinement_graphs), 741
codegrees()(sage.groups.cubic_braid.CubicBraid770

Group method), 211
codegrees()(sage.groups.perm_gps.permgroup_named.ComplexReflectionGroupmethod), 504
cohomology() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 429
cohomology()(sage.groups.raag.RightAngledArtinGroup method), 237
cohomology_part()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),430
CohomologyRAAG (class in sage.groups.raag), 233
CohomologyRAAG.Element(classin
sage.groups.raag), 233
color_of_square()(inmodulesage.groups.perm_gps.cubegroup), 587
colored_jones_polynomial()(sage.groups.braid.Braid method), 155
commutator() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 431
ComplexReflectionGroup(classin
sage.groups.perm_gps.permgroup_named),502
components_in_closure()(sage.groups.braid.Braid method), 156
composition_series() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 433
conjugacy_class()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 41
conjugacy_class()(sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),541
conjugacy_class()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),434
conjugacy_class_iterator()(inmodulesage.groups.perm_gps.symgp_conjugacy_class),
593
conjugacy_classes()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 42
conjugacy_classes() (sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),541
conjugacy_classes() (sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),434
conjugacy_classes_iterator()(sage.groups.perm_gps.permgroup_named.SymmetricGroup method), 542
conjugacy_classes_representatives()(sage.groups.libgap_mixin.GroupMixinLibGAP
method), 42
conjugacy_classes_representatives()(sage.groups.perm_gps.permgroup_named.SymIndex

Groups, Release 10.4

metricGroup method), 542
sage.groups.matrix_gps.coxeter_group), 648
conjugacy_classes_representatives()
create_key_and_extra_args()(sage.groups.perm_gps.permgroup.Permutation(sage.groups.misc_gps.argument_groups.ArGroup_generic method), 435
gumentGroupFactory method), 399
conjugacy_classes_subgroups()
create_object()(sage.groups.misc_gps.argu(sage.groups.libgap_mixin.GroupMixinLibGAP
ment_groups.ArgumentGroupFactory method),
method), 43
399
conjugacy_classes_subgroups()
create_poly()(inmodule(sage.groups.perm_gps.permgroup.Permutasage.groups.perm_gps.cubegroup), 587
tionGroup_generic method), 435
CubeGroup (class in sage.groups.perm_gps.cubegroup),
ConjugacyClass(classin
sage.groups.conju572
gacy_classes), 300
cubic_braid_subgroup()(sage.groups.cuConjugacyClassGAP (class in sage.groups.conjubic_braid.CubicBraidGroup method), 211
gacy_classes), 303
CubicBraidElement (class in sage.groups.cuconjugate() (sage.groups.perm_gps.permgroup.Perbic_braid), 195
mutationGroup_generic method), 437
CubicBraidGroup (class in sage.groups.cubic_braid),
conjugating_braid()(sage.groups.braid.Braid
198
method), 156
CubicBraidGroup.type (class in sage.groups.cuconjugation()(sage.groups.lie_gps.nilpobic_braid), 214
tent_lie_group.NilpotentLieGroupmethod), cubie() (sage.groups.perm_gps.cubegroup.RubiksCube724
method), 583
construction() (sage.groups.group_semidirect_prod- cubie_centers()(inmoduleuct.GroupSemidirectProduct method), 261
sage.groups.perm_gps.cubegroup), 587
construction()(sage.groups.perm_gps.per- cubie_colors()(inmodulemgroup.PermutationGroup_genericmethod),sage.groups.perm_gps.cubegroup), 588
439
cubie_faces()(inmodulecosets() (sage.groups.perm_gps.permgroup.Permutasage.groups.perm_gps.cubegroup), 588
tionGroup_generic method), 440
cycle_string()(sage.groups.perm_gps.percover() (sage.groups.abelian_gps.abelian_group_gap.Abelianmgroup_element.PermutationGroupElement
GroupQuotient_gap method), 336
method), 554
cover_and_relations_from_invariants()
cycle_tuples()(sage.groups.perm_gps.per(in module sage.groups.additive_abelian.addimgroup_element.PermutationGroupElement
tive_abelian_group), 385
method), 554
covering_matrix_ring()
cycle_type() (sage.groups.perm_gps.permgroup_ele(sage.groups.abelian_gps.abelian_aut.Abelianment.PermutationGroupElement method), 555
GroupAutomorphismGroup_gap method), 350
cycles()(sage.groups.perm_gps.permgroup_eleCoxeter (sage.groups.cubic_braid.CubicBraidGroup.type
ment.PermutationGroupElement method), 556
attribute), 214
CyclicPermutationGroup(classincoxeter_group()(sage.groups.artin.ArtinGroupsage.groups.perm_gps.permgroup_named),
method), 224508
coxeter_group_element() (sage.groups.artin.Art- CyclicPresentation()(inmoduleinGroupElement method), 227
sage.groups.finitely_presented_named), 139
coxeter_matrix()(sage.groups.artin.ArtinGroupD
method), 224
coxeter_matrix()(sage.groups.matrix_gps.cox- D()(sage.groups.perm_gps.cubegroup.CubeGroup
eter_group.CoxeterMatrixGroup method), 651
method), 573
coxeter_matrix()(sage.groups.perm_gps.per- decompose() (sage.groups.class_function.ClassFuncmgroup_named.SymmetricGroupmethod),tion_gap method), 283
543
decompose() (sage.groups.class_function.ClassFunccoxeter_type()(sage.groups.artin.ArtinGroup
tion_libgap method), 291
method), 225
default_representative()(inmoduleCoxeterMatrixGroup (class in sage.groups.masage.groups.perm_gps.symgp_conjugacy_class),
trix_gps.coxeter_group), 643
595
CoxeterMatrixGroup.Element(class
in
Index

771

Groups, Release 10.4

defining_morphism()(sage.groups.kernel_subgroup.KernelSubgroup method), 277
deformed_burau_matrix()(sage.groups.braid.Braid method), 158
degree() (sage.groups.affine_gps.affine_group.AffineGroup method), 703
degree()(sage.groups.class_function.ClassFunction_gap method), 283
degree()(sage.groups.class_function.ClassFunction_libgap method), 291
degree() (sage.groups.matrix_gps.matrix_group.MatrixGroup_generic method), 602
degree() (sage.groups.pari_group.PariGroup method),59
degree()(sage.groups.perm_gps.permgroup_named.TransitiveGroupmethod),547
degree() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 442
degree()(sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroupmethod), 271
degree_on_basis() (sage.groups.raag.CohomologyRAAG method), 233
degrees() (sage.groups.cubic_braid.CubicBraidGroupmethod), 212
degrees()(sage.groups.perm_gps.permgroup_named.ComplexReflectionGroupmethod), 505
delta()(sage.groups.artin.FiniteTypeArtinGroupmethod), 230
derived_series()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),443
descents()(sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup.Element
method), 648
determinant_character()(sage.groups.class_function.ClassFunction_gap
method), 283
determinant_character()(sage.groups.class_function.ClassFunction_libgap method), 291
dict() (sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 556
DiCyclicGroup (class in sage.groups.perm_gps.permgroup_named), 510
DiCyclicPresentation()(inmodulesage.groups.finitely_presented_named), 139
DihedralGroup (class in sage.groups.perm_gps.permgroup_named), 513
DihedralPresentation()(inmodulesage.groups.finitely_presented_named), 140772

dimension_of_TL_space()(sage.groups.braid.BraidGroup_class method),183
direct_product()(sage.groups.finitely_presented.FinitelyPresentedGroup method), 114
direct_product()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),443
direct_product_permgroups() (in module
sage.groups.perm_gps.permgroup), 498
discrete_exp()(sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper method), 388
discrete_log() (in module sage.groups.generic), 68
discrete_log()(sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper method), 388
discrete_log_generic()(inmodulesage.groups.generic), 74
discrete_log_lambda()(inmodulesage.groups.generic), 74
discrete_log_rho()(inmodulesage.groups.generic), 75
display()(sage.groups.perm_gps.partn_ref.refinement_matrices.MatrixStruct method), 754
display2d() (sage.groups.perm_gps.cubegroup.CubeGroup method), 574
domain() (sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup_gap method), 350
domain()(sage.groups.class_function.ClassFunction_gap method), 284
domain()(sage.groups.class_function.ClassFunction_libgap method), 292
domain()(sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 557
domain() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 445
dual_group() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 313
DualAbelianGroup_class(classin
sage.groups.abelian_gps.dual_abelian_group),
360
DualAbelianGroupElement(classin
sage.groups.abelian_gps.dual_abelian_group_element), 375

E
Element (sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup attribute), 349
Element (sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup_gap attribute), 350
Element (sage.groups.abelian_gps.abelian_aut.AbelianGroupAutomorphismGroup_subgroup attribute),
352
Index

Groups, Release 10.4

Element (sage.groups.abelian_gps.abelian_group_gap.AbelianGroup_generic attribute), 421
Group_gap attribute), 340
Element(sage.groups.semimonomial_transElement (sage.groups.abelian_gps.abelian_group.Abelianformations.semimonomial_transformaGroup_class attribute), 312
tion_group.SemimonomialTransformationGroup
Element (sage.groups.abelian_gps.dual_abelian_group.Duattribute), 271
alAbelianGroup_class attribute), 361
element()(sage.groups.additive_abelian.addiElement (sage.groups.abelian_gps.values.AbelianGrouptive_abelian_wrapper.AdditiveAbelianGroupWithValues_class attribute), 357
WrapperElement method), 393
Element(sage.groups.additive_abelian.addi- elementary_divisors()
tive_abelian_group.AdditiveAbelianGroup_class(sage.groups.abelian_gps.abelian_group_gap.Abelianattribute), 382
Group_gap method), 341
Element(sage.groups.additive_abelian.addi- elementary_divisors()
tive_abelian_wrapper.AdditiveAbelianGroup(sage.groups.abelian_gps.abelian_group.AbelianWrapper attribute), 388
Group_class method), 314
Element(sage.groups.affine_gps.affine_group.Affine- ElementLibGAP (class in sage.groups.libgap_wrapper),Group attribute), 703
20
Element (sage.groups.artin.ArtinGroup attribute), 222
epimorphisms() (sage.groups.braid.BraidGroup_class
Element(sage.groups.artin.FiniteTypeArtinGroupmethod), 184
attribute), 230
epimorphisms()(sage.groups.finitely_preElement (sage.groups.braid.BraidGroup_class attribute),
sented.FinitelyPresentedGroup method), 115
180
eps() (sage.groups.braid.RightQuantumWord method),
Element (sage.groups.cubic_braid.CubicBraidGroup at189
tribute), 201
equals() (sage.groups.abelian_gps.abelian_group.AbelianElement (sage.groups.finitely_presented.FinitelyPresentGroup_subgroup method), 328
edGroup attribute), 105
EuclideanGroup (class in sage.groups.affine_gps.euElement(sage.groups.free_group.FreeGroup_classclidean_group), 708
attribute), 97
exp()(sage.groups.lie_gps.nilpotent_lie_group.NilpoElement(sage.groups.group_exp.GroupExp_Class
tentLieGroup method), 725
attribute), 255
exponent (sage.groups.misc_gps.argument_groups.UnitElement(sage.groups.group_semidirect_prodCirclePoint property), 403
uct.GroupSemidirectProduct attribute), 261
exponent() (sage.groups.abelian_gps.abelian_group_gap.AbelianElement(sage.groups.libgap_group.GroupLibGAP
Group_gap method), 341
attribute), 33
exponent() (sage.groups.abelian_gps.abelian_group.AbelianElement(sage.groups.libgap_morphism.GroupHomGroup_class method), 315
set_libgap attribute), 10
exponent()(sage.groups.additive_abelian.addiElement (sage.groups.matrix_gps.matrix_group_gap.Mative_abelian_group.AdditiveAbelianGroup_classtrixGroup_gap attribute), 604
method), 382
Element (sage.groups.matrix_gps.matrix_group.Matrix- exponent() (sage.groups.libgap_mixin.GroupMixinLibGroup_generic attribute), 602
GAP method), 44
Element(sage.groups.misc_gps.argument_groups.Ab- exponent() (sage.groups.perm_gps.permgroup.PermustractArgumentGroup attribute), 396
tationGroup_generic method), 445
Element (sage.groups.misc_gps.argument_groups.Argu- exponent_denominator()
mentByElementGroup attribute), 397(sage.groups.misc_gps.argument_groups.RootOElement (sage.groups.misc_gps.argument_groups.RootfUnity method), 399
sOfUnityGroup attribute), 401
exponent_numerator() (sage.groups.misc_gps.arElement (sage.groups.misc_gps.argument_groups.Signgument_groups.RootOfUnity method), 400
Group attribute), 402
exponent_sum() (sage.groups.artin.ArtinGroupEleElement (sage.groups.misc_gps.argument_groups.Unitment method), 228
CircleGroup attribute), 403
exponents() (sage.groups.abelian_gps.abelian_group_gap.AbelianElement (sage.groups.misc_gps.imaginary_groups.ImagGroupElement_gap method), 333
inaryGroup attribute), 406
exponents() (sage.groups.abelian_gps.abelian_group_gap.AbelianElement (sage.groups.perm_gps.permgroup_named.SymGroupElement_polycyclic method), 334
metricGroup attribute), 539
exponents()(sage.groups.abelian_gps.eleElement (sage.groups.perm_gps.permgroup.Permutationment_base.AbelianGroupElementBase method),
Index

773

Groups, Release 10.4367
fox_derivative()(sage.groups.free_group.Freeexterior_power() (sage.groups.class_function.ClassGroupElement method), 95
Function_gap method), 284
frattini_subgroup() (sage.groups.perm_gps.perexterior_power() (sage.groups.class_function.Classmgroup.PermutationGroup_genericmethod),Function_libgap method), 292
447
free_group() (sage.groups.finitely_presented.FiniteF
lyPresentedGroup method), 117
free_group()(sage.groups.finitely_presented.RewritF()(sage.groups.perm_gps.cubegroup.CubeGroup
ingSystem method), 130
method), 573
faces() (sage.groups.perm_gps.cubegroup.CubeGroup FreeGroup() (in module sage.groups.free_group), 92
FreeGroup_class (class in sage.groups.free_group),
method), 575
97
facets() (sage.groups.perm_gps.cubegroup.CubeGroup
FreeGroupElement (class in sage.groups.free_group),
method), 576
93
facets() (sage.groups.perm_gps.cubegroup.RubiksCube
from_gap_list()(inmodulemethod), 583
sage.groups.perm_gps.permgroup), 499
field_of_definition()
from_generators()(sage.groups.addi(sage.groups.perm_gps.permgroup_named.Pertive_abelian.additive_abelian_wrapper.AdmutationGroup_pug method), 525
ditiveAbelianGroupWrapper static method),finite_field_sqrt() (in module sage.groups.ma390
trix_gps.unitary), 696
fundamental_weight()(sage.groups.maFiniteGroup (class in sage.groups.group), 3
trix_gps.coxeter_group.CoxeterMatrixGroup
finitely_presented_group()
method), 651(sage.groups.finitely_presented.RewritingSysfundamental_weights()(sage.groups.matem method), 129
trix_gps.coxeter_group.CoxeterMatrixGroup
FinitelyGeneratedAbelianPresentamethod), 652
tion() (in module sage.groups.finitely_presented_named), 140
G
FinitelyGeneratedHeisenbergPresentation() (in module sage.groups.finitely_pre- gap() (sage.groups.class_function.ClassFunction_libgap
method), 292
sented_named), 142(sage.groups.finitely_presented.RewritingSystem
FinitelyGeneratedMatrixGroup_gap (class in gap()
method), 130
sage.groups.matrix_gps.finitely_generated_gap),
gap()(sage.groups.libgap_morphism.GroupMor625
phism_libgap method), 12
FinitelyGeneratedMatrixGroup_generic(sage.groups.libgap_wrapper.ElementLibGAP(class in sage.groups.matrix_gps.finitely_gener- gap()
method), 21
ated), 619(sage.groups.libgap_wrapper.ParentLibGAP
FinitelyPresentedGroup(classin gap()method), 25
sage.groups.finitely_presented), 104
FinitelyPresentedGroupElement (class in gap() (sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 557
sage.groups.finitely_presented), 125
FiniteTypeArtinGroup (class in sage.groups.artin), gap() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 447
229(sage.groups.perm_gps.perFiniteTypeArtinGroupElement(classin gap_small_group()
mgroup_named.SmallPermutationGroupsage.groups.artin), 231
method), 534
first_descent()(sage.groups.matrix_gps.coxgcd() (sage.groups.braid.Braid method), 160
eter_group.CoxeterMatrixGroup.Element
gen() (sage.groups.abelian_gps.abelian_group.Abelianmethod), 649
Group_class method), 315
fitting_subgroup()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod), gen() (sage.groups.abelian_gps.abelian_group.AbelianGroup_subgroup method), 329
446
fixed_points()(sage.groups.perm_gps.per- gen() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 361
mgroup.PermutationGroup_genericmethod),gen()(sage.groups.abelian_gps.values.AbelianGroup446
WithValues_class method), 357
774

Index

Groups, Release 10.4

gen() (sage.groups.cactus_group.CactusGroup method),
245
gen()
(sage.groups.cactus_group.PureCactusGroupmethod), 249
gen()(sage.groups.indexed_free_group.IndexedFreeAbelianGroup method), 215
gen()(sage.groups.indexed_free_group.IndexedFreeGroup method), 217
gen()(sage.groups.libgap_wrapper.ParentLibGAP
method), 26
gen() (sage.groups.matrix_gps.finitely_generated.FinitelyGeneratedMatrixGroup_genericmethod),619
gen() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 448
gen() (sage.groups.raag.CohomologyRAAG method), 234
gen()(sage.groups.raag.RightAngledArtinGroupmethod), 238
gen_names() (sage.groups.perm_gps.cubegroup.CubeGroup method), 576
GeneralDihedralGroup(classin
sage.groups.perm_gps.permgroup_named),514
generate_dense_graphs_edge_addition()(in module sage.groups.perm_gps.partn_ref.refinement_graphs), 741
generate_dense_graphs_vert_addition()(in module sage.groups.perm_gps.partn_ref.refinement_graphs), 742
generator_orders()(sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper method), 391
generators() (sage.groups.libgap_wrapper.ParentLibGAP method), 27
gens() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 316
gens() (sage.groups.abelian_gps.abelian_group.AbelianGroup_subgroup method), 329
gens() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 362
gens()(sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_fixed_gens method), 384
gens() (sage.groups.cactus_group.CactusGroup method),246
gens()(sage.groups.cactus_group.PureCactusGroupmethod), 250
gens() (sage.groups.indexed_free_group.IndexedGroupmethod), 218gens()(sage.groups.kernel_subgroup.KernelSubgroupmethod), 278
gens()(sage.groups.libgap_wrapper.ParentLibGAP
method), 27
gens() (sage.groups.lie_gps.nilpotent_lie_group.NilpoIndex

tentLieGroup method), 725
gens() (sage.groups.matrix_gps.finitely_generated.FinitelyGeneratedMatrixGroup_generic method), 620
gens() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 448
gens() (sage.groups.raag.CohomologyRAAG method),234
gens()(sage.groups.raag.RightAngledArtinGroupmethod), 238
gens()(sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroupmethod), 271
gens_orders() (sage.groups.abelian_gps.abelian_group_gap.AbelianGroup_gap method), 342
gens_orders() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 316
gens_orders() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 362
gens_small() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 449
gens_values()(sage.groups.abelian_gps.values.AbelianGroupWithValues_classmethod),358
geometric_representation_generators()(sage.groups.cactus_group.CactusGroupmethod), 246
get_autom() (sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation method), 274
get_orbits()(inmodulesage.groups.perm_gps.partn_ref.refinement_graphs), 743
get_perm() (sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation method), 274
get_v()(sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation method), 275
get_v_inverse() (sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation method), 275
GL() (in module sage.groups.matrix_gps.linear), 658
GO() (in module sage.groups.matrix_gps.orthogonal), 666
graph()(sage.groups.raag.RightAngledArtinGroupmethod), 238
GraphStruct(classin
sage.groups.perm_gps.partn_ref.refinement_graphs), 740
Group (class in sage.groups.group), 3
group() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 362
group_generators()(sage.groups.cactus_group.CactusGroup method), 247
775

Groups, Release 10.4

group_generators()(sage.groups.group_exp.GroupExp_Class
method), 256
group_generators()(sage.groups.group_semidirect_product.GroupSemidirectProduct method),262
group_generators()(sage.groups.indexed_free_group.IndexedGroupmethod),218
group_id() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 45
group_id() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 450
group_primitive_id() (sage.groups.perm_gps.permgroup_named.PrimitiveGroup method), 527
group_primitive_id() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 450
GroupActionOnQuotientModule(classin
sage.groups.matrix_gps.isometries), 679
GroupActionOnSubmodule (class in sage.groups.matrix_gps.isometries), 680
GroupExp (class in sage.groups.group_exp), 253
GroupExp_Class (class in sage.groups.group_exp), 255
GroupExpElement (class in sage.groups.group_exp),
255
GroupHomset_libgap (class in sage.groups.libgap_morphism), 9GroupLibGAP (class in sage.groups.libgap_group), 33
GroupMixinLibGAP (class in sage.groups.libgap_mixin), 35
GroupMorphism_libgap (class in sage.groups.libgap_morphism), 10
GroupMorphismWithGensImages(classin
sage.groups.finitely_presented), 127
GroupOfIsometries (class in sage.groups.matrix_gps.isometries), 681
GroupSemidirectProduct(classin
sage.groups.group_semidirect_product), 259
GroupSemidirectProductElement (class insage.groups.group_semidirect_product), 264
GU() (in module sage.groups.matrix_gps.unitary), 689

has_regular_subgroup()(sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 452
has_right_descent() (sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup.Element
method), 649
HeisenbergGroup(classin
sage.groups.matrix_gps.heisenberg), 697
holomorph() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 453
homology() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 454
homology_part()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),455

I(sage.groups.libgap_mixin.GroupMixinLibGAP
method), 45
id()(sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 455
identity() (sage.groups.abelian_gps.abelian_group_gap.AbelianGroup_gap method), 343
identity() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 317
identity()(sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_fixed_gens method), 384
identity() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 456
imag() (sage.groups.misc_gps.imaginary_groups.ImaginaryElement method), 405
image() (sage.groups.abelian_gps.abelian_group_morphism.AbelianGroupMorphism method), 377
image()(sage.groups.libgap_morphism.GroupMorphism_libgap method), 12
image()(sage.groups.perm_gps.permgroup_morphism.PermutationGroupMorphism
method),566
ImaginaryElement(classin
sage.groups.misc_gps.imaginary_groups),
405
H
ImaginaryGroup (class in sage.groups.misc_gps.imaginary_groups), 406
hap_decorator()(inmoduleindex2singmaster()(inmodulesage.groups.perm_gps.permgroup), 499
sage.groups.perm_gps.cubegroup), 589
has_descent() (sage.groups.perm_gps.permgroup_elindex_set() (sage.groups.artin.ArtinGroup method),ement.PermutationGroupElement method), 558
225
has_element()(sage.groups.perm_gps.per(sage.groups.cubic_braid.CubicBraidmgroup.PermutationGroup_genericmethod), index_set()Group method), 212
451(sage.groups.perm_gps.perhas_left_descent()(sage.groups.perm_gps.per- index_set()
mgroup_named.ComplexReflectionGroupmgroup_element.SymmetricGroupElement
method), 506
method), 564
has_order() (in module sage.groups.generic), 78
776

id()

Index

Groups, Release 10.4

index_set()(sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),543
IndexedFreeAbelianGroup(classin
sage.groups.indexed_free_group), 215
IndexedFreeAbelianGroup.Element (class insage.groups.indexed_free_group), 215
IndexedFreeGroup(classin
sage.groups.indexed_free_group), 216
IndexedFreeGroup.Element(classin
sage.groups.indexed_free_group), 216
IndexedGroup(classin
sage.groups.indexed_free_group), 218
induct()(sage.groups.class_function.ClassFunction_gap method), 285
induct()(sage.groups.class_function.ClassFunction_libgap method), 293
intersection() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 46
intersection()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),456
inv_list() (in module sage.groups.perm_gps.cubegroup), 589
invariant_bilinear_form() (sage.groups.matrix_gps.isometries.GroupOfIsometries method),682
invariant_bilinear_form() (sage.groups.matrix_gps.orthogonal_gap.OrthogonalMatrixGroup_gap method), 675
invariant_bilinear_form() (sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_generic method), 670
invariant_form() (sage.groups.matrix_gps.orthogonal_gap.OrthogonalMatrixGroup_gap method),676
invariant_form() (sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_generic method),671
invariant_form() (sage.groups.matrix_gps.symplectic_gap.SymplecticMatrixGroup_gap
method),688
invariant_form() (sage.groups.matrix_gps.symplectic.SymplecticMatrixGroup_generic method), 687
invariant_form()(sage.groups.matrix_gps.unitary_gap.UnitaryMatrixGroup_gap
method),696
invariant_form()(sage.groups.matrix_gps.unitary.UnitaryMatrixGroup_genericmethod),695
invariant_generators()(sage.groups.matrix_gps.finitely_generated_gap.FinitelyGeneratedMatrixGroup_gap method), 627
invariant_quadratic_form() (sage.groups.maIndex

trix_gps.orthogonal_gap.OrthogonalMatrixGroup_gap method), 677
invariant_quadratic_form() (sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_generic method), 671
invariants() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 317
invariants() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 363
invariants_of_degree()(sage.groups.matrix_gps.finitely_generated_gap.FinitelyGeneratedMatrixGroup_gap method), 629
inverse() (sage.groups.libgap_wrapper.ElementLibGAP method), 21
inverse() (sage.groups.matrix_gps.group_element.MatrixGroupElement_generic method), 609
inverse()(sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 559
invert_v() (sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation method), 275
irreducible_characters()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 47
irreducible_characters()(sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 458
irreducible_constituents()(sage.groups.class_function.ClassFunction_gap
method), 285
irreducible_constituents()(sage.groups.class_function.ClassFunction_libgap method), 293
is_abelian()(sage.groups.group.AbelianGroupmethod), 3
is_abelian() (sage.groups.group.Group method), 4
is_abelian() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 48
is_abelian()(sage.groups.perm_gps.permgroup_named.CyclicPermutationGroupmethod), 509
is_abelian()(sage.groups.perm_gps.permgroup_named.DiCyclicGroup method), 512
is_abelian() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 458
is_AbelianGroup()(inmodulesage.groups.abelian_gps.abelian_group), 330
is_AbelianGroupElement()(inmodulesage.groups.abelian_gps.abelian_group_element), 373
is_AbelianGroupMorphism()(inmodulesage.groups.abelian_gps.abelian_group_morphism), 379
is_commutative() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 318
777

Groups, Release 10.4

is_commutative() (sage.groups.abelian_gps.dual_abelian_group.Dusage.groups.perm_gps.partn_ref.refinealAbelianGroup_class method), 363
ment_lists), 752
is_commutative()(sage.groups.group.Group is_isomorphic() (sage.groups.abelian_gps.abelian_group.Abelianmethod), 4Group_class method), 320
is_commutative()(sage.groups.matrix_gps.cox- is_isomorphic() (sage.groups.libgap_mixin.Groupeter_group.CoxeterMatrixGroup method), 652
MixinLibGAP method), 49
is_commutative()(sage.groups.perm_gps.per- is_isomorphic() (sage.groups.perm_gps.partn_ref.remgroup_named.CyclicPermutationGroup
finement_matrices.MatrixStruct method), 754
method), 509
is_isomorphic()(sage.groups.perm_gps.peris_commutative()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),mgroup_named.DiCyclicGroup method), 512459
is_commutative()(sage.groups.perm_gps.per- is_MatrixGroup() (in module sage.groups.mamgroup.PermutationGroup_genericmethod),trix_gps.matrix_group), 603
458
is_MatrixGroupElement()(inmoduleis_confluent()(sage.groups.finitely_presage.groups.matrix_gps.group_element), 612
sented.RewritingSystem method), 130
is_MatrixGroupHomset()(inmoduleis_conjugate()(sage.groups.libgap_wrapper.Elesage.groups.matrix_gps.homset), 641
mentLibGAP method), 21
is_minus_one()(sage.groups.misc_gps.arguis_conjugated() (sage.groups.braid.Braid method),
ment_groups.Sign method), 401160
is_minus_one()(sage.groups.misc_gps.arguis_cyclic() (sage.groups.abelian_gps.abelian_group.Abelianment_groups.UnitCirclePoint method), 403
Group_class method), 319
is_monomial()(sage.groups.perm_gps.peris_cyclic()(sage.groups.additive_abelian.addimgroup.PermutationGroup_genericmethod),tive_abelian_group.AdditiveAbelianGroup_class
460
method), 382
is_multiplicative()(sage.groups.addiis_cyclic() (sage.groups.perm_gps.permgroup.Pertive_abelian.additive_abelian_group.AddimutationGroup_generic method), 459
tiveAbelianGroup_class method), 383
is_DualAbelianGroup()(inmodule is_multiplicative()(sage.groups.group.Groupsage.groups.abelian_gps.dual_abelian_group),
method), 5
365
is_nilpotent() (sage.groups.libgap_mixin.Groupis_DualAbelianGroupElement() (in module
MixinLibGAP method), 50
sage.groups.abelian_gps.dual_abelian_group_el- is_nilpotent()(sage.groups.perm_gps.perement), 375
mgroup.PermutationGroup_genericmethod),is_elementary_abelian()
460(sage.groups.perm_gps.permgroup.Permutais_normal() (sage.groups.perm_gps.permgroup.PertionGroup_generic method), 459
mutationGroup_generic method), 461
is_finite()(sage.groups.cubic_braid.CubicBraid- is_normal() (sage.groups.perm_gps.permgroup.PerGroup method), 213
mutationGroup_subgroup method), 498
is_finite() (sage.groups.group.FiniteGroup method), is_one() (sage.groups.libgap_wrapper.ElementLibGAP
3
method), 22
is_finite() (sage.groups.group.Group method), 4
is_one() (sage.groups.matrix_gps.group_element.Mais_finite() (sage.groups.libgap_mixin.GroupMixintrixGroupElement_generic method), 610
LibGAP method), 48
is_one() (sage.groups.misc_gps.argument_groups.Sign
is_finite()(sage.groups.matrix_gps.coxmethod), 401
eter_group.CoxeterMatrixGroupmethod), is_one() (sage.groups.misc_gps.argument_groups.Unit652
CirclePoint method), 404
is_FreeGroup() (in module sage.groups.free_group), is_p_group() (sage.groups.libgap_mixin.GroupMixin99
LibGAP method), 50
is_Group() (in module sage.groups.group), 6
is_perfect() (sage.groups.libgap_mixin.GroupMixinis_irreducible() (sage.groups.class_function.ClassLibGAP method), 50
Function_gap method), 286
is_perfect() (sage.groups.perm_gps.permgroup.Peris_irreducible() (sage.groups.class_function.ClassmutationGroup_generic method), 461
Function_libgap method), 295
is_periodic() (sage.groups.braid.Braid method), 161
is_isomorphic()(inmodule is_PermutationGroupElement() (in module
778

Index

Groups, Release 10.4

sage.groups.perm_gps.permgroup_element), 564466
is_PermutationGroupMorphism() (in module is_trivial() (sage.groups.abelian_gps.abelian_group_gap.Abeliansage.groups.perm_gps.permgroup_morphism),Group_gap method), 343570
is_trivial() (sage.groups.abelian_gps.abelian_group.Abelianis_pgroup() (sage.groups.perm_gps.permgroup.PerGroup_class method), 321
mutationGroup_generic method), 461
is_trivial()(sage.groups.abelian_gps.eleis_polycyclic() (sage.groups.libgap_mixin.Groupment_base.AbelianGroupElementBase method),
MixinLibGAP method), 51
367
is_polycyclic()(sage.groups.perm_gps.per- is_trivial() (sage.groups.group.Group method), 5
mgroup.PermutationGroup_genericmethod), is_trivial()(sage.groups.matrix_gps.ma462
trix_group.MatrixGroup_genericmethod),is_primitive()(sage.groups.perm_gps.per602
mgroup.PermutationGroup_genericmethod), is_trivial() (sage.groups.perm_gps.permgroup.Per462
mutationGroup_generic method), 467
is_pseudoanosov()(sage.groups.braid.Braid isomorphic()(inmodulemethod), 161
sage.groups.perm_gps.partn_ref.refineis_rational() (sage.groups.conjugacy_classes.Conjument_graphs), 744
gacyClass method), 300
isomorphism_to()(sage.groups.perm_gps.peris_real() (sage.groups.conjugacy_classes.Conjugacymgroup.PermutationGroup_genericmethod),Class method), 301468
is_reducible() (sage.groups.braid.Braid method), isomorphism_type_info_simple_group()161(sage.groups.perm_gps.permgroup.Permutationis_regular() (sage.groups.perm_gps.permgroup.PerGroup_generic method), 468
mutationGroup_generic method), 463
iteration() (sage.groups.perm_gps.permgroup.Peris_semi_regular()(sage.groups.perm_gps.permutationGroup_generic method), 469
mgroup.PermutationGroup_genericmethod),J464
is_simple() (sage.groups.libgap_mixin.GroupMixin- JankoGroup (class in sage.groups.perm_gps.perLibGAP method), 51
mgroup_named), 517
is_simple() (sage.groups.perm_gps.permgroup.Per- jones_polynomial()(sage.groups.braid.BraidmutationGroup_generic method), 465
method), 162
is_solvable()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 51
K
is_solvable()(sage.groups.perm_gps.per- kernel() (sage.groups.abelian_gps.abelian_group_mormgroup.PermutationGroup_genericmethod),phism.AbelianGroupMorphism method), 378465
kernel()(sage.groups.libgap_morphism.GroupMoris_subgroup() (sage.groups.abelian_gps.abelian_group.Abelian- phism_libgap method), 13
Group_class method), 320
kernel()(sage.groups.perm_gps.permgroup_moris_subgroup()(sage.groups.libgap_wrapper.Parphism.PermutationGroupMorphism
method),entLibGAP method), 28
567
is_subgroup()(sage.groups.perm_gps.per- KernelSubgroup (class in sage.groups.kernel_submgroup.PermutationGroup_genericmethod),group), 277
465
KernelSubgroup.Element (class in sage.groups.keris_subgroup_of() (sage.groups.abelian_gps.abelian_aut.Abelian- nel_subgroup), 277
GroupAutomorphismGroup_gap method), 351
KleinFourGroup (class in sage.groups.perm_gps.peris_subgroup_of() (sage.groups.abelian_gps.abelian_group_gap.Abelianmgroup_named), 517
Group_gap method), 343
KleinFourPresentation()(inmoduleis_supersolvable()(sage.groups.libsage.groups.finitely_presented_named), 143
gap_mixin.GroupMixinLibGAP method), 52
is_supersolvable()(sage.groups.perm_gps.per- L
mgroup.PermutationGroup_genericmethod),L()(sage.groups.perm_gps.cubegroup.CubeGroup465
method), 573
is_transitive()(sage.groups.perm_gps.perlabel() (sage.groups.pari_group.PariGroup method), 60
mgroup.PermutationGroup_genericmethod),
Index

779

Groups, Release 10.4

largest_moved_point()
list() (sage.groups.conjugacy_classes.ConjugacyClass(sage.groups.perm_gps.permgroup.Permutamethod), 301
tionGroup_generic method), 469
list() (sage.groups.libgap_mixin.GroupMixinLibGAP
lcm() (sage.groups.braid.Braid method), 164
method), 52
left_invariant_extension()list() (sage.groups.matrix_gps.group_element_gap.Ma(sage.groups.lie_gps.nilpotent_lie_group.NilpotrixGroupElement_gap method), 613
tentLieGroup method), 726
list() (sage.groups.matrix_gps.group_element.Matrixleft_invariant_frame()
GroupElement_generic method), 611(sage.groups.lie_gps.nilpotent_lie_group.Nilpolist() (sage.groups.perm_gps.permgroup.PermutationtentLieGroup method), 727
Group_generic method), 470
left_normal_form() (sage.groups.artin.FiniteTy- livf() (sage.groups.lie_gps.nilpotent_lie_group.NilpopeArtinGroupElement method), 231
tentLieGroup method), 729
left_normal_form()(sage.groups.braid.Braid LKB_matrix() (sage.groups.braid.Braid method), 147
method), 165
load_hap() (in module sage.groups.perm_gps.perleft_translation()(sage.groups.lie_gps.nilpomgroup), 500
tent_lie_group.NilpotentLieGroupmethod), log()(sage.groups.lie_gps.nilpotent_lie_group.Nilpo727
tentLieGroup method), 730
legal() (sage.groups.perm_gps.cubegroup.CubeGroup lower_central_series()
method), 576(sage.groups.perm_gps.permgroup.Permutalength()(sage.groups.indexed_free_group.IndexedtionGroup_generic method), 471
FreeGroup.Element method), 216
lie_algebra()(sage.groups.lie_gps.nilpo- M
tent_lie_group.NilpotentLieGroupmethod), major_index()(sage.groups.perm_gps.per728
mgroup_named.SymmetricGroupmethod),lift() (sage.groups.abelian_gps.abelian_group_gap.Abelian543
GroupQuotient_gap method), 337
make_confluent()(sage.groups.finitely_prelift() (sage.groups.abelian_gps.abelian_group_gap.Abeliansented.RewritingSystem method), 132
GroupSubgroup_gap method), 338
make_permgroup_element()(inmodulelift()(sage.groups.kernel_subgroup.KernelSubgroup
sage.groups.perm_gps.permgroup_element),
method), 278564
lift()(sage.groups.libgap_morphism.GroupMor- make_permgroup_element_v2() (in module
phism_libgap method), 14
sage.groups.perm_gps.permgroup_element), 565
linear() (sage.groups.affine_gps.affine_group.Affine- mapping_class_action()Group method), 704(sage.groups.braid.BraidGroup_class method),linear_relation() (in module sage.groups.generic),
184
79
MappingClassGroupAction(classinlinear_space() (sage.groups.affine_gps.affine_group.Affinesage.groups.braid), 187
Group method), 704
markov_trace() (sage.groups.braid.Braid method),LinearMatrixGroup_gap (class in sage.groups.ma167
trix_gps.linear_gap), 665
MathieuGroup (class in sage.groups.perm_gps.perLinearMatrixGroup_generic(classinmgroup_named), 518
sage.groups.matrix_gps.linear), 661
matrix() (sage.groups.abelian_gps.abelian_aut.Abelianlinks_gould_matrix() (sage.groups.braid.Braid
GroupAutomorphism method), 348
method), 166
matrix() (sage.groups.affine_gps.group_element.Affinelinks_gould_polynomial()
GroupElement method), 715(sage.groups.braid.Braid method), 166
matrix()(sage.groups.matrix_gps.group_elelist() (sage.groups.abelian_gps.abelian_group.Abelianment_gap.MatrixGroupElement_gap
method),Group_class method), 321613
list() (sage.groups.abelian_gps.dual_abelian_group.Du- matrix() (sage.groups.matrix_gps.group_element.MaalAbelianGroup_class method), 363
trixGroupElement_generic method), 611
list() (sage.groups.abelian_gps.element_base.Abelian- matrix()(sage.groups.perm_gps.permgroup_eleGroupElementBase method), 367
ment.PermutationGroupElement method), 560
list()(sage.groups.affine_gps.group_element.Affine- matrix_degree()(sage.groups.perm_gps.perGroupElement method), 714
mgroup_named.PermutationGroup_plg method),
780

Index

Groups, Release 10.4

525
sage.groups.abelian_gps.elematrix_space() (sage.groups.affine_gps.affine_group.Affinement_base, 366
Group method), 704
sage.groups.abelian_gps.values, 352
matrix_space()(sage.groups.matrix_gps.masage.groups.additive_abelian.additrix_group.MatrixGroup_genericmethod),tive_abelian_group, 379
602
sage.groups.additive_abelian.addiMatrixGroup()(inmodulesage.groups.mative_abelian_wrapper, 386
trix_gps.finitely_generated), 621
sage.groups.affine_gps.affine_group,
MatrixGroup_base (class in sage.groups.ma700
trix_gps.matrix_group), 597
sage.groups.affine_gps.euMatrixGroup_gap(classin
sage.groups.maclidean_group, 708
trix_gps.matrix_group_gap), 604
sage.groups.affine_gps.group_eleMatrixGroup_generic (class in sage.groups.mament, 711
trix_gps.matrix_group), 601
sage.groups.artin, 221
MatrixGroupElement_gap (class in sage.groups.masage.groups.braid, 145
trix_gps.group_element_gap), 612
sage.groups.cactus_group, 241
MatrixGroupElement_generic(classin
sage.groups.class_function, 281
sage.groups.matrix_gps.group_element), 609
sage.groups.conjugacy_classes, 299
MatrixStruct(classin
sage.groups.cubic_braid, 193
sage.groups.perm_gps.partn_ref.refinement_masage.groups.finitely_presented, 101
trices), 753
sage.groups.finitely_premaximal_normal_subgroups() (sage.groups.libsented_named, 137
gap_wrapper.ParentLibGAP method), 28
sage.groups.free_group, 91
maximal_normal_subgroups()
sage.groups.generic, 63(sage.groups.perm_gps.permgroup.Permutasage.groups.group, 3
tionGroup_generic method), 471
sage.groups.group_exp, 253
merge_points() (in module sage.groups.generic), 80
sage.groups.group_semidirect_prodminimal_generating_set()uct, 259(sage.groups.perm_gps.permgroup.Permutasage.groups.groups_catalog, 1tionGroup_generic method), 472
sage.groups.indexed_free_group, 215
minimal_normal_subgroups() (sage.groups.libsage.groups.kernel_subgroup, 277
gap_wrapper.ParentLibGAP method), 29
sage.groups.libgap_group, 33
minimal_normal_subgroups()
sage.groups.libgap_mixin, 35(sage.groups.perm_gps.permgroup.Permutasage.groups.libgap_morphism, 9tionGroup_generic method), 472
sage.groups.libgap_wrapper, 19
mirror_image() (sage.groups.braid.Braid method),
sage.groups.lie_gps.nilpo168
tent_lie_group, 717
mirror_involution()(sage.groups.braid.Braidsage.groups.matrix_gps.binary_diGroup_class method), 185
hedral, 642
modulesage.groups.matrix_gps.catalog, 597
sage.groups.abelian_gps.abelian_aut,
sage.groups.matrix_gps.cox345
eter_group, 643
sage.groups.abelian_gps.abelian_group,sage.groups.ma307
trix_gps.finitely_generated,sage.groups.abelian_gps.abelian_group_el- 618
ement, 370
sage.groups.masage.groups.abelian_gps.abelian_group_gap, trix_gps.finitely_generated_gap,
332
625
sage.groups.abelian_gps.abelian_group_morsage.groups.matrix_gps.group_elephism, 376
ment, 607
sage.groups.abelian_gps.dual_abelian_group,sage.groups.matrix_gps.group_ele359
ment_gap, 612
sage.groups.abelian_gps.dual_abelian_group_elsage.groups.matrix_gps.heisenberg,
ement, 374
697
Index

781

Groups, Release 10.4

sage.groups.matrix_gps.homset, 641
tion_groups_catalog, 407
sage.groups.matrix_gps.isometries,
sage.groups.perm_gps.symgp_conju679
gacy_class, 591
sage.groups.matrix_gps.linear, 657
sage.groups.raag, 233
sage.groups.matrix_gps.linear_gap,
sage.groups.semimonomial_transfor665
mations.semimonomial_transforsage.groups.matrix_gps.mamation, 273
trix_group, 597
sage.groups.semimonomial_transforsage.groups.matrix_gps.mamations.semimonomial_transfortrix_group_gap, 604
mation_group, 269
sage.groups.matrix_gps.morphism, 641 module_composition_factors()sage.groups.matrix_gps.named_group,(sage.groups.matrix_gps.finitely_gener757
ated_gap.FinitelyGeneratedMatrixGroup_gap
sage.groups.mamethod), 631
trix_gps.named_group_gap, 759
molien_series()(sage.groups.masage.groups.matrix_gps.orthogonal,
trix_gps.finitely_generated_gap.FinitelyGen665
eratedMatrixGroup_gap method), 632
sage.groups.matrix_gps.orthogomolien_series()(sage.groups.perm_gps.pernal_gap, 675
mgroup.PermutationGroup_genericmethod),sage.groups.matrix_gps.symplectic,
472
683
move()(sage.groups.perm_gps.cubegroup.CubeGroupsage.groups.matrix_gps.symplecmethod), 577
tic_gap, 687
move()(sage.groups.perm_gps.cubegroup.RubiksCube
sage.groups.matrix_gps.unitary, 688
method), 584
sage.groups.matrix_gps.unitary_gap, multiple() (in module sage.groups.generic), 82
696
multiples (class in sage.groups.generic), 83
sage.groups.misc_gps.argumultiplicative_order()ment_groups, 395(sage.groups.abelian_gps.element_base.Abeliansage.groups.misc_gps.imagiGroupElementBase method), 368
nary_groups, 404
multiplicative_order()(sage.groups.libsage.groups.misc_gps.misc_groups,
gap_wrapper.ElementLibGAP method), 22
267
multiplicative_order()(sage.groups.masage.groups.pari_group, 59
trix_gps.group_element_gap.MatrixGroupElesage.groups.perm_gps.constructor,
ment_gap method), 614
407
multiplicative_order()sage.groups.perm_gps.cubegroup, 570(sage.groups.perm_gps.permgroup_element.Persage.groups.perm_gps.partn_ref.canonmutationGroupElement method), 560
ical_augmentation, 737
Nsage.groups.perm_gps.partn_ref.data_structures, 739
n() (sage.groups.cactus_group.CactusGroup method), 248
sage.groups.perm_gps.partn_ref.ren() (sage.groups.cactus_group.PureCactusGroup method),
finement_graphs, 740
250
sage.groups.perm_gps.partn_ref.reNamedMatrixGroup_gap (class in sage.groups.mafinement_lists, 752
trix_gps.named_group_gap), 759
sage.groups.perm_gps.partn_ref.reNamedMatrixGroup_generic(classinfinement_matrices, 753
sage.groups.matrix_gps.named_group), 758
sage.groups.perm_gps.permgroup, 412
natural_homomorphism()sage.groups.perm_gps.permgroup_el(sage.groups.abelian_gps.abelian_group_gap.Abelianement, 550
GroupQuotient_gap method), 337
sage.groups.perm_gps.pernatural_map()(sage.groups.libgap_mormgroup_morphism, 565
phism.GroupHomset_libgap method), 10
sage.groups.perm_gps.pernatural_representation()(sage.groups.mamgroup_named, 500
trix_gps.matrix_group.MatrixGroup_base
sage.groups.perm_gps.permutamethod), 599
782

Index

Groups, Release 10.4

next() (sage.groups.generic.multiples method), 85
one() (sage.groups.group_exp.GroupExp_Class method),ngens() (sage.groups.abelian_gps.abelian_group.Abelian256
Group_class method), 322
one()(sage.groups.group_semidirect_prodngens() (sage.groups.abelian_gps.dual_abelian_group.Duuct.GroupSemidirectProduct method), 262
alAbelianGroup_class method), 364
one()(sage.groups.indexed_free_group.IndexedFreengens()(sage.groups.libgap_wrapper.ParentLibGAP
AbelianGroup method), 216
method), 29
one()(sage.groups.indexed_free_group.IndexedFreengens()(sage.groups.matrix_gps.finitely_generGroup method), 218
ated.FinitelyGeneratedMatrixGroup_genericone()(sage.groups.libgap_wrapper.ParentLibGAP
method), 621
method), 29
ngens() (sage.groups.perm_gps.permgroup.Permutation- one()(sage.groups.lie_gps.nilpotent_lie_group.NilpoGroup_generic method), 474
tentLieGroup method), 730
ngens() (sage.groups.raag.CohomologyRAAG method), one() (sage.groups.perm_gps.permgroup.Permutation235
Group_generic method), 476
ngens()(sage.groups.raag.RightAngledArtinGroup one()(sage.groups.raag.RightAngledArtinGroupmethod), 239
method), 239
NilpotentLieGroup(classin one_basis()(sage.groups.raag.CohomologyRAAG
sage.groups.lie_gps.nilpotent_lie_group), 717
method), 235
NilpotentLieGroup.Element(classin one_element() (sage.groups.raag.RightAngledArtinsage.groups.lie_gps.nilpotent_lie_group), 721
Group method), 239
non_fixed_points()(sage.groups.perm_gps.per- OP_represent()(inmodulemgroup.PermutationGroup_genericmethod),sage.groups.perm_gps.partn_ref.data_struc474
tures), 739
norm() (sage.groups.class_function.ClassFunction_gap opposite_semidirect_product()
method), 287(sage.groups.group_semidirect_prodnorm() (sage.groups.class_function.ClassFunction_libgap
uct.GroupSemidirectProduct method), 263
method), 295
orbit() (sage.groups.perm_gps.permgroup_element.Pernormal_subgroups()(sage.groups.perm_gps.permutationGroupElement method), 561
mgroup.PermutationGroup_genericmethod), orbit() (sage.groups.perm_gps.permgroup.Permutation474
Group_generic method), 477
normalize_args_e() (in module sage.groups.ma- orbit_partition()(inmoduletrix_gps.orthogonal), 675
sage.groups.perm_gps.partn_ref.refinenormalize_args_invariant_form() (in module
ment_graphs), 745
sage.groups.matrix_gps.named_group), 758
orbits() (sage.groups.perm_gps.permgroup.Permutanormalize_args_vectorspace() (in module
tionGroup_action method), 420
sage.groups.matrix_gps.named_group), 759
orbits() (sage.groups.perm_gps.permgroup.Permutanormalize_square_matrices() (in module
tionGroup_generic method), 479
sage.groups.matrix_gps.finitely_generated), 624
order() (sage.groups.abelian_gps.abelian_group_gap.Abeliannormalizer()(sage.groups.libgap_wrapper.EleGroupElement_gap method), 334
mentLibGAP method), 23
order() (sage.groups.abelian_gps.abelian_group.Abeliannormalizer() (sage.groups.perm_gps.permgroup.PerGroup_class method), 323
mutationGroup_generic method), 475
order() (sage.groups.abelian_gps.dual_abelian_group.Dunormalizes() (sage.groups.perm_gps.permgroup.PeralAbelianGroup_class method), 364
mutationGroup_generic method), 475
order()(sage.groups.abelian_gps.elenth_roots() (sage.groups.libgap_wrapper.ElementLibment_base.AbelianGroupElementBase method),
GAP method), 23
369
number_of_subgroups()
order()(sage.groups.additive_abelian.addi(sage.groups.abelian_gps.abelian_group.Abeliantive_abelian_group.AdditiveAbelianGroup_classGroup_class method), 322
method), 383
order() (sage.groups.artin.ArtinGroup method), 225O
order() (sage.groups.braid.BraidGroup_class method),186
one() (sage.groups.cactus_group.CactusGroup method),order()(sage.groups.cubic_braid.CubicBraidGroup248
method), 213
Index

783

Groups, Release 10.4

order() (sage.groups.finitely_presented.FinitelyPresentedGroup method), 117order() (sage.groups.group.Group method), 6
order() (sage.groups.indexed_free_group.IndexedGroupmethod), 219
order() (sage.groups.libgap_mixin.GroupMixinLibGAP
method), 54
order() (sage.groups.libgap_wrapper.ElementLibGAP
method), 24
order() (sage.groups.matrix_gps.binary_dihedral.BinaryDihedralGroup method), 643
order() (sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup method), 653
order()(sage.groups.matrix_gps.heisenberg.HeisenbergGroup method), 699
order() (sage.groups.matrix_gps.linear.LinearMatrixGroup_generic method), 662
order() (sage.groups.pari_group.PariGroup method), 60
order()(sage.groups.perm_gps.permgroup_named.SmallPermutationGroupmethod), 534
order() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 480
order()(sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroupmethod), 272
order_from_bounds()(inmodulesage.groups.generic), 85
order_from_multiple()(inmodulesage.groups.generic), 86
OrthogonalMatrixGroup_gap(classin
sage.groups.matrix_gps.orthogonal_gap), 675
OrthogonalMatrixGroup_generic (class insage.groups.matrix_gps.orthogonal), 669

P
ParentLibGAP (class in sage.groups.libgap_wrapper),24
PariGroup (class in sage.groups.pari_group), 59
parse() (sage.groups.perm_gps.cubegroup.CubeGroupmethod), 577
partition()(sage.groups.perm_gps.symgp_conjugacy_class.SymmetricGroupConjugacyClassMixin method), 593
permutation() (sage.groups.braid.Braid method), 168
permutation_group()(sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 323
permutation_group()(sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_fixed_gens method), 385
permutation_group()(sage.groups.pari_group.PariGroupmethod),784

60
PermutationGroup()(inmodulesage.groups.perm_gps.permgroup), 416
PermutationGroup_action(classin
sage.groups.perm_gps.permgroup), 419
PermutationGroup_generic(classin
sage.groups.perm_gps.permgroup), 421
PermutationGroup_plg(classin
sage.groups.perm_gps.permgroup_named),
524
PermutationGroup_pug(classin
sage.groups.perm_gps.permgroup_named),
525
PermutationGroup_subgroup(classin
sage.groups.perm_gps.permgroup), 497
PermutationGroup_symalt(classin
sage.groups.perm_gps.permgroup_named),
525
PermutationGroup_unique(classin
sage.groups.perm_gps.permgroup_named),
525
PermutationGroupElement(classin
sage.groups.perm_gps.permgroup_element),
553
PermutationGroupElement()(inmodulesage.groups.perm_gps.constructor), 407
PermutationGroupMorphism(classin
sage.groups.perm_gps.permgroup_morphism),
566
PermutationGroupMorphism_from_gap (classin sage.groups.perm_gps.permgroup_morphism),
568
PermutationGroupMorphism_id(classin
sage.groups.perm_gps.permgroup_morphism),
569
PermutationGroupMorphism_im_gens (class insage.groups.perm_gps.permgroup_morphism),
569
PermutationsConjugacyClass(classin
sage.groups.perm_gps.symgp_conjugacy_class),
591
PGL (class in sage.groups.perm_gps.permgroup_named),518
PGU (class in sage.groups.perm_gps.permgroup_named),519
plot() (sage.groups.braid.Braid method), 169plot()(sage.groups.perm_gps.cubegroup.RubiksCube
method), 584
plot3d() (sage.groups.braid.Braid method), 171
plot3d() (sage.groups.perm_gps.cubegroup.RubiksCube
method), 584
plot3d_cube()(sage.groups.perm_gps.cubegroup.CubeGroup method), 579
plot3d_cubie()(inmoduleIndex

Groups, Release 10.4

sage.groups.perm_gps.cubegroup), 590
plot_cube() (sage.groups.perm_gps.cubegroup.CubeGroup method), 579
poincare_series()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),481
polygon_plot3d()(inmodulesage.groups.perm_gps.cubegroup), 590
positive_roots()(sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup method), 654
preimage() (sage.groups.libgap_morphism.GroupMorphism_libgap method), 15
presentation_two_generators()(sage.groups.braid.BraidGroup_class method),186
PrimitiveGroup (class in sage.groups.perm_gps.permgroup_named), 526
PrimitiveGroups()(inmodulesage.groups.perm_gps.permgroup_named),
527
PrimitiveGroupsAll(classin
sage.groups.perm_gps.permgroup_named),
528
PrimitiveGroupsOfDegree(classin
sage.groups.perm_gps.permgroup_named),529
product()(sage.groups.group_exp.GroupExp_Class
method), 256
product()(sage.groups.group_semidirect_product.GroupSemidirectProduct method), 264
PS_represent()(inmodulesage.groups.perm_gps.partn_ref.data_structures), 739
PSL (class in sage.groups.perm_gps.permgroup_named),520
PSp (class in sage.groups.perm_gps.permgroup_named),523
PSP (in module sage.groups.perm_gps.permgroup_named),522
PSU (class in sage.groups.perm_gps.permgroup_named),522
pure_conjugating_braid()(sage.groups.braid.Braid method), 171
PureCactusGroup (class in sage.groups.cactus_group),249
pushforward() (sage.groups.libgap_morphism.GroupMorphism_libgap method), 16

QuaternionPresentation()(inmodulesage.groups.finitely_presented_named), 144
quotient() (sage.groups.abelian_gps.abelian_group_gap.AbelianGroup_gap method), 344
quotient() (sage.groups.free_group.FreeGroup_classmethod), 98
quotient() (sage.groups.group.Group method), 6
quotient() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 481

R(sage.groups.perm_gps.cubegroup.CubeGroupmethod), 574
ramification_module_decomposition_hurwitz_curve() (sage.groups.perm_gps.permgroup_named.PSL method), 521
ramification_module_decomposition_modular_curve() (sage.groups.perm_gps.permgroup_named.PSL method), 522
random_element() (sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 324
random_element() (sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class method), 364
random_element() (sage.groups.affine_gps.affine_group.AffineGroup method), 705
random_element()(sage.groups.affine_gps.euclidean_group.EuclideanGroup method), 711
random_element() (sage.groups.cactus_group.CactusGroup method), 248
random_element() (sage.groups.libgap_mixin.GroupMixinLibGAP method), 56
random_element()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),482
random_tests()(inmodulesage.groups.perm_gps.partn_ref.refinement_graphs), 745
random_tests()(inmodulesage.groups.perm_gps.partn_ref.refinement_matrices), 756
rank()(sage.groups.free_group.FreeGroup_classmethod), 99
rank() (sage.groups.indexed_free_group.IndexedGroupmethod), 219
real() (sage.groups.misc_gps.imaginary_groups.ImaginaryElement method), 405
reduce() (sage.groups.finitely_presented.RewritingSystem method), 133Q
reduced_word() (sage.groups.braid.RightQuantumWord method), 190
QuaternionGroup (class in sage.groups.perm_gps.perreflection() (sage.groups.affine_gps.affine_group.Affinemgroup_named), 530
Group method), 705
QuaternionMatrixGroupGF3()(inmodulereflections()(sage.groups.matrix_gps.coxsage.groups.matrix_gps.finitely_generated), 623
eter_group.CoxeterMatrixGroupmethod),
Index

R()

785

Groups, Release 10.4

655
ment_groups), 399
reflections()(sage.groups.perm_gps.per- roots() (sage.groups.matrix_gps.coxeter_group.Coxetermgroup_named.SymmetricGroupmethod),MatrixGroup method), 655
544
RootsOfUnityGroup(classinrelations() (sage.groups.abelian_gps.abelian_group_gap.Abelian- sage.groups.misc_gps.argument_groups), 400
GroupQuotient_gap method), 337
rotation_list()(inmodulerelations() (sage.groups.finitely_presented.FinitelyPsage.groups.perm_gps.cubegroup), 590
resentedGroup method), 118
RubiksCube (class in sage.groups.perm_gps.cubegroup),
repr2d() (sage.groups.perm_gps.cubegroup.CubeGroup582
method), 580
rules() (sage.groups.finitely_presented.RewritingSystemrepresentative()(sage.groups.conjumethod), 133
gacy_classes.ConjugacyClass method), 301
run() (sage.groups.perm_gps.partn_ref.refinement_matrirepresentative_action()
ces.MatrixStruct method), 755(sage.groups.perm_gps.permgroup.PermutaStionGroup_generic method), 482
restrict()(sage.groups.class_function.ClassFunc- sage.groups.abelian_gps.abelian_aut
tion_gap method), 287
module, 345
restrict()(sage.groups.class_function.ClassFunc- sage.groups.abelian_gps.abelian_grouption_libgap method), 295
module, 307
retract() (sage.groups.abelian_gps.abelian_group_gap.Abeliansage.groups.abelian_gps.abelian_group_elGroupSubgroup_gap method), 339
ement
retract()(sage.groups.kernel_subgroup.KernelSubmodule, 370
group method), 278
sage.groups.abelian_gps.abelian_group_gap
reverse() (sage.groups.braid.Braid method), 173
module, 332
rewriting_system()(sage.groups.finitely_pre- sage.groups.abelian_gps.abelian_group_morsented.FinitelyPresentedGroup method), 118
phism
RewritingSystem (class in sage.groups.finitely_premodule, 376
sented), 127
sage.groups.abelian_gps.dual_abelian_group
reynolds_operator()(sage.groups.mamodule, 359
trix_gps.finitely_generated_gap.FinitelyGensage.groups.abelian_gps.dual_abelian_group_eleratedMatrixGroup_gap method), 636
ementright_angled_coxeter_group()
module, 374(sage.groups.cactus_group.CactusGroupsage.groups.abelian_gps.element_base
method), 248
module, 366
right_invariant_extension()sage.groups.abelian_gps.values(sage.groups.lie_gps.nilpotent_lie_group.Nilpomodule, 352
tentLieGroup method), 731
sage.groups.additive_abelian.addiright_invariant_frame()tive_abelian_group(sage.groups.lie_gps.nilpotent_lie_group.Nilpomodule, 379
tentLieGroup method), 732
sage.groups.additive_abelian.addiright_normal_form()(sage.groups.braid.Braidtive_abelian_wrapper
method), 174
module, 386
right_translation() (sage.groups.lie_gps.nilpo- sage.groups.affine_gps.affine_group
tent_lie_group.NilpotentLieGroupmethod),module, 700732
sage.groups.affine_gps.euclidean_group
RightAngledArtinGroup(classinmodule, 708
sage.groups.raag), 235
sage.groups.affine_gps.group_element
RightAngledArtinGroup.Element (class inmodule, 711
sage.groups.raag), 237
sage.groups.artin
RightQuantumWord (class in sage.groups.braid), 188
module, 221
rigidity() (sage.groups.braid.Braid method), 174
sage.groups.braidrivf() (sage.groups.lie_gps.nilpotent_lie_group.Nilpomodule, 145
tentLieGroup method), 733
sage.groups.cactus_group
RootOfUnity (class in sage.groups.misc_gps.argumodule, 241
786

Index

Groups, Release 10.4

sage.groups.class_function
module, 281
sage.groups.conjugacy_classes
module, 299
sage.groups.cubic_braid
module, 193
sage.groups.finitely_presented
module, 101
sage.groups.finitely_presented_named
module, 137
sage.groups.free_groupmodule, 91
sage.groups.genericmodule, 63
sage.groups.groupmodule, 3
sage.groups.group_exp
module, 253
sage.groups.group_semidirect_productmodule, 259
sage.groups.groups_catalog
module, 1
sage.groups.indexed_free_groupmodule, 215
sage.groups.kernel_subgroupmodule, 277
sage.groups.libgap_groupmodule, 33
sage.groups.libgap_mixin
module, 35
sage.groups.libgap_morphism
module, 9
sage.groups.libgap_wrapper
module, 19
sage.groups.lie_gps.nilpotent_lie_groupmodule, 717
sage.groups.matrix_gps.binary_dihedral
module, 642
sage.groups.matrix_gps.catalog
module, 597
sage.groups.matrix_gps.coxeter_groupmodule, 643
sage.groups.matrix_gps.finitely_generated
module, 618
sage.groups.matrix_gps.finitely_generated_gap
module, 625
sage.groups.matrix_gps.group_element
module, 607
sage.groups.matrix_gps.group_element_gap
module, 612
Indexsage.groups.matrix_gps.heisenberg
module, 697
sage.groups.matrix_gps.homset
module, 641
sage.groups.matrix_gps.isometries
module, 679
sage.groups.matrix_gps.linear
module, 657
sage.groups.matrix_gps.linear_gap
module, 665
sage.groups.matrix_gps.matrix_groupmodule, 597
sage.groups.matrix_gps.matrix_group_gap
module, 604
sage.groups.matrix_gps.morphism
module, 641
sage.groups.matrix_gps.named_groupmodule, 757
sage.groups.matrix_gps.named_group_gap
module, 759
sage.groups.matrix_gps.orthogonal
module, 665
sage.groups.matrix_gps.orthogonal_gap
module, 675
sage.groups.matrix_gps.symplectic
module, 683
sage.groups.matrix_gps.symplectic_gap
module, 687
sage.groups.matrix_gps.unitarymodule, 688
sage.groups.matrix_gps.unitary_gap
module, 696
sage.groups.misc_gps.argument_groups
module, 395
sage.groups.misc_gps.imaginary_groups
module, 404
sage.groups.misc_gps.misc_groups
module, 267
sage.groups.pari_groupmodule, 59
sage.groups.perm_gps.constructor
module, 407
sage.groups.perm_gps.cubegroupmodule, 570
sage.groups.perm_gps.partn_ref.canonical_augmentation
module, 737
sage.groups.perm_gps.partn_ref.data_structuresmodule, 739
sage.groups.perm_gps.partn_ref.refinement_graphs
module, 740
787

Groups, Release 10.4

sage.groups.perm_gps.partn_ref.refinement_lists
module, 752
sage.groups.perm_gps.partn_ref.refinement_matrices
module, 753
sage.groups.perm_gps.permgroupmodule, 412
sage.groups.perm_gps.permgroup_element
module, 550
sage.groups.perm_gps.permgroup_morphism
module, 565
sage.groups.perm_gps.permgroup_named
module, 500
sage.groups.perm_gps.permutation_groups_catalog
module, 407
sage.groups.perm_gps.symgp_conjugacy_classmodule, 591
sage.groups.raag
module, 233
sage.groups.semimonomial_transformations.semimonomial_transformation
module, 273
sage.groups.semimonomial_transformations.semimonomial_transformation_groupmodule, 269
SC_test_list_perms()(inmodulesage.groups.perm_gps.partn_ref.data_structures), 739
scalar_product() (sage.groups.class_function.ClassFunction_gap method), 287
scalar_product() (sage.groups.class_function.ClassFunction_libgap method), 296
scramble()(sage.groups.perm_gps.cubegroup.RubiksCube method), 584
search_tree()(inmodulesage.groups.perm_gps.partn_ref.refinement_graphs), 746
section() (sage.groups.libgap_morphism.GroupMorphism_libgap method), 17
SemidihedralGroup(classin
sage.groups.perm_gps.permgroup_named),531
semidirect_product() (sage.groups.finitely_presented.FinitelyPresentedGroup method), 119
semidirect_product() (sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 483
SemimonomialActionMat (class in sage.groups.semimonomial_transformations.semimono788

mial_transformation_group), 269
SemimonomialActionVec (class in sage.groups.semimonomial_transformations.semimonomial_transformation_group), 270
SemimonomialTransformation(classin
sage.groups.semimonomial_transformations.semimonomial_transformation), 273
SemimonomialTransformationGroup(classin
sage.groups.semimonomial_transformations.semimonomial_transformation_group),
270
set()
(sage.groups.conjugacy_classes.ConjugacyClass
method), 302
set() (sage.groups.conjugacy_classes.ConjugacyClassGAP method), 304
set()(sage.groups.perm_gps.symgp_conjugacy_class.PermutationsConjugacyClass
method), 592
set()(sage.groups.perm_gps.symgp_conjugacy_class.SymmetricGroupConjugacyClass
method), 592
short_name()(sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_classmethod), 384
show()(sage.groups.perm_gps.cubegroup.RubiksCube
method), 585
show3d() (sage.groups.perm_gps.cubegroup.RubiksCube
method), 585
Sign (class in sage.groups.misc_gps.argument_groups),401
sign() (sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 561
sign_representation()(sage.groups.matrix_gps.matrix_group.MatrixGroup_base
method), 599
sign_representation()(sage.groups.perm_gps.permgroup.PermutationGroup_generic method), 485
signature()(sage.groups.pari_group.PariGroupmethod), 61
SignGroup (class in sage.groups.misc_gps.argument_groups), 401
simple_reflection() (sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup method), 656
simple_reflection() (sage.groups.perm_gps.permgroup_named.ComplexReflectionGroupmethod), 507
simple_reflection() (sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),544
simple_reflections()(sage.groups.cubic_braid.CubicBraidGroup method), 213
simple_root_index() (sage.groups.matrix_gps.coxeter_group.CoxeterMatrixGroup method), 656
Index

Groups, Release 10.4

simplification_isomorphism()
structure_description()(sage.groups.finitely_presented.FinitelyPre(sage.groups.finitely_presented.FinitelyPresentedGroup method), 122sentedGroup method), 124
simplified() (sage.groups.finitely_presented.Finite- structure_description()(sage.groups.malyPresentedGroup method), 122
trix_gps.matrix_group_gap.MatrixGroup_gap
SL() (in module sage.groups.matrix_gps.linear), 663
method), 604
sliding_circuits()(sage.groups.braid.Braid structure_description()
method), 174(sage.groups.perm_gps.permgroup.Permutasmallest_moved_point()
tionGroup_generic method), 492(sage.groups.perm_gps.permgroup.PermutaSU() (in module sage.groups.matrix_gps.unitary), 692
tionGroup_generic method), 485
Subgroup (sage.groups.abelian_gps.abelian_group.AbelianSmallPermutationGroup(classinGroup_class attribute), 312
sage.groups.perm_gps.permgroup_named),
Subgroup (sage.groups.perm_gps.permgroup.Permuta532
tionGroup_generic attribute), 421
SO() (in module sage.groups.matrix_gps.orthogonal), 672 subgroup() (sage.groups.abelian_gps.abelian_group_gap.Abeliansocle() (sage.groups.perm_gps.permgroup.PermutationGroup_gap method), 344
Group_generic method), 486
subgroup() (sage.groups.abelian_gps.abelian_group.Abeliansolvable_radical()(sage.groups.perm_gps.perGroup_class method), 324
mgroup.PermutationGroup_genericmethod), subgroup() (sage.groups.libgap_wrapper.ParentLib486
GAP method), 30
solve() (sage.groups.perm_gps.cubegroup.CubeGroup subgroup()(sage.groups.matrix_gps.mamethod), 581
trix_group_gap.MatrixGroup_gap
method),solve() (sage.groups.perm_gps.cubegroup.RubiksCube
606
method), 586
subgroup() (sage.groups.matrix_gps.matrix_group.Masome_elements() (sage.groups.affine_gps.affine_group.AffinetrixGroup_base method), 600
Group method), 706
subgroup() (sage.groups.perm_gps.permgroup.Permusome_elements()(sage.groups.artin.ArtinGrouptationGroup_generic method), 494
method), 226
subgroup_reduced()
some_elements()(sage.groups.braid.Braid(sage.groups.abelian_gps.abelian_group.AbelianGroup_class method), 187
Group_class method), 325
sorted_presentation() (sage.groups.finitely_pre- subgroups() (sage.groups.abelian_gps.abelian_group.Abeliansented.FinitelyPresentedGroup method), 123
Group_class method), 325
Sp() (in module sage.groups.matrix_gps.symplectic), 684 subgroups() (sage.groups.libgap_mixin.GroupMixinSplitMetacyclicGroup(classin
LibGAP method), 57
sage.groups.perm_gps.permgroup_named),
subgroups() (sage.groups.perm_gps.permgroup.Per534
mutationGroup_generic method), 494
stabilizer() (sage.groups.perm_gps.permgroup.Per- super_summit_set()(sage.groups.braid.BraidmutationGroup_generic method), 487
method), 176
standardize_generator()(inmodule SuzukiGroup (class in sage.groups.perm_gps.persage.groups.perm_gps.constructor), 409
mgroup_named), 536
step() (sage.groups.lie_gps.nilpotent_lie_group.Nilpo- SuzukiSporadicGroup(classintentLieGroup method), 734
sage.groups.perm_gps.permgroup_named),
strands() (sage.groups.braid.Braid method), 175
537
strands()(sage.groups.braid.BraidGroup_class syllables() (sage.groups.free_group.FreeGroupElemethod), 187
ment method), 97
strands() (sage.groups.cubic_braid.CubicBraidGroup sylow_subgroup()(sage.groups.perm_gps.permethod), 214
mgroup.PermutationGroup_genericmethod),string_to_tuples()(in
module495
sage.groups.perm_gps.constructor), 411
symmetric_power()(sage.groups.class_funcstrong_generating_system()tion.ClassFunction_gap method), 288(sage.groups.perm_gps.permgroup.Permutasymmetric_power()(sage.groups.class_functionGroup_generic method), 489
tion.ClassFunction_libgap method), 296
structure_description()(inmodule SymmetricGroup (class in sage.groups.perm_gps.persage.groups.generic), 88
mgroup_named), 537
Index

789

Groups, Release 10.4

SymmetricGroupConjugacyClass(classin
sage.groups.perm_gps.symgp_conjugacy_class),
592
SymmetricGroupConjugacyClassMixin(class in sage.groups.perm_gps.symgp_conjugacy_class), 593
SymmetricGroupElement(classin
sage.groups.perm_gps.permgroup_element),
563
SymmetricPresentation()(inmodulesage.groups.finitely_presented_named), 144
SymplecticMatrixGroup_gap(classin
sage.groups.matrix_gps.symplectic_gap), 687
SymplecticMatrixGroup_generic (class insage.groups.matrix_gps.symplectic), 686

TransitiveGroup (class in sage.groups.perm_gps.permgroup_named), 545
TransitiveGroups()(inmodulesage.groups.perm_gps.permgroup_named),
547
TransitiveGroupsAll(classin
sage.groups.perm_gps.permgroup_named),
548
TransitiveGroupsOfDegree(classin
sage.groups.perm_gps.permgroup_named),549
translation() (sage.groups.affine_gps.affine_group.AffineGroup method), 707
transversals()(sage.groups.perm_gps.permgroup.PermutationGroup_genericmethod),496
Ttrivial_character()(sage.groups.libgap_mixin.GroupMixinLibGAP method), 58
tensor_product() (sage.groups.class_function.Classtrivial_character() (sage.groups.perm_gps.perFunction_gap method), 288
mgroup.PermutationGroup_genericmethod),tensor_product() (sage.groups.class_function.Class496
Function_libgap method), 297
thurston_type() (sage.groups.braid.Braid method), tropical_coordinates() (sage.groups.braid.Braidmethod), 177
176
Tietze()(sage.groups.finitely_presented.FinitelyPre- tuple() (sage.groups.perm_gps.permgroup_element.PermutationGroupElement method), 562
sentedGroupElement method), 126(sage.groups.braid.RightQuantumWord
Tietze() (sage.groups.free_group.FreeGroupElement tuples()method), 190
method), 94
TL_basis_with_drain() (sage.groups.braid.BraidU
Group_class method), 180U()(sage.groups.perm_gps.cubegroup.CubeGroupTL_matrix() (sage.groups.braid.Braid method), 147
method), 574
TL_representation()(sage.groups.braid.Braidultra_summit_set()(sage.groups.braid.Braid
Group_class method), 181
method), 177
to_libgap() (in module sage.groups.matrix_gps.morundo()(sage.groups.perm_gps.cubegroup.RubiksCube
phism), 641
method), 586
to_matrix()(sage.groups.cactus_group.CactusUnitaryMatrixGroup_gap (class in sage.groups.maGroup.Element method), 242
trix_gps.unitary_gap), 696
to_opposite() (sage.groups.group_semidirect_prod(classin
uct.GroupSemidirectProductElement
method), UnitaryMatrixGroup_genericsage.groups.matrix_gps.unitary), 694264
to_permutation() (sage.groups.cactus_group.Cac- UnitCircleGroup (class in sage.groups.misc_gps.argument_groups), 402
tusGroup.Element method), 243
to_word_list() (sage.groups.indexed_free_group.In- UnitCirclePoint (class in sage.groups.misc_gps.argument_groups), 403
dexedFreeGroup.Element method), 217
universe()(sage.groups.additive_abelian.additorsion_subgroup()
tive_abelian_wrapper.AdditiveAbelianGroup(sage.groups.abelian_gps.abelian_group.AbelianWrapper method), 393
Group_class method), 326
torsion_subgroup()(sage.groups.addi- UnwrappingMorphism (class in sage.groups.additive_abelian.additive_abelian_wrapper), 394
tive_abelian.additive_abelian_wrapper.Adupper_central_series()
ditiveAbelianGroupWrapper method), 391(sage.groups.perm_gps.permgroup.Permutatransitive_number()tionGroup_generic method), 497(sage.groups.pari_group.PariGroupmethod),61transitive_number() (sage.groups.perm_gps.per- V
mgroup_named.TransitiveGroup method), 547
value() (sage.groups.abelian_gps.values.AbelianGroup790

Index

Groups, Release 10.4

WithValuesElement method), 356
values()(sage.groups.class_function.ClassFunction_gap method), 289
values()(sage.groups.class_function.ClassFunction_libgap method), 297
values_embedding() (sage.groups.abelian_gps.values.AbelianGroupWithValues_classmethod),358
values_group()(sage.groups.abelian_gps.values.AbelianGroupWithValues_classmethod),359
vector_space() (sage.groups.affine_gps.affine_group.AffineGroup method), 707

W
word_problem()(inmodulesage.groups.abelian_gps.abelian_group), 330
word_problem() (sage.groups.abelian_gps.abelian_group_element.AbelianGroupElement method), 372
word_problem() (sage.groups.abelian_gps.dual_abelian_group_element.DualAbelianGroupElement method), 375
word_problem() (sage.groups.matrix_gps.group_element_gap.MatrixGroupElement_gap method),615
word_problem()(sage.groups.perm_gps.permgroup_element.PermutationGroupElement
method), 562
wrap_FpGroup() (in module sage.groups.finitely_presented), 134
wrap_FreeGroup()(inmodulesage.groups.free_group), 100X
xproj() (in module sage.groups.perm_gps.cubegroup),
591

Yyoung_subgroup()(sage.groups.perm_gps.permgroup_named.SymmetricGroupmethod),545
yproj() (in module sage.groups.perm_gps.cubegroup),
591

Index

791