Sage Quickstart for Abstract Algebra - PREP Tutorials

Skip to content
Back to top
View this page
Edit this page

# Sage Quickstart for Abstract Algebra

This Sage quickstart tutorial was developed for the MAA PREP Workshop “Sage: Using Open-Source Mathematics Software with Undergraduates” (funding provided by NSF DUE 0817071). It is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA).

As computers are discrete and finite, anything with a discrete, finite set of generators is natural to implement and explore.

## Group Theory

Many common groups are pre-defined, usually as permutation groups: that is, explicitly described as subgroups of symmetric groups.

- Every group of order 15 or less is available as a permutation group.

- Sometimes they are available under special names, though.

Sage

    sage: G = QuaternionGroup()
    sage: G
    Quaternion group of order 8 as a permutation group

Python

    >>> from sage.all import *
    >>> G = QuaternionGroup()
    >>> G
    Quaternion group of order 8 as a permutation group

Sage

    sage: H = AlternatingGroup(5)
    sage: H
    Alternating group of order 5!/2 as a permutation group

[Python]

    >>> from sage.all import *
    >>> H = AlternatingGroup(Integer(5))
    >>> H
    Alternating group of order 5!/2 as a permutation group

Sage

    sage: H.is_simple()
    True

Python

    >>> from sage.all import *
    >>> H.is_simple()
    True

Sage

    sage: D = DihedralGroup(8)
    sage: D
    Dihedral group of order 16 as a permutation group

[Python]

    >>> from sage.all import *
    >>> D = DihedralGroup(Integer(8))
    >>> D
    Dihedral group of order 16 as a permutation group

We can access a lot of information about groups, such as:

- A list of subgroups up to conjugacy,

- or a stabilizer,

- or other things demonstrated below.

Sage

    sage: for K in D.conjugacy_classes_subgroups():
    ....:     print(K)
    Subgroup generated by [()] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (1,2,3,4,5,6,7,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8)] of (Dihedral group of order 16 as a permutation group)

Python

    >>> from sage.all import *
    >>> for K in D.conjugacy_classes_subgroups():
    ...     print(K)
    Subgroup generated by [()] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (2,8)(3,7)(4,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (1,2,3,4,5,6,7,8)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (1,2)(3,8)(4,7)(5,6)] of (Dihedral group of order 16 as a permutation group)
    Subgroup generated by [(1,5)(2,6)(3,7)(4,8), (1,3,5,7)(2,4,6,8), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8)] of (Dihedral group of order 16 as a permutation group)

In the previous cell we once again did a for loop over a set of objects rather than just a list of numbers. This can be very powerful.

Sage

    sage: D.stabilizer(3)
    Subgroup generated by [(1,5)(2,4)(6,8)] of (Dihedral group of order 16 as a permutation group)

[Python]

    >>> from sage.all import *
    >>> D.stabilizer(Integer(3))
    Subgroup generated by [(1,5)(2,4)(6,8)] of (Dihedral group of order 16 as a permutation group)

Sage

    sage: len(D.normal_subgroups())
    7
    sage: for K in sorted(D.normal_subgroups()):
    ....:     print(K)
    Subgroup generated by [()] of (Dihedral group of order 16 as a permutation group)
    ...
    Subgroup generated by [(1,2,3,4,5,6,7,8), (1,8)(2,7)(3,6)(4,5)] of (Dihedral group of order 16 as a permutation group)

Python

    >>> from sage.all import *
    >>> len(D.normal_subgroups())
    7
    >>> for K in sorted(D.normal_subgroups()):
    ...     print(K)
    Subgroup generated by [()] of (Dihedral group of order 16 as a permutation group)
    ...
    Subgroup generated by [(1,2,3,4,5,6,7,8), (1,8)(2,7)(3,6)(4,5)] of (Dihedral group of order 16 as a permutation group)

We can access specific subgroups if we know the generators as a permutation group.

Sage

    sage: L = D.subgroup(["(1,3,5,7)(2,4,6,8)"])

[Python]

    >>> from sage.all import *
    >>> L = D.subgroup(["(1,3,5,7)(2,4,6,8)"])

Sage

    sage: L.is_normal(D)
    True

Python

    >>> from sage.all import *
    >>> L.is_normal(D)
    True

Sage

    sage: Q=D.quotient(L)
    sage: Q
    Permutation Group with generators [(1,2)(3,4), (1,3)(2,4)]

[Python]

    >>> from sage.all import *
    >>> Q=D.quotient(L)
    >>> Q
    Permutation Group with generators [(1,2)(3,4), (1,3)(2,4)]

Sage

    sage: Q.is_isomorphic(KleinFourGroup())
    True

Python

    >>> from sage.all import *
    >>> Q.is_isomorphic(KleinFourGroup())
    True

