Finite dimensional modules with basis - Category Framework

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

# Finite dimensional modules with basis

class sage.categories.finite_dimensional_modules_with_basis.FiniteDimensionalModulesWithBasis(base_category)

  Bases: `CategoryWithAxiom_over_base_ring`

  The category of finite dimensional modules with a distinguished basis.

  EXAMPLES:

  Sage

      sage: C = FiniteDimensionalModulesWithBasis(ZZ); C
      Category of finite dimensional modules with basis over Integer Ring
      sage: sorted(C.super_categories(), key=str)
      [Category of finite dimensional modules over Integer Ring,
       Category of modules with basis over Integer Ring]
      sage: C is Modules(ZZ).WithBasis().FiniteDimensional()
      True

  Python

      >>> from sage.all import *
      >>> C = FiniteDimensionalModulesWithBasis(ZZ); C
      Category of finite dimensional modules with basis over Integer Ring
      >>> sorted(C.super_categories(), key=str)
      [Category of finite dimensional modules over Integer Ring,
       Category of modules with basis over Integer Ring]
      >>> C is Modules(ZZ).WithBasis().FiniteDimensional()
      True

  class ElementMethods

    Bases: `object`

    dense_coefficient_list(order=None)

      Return a list of all coefficients of `self`.

      By default, this list is ordered in the same way as the indexing set of the basis of the parent of `self`.

      INPUT:

      - `order` – (optional) an ordering of the basis indexing set

      EXAMPLES:

      Sage

          sage: # needs sage.modules
          sage: v = vector([0, -1, -3])
          sage: v.dense_coefficient_list()
          [0, -1, -3]
          sage: v.dense_coefficient_list([2,1,0])
          [-3, -1, 0]
          sage: sorted(v.coefficients())
          [-3, -1]

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> v = vector([Integer(0), -Integer(1), -Integer(3)])
          >>> v.dense_coefficient_list()
          [0, -1, -3]
          >>> v.dense_coefficient_list([Integer(2),Integer(1),Integer(0)])
          [-3, -1, 0]
          >>> sorted(v.coefficients())
          [-3, -1]

  class Homsets(category, *args)

    Bases: `HomsetsCategory`

    class Endset(base_category)

      Bases: `CategoryWithAxiom`

      class ElementMethods

        Bases: `object`

        characteristic_polynomial()

          Return the characteristic polynomial of this endomorphism.

          `characteristic_polynomial()` and `charpoly()` are the same method.

          INPUT:

          - `var` – variable

          EXAMPLES:

          Sage

              sage: # needs sage.modules
              sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1])
              sage: phi.characteristic_polynomial()
              x^2 - 3*x + 2
              sage: phi.charpoly()
              x^2 - 3*x + 2
              sage: phi.matrix().charpoly()
              x^2 - 3*x + 2
              sage: phi.charpoly('T')
              T^2 - 3*T + 2
              sage: W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              sage: M = matrix(ZZ, [[1, 0], [1, 2]])
              sage: psi = W.module_morphism(matrix=M, codomain=W)
              sage: psi.charpoly()
              x^2 - 3*x + 2

          Python

              >>> from sage.all import *
              >>> # needs sage.modules
              >>> V = ZZ**Integer(2); phi = V.hom([V.gen(0) + V.gen(1), Integer(2)*V.gen(1)])
              >>> phi.characteristic_polynomial()
              x^2 - 3*x + 2
              >>> phi.charpoly()
              x^2 - 3*x + 2
              >>> phi.matrix().charpoly()
              x^2 - 3*x + 2
              >>> phi.charpoly('T')
              T^2 - 3*T + 2
              >>> W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              >>> M = matrix(ZZ, [[Integer(1), Integer(0)], [Integer(1), Integer(2)]])
              >>> psi = W.module_morphism(matrix=M, codomain=W)
              >>> psi.charpoly()
              x^2 - 3*x + 2

        charpoly()

          alias of `characteristic_polynomial()`.

        det()

          alias of `determinant()`.

        determinant()

          Return the determinant of this endomorphism.

          `determinant()` and `det()` are the same method.

          EXAMPLES:

          Sage

              sage: # needs sage.modules
              sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1])
              sage: phi.determinant()
              2
              sage: phi.det()
              2
              sage: W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              sage: M = matrix(ZZ, [[1, 0], [1, 2]])
              sage: psi = W.module_morphism(matrix=M, codomain=W)
              sage: psi.det()
              2

          Python

              >>> from sage.all import *
              >>> # needs sage.modules
              >>> V = ZZ**Integer(2); phi = V.hom([V.gen(0) + V.gen(1), Integer(2)*V.gen(1)])
              >>> phi.determinant()
              2
              >>> phi.det()
              2
              >>> W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              >>> M = matrix(ZZ, [[Integer(1), Integer(0)], [Integer(1), Integer(2)]])
              >>> psi = W.module_morphism(matrix=M, codomain=W)
              >>> psi.det()
              2

        fcp()

          Return the factorization of the characteristic polynomial.

          INPUT:

          - `var` – variable

          EXAMPLES:

          Sage

              sage: # needs sage.modules
              sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1])
              sage: phi.fcp()                                                         # needs sage.libs.pari
              (x - 2) * (x - 1)
              sage: phi.fcp('T')                                                      # needs sage.libs.pari
              (T - 2) * (T - 1)
              sage: W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              sage: M = matrix(ZZ, [[1, 0], [1, 2]])
              sage: psi = W.module_morphism(matrix=M, codomain=W)
              sage: psi.fcp()                                                         # needs sage.libs.pari
              (x - 2) * (x - 1)

          Python

              >>> from sage.all import *
              >>> # needs sage.modules
              >>> V = ZZ**Integer(2); phi = V.hom([V.gen(0) + V.gen(1), Integer(2)*V.gen(1)])
              >>> phi.fcp()                                                         # needs sage.libs.pari
              (x - 2) * (x - 1)
              >>> phi.fcp('T')                                                      # needs sage.libs.pari
              (T - 2) * (T - 1)
              >>> W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              >>> M = matrix(ZZ, [[Integer(1), Integer(0)], [Integer(1), Integer(2)]])
              >>> psi = W.module_morphism(matrix=M, codomain=W)
              >>> psi.fcp()                                                         # needs sage.libs.pari
              (x - 2) * (x - 1)

        minimal_polynomial()

          Return the minimal polynomial of this endomorphism.

          `minimal_polynomial()` and `minpoly()` are the same method.

          INPUT:

          - `var` – string (default: `'x'`); a variable name

          EXAMPLES:

          Compute the minimal polynomial, and check it.

          Sage

              sage: # needs sage.modules
              sage: V = GF(7)^3
              sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]); H
              Vector space morphism represented by the matrix:
              [0 1 2]
              [6 0 3]
              [2 4 1]
              Domain:   Vector space of dimension 3 over Finite Field of size 7
              Codomain: Vector space of dimension 3 over Finite Field of size 7
              sage: H.minpoly()                                                       # needs sage.libs.pari
              x^3 + 6*x^2 + 6*x + 1
              sage: H.minimal_polynomial()                                            # needs sage.libs.pari
              x^3 + 6*x^2 + 6*x + 1
              sage: H^3 + (H^2)*6 + H*6 + 1
              Vector space morphism represented by the matrix:
              [0 0 0]
              [0 0 0]
              [0 0 0]
              Domain:   Vector space of dimension 3 over Finite Field of size 7
              Codomain: Vector space of dimension 3 over Finite Field of size 7

              sage: # needs sage.modules sage.rings.finite_rings
              sage: k = GF(9, 'c')
              sage: V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w'])
              sage: A = matrix(k, 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5])
              sage: phi = V.module_morphism(matrix=A, codomain=V)
              sage: factor(phi.minpoly())
              (x + 1) * (x + 2)^2
              sage: A.minpoly()(A) == 0
              True
              sage: factor(phi.charpoly())
              (x + 1)^2 * (x + 2)^2

          Python

              >>> from sage.all import *
              >>> # needs sage.modules
              >>> V = GF(Integer(7))**Integer(3)
              >>> H = V.Hom(V)([[Integer(0),Integer(1),Integer(2)], [-Integer(1),Integer(0),Integer(3)], [Integer(2),Integer(4),Integer(1)]]); H
              Vector space morphism represented by the matrix:
              [0 1 2]
              [6 0 3]
              [2 4 1]
              Domain:   Vector space of dimension 3 over Finite Field of size 7
              Codomain: Vector space of dimension 3 over Finite Field of size 7
              >>> H.minpoly()                                                       # needs sage.libs.pari
              x^3 + 6*x^2 + 6*x + 1
              >>> H.minimal_polynomial()                                            # needs sage.libs.pari
              x^3 + 6*x^2 + 6*x + 1
              >>> H**Integer(3) + (H**Integer(2))*Integer(6) + H*Integer(6) + Integer(1)
              Vector space morphism represented by the matrix:
              [0 0 0]
              [0 0 0]
              [0 0 0]
              Domain:   Vector space of dimension 3 over Finite Field of size 7
              Codomain: Vector space of dimension 3 over Finite Field of size 7

              >>> # needs sage.modules sage.rings.finite_rings
              >>> k = GF(Integer(9), 'c')
              >>> V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w'])
              >>> A = matrix(k, Integer(4), [Integer(1),Integer(1),Integer(0),Integer(0), Integer(0),Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),Integer(5),Integer(0), Integer(0),Integer(0),Integer(0),Integer(5)])
              >>> phi = V.module_morphism(matrix=A, codomain=V)
              >>> factor(phi.minpoly())
              (x + 1) * (x + 2)^2
              >>> A.minpoly()(A) == Integer(0)
              True
              >>> factor(phi.charpoly())
              (x + 1)^2 * (x + 2)^2

        minpoly()

          alias of `minimal_polynomial()`.

        trace()

          Return the trace of this endomorphism.

          EXAMPLES:

          Sage

              sage: # needs sage.modules
              sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1])
              sage: phi.trace()
              3
              sage: W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              sage: M = matrix(ZZ, [[1, 0], [1, 2]])
              sage: psi = W.module_morphism(matrix=M, codomain=W)
              sage: psi.trace()
              3

          Python

              >>> from sage.all import *
              >>> # needs sage.modules
              >>> V = ZZ**Integer(2); phi = V.hom([V.gen(0) + V.gen(1), Integer(2)*V.gen(1)])
              >>> phi.trace()
              3
              >>> W = CombinatorialFreeModule(ZZ, ['x', 'y'])
              >>> M = matrix(ZZ, [[Integer(1), Integer(0)], [Integer(1), Integer(2)]])
              >>> psi = W.module_morphism(matrix=M, codomain=W)
              >>> psi.trace()
              3

  class MorphismMethods

    Bases: `object`

    image()

      Return the image of `self` as a submodule of the codomain.

      EXAMPLES:

      Sage

          sage: SGA = SymmetricGroupAlgebra(QQ, 3)                                # needs sage.groups sage.modules
          sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA)        # needs sage.groups sage.modules
          sage: f.image()                                                         # needs sage.groups sage.modules
          Free module generated by {0, 1, 2} over Rational Field

      Python

          >>> from sage.all import *
          >>> SGA = SymmetricGroupAlgebra(QQ, Integer(3))                                # needs sage.groups sage.modules
          >>> f = SGA.module_morphism(lambda x: SGA(x**Integer(2)), codomain=SGA)        # needs sage.groups sage.modules
          >>> f.image()                                                         # needs sage.groups sage.modules
          Free module generated by {0, 1, 2} over Rational Field

    image_basis()

      Return a basis for the image of `self` in echelon form.

      EXAMPLES:

      Sage

          sage: SGA = SymmetricGroupAlgebra(QQ, 3)                                # needs sage.groups sage.modules
          sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA)        # needs sage.groups sage.modules
          sage: f.image_basis()                                                   # needs sage.groups sage.modules
          ([1, 2, 3], [2, 3, 1], [3, 1, 2])

      Python

          >>> from sage.all import *
          >>> SGA = SymmetricGroupAlgebra(QQ, Integer(3))                                # needs sage.groups sage.modules
          >>> f = SGA.module_morphism(lambda x: SGA(x**Integer(2)), codomain=SGA)        # needs sage.groups sage.modules
          >>> f.image_basis()                                                   # needs sage.groups sage.modules
          ([1, 2, 3], [2, 3, 1], [3, 1, 2])

    kernel()

      Return the kernel of `self` as a submodule of the domain.

      EXAMPLES:

      Sage

          sage: # needs sage.groups sage.modules
          sage: SGA = SymmetricGroupAlgebra(QQ, 3)
          sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA)
          sage: K = f.kernel()
          sage: K
          Free module generated by {0, 1, 2} over Rational Field
          sage: K.ambient()
          Symmetric group algebra of order 3 over Rational Field

      Python

          >>> from sage.all import *
          >>> # needs sage.groups sage.modules
          >>> SGA = SymmetricGroupAlgebra(QQ, Integer(3))
          >>> f = SGA.module_morphism(lambda x: SGA(x**Integer(2)), codomain=SGA)
          >>> K = f.kernel()
          >>> K
          Free module generated by {0, 1, 2} over Rational Field
          >>> K.ambient()
          Symmetric group algebra of order 3 over Rational Field

    kernel_basis()

      Return a basis of the kernel of `self` in echelon form.

      EXAMPLES:

      Sage

          sage: SGA = SymmetricGroupAlgebra(QQ, 3)                                # needs sage.groups sage.modules
          sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA)        # needs sage.groups sage.modules
          sage: f.kernel_basis()                                                  # needs sage.groups sage.modules
          ([1, 2, 3] - [3, 2, 1], [1, 3, 2] - [3, 2, 1], [2, 1, 3] - [3, 2, 1])

      Python

          >>> from sage.all import *
          >>> SGA = SymmetricGroupAlgebra(QQ, Integer(3))                                # needs sage.groups sage.modules
          >>> f = SGA.module_morphism(lambda x: SGA(x**Integer(2)), codomain=SGA)        # needs sage.groups sage.modules
          >>> f.kernel_basis()                                                  # needs sage.groups sage.modules
          ([1, 2, 3] - [3, 2, 1], [1, 3, 2] - [3, 2, 1], [2, 1, 3] - [3, 2, 1])

    matrix(base_ring=None, side='left')

      Return the matrix of this morphism in the distinguished bases of the domain and codomain.

      INPUT:

      - `base_ring` – a ring (default: `None`, meaning the base ring of the codomain)

      - `side` – `'left'` or `'right'` (default: `'left'`)

      If `side` is “left”, this morphism is considered as acting on the left; i.e. each column of the matrix represents the image of an element of the basis of the domain.

      The order of the rows and columns matches with the order in which the bases are enumerated.

      See also

      `Modules.WithBasis.ParentMethods.module_morphism()`

      EXAMPLES:

      Sage

          sage: # needs sage.modules
          sage: X = CombinatorialFreeModule(ZZ, [1,2]); x = X.basis()
          sage: Y = CombinatorialFreeModule(ZZ, [3,4]); y = Y.basis()
          sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4],
          ....:                                   2: 2*y[3] + 5*y[4]}.__getitem__,
          ....:                         codomain=Y)
          sage: phi.matrix()
          [1 2]
          [3 5]
          sage: phi.matrix(side='right')
          [1 3]
          [2 5]

          sage: phi.matrix().parent()                                             # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
          sage: phi.matrix(QQ).parent()                                           # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Rational Field

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> X = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2)]); x = X.basis()
          >>> Y = CombinatorialFreeModule(ZZ, [Integer(3),Integer(4)]); y = Y.basis()
          >>> phi = X.module_morphism(on_basis={Integer(1): y[Integer(3)] + Integer(3)*y[Integer(4)],
          ...                                   Integer(2): Integer(2)*y[Integer(3)] + Integer(5)*y[Integer(4)]}.__getitem__,
          ...                         codomain=Y)
          >>> phi.matrix()
          [1 2]
          [3 5]
          >>> phi.matrix(side='right')
          [1 3]
          [2 5]

          >>> phi.matrix().parent()                                             # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
          >>> phi.matrix(QQ).parent()                                           # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Rational Field

      The resulting matrix is immutable:

      Sage

          sage: phi.matrix().is_mutable()                                         # needs sage.modules
          False

      [Python]

          >>> from sage.all import *
          >>> phi.matrix().is_mutable()                                         # needs sage.modules
          False

      The zero morphism has a zero matrix:

      Sage

          sage: Hom(X, Y).zero().matrix()                                         # needs sage.modules
          [0 0]
          [0 0]

      Python

          >>> from sage.all import *
          >>> Hom(X, Y).zero().matrix()                                         # needs sage.modules
          [0 0]
          [0 0]

      Todo

      Add support for morphisms where the codomain has a different base ring than the domain:

      Sage

          sage: Y = CombinatorialFreeModule(QQ, [3,4]); y = Y.basis()         # needs sage.modules
          sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4],           # needs sage.modules
          ....:                                   2: 2*y[3] + 5/2*y[4]}.__getitem__,
          ....:                         codomain=Y)
          sage: phi.matrix().parent()         # not implemented               # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Rational Field

      Python

          >>> from sage.all import *
          >>> Y = CombinatorialFreeModule(QQ, [Integer(3),Integer(4)]); y = Y.basis()         # needs sage.modules
          >>> phi = X.module_morphism(on_basis={Integer(1): y[Integer(3)] + Integer(3)*y[Integer(4)],           # needs sage.modules
          ...                                   Integer(2): Integer(2)*y[Integer(3)] + Integer(5)/Integer(2)*y[Integer(4)]}.__getitem__,
          ...                         codomain=Y)
          >>> phi.matrix().parent()         # not implemented               # needs sage.modules
          Full MatrixSpace of 2 by 2 dense matrices over Rational Field

      This currently does not work because, in this case, the morphism is just in the category of commutative additive groups (i.e. the intersection of the categories of modules over \(\ZZ\) and over \(\QQ\)):

      Sage

          sage: phi.parent().homset_category()                                # needs sage.modules
          Category of commutative additive semigroups
          sage: phi.parent().homset_category()        # not implemented, needs sage.modules
          Category of finite dimensional modules with basis over Integer Ring

      [Python]

          >>> from sage.all import *
          >>> phi.parent().homset_category()                                # needs sage.modules
          Category of commutative additive semigroups
          >>> phi.parent().homset_category()        # not implemented, needs sage.modules
          Category of finite dimensional modules with basis over Integer Ring

  class ParentMethods

    Bases: `object`

    annihilator(S, action=<built-in function mul>, side='right', category=None)

      Return the annihilator of a finite set.

      INPUT:

      - `S` – a finite set

      - `action` – a function (default: `operator.mul`)

      - `side` – `'left'` or `'right'` (default: `'right'`)

      - `category` – a category

      Assumptions:

      - `action` takes elements of `self` as first argument and elements of `S` as second argument;

      - The codomain is any vector space, and `action` is linear on its first argument; typically it is bilinear;

      - If `side` is ‘left’, this is reversed.

      OUTPUT:

      The subspace of the elements \(x\) of `self` such that `action(x,s) = 0` for all \(s\in S\). If `side` is ‘left’ replace the above equation by `action(s,x) = 0`.

      If `self` is a ring, `action` an action of `self` on a module \(M\) and \(S\) is a subset of \(M\), we recover the Wikipedia article Annihilator_%28ring_theory%29. Similarly this can be used to compute torsion or orthogonals.

      See also

      `annihilator_basis()` for lots of examples.

      EXAMPLES:

      Sage

          sage: # needs sage.modules
          sage: F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F
          An example of a finite dimensional algebra with basis:
          the path algebra of the Kronecker quiver
          (containing the arrows a:x->y and b:x->y) over Rational Field
          sage: x, y, a, b = F.basis()
          sage: A = F.annihilator([a + 3*b + 2*y]); A
          Free module generated by {0} over Rational Field
          sage: [b.lift() for b in A.basis()]
          [-1/2*a - 3/2*b + x]

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F
          An example of a finite dimensional algebra with basis:
          the path algebra of the Kronecker quiver
          (containing the arrows a:x->y and b:x->y) over Rational Field
          >>> x, y, a, b = F.basis()
          >>> A = F.annihilator([a + Integer(3)*b + Integer(2)*y]); A
          Free module generated by {0} over Rational Field
          >>> [b.lift() for b in A.basis()]
          [-1/2*a - 3/2*b + x]

      The category can be used to specify other properties of this subspace, like that this is a subalgebra:

      Sage

          sage: # needs sage.modules
          sage: center = F.annihilator(F.basis(), F.bracket,
          ....:                        category=Algebras(QQ).Subobjects())
          sage: (e,) = center.basis()
          sage: e.lift()
          x + y
          sage: e * e == e
          True

      [Python]

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> center = F.annihilator(F.basis(), F.bracket,
          ...                        category=Algebras(QQ).Subobjects())
          >>> (e,) = center.basis()
          >>> e.lift()
          x + y
          >>> e * e == e
          True

      Taking annihilator is order reversing for inclusion:

      Sage

          sage: # needs sage.modules
          sage: A   = F.annihilator([]);    A  .rename('A')
          sage: Ax  = F.annihilator([x]);   Ax .rename('Ax')
          sage: Ay  = F.annihilator([y]);   Ay .rename('Ay')
          sage: Axy = F.annihilator([x,y]); Axy.rename('Axy')
          sage: P = Poset(([A, Ax, Ay, Axy], attrcall("is_submodule")))           # needs sage.graphs
          sage: sorted(P.cover_relations(), key=str)                              # needs sage.graphs
          [[Ax, A], [Axy, Ax], [Axy, Ay], [Ay, A]]

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> A   = F.annihilator([]);    A  .rename('A')
          >>> Ax  = F.annihilator([x]);   Ax .rename('Ax')
          >>> Ay  = F.annihilator([y]);   Ay .rename('Ay')
          >>> Axy = F.annihilator([x,y]); Axy.rename('Axy')
          >>> P = Poset(([A, Ax, Ay, Axy], attrcall("is_submodule")))           # needs sage.graphs
          >>> sorted(P.cover_relations(), key=str)                              # needs sage.graphs
          [[Ax, A], [Axy, Ax], [Axy, Ay], [Ay, A]]

    annihilator_basis(S, action=<built-in function mul>, side='right')

      Return a basis of the annihilator of a finite set of elements.

      INPUT:

      - `S` – a finite set of objects

      - `action` – a function (default: `operator.mul`)

      - `side` – `'left'` or `'right'` (default: `'right'`): on which side of `self` the elements of \(S\) acts

      See `annihilator()` for the assumptions and definition of the annihilator.

      EXAMPLES:

      By default, the action is the standard \(*\) operation. So our first example is about an algebra:

      Sage

          sage: # needs sage.graphs sage.modules
          sage: F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F
          An example of a finite dimensional algebra with basis:
          the path algebra of the Kronecker quiver
          (containing the arrows a:x->y and b:x->y) over Rational Field
          sage: x,y,a,b = F.basis()

      Python

          >>> from sage.all import *
          >>> # needs sage.graphs sage.modules
          >>> F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F
          An example of a finite dimensional algebra with basis:
          the path algebra of the Kronecker quiver
          (containing the arrows a:x->y and b:x->y) over Rational Field
          >>> x,y,a,b = F.basis()

      In this algebra, multiplication on the right by \(x\) annihilates all basis elements but \(x\):

      Sage

          sage: x*x, y*x, a*x, b*x                                                # needs sage.graphs sage.modules
          (x, 0, 0, 0)

      [Python]

          >>> from sage.all import *
          >>> x*x, y*x, a*x, b*x                                                # needs sage.graphs sage.modules
          (x, 0, 0, 0)

      So the annihilator is the subspace spanned by \(y\), \(a\), and \(b\):

      Sage

          sage: F.annihilator_basis([x])                                          # needs sage.graphs sage.modules
          (y, a, b)

      Python

          >>> from sage.all import *
          >>> F.annihilator_basis([x])                                          # needs sage.graphs sage.modules
          (y, a, b)

      The same holds for \(a\) and \(b\):

      Sage

          sage: x*a, y*a, a*a, b*a                                                # needs sage.graphs sage.modules
          (a, 0, 0, 0)
          sage: F.annihilator_basis([a])                                          # needs sage.graphs sage.modules
          (y, a, b)

      [Python]

          >>> from sage.all import *
          >>> x*a, y*a, a*a, b*a                                                # needs sage.graphs sage.modules
          (a, 0, 0, 0)
          >>> F.annihilator_basis([a])                                          # needs sage.graphs sage.modules
          (y, a, b)

      On the other hand, \(y\) annihilates only \(x\):

      Sage

          sage: F.annihilator_basis([y])                                          # needs sage.graphs sage.modules
          (x,)

      Python

          >>> from sage.all import *
          >>> F.annihilator_basis([y])                                          # needs sage.graphs sage.modules
          (x,)

      Here is a non trivial annihilator:

      Sage

          sage: F.annihilator_basis([a + 3*b + 2*y])                              # needs sage.graphs sage.modules
          (-1/2*a - 3/2*b + x,)

      [Python]

          >>> from sage.all import *
          >>> F.annihilator_basis([a + Integer(3)*b + Integer(2)*y])                              # needs sage.graphs sage.modules
          (-1/2*a - 3/2*b + x,)

      Let’s check it:

      Sage

          sage: (-1/2*a - 3/2*b + x) * (a + 3*b + 2*y)                            # needs sage.graphs sage.modules
          0

      Python

          >>> from sage.all import *
          >>> (-Integer(1)/Integer(2)*a - Integer(3)/Integer(2)*b + x) * (a + Integer(3)*b + Integer(2)*y)                            # needs sage.graphs sage.modules
          0

      Doing the same calculations on the left exchanges the roles of \(x\) and \(y\):

      Sage

          sage: # needs sage.graphs sage.modules
          sage: F.annihilator_basis([y], side='left')
          (x, a, b)
          sage: F.annihilator_basis([a], side='left')
          (x, a, b)
          sage: F.annihilator_basis([b], side='left')
          (x, a, b)
          sage: F.annihilator_basis([x], side='left')
          (y,)
          sage: F.annihilator_basis([a + 3*b + 2*x], side='left')
          (-1/2*a - 3/2*b + y,)

      [Python]

          >>> from sage.all import *
          >>> # needs sage.graphs sage.modules
          >>> F.annihilator_basis([y], side='left')
          (x, a, b)
          >>> F.annihilator_basis([a], side='left')
          (x, a, b)
          >>> F.annihilator_basis([b], side='left')
          (x, a, b)
          >>> F.annihilator_basis([x], side='left')
          (y,)
          >>> F.annihilator_basis([a + Integer(3)*b + Integer(2)*x], side='left')
          (-1/2*a - 3/2*b + y,)

      By specifying an inner product, this method can be used to compute the orthogonal of a subspace:

      Sage

          sage: # needs sage.graphs sage.modules
          sage: x,y,a,b = F.basis()
          sage: def scalar(u, v):
          ....:     return vector([sum(u[i]*v[i] for i in F.basis().keys())])
          sage: F.annihilator_basis([x + y, a + b], scalar)
          (x - y, a - b)

      Python

          >>> from sage.all import *
          >>> # needs sage.graphs sage.modules
          >>> x,y,a,b = F.basis()
          >>> def scalar(u, v):
          ...     return vector([sum(u[i]*v[i] for i in F.basis().keys())])
          >>> F.annihilator_basis([x + y, a + b], scalar)
          (x - y, a - b)

      By specifying the standard Lie bracket as action, one can compute the commutator of a subspace of \(F\):

      Sage

          sage: F.annihilator_basis([a + b], action=F.bracket)                    # needs sage.graphs sage.modules
          (x + y, a, b)

      [Python]

          >>> from sage.all import *
          >>> F.annihilator_basis([a + b], action=F.bracket)                    # needs sage.graphs sage.modules
          (x + y, a, b)

      In particular one can compute a basis of the center of the algebra. In our example, it is reduced to the identity:

      Sage

          sage: F.annihilator_basis(F.algebra_generators(), action=F.bracket)     # needs sage.graphs sage.modules
          (x + y,)

      Python

          >>> from sage.all import *
          >>> F.annihilator_basis(F.algebra_generators(), action=F.bracket)     # needs sage.graphs sage.modules
          (x + y,)

      But see also `FiniteDimensionalAlgebrasWithBasis.ParentMethods.center_basis()`.

    echelon_form(elements, row_reduced=False, order=None)

      Return a basis in echelon form of the subspace spanned by a finite set of elements.

      INPUT:

      - `elements` – list or finite iterable of elements of `self`

      - `row_reduced` – boolean (default: `False`); whether to compute the basis for the row reduced echelon form

      - `order` – (optional) either something that can be converted into a tuple or a key function

      OUTPUT:

      A list of elements of `self` whose expressions as vectors form a matrix in echelon form. If `base_ring` is specified, then the calculation is achieved in this base ring.

      EXAMPLES:

      Sage

          sage: # needs sage.modules
          sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x')
          sage: x = X.basis()
          sage: V = X.echelon_form([x[0]-x[1], x[0]-x[2], x[1]-x[2]]); V
          [x[0] - x[2], x[1] - x[2]]
          sage: matrix(list(map(vector, V)))
          [ 1  0 -1]
          [ 0  1 -1]

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> X = CombinatorialFreeModule(QQ, range(Integer(3)), prefix='x')
          >>> x = X.basis()
          >>> V = X.echelon_form([x[Integer(0)]-x[Integer(1)], x[Integer(0)]-x[Integer(2)], x[Integer(1)]-x[Integer(2)]]); V
          [x[0] - x[2], x[1] - x[2]]
          >>> matrix(list(map(vector, V)))
          [ 1  0 -1]
          [ 0  1 -1]

      Sage

          sage: # needs sage.modules
          sage: F = CombinatorialFreeModule(ZZ, [1,2,3,4])
          sage: B = F.basis()
          sage: elements = [B[1]-17*B[2]+6*B[3], B[1]-17*B[2]+B[4]]
          sage: F.echelon_form(elements)
          [B[1] - 17*B[2] + B[4], 6*B[3] - B[4]]

      [Python]

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> F = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2),Integer(3),Integer(4)])
          >>> B = F.basis()
          >>> elements = [B[Integer(1)]-Integer(17)*B[Integer(2)]+Integer(6)*B[Integer(3)], B[Integer(1)]-Integer(17)*B[Integer(2)]+B[Integer(4)]]
          >>> F.echelon_form(elements)
          [B[1] - 17*B[2] + B[4], 6*B[3] - B[4]]

      Sage

          sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])                    # needs sage.modules
          sage: a,b,c = F.basis()                                                 # needs sage.modules
          sage: F.echelon_form([8*a+b+10*c, -3*a+b-c, a-b-c])                     # needs sage.modules
          [B['a'] + B['c'], B['b'] + 2*B['c']]

      Python

          >>> from sage.all import *
          >>> F = CombinatorialFreeModule(QQ, ['a','b','c'])                    # needs sage.modules
          >>> a,b,c = F.basis()                                                 # needs sage.modules
          >>> F.echelon_form([Integer(8)*a+b+Integer(10)*c, -Integer(3)*a+b-c, a-b-c])                     # needs sage.modules
          [B['a'] + B['c'], B['b'] + 2*B['c']]

      Sage

          sage: R.<x,y> = QQ[]
          sage: C = CombinatorialFreeModule(R, range(3), prefix='x')              # needs sage.modules
          sage: x = C.basis()                                                     # needs sage.modules
          sage: C.echelon_form([x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]])       # needs sage.modules sage.rings.function_field
          [x[0] - x[2], x[1] - x[2]]

      [Python]

          >>> from sage.all import *
          >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
          >>> C = CombinatorialFreeModule(R, range(Integer(3)), prefix='x')              # needs sage.modules
          >>> x = C.basis()                                                     # needs sage.modules
          >>> C.echelon_form([x[Integer(0)] - x[Integer(1)], Integer(2)*x[Integer(1)] - Integer(2)*x[Integer(2)], x[Integer(0)] - x[Integer(2)]])       # needs sage.modules sage.rings.function_field
          [x[0] - x[2], x[1] - x[2]]

      Sage

          sage: M = MatrixSpace(QQ, 3, 3)                                         # needs sage.modules
          sage: A = M([[0, 0, 2], [0, 0, 0], [0, 0, 0]])                          # needs sage.modules
          sage: M.echelon_form([A, A])                                            # needs sage.modules
          [
          [0 0 1]
          [0 0 0]
          [0 0 0]
          ]

      Python

          >>> from sage.all import *
          >>> M = MatrixSpace(QQ, Integer(3), Integer(3))                                         # needs sage.modules
          >>> A = M([[Integer(0), Integer(0), Integer(2)], [Integer(0), Integer(0), Integer(0)], [Integer(0), Integer(0), Integer(0)]])                          # needs sage.modules
          >>> M.echelon_form([A, A])                                            # needs sage.modules
          [
          [0 0 1]
          [0 0 0]
          [0 0 0]
          ]

    from_vector(vector, order=None, coerce=True)

      Build an element of `self` from a vector.

      EXAMPLES:

      Sage

          sage: # needs sage.modules
          sage: p_mult = matrix([[0,0,0], [0,0,-1], [0,0,0]])
          sage: q_mult = matrix([[0,0,1], [0,0,0], [0,0,0]])
          sage: A = algebras.FiniteDimensional(
          ....:         QQ, [p_mult, q_mult, matrix(QQ, 3, 3)], 'p,q,z')
          sage: A.from_vector(vector([1,0,2]))
          p + 2*z

      Python

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> p_mult = matrix([[Integer(0),Integer(0),Integer(0)], [Integer(0),Integer(0),-Integer(1)], [Integer(0),Integer(0),Integer(0)]])
          >>> q_mult = matrix([[Integer(0),Integer(0),Integer(1)], [Integer(0),Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(0)]])
          >>> A = algebras.FiniteDimensional(
          ...         QQ, [p_mult, q_mult, matrix(QQ, Integer(3), Integer(3))], 'p,q,z')
          >>> A.from_vector(vector([Integer(1),Integer(0),Integer(2)]))
          p + 2*z

    gens()

      Return the generators of `self`.

      OUTPUT: a tuple containing the basis elements of `self`

      EXAMPLES:

      Sage

          sage: F = CombinatorialFreeModule(ZZ, ['a', 'b', 'c'])                  # needs sage.modules
          sage: F.gens()                                                          # needs sage.modules
          (B['a'], B['b'], B['c'])

      Python

          >>> from sage.all import *
          >>> F = CombinatorialFreeModule(ZZ, ['a', 'b', 'c'])                  # needs sage.modules
          >>> F.gens()                                                          # needs sage.modules
          (B['a'], B['b'], B['c'])

    invariant_module(S, action=<built-in function mul>, action_on_basis=None, side='left', **kwargs)

      Return the submodule of `self` invariant under the action of `S`.

      For a semigroup \(S\) acting on a module \(M\), the invariant submodule is given by

      \[M^S = \{m \in M : s \cdot m = m,\, \forall s \in S\}.\]

      INPUT:

      - `S` – a finitely-generated semigroup

      - `action` – a function (default: `operator.mul`)

      - `side` – `'left'` or `'right'` (default: `'right'`); which side of `self` the elements of `S` acts

      - `action_on_basis` – (optional) define the action of `S` on the basis of `self`

      OUTPUT: `FiniteDimensionalInvariantModule`

      EXAMPLES:

      We build the invariant module of the permutation representation of the symmetric group:

      Sage

          sage: # needs sage.combinat sage.groups sage.modules
          sage: G = SymmetricGroup(3); G.rename('S3')
          sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M')
          sage: action = lambda g, x: M.term(g(x))
          sage: I = M.invariant_module(G, action_on_basis=action); I
          (S3)-invariant submodule of M
          sage: I.basis()
          Finite family {0: B[0]}
          sage: [I.lift(b) for b in I.basis()]
          [M[1] + M[2] + M[3]]
          sage: G.rename(); M.rename()  # reset the names

      Python

          >>> from sage.all import *
          >>> # needs sage.combinat sage.groups sage.modules
          >>> G = SymmetricGroup(Integer(3)); G.rename('S3')
          >>> M = FreeModule(ZZ, [Integer(1),Integer(2),Integer(3)], prefix='M'); M.rename('M')
          >>> action = lambda g, x: M.term(g(x))
          >>> I = M.invariant_module(G, action_on_basis=action); I
          (S3)-invariant submodule of M
          >>> I.basis()
          Finite family {0: B[0]}
          >>> [I.lift(b) for b in I.basis()]
          [M[1] + M[2] + M[3]]
          >>> G.rename(); M.rename()  # reset the names

      We can construct the invariant module of any module that has an action of `S`. In this example, we consider the dihedral group \(G = D_4\) and the subgroup \(H < G\) of all rotations. We construct the \(H\)-invariant module of the group algebra \(\QQ[G]\):

      Sage

          sage: # needs sage.groups
          sage: G = groups.permutation.Dihedral(4)
          sage: H = G.subgroup(G.gen(0))
          sage: H
          Subgroup generated by [(1,2,3,4)]
           of (Dihedral group of order 8 as a permutation group)
          sage: H.cardinality()
          4

          sage: # needs sage.groups sage.modules
          sage: A = G.algebra(QQ)
          sage: I = A.invariant_module(H)
          sage: [I.lift(b) for b in I.basis()]
          [() + (1,2,3,4) + (1,3)(2,4) + (1,4,3,2),
           (2,4) + (1,2)(3,4) + (1,3) + (1,4)(2,3)]
          sage: all(h * I.lift(b) == I.lift(b)
          ....:     for b in I.basis() for h in H)
          True

      [Python]

          >>> from sage.all import *
          >>> # needs sage.groups
          >>> G = groups.permutation.Dihedral(Integer(4))
          >>> H = G.subgroup(G.gen(Integer(0)))
          >>> H
          Subgroup generated by [(1,2,3,4)]
           of (Dihedral group of order 8 as a permutation group)
          >>> H.cardinality()
          4

          >>> # needs sage.groups sage.modules
          >>> A = G.algebra(QQ)
          >>> I = A.invariant_module(H)
          >>> [I.lift(b) for b in I.basis()]
          [() + (1,2,3,4) + (1,3)(2,4) + (1,4,3,2),
           (2,4) + (1,2)(3,4) + (1,3) + (1,4)(2,3)]
          >>> all(h * I.lift(b) == I.lift(b)
          ...     for b in I.basis() for h in H)
          True

    twisted_invariant_module(G, chi, action=<built-in function mul>, action_on_basis=None, side='left', **kwargs)

      Create the isotypic component of the action of `G` on `self` with irreducible character given by `chi`.

      See also

      -`FiniteDimensionalTwistedInvariantModule`

      INPUT:

      - `G` – a finitely-generated group

      - `chi` – list/tuple of character values or an instance of `ClassFunction_gap`

      - `action` – a function (default: `operator.mul`)

      - `action_on_basis` – (optional) define the action of `g` on the basis of `self`

      - `side` – `'left'` or `'right'` (default: `'right'`); which side of `self` the elements of `S` acts

      OUTPUT: `FiniteDimensionalTwistedInvariantModule`

      EXAMPLES:

      Sage

          sage: # needs sage.combinat sage.groups sage.modules
          sage: M = CombinatorialFreeModule(QQ, [1,2,3])
          sage: G = SymmetricGroup(3)
          sage: def action(g, x): return(M.term(g(x)))  # permute coordinates
          sage: T = M.twisted_invariant_module(G, [2,0,-1],
          ....:                                action_on_basis=action)
          sage: import __main__; __main__.action = action
          sage: TestSuite(T).run()

      Python

          >>> from sage.all import *
          >>> # needs sage.combinat sage.groups sage.modules
          >>> M = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3)])
          >>> G = SymmetricGroup(Integer(3))
          >>> def action(g, x): return(M.term(g(x)))  # permute coordinates
          >>> T = M.twisted_invariant_module(G, [Integer(2),Integer(0),-Integer(1)],
          ...                                action_on_basis=action)
          >>> import __main__; __main__.action = action
          >>> TestSuite(T).run()

  class TensorProducts(category, *args)

    Bases: `TensorProductsCategory`

    extra_super_categories()

      Implement the fact that a (finite) tensor product of finite dimensional modules is a finite dimensional module.

      EXAMPLES:

      Sage

          sage: C = ModulesWithBasis(ZZ).FiniteDimensional().TensorProducts()
          sage: C.extra_super_categories()
          [Category of finite dimensional modules with basis over Integer Ring]
          sage: C.FiniteDimensional()
          Category of tensor products of
           finite dimensional modules with basis over Integer Ring

      Python

          >>> from sage.all import *
          >>> C = ModulesWithBasis(ZZ).FiniteDimensional().TensorProducts()
          >>> C.extra_super_categories()
          [Category of finite dimensional modules with basis over Integer Ring]
          >>> C.FiniteDimensional()
          Category of tensor products of
           finite dimensional modules with basis over Integer Ring