There are some matrix groups as well, both finite and infinite.

Sage

    sage: S = SL(2, GF(3))
    sage: S
    Special Linear Group of degree 2 over Finite Field of size 3

[Python]

    >>> from sage.all import *
    >>> S = SL(Integer(2), GF(Integer(3)))
    >>> S
    Special Linear Group of degree 2 over Finite Field of size 3

We can print out all of the elements of this group.

Sage

    sage: for a in S:
    ....:     print(a)
    [1 0]
    [0 1]
    ...
    [2 2]
    [2 1]

Python

    >>> from sage.all import *
    >>> for a in S:
    ...     print(a)
    [1 0]
    [0 1]
    ...
    [2 2]
    [2 1]

Sage

    sage: SS = SL(2, ZZ)

[Python]

    >>> from sage.all import *
    >>> SS = SL(Integer(2), ZZ)

Of course, you have to be careful what you try to do!

Sage

    sage: SS.list()
    Traceback (most recent call last):
    ...
    NotImplementedError: group must be finite

Python

    >>> from sage.all import *
    >>> SS.list()
    Traceback (most recent call last):
    ...
    NotImplementedError: group must be finite

Sage

    sage: for a in SS.gens():
    ....:     print(a)
    [ 0  1]
    [-1  0]
    ...

[Python]

    >>> from sage.all import *
    >>> for a in SS.gens():
    ...     print(a)
    [ 0  1]
    [-1  0]
    ...

## Rings

Sage has many pre-defined rings to experiment with. Here is how one would access \(\ZZ/12\ZZ\), for instance.

Sage

    sage: twelve = Integers(12)
    sage: twelve
    Ring of integers modulo 12

Python

    >>> from sage.all import *
    >>> twelve = Integers(Integer(12))
    >>> twelve
    Ring of integers modulo 12

Sage

    sage: twelve.is_field()
    False

[Python]

    >>> from sage.all import *
    >>> twelve.is_field()
    False

Sage

    sage: twelve.is_integral_domain()
    False

Python

    >>> from sage.all import *
    >>> twelve.is_integral_domain()
    False

### Quaternions, and generalizations

We can define generalized quaternion algebras, where \(i^2=a\), \(j^2=b\), and \(k=i\cdot j\), all over \(\QQ\):

Sage

    sage: quat = QuaternionAlgebra(-1, -1)
    sage: quat
    Quaternion Algebra (-1, -1) with base ring Rational Field

Python

    >>> from sage.all import *
    >>> quat = QuaternionAlgebra(-Integer(1), -Integer(1))
    >>> quat
    Quaternion Algebra (-1, -1) with base ring Rational Field

Sage

    sage: quat.is_field()
    False

[Python]

    >>> from sage.all import *
    >>> quat.is_field()
    False

Sage

    sage: quat.is_commutative()
    False

Python

    >>> from sage.all import *
    >>> quat.is_commutative()
    False

Sage

    sage: quat.is_division_algebra()
    True

[Python]

    >>> from sage.all import *
    >>> quat.is_division_algebra()
    True

Sage

    sage: quat2 = QuaternionAlgebra(5, -7)

Python

    >>> from sage.all import *
    >>> quat2 = QuaternionAlgebra(Integer(5), -Integer(7))

Sage

    sage: quat2.is_division_algebra()
    True

[Python]

    >>> from sage.all import *
    >>> quat2.is_division_algebra()
    True

Sage

    sage: quat2.is_field()
    False

Python

    >>> from sage.all import *
    >>> quat2.is_field()
    False

### Polynomial Rings

Polynomial arithmetic in Sage is a very important tool.

The first cell brings us back to the symbolic world. This is not the same thing as polynomials!

[Sage]

    sage: reset('x') # This returns x to being a variable
    sage: (x^4 + 2*x).parent()
    Symbolic Ring

[Python]

    >>> from sage.all import *
    >>> reset('x') # This returns x to being a variable
    >>> (x**Integer(4) + Integer(2)*x).parent()
    Symbolic Ring

Now we will turn \(x\) into the generator of a polynomial ring. The syntax is a little unusual, but you will see it often.

[Sage]

    sage: R.<x> = QQ[]
    sage: R
    Univariate Polynomial Ring in x over Rational Field

[Python]

    >>> from sage.all import *
    >>> R = QQ['x']; (x,) = R._first_ngens(1)
    >>> R
    Univariate Polynomial Ring in x over Rational Field

[Sage]

    sage: R.random_element() # random
    -5/2*x^2 - 1/4*x - 1

[Python]

    >>> from sage.all import *
    >>> R.random_element() # random
    -5/2*x^2 - 1/4*x - 1

[Sage]

    sage: R.is_integral_domain()
    True

[Python]

    >>> from sage.all import *
    >>> R.is_integral_domain()
    True

[Sage]

    sage: (x^4 + 2*x).parent()
    Univariate Polynomial Ring in x over Rational Field

[Python]

    >>> from sage.all import *
    >>> (x**Integer(4) + Integer(2)*x).parent()
    Univariate Polynomial Ring in x over Rational Field

[Sage]

    sage: (x^2+x+1).is_irreducible()
    True

[Python]

    >>> from sage.all import *
    >>> (x**Integer(2)+x+Integer(1)).is_irreducible()
    True

[Sage]

    sage: F = GF(5)
    sage: P.<y> = F[]

[Python]

    >>> from sage.all import *
    >>> F = GF(Integer(5))
    >>> P = F['y']; (y,) = P._first_ngens(1)

[Sage]

    sage: P.random_element() # random
    2*y

[Python]

    >>> from sage.all import *
    >>> P.random_element() # random
    2*y

[Sage]

    sage: I = P.ideal(y^3+2*y)
    sage: I
    Principal ideal (y^3 + 2*y) of Univariate Polynomial Ring in y over Finite Field of size 5

[Python]

    >>> from sage.all import *
    >>> I = P.ideal(y**Integer(3)+Integer(2)*y)
    >>> I
    Principal ideal (y^3 + 2*y) of Univariate Polynomial Ring in y over Finite Field of size 5

[Sage]

    sage: Q = P.quotient(I)

[Python]

    >>> from sage.all import *
    >>> Q = P.quotient(I)

[Sage]

    sage: Q
    Univariate Quotient Polynomial Ring in ybar over Finite Field of size 5 with modulus y^3 + 2*y

[Python]

    >>> from sage.all import *
    >>> Q
    Univariate Quotient Polynomial Ring in ybar over Finite Field of size 5 with modulus y^3 + 2*y

## Fields

Sage has superb support for finite fields and extensions of the rationals.

### Finite Fields

Sage

    sage: F.<a> = GF(3^4)
    sage: F
    Finite Field in a of size 3^4

Python

    >>> from sage.all import *
    >>> F = GF(Integer(3)**Integer(4), names=('a',)); (a,) = F._first_ngens(1)
    >>> F
    Finite Field in a of size 3^4

The generator satisfies a Conway polynomial, by default, or the polynomial can be specified.

Sage

    sage: F.polynomial()
    a^4 + 2*a^3 + 2

[Python]

    >>> from sage.all import *
    >>> F.polynomial()
    a^4 + 2*a^3 + 2

Sage

    sage: F.list()
    [0, a, a^2, a^3, a^3 + 1, a^3 + a + 1, a^3 + a^2 + a + 1, 2*a^3 + a^2 + a + 1, a^2 + a + 2, a^3 + a^2 + 2*a, 2*a^3 + 2*a^2 + 1, a^3 + a + 2, a^3 + a^2 + 2*a + 1, 2*a^3 + 2*a^2 + a + 1, a^3 + a^2 + a + 2, 2*a^3 + a^2 + 2*a + 1, 2*a^2 + a + 2, 2*a^3 + a^2 + 2*a, 2*a^2 + 2, 2*a^3 + 2*a, 2*a^3 + 2*a^2 + 2, a^3 + 2*a + 2, a^3 + 2*a^2 + 2*a + 1, 2*a^2 + a + 1, 2*a^3 + a^2 + a, a^2 + 2, a^3 + 2*a, a^3 + 2*a^2 + 1, a + 1, a^2 + a, a^3 + a^2, 2*a^3 + 1, 2*a^3 + a + 2, 2*a^3 + a^2 + 2*a + 2, 2*a^2 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a, a^3 + 2*a^2 + 2, 2*a + 1, 2*a^2 + a, 2*a^3 + a^2, 2, 2*a, 2*a^2, 2*a^3, 2*a^3 + 2, 2*a^3 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a + 2, a^3 + 2*a^2 + 2*a + 2, 2*a^2 + 2*a + 1, 2*a^3 + 2*a^2 + a, a^3 + a^2 + 2, 2*a^3 + 2*a + 1, 2*a^3 + 2*a^2 + a + 2, a^3 + a^2 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a + 1, a^3 + 2*a^2 + a + 2, a^2 + 2*a + 1, a^3 + 2*a^2 + a, a^2 + 1, a^3 + a, a^3 + a^2 + 1, 2*a^3 + a + 1, 2*a^3 + a^2 + a + 2, a^2 + 2*a + 2, a^3 + 2*a^2 + 2*a, 2*a^2 + 1, 2*a^3 + a, 2*a^3 + a^2 + 2, 2*a + 2, 2*a^2 + 2*a, 2*a^3 + 2*a^2, a^3 + 2, a^3 + 2*a + 1, a^3 + 2*a^2 + a + 1, a^2 + a + 1, a^3 + a^2 + a, 2*a^3 + a^2 + 1, a + 2, a^2 + 2*a, a^3 + 2*a^2, 1]

Python

    >>> from sage.all import *
    >>> F.list()
    [0, a, a^2, a^3, a^3 + 1, a^3 + a + 1, a^3 + a^2 + a + 1, 2*a^3 + a^2 + a + 1, a^2 + a + 2, a^3 + a^2 + 2*a, 2*a^3 + 2*a^2 + 1, a^3 + a + 2, a^3 + a^2 + 2*a + 1, 2*a^3 + 2*a^2 + a + 1, a^3 + a^2 + a + 2, 2*a^3 + a^2 + 2*a + 1, 2*a^2 + a + 2, 2*a^3 + a^2 + 2*a, 2*a^2 + 2, 2*a^3 + 2*a, 2*a^3 + 2*a^2 + 2, a^3 + 2*a + 2, a^3 + 2*a^2 + 2*a + 1, 2*a^2 + a + 1, 2*a^3 + a^2 + a, a^2 + 2, a^3 + 2*a, a^3 + 2*a^2 + 1, a + 1, a^2 + a, a^3 + a^2, 2*a^3 + 1, 2*a^3 + a + 2, 2*a^3 + a^2 + 2*a + 2, 2*a^2 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a, a^3 + 2*a^2 + 2, 2*a + 1, 2*a^2 + a, 2*a^3 + a^2, 2, 2*a, 2*a^2, 2*a^3, 2*a^3 + 2, 2*a^3 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a + 2, a^3 + 2*a^2 + 2*a + 2, 2*a^2 + 2*a + 1, 2*a^3 + 2*a^2 + a, a^3 + a^2 + 2, 2*a^3 + 2*a + 1, 2*a^3 + 2*a^2 + a + 2, a^3 + a^2 + 2*a + 2, 2*a^3 + 2*a^2 + 2*a + 1, a^3 + 2*a^2 + a + 2, a^2 + 2*a + 1, a^3 + 2*a^2 + a, a^2 + 1, a^3 + a, a^3 + a^2 + 1, 2*a^3 + a + 1, 2*a^3 + a^2 + a + 2, a^2 + 2*a + 2, a^3 + 2*a^2 + 2*a, 2*a^2 + 1, 2*a^3 + a, 2*a^3 + a^2 + 2, 2*a + 2, 2*a^2 + 2*a, 2*a^3 + 2*a^2, a^3 + 2, a^3 + 2*a + 1, a^3 + 2*a^2 + a + 1, a^2 + a + 1, a^3 + a^2 + a, 2*a^3 + a^2 + 1, a + 2, a^2 + 2*a, a^3 + 2*a^2, 1]

Sage

    sage: (a^3 + 2*a^2 + 2)*(2*a^3 + 2*a + 1)
    2*a^3 + a^2 + a + 1

[Python]

    >>> from sage.all import *
    >>> (a**Integer(3) + Integer(2)*a**Integer(2) + Integer(2))*(Integer(2)*a**Integer(3) + Integer(2)*a + Integer(1))
    2*a^3 + a^2 + a + 1

\(F\) should be the splitting field of the polynomial \(x^{81}-x\), so it is very good that we get no output from the following cell, which combines a loop and a conditional statement.

Sage

    sage: for a in F:
    ....:     if not (a^81 - a == 0):
    ....:         print("Oops!")

Python

    >>> from sage.all import *
    >>> for a in F:
    ...     if not (a**Integer(81) - a == Integer(0)):
    ...         print("Oops!")

### Field Extensions, Number Fields

Most things you will need in an undergraduate algebra classroom are already in Sage.

Sage

    sage: N = QQ[sqrt(2)]
    sage: N
    Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?

Python

    >>> from sage.all import *
    >>> N = QQ[sqrt(Integer(2))]
    >>> N
    Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?

Sage

    sage: var('z')
    z
    sage: M.<a>=NumberField(z^2-2)
    sage: M
    Number Field in a with defining polynomial z^2 - 2

[Python]

    >>> from sage.all import *
    >>> var('z')
    z
    >>> M = NumberField(z**Integer(2)-Integer(2), names=('a',)); (a,) = M._first_ngens(1)
    >>> M
    Number Field in a with defining polynomial z^2 - 2

Sage

    sage: M.degree()
    2

Python

    >>> from sage.all import *
    >>> M.degree()
    2

Sage

    sage: M.is_galois()
    True

[Python]

    >>> from sage.all import *
    >>> M.is_galois()
    True

Sage

    sage: M.is_isomorphic(N)
    True

Python

    >>> from sage.all import *
    >>> M.is_isomorphic(N)
    True