Alternating contravariant tensors on free modules - Tensors on free modules of finite rank

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

# Alternating contravariant tensors on free modules

Given a free module \(M\) of finite rank over a commutative ring \(R\) and a positive integer \(p\), an alternating contravariant tensor of degree \(p\) is a map

\[a:\ \underbrace{M^*\times\cdots\times M^*}_{p\ \; \mbox{times}} \longrightarrow R\]

that (i) is multilinear and (ii) vanishes whenever any of two of its arguments are equal (\(M^*\) stands for the dual of \(M\)). \(a\) is an element of the \(p\)-th exterior power of \(M\), \(\Lambda^p(M)\).

Alternating contravariant tensors are implemented via the class `AlternatingContrTensor`, which is a subclass of the generic tensor class `FreeModuleTensor`.

AUTHORS:

- Eric Gourgoulhon (2017): initial version

REFERENCES:

- Chap. 23 of R. Godement : Algebra [God1968]

- Chap. 15 of S. Lang : Algebra [Lan2002]

class sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor(fmodule, degree, name=None, latex_name=None)

  Bases: `FreeModuleTensor`

  Alternating contravariant tensor on a free module of finite rank over a commutative ring.

  This is a Sage element class, the corresponding parent class being `ExtPowerFreeModule`.

  INPUT:

  - `fmodule` – free module \(M\) of finite rank over a commutative ring \(R\), as an instance of `FiniteRankFreeModule`

  - `degree` – positive integer; the degree \(p\) of the alternating contravariant tensor (i.e. the tensor rank)

  - `name` – (default: `None`) string; name given to the alternating contravariant tensor

  - `latex_name` – (default: `None`) string; LaTeX symbol to denote the alternating contravariant tensor; if none is provided, `name` is used

  EXAMPLES:

  Alternating contravariant tensor of degree 2 on a rank-3 free module:

  Sage

      sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
      sage: e = M.basis('e')
      sage: a = M.alternating_contravariant_tensor(2, name='a') ; a
      Alternating contravariant tensor a of degree 2 on the Rank-3
       free module M over the Integer Ring
      sage: type(a)
      <class 'sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule_with_category.element_class'>
      sage: a.parent()
      2nd exterior power of the Rank-3 free module M over the Integer Ring
      sage: a[1,2], a[2,3] = 4, -3
      sage: a.display(e)
      a = 4 e_1∧e_2 - 3 e_2∧e_3

  Python

      >>> from sage.all import *
      >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M', start_index=Integer(1))
      >>> e = M.basis('e')
      >>> a = M.alternating_contravariant_tensor(Integer(2), name='a') ; a
      Alternating contravariant tensor a of degree 2 on the Rank-3
       free module M over the Integer Ring
      >>> type(a)
      <class 'sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule_with_category.element_class'>
      >>> a.parent()
      2nd exterior power of the Rank-3 free module M over the Integer Ring
      >>> a[Integer(1),Integer(2)], a[Integer(2),Integer(3)] = Integer(4), -Integer(3)
      >>> a.display(e)
      a = 4 e_1∧e_2 - 3 e_2∧e_3

  The alternating contravariant tensor acting on the dual basis elements:

  Sage

      sage: f = e.dual_basis(); f
      Dual basis (e^1,e^2,e^3) on the Rank-3 free module M over the
       Integer Ring
      sage: a(f[1],f[2])
      4
      sage: a(f[1],f[3])
      0
      sage: a(f[2],f[3])
      -3
      sage: a(f[2],f[1])
      -4

  [Python]

      >>> from sage.all import *
      >>> f = e.dual_basis(); f
      Dual basis (e^1,e^2,e^3) on the Rank-3 free module M over the
       Integer Ring
      >>> a(f[Integer(1)],f[Integer(2)])
      4
      >>> a(f[Integer(1)],f[Integer(3)])
      0
      >>> a(f[Integer(2)],f[Integer(3)])
      -3
      >>> a(f[Integer(2)],f[Integer(1)])
      -4

  An alternating contravariant tensor of degree 1 is an element of the module \(M\):

  Sage

      sage: b = M.alternating_contravariant_tensor(1, name='b') ; b
      Element b of the Rank-3 free module M over the Integer Ring
      sage: b[:] = [2,-1,3]  # components w.r.t. the module's default basis (e)
      sage: b.parent() is M
      True

  Python

      >>> from sage.all import *
      >>> b = M.alternating_contravariant_tensor(Integer(1), name='b') ; b
      Element b of the Rank-3 free module M over the Integer Ring
      >>> b[:] = [Integer(2),-Integer(1),Integer(3)]  # components w.r.t. the module's default basis (e)
      >>> b.parent() is M
      True

  The standard tensor operations apply to alternating contravariant tensors, like the extraction of components with respect to a given basis:

  Sage

      sage: a[e,1,2]
      4
      sage: a[1,2]  # since e is the module's default basis
      4
      sage: all( a[i,j] == - a[j,i] for i in {1,2,3} for j in {1,2,3} )
      True

  [Python]

      >>> from sage.all import *
      >>> a[e,Integer(1),Integer(2)]
      4
      >>> a[Integer(1),Integer(2)]  # since e is the module's default basis
      4
      >>> all( a[i,j] == - a[j,i] for i in {Integer(1),Integer(2),Integer(3)} for j in {Integer(1),Integer(2),Integer(3)} )
      True

  the tensor product:

  Sage

      sage: c = b*b ; c
      Type-(2,0) tensor b⊗b on the Rank-3 free module M over the
       Integer Ring
      sage: c.symmetries()
      symmetry: (0, 1); no antisymmetry
      sage: c.parent()
      Free module of type-(2,0) tensors on the Rank-3 free module M
       over the Integer Ring
      sage: c.display(e)
      b⊗b = 4 e_1⊗e_1 - 2 e_1⊗e_2 + 6 e_1⊗e_3 - 2 e_2⊗e_1 + e_2⊗e_2
       - 3 e_2⊗e_3 + 6 e_3⊗e_1 - 3 e_3⊗e_2 + 9 e_3⊗e_3

  Python

      >>> from sage.all import *
      >>> c = b*b ; c
      Type-(2,0) tensor b⊗b on the Rank-3 free module M over the
       Integer Ring
      >>> c.symmetries()
      symmetry: (0, 1); no antisymmetry
      >>> c.parent()
      Free module of type-(2,0) tensors on the Rank-3 free module M
       over the Integer Ring
      >>> c.display(e)
      b⊗b = 4 e_1⊗e_1 - 2 e_1⊗e_2 + 6 e_1⊗e_3 - 2 e_2⊗e_1 + e_2⊗e_2
       - 3 e_2⊗e_3 + 6 e_3⊗e_1 - 3 e_3⊗e_2 + 9 e_3⊗e_3

  the contractions:

  Sage

      sage: w = f[1] + f[2] + f[3]  # a linear form
      sage: s = a.contract(w) ; s
      Element of the Rank-3 free module M over the Integer Ring
      sage: s.display(e)
      4 e_1 - 7 e_2 + 3 e_3

  [Python]

      >>> from sage.all import *
      >>> w = f[Integer(1)] + f[Integer(2)] + f[Integer(3)]  # a linear form
      >>> s = a.contract(w) ; s
      Element of the Rank-3 free module M over the Integer Ring
      >>> s.display(e)
      4 e_1 - 7 e_2 + 3 e_3

  or tensor arithmetics:

  Sage

      sage: s = 3*a + c ; s
      Type-(2,0) tensor on the Rank-3 free module M over the Integer Ring
      sage: s.parent()
      Free module of type-(2,0) tensors on the Rank-3 free module M
       over the Integer Ring
      sage: s.display(e)
      4 e_1⊗e_1 + 10 e_1⊗e_2 + 6 e_1⊗e_3 - 14 e_2⊗e_1 + e_2⊗e_2
       - 12 e_2⊗e_3 + 6 e_3⊗e_1 + 6 e_3⊗e_2 + 9 e_3⊗e_3

  Python

      >>> from sage.all import *
      >>> s = Integer(3)*a + c ; s
      Type-(2,0) tensor on the Rank-3 free module M over the Integer Ring
      >>> s.parent()
      Free module of type-(2,0) tensors on the Rank-3 free module M
       over the Integer Ring
      >>> s.display(e)
      4 e_1⊗e_1 + 10 e_1⊗e_2 + 6 e_1⊗e_3 - 14 e_2⊗e_1 + e_2⊗e_2
       - 12 e_2⊗e_3 + 6 e_3⊗e_1 + 6 e_3⊗e_2 + 9 e_3⊗e_3

  Note that tensor arithmetics preserves the alternating character if both operands are alternating:

  Sage

      sage: s = a - 2*a ; s
      Alternating contravariant tensor of degree 2 on the Rank-3 free
       module M over the Integer Ring
      sage: s.parent() # note the difference with s = 3*a + c above
      2nd exterior power of the Rank-3 free module M over the Integer
       Ring
      sage: s == -a
      True

  [Python]

      >>> from sage.all import *
      >>> s = a - Integer(2)*a ; s
      Alternating contravariant tensor of degree 2 on the Rank-3 free
       module M over the Integer Ring
      >>> s.parent() # note the difference with s = 3*a + c above
      2nd exterior power of the Rank-3 free module M over the Integer
       Ring
      >>> s == -a
      True

  An operation specific to alternating contravariant tensors is of course the exterior product:

  Sage

      sage: s = a.wedge(b) ; s
      Alternating contravariant tensor a∧b of degree 3 on the Rank-3 free
       module M over the Integer Ring
      sage: s.parent()
      3rd exterior power of the Rank-3 free module M over the Integer Ring
      sage: s.display(e)
      a∧b = 6 e_1∧e_2∧e_3
      sage: s[1,2,3] == a[1,2]*b[3] + a[2,3]*b[1] + a[3,1]*b[2]
      True

  Python

      >>> from sage.all import *
      >>> s = a.wedge(b) ; s
      Alternating contravariant tensor a∧b of degree 3 on the Rank-3 free
       module M over the Integer Ring
      >>> s.parent()
      3rd exterior power of the Rank-3 free module M over the Integer Ring
      >>> s.display(e)
      a∧b = 6 e_1∧e_2∧e_3
      >>> s[Integer(1),Integer(2),Integer(3)] == a[Integer(1),Integer(2)]*b[Integer(3)] + a[Integer(2),Integer(3)]*b[Integer(1)] + a[Integer(3),Integer(1)]*b[Integer(2)]
      True

  The exterior product is nilpotent on module elements:

  Sage

      sage: s = b.wedge(b) ; s
      Alternating contravariant tensor b∧b of degree 2 on the Rank-3 free
       module M over the Integer Ring
      sage: s.display(e)
      b∧b = 0

  [Python]

      >>> from sage.all import *
      >>> s = b.wedge(b) ; s
      Alternating contravariant tensor b∧b of degree 2 on the Rank-3 free
       module M over the Integer Ring
      >>> s.display(e)
      b∧b = 0

  degree()

    Return the degree of `self`.

    EXAMPLES:

    Sage

        sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
        sage: a = M.alternating_contravariant_tensor(2, name='a')
        sage: a.degree()
        2

    Python

        >>> from sage.all import *
        >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
        >>> a = M.alternating_contravariant_tensor(Integer(2), name='a')
        >>> a.degree()
        2

  disp(basis=None, format_spec=None)

    alias of `display()`.

  display(basis=None, format_spec=None)

    Display the alternating contravariant tensor `self` in terms of its expansion w.r.t. a given module basis.

    The expansion is actually performed onto exterior products of elements of `basis` (see examples below). The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

    INPUT:

    - `basis` – (default: `None`) basis of the free module with respect to which `self` is expanded; if none is provided, the module’s default basis is assumed

    - `format_spec` – (default: `None`) format specification passed to `self._fmodule._output_formatter` to format the output

    EXAMPLES:

    Display of an alternating contravariant tensor of degree 2 on a rank-3 free module:

    Sage

        sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
        sage: e = M.basis('e')
        sage: a = M.alternating_contravariant_tensor(2, 'a', latex_name=r'\alpha')
        sage: a[0,1], a[0,2], a[1,2] = 3, 2, -1
        sage: a.display()
        a = 3 e_0∧e_1 + 2 e_0∧e_2 - e_1∧e_2
        sage: latex(a.display())  # display in the notebook
        \alpha = 3 e_{0}\wedge e_{1} + 2 e_{0}\wedge e_{2} -e_{1}\wedge e_{2}

    Python

        >>> from sage.all import *
        >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
        >>> e = M.basis('e')
        >>> a = M.alternating_contravariant_tensor(Integer(2), 'a', latex_name=r'\alpha')
        >>> a[Integer(0),Integer(1)], a[Integer(0),Integer(2)], a[Integer(1),Integer(2)] = Integer(3), Integer(2), -Integer(1)
        >>> a.display()
        a = 3 e_0∧e_1 + 2 e_0∧e_2 - e_1∧e_2
        >>> latex(a.display())  # display in the notebook
        \alpha = 3 e_{0}\wedge e_{1} + 2 e_{0}\wedge e_{2} -e_{1}\wedge e_{2}

    Display of an alternating contravariant tensor of degree 3 on a rank-3 free module:

    Sage

        sage: b = M.alternating_contravariant_tensor(3, 'b')
        sage: b[0,1,2] = 4
        sage: b.display()
        b = 4 e_0∧e_1∧e_2
        sage: latex(b.display())
        b = 4 e_{0}\wedge e_{1}\wedge e_{2}

    [Python]

        >>> from sage.all import *
        >>> b = M.alternating_contravariant_tensor(Integer(3), 'b')
        >>> b[Integer(0),Integer(1),Integer(2)] = Integer(4)
        >>> b.display()
        b = 4 e_0∧e_1∧e_2
        >>> latex(b.display())
        b = 4 e_{0}\wedge e_{1}\wedge e_{2}

    Display of a vanishing alternating contravariant tensor:

    Sage

        sage: b[0,1,2] = 0  # the only independent component set to zero
        sage: b.is_zero()
        True
        sage: b.display()
        b = 0
        sage: latex(b.display())
        b = 0
        sage: b[0,1,2] = 4  # value restored for what follows

    Python

        >>> from sage.all import *
        >>> b[Integer(0),Integer(1),Integer(2)] = Integer(0)  # the only independent component set to zero
        >>> b.is_zero()
        True
        >>> b.display()
        b = 0
        >>> latex(b.display())
        b = 0
        >>> b[Integer(0),Integer(1),Integer(2)] = Integer(4)  # value restored for what follows

    Display in a basis which is not the default one:

    Sage

        sage: aut = M.automorphism(matrix=[[0,1,0], [0,0,-1], [1,0,0]],
        ....:                      basis=e)
        sage: f = e.new_basis(aut, 'f')
        sage: a.display(f)
        a = -2 f_0∧f_1 - f_0∧f_2 - 3 f_1∧f_2
        sage: a.disp(f)     # shortcut notation
        a = -2 f_0∧f_1 - f_0∧f_2 - 3 f_1∧f_2
        sage: b.display(f)
        b = -4 f_0∧f_1∧f_2

    [Python]

        >>> from sage.all import *
        >>> aut = M.automorphism(matrix=[[Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(0),-Integer(1)], [Integer(1),Integer(0),Integer(0)]],
        ...                      basis=e)
        >>> f = e.new_basis(aut, 'f')
        >>> a.display(f)
        a = -2 f_0∧f_1 - f_0∧f_2 - 3 f_1∧f_2
        >>> a.disp(f)     # shortcut notation
        a = -2 f_0∧f_1 - f_0∧f_2 - 3 f_1∧f_2
        >>> b.display(f)
        b = -4 f_0∧f_1∧f_2

    The output format can be set via the argument `output_formatter` passed at the module construction:

    Sage

        sage: N = FiniteRankFreeModule(QQ, 3, name='N', start_index=1,
        ....:                   output_formatter=Rational.numerical_approx)
        sage: e = N.basis('e')
        sage: a = N.alternating_contravariant_tensor(2, 'a')
        sage: a[1,2], a[1,3], a[2,3] = 1/3, 5/2, 4
        sage: a.display()  # default format (53 bits of precision)
        a = 0.333333333333333 e_1∧e_2 + 2.50000000000000 e_1∧e_3
         + 4.00000000000000 e_2∧e_3

    Python

        >>> from sage.all import *
        >>> N = FiniteRankFreeModule(QQ, Integer(3), name='N', start_index=Integer(1),
        ...                   output_formatter=Rational.numerical_approx)
        >>> e = N.basis('e')
        >>> a = N.alternating_contravariant_tensor(Integer(2), 'a')
        >>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(2),Integer(3)] = Integer(1)/Integer(3), Integer(5)/Integer(2), Integer(4)
        >>> a.display()  # default format (53 bits of precision)
        a = 0.333333333333333 e_1∧e_2 + 2.50000000000000 e_1∧e_3
         + 4.00000000000000 e_2∧e_3

    The output format is then controlled by the argument `format_spec` of the method `display()`:

    Sage

        sage: a.display(format_spec=10)  # 10 bits of precision
        a = 0.33 e_1∧e_2 + 2.5 e_1∧e_3 + 4.0 e_2∧e_3

    [Python]

        >>> from sage.all import *
        >>> a.display(format_spec=Integer(10))  # 10 bits of precision
        a = 0.33 e_1∧e_2 + 2.5 e_1∧e_3 + 4.0 e_2∧e_3

  interior_product(form)

    Interior product with an alternating form.

    If `self` is an alternating contravariant tensor \(A\) of degree \(p\) and \(B\) is an alternating form of degree \(q\geq p\) on the same free module, the interior product of \(A\) by \(B\) is the alternating form \(\iota_A B\) of degree \(q-p\) defined by

    \[(\iota_A B)_{i_1\ldots i_{q-p}} = A^{k_1\ldots k_p} B_{k_1\ldots k_p i_1\ldots i_{q-p}}\]

    Note

    `A.interior_product(B)` yields the same result as `A.contract(0,..., p-1, B, 0,..., p-1)` (cf. `contract()`), but `interior_product` is more efficient, the alternating character of \(A\) being not used to reduce the computation in `contract()`

    INPUT:

    - `form` – alternating form \(B\) (instance of `FreeModuleAltForm`); the degree of \(B\) must be at least equal to the degree of `self`

    OUTPUT:

    - element of the base ring (case \(p=q\)) or `FreeModuleAltForm` (case \(p<q\)) representing the interior product \(\iota_A B\), where \(A\) is `self`

    See also

    `interior_product()` for the interior product of an alternating form by an alternating contravariant tensor

    EXAMPLES:

    Let us consider a rank-4 free module:

    Sage

        sage: M = FiniteRankFreeModule(ZZ, 4, name='M', start_index=1)
        sage: e = M.basis('e')

    Python

        >>> from sage.all import *
        >>> M = FiniteRankFreeModule(ZZ, Integer(4), name='M', start_index=Integer(1))
        >>> e = M.basis('e')

    and various interior products on it, starting with a module element (`p=1`) and a linear form (`q=1`):

    Sage

        sage: a = M([-2,1,2,3], basis=e, name='A')
        sage: b = M.linear_form(name='B')
        sage: b[:] = [2, 0, -3, 4]
        sage: c = a.interior_product(b); c
        2
        sage: c == a.contract(b)
        True

    [Python]

        >>> from sage.all import *
        >>> a = M([-Integer(2),Integer(1),Integer(2),Integer(3)], basis=e, name='A')
        >>> b = M.linear_form(name='B')
        >>> b[:] = [Integer(2), Integer(0), -Integer(3), Integer(4)]
        >>> c = a.interior_product(b); c
        2
        >>> c == a.contract(b)
        True

    Case `p=1` and `q=3`:

    Sage

        sage: b = M.alternating_form(3, name='B')
        sage: b[1,2,3], b[1,2,4], b[1,3,4], b[2,3,4] = 3, -1, 2, 5
        sage: c = a.interior_product(b); c
        Alternating form i_A B of degree 2 on the Rank-4 free module M over the Integer Ring
        sage: c.display()
        i_A B = 3 e^1∧e^2 + 3 e^1∧e^3 - 3 e^1∧e^4 + 9 e^2∧e^3 - 8 e^2∧e^4 + e^3∧e^4
        sage: latex(c)
        \iota_{A} B
        sage: c == a.contract(b)
        True

    Python

        >>> from sage.all import *
        >>> b = M.alternating_form(Integer(3), name='B')
        >>> b[Integer(1),Integer(2),Integer(3)], b[Integer(1),Integer(2),Integer(4)], b[Integer(1),Integer(3),Integer(4)], b[Integer(2),Integer(3),Integer(4)] = Integer(3), -Integer(1), Integer(2), Integer(5)
        >>> c = a.interior_product(b); c
        Alternating form i_A B of degree 2 on the Rank-4 free module M over the Integer Ring
        >>> c.display()
        i_A B = 3 e^1∧e^2 + 3 e^1∧e^3 - 3 e^1∧e^4 + 9 e^2∧e^3 - 8 e^2∧e^4 + e^3∧e^4
        >>> latex(c)
        \iota_{A} B
        >>> c == a.contract(b)
        True

    Case `p=2` and `q=3`:

    Sage

        sage: a = M.alternating_contravariant_tensor(2, name='A')
        sage: a[1,2], a[1,3], a[1,4] = 2, -5, 3
        sage: a[2,3], a[2,4], a[3,4] = -1, 4, 2
        sage: c = a.interior_product(b); c
        Linear form i_A B on the Rank-4 free module M over the Integer Ring
        sage: c.display()
        i_A B = -6 e^1 + 56 e^2 - 40 e^3 - 34 e^4
        sage: c == a.contract(0, 1, b, 0, 1)  # contraction on all indices of a
        True

    [Python]

        >>> from sage.all import *
        >>> a = M.alternating_contravariant_tensor(Integer(2), name='A')
        >>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(1),Integer(4)] = Integer(2), -Integer(5), Integer(3)
        >>> a[Integer(2),Integer(3)], a[Integer(2),Integer(4)], a[Integer(3),Integer(4)] = -Integer(1), Integer(4), Integer(2)
        >>> c = a.interior_product(b); c
        Linear form i_A B on the Rank-4 free module M over the Integer Ring
        >>> c.display()
        i_A B = -6 e^1 + 56 e^2 - 40 e^3 - 34 e^4
        >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1))  # contraction on all indices of a
        True

    Case `p=2` and `q=4`:

    Sage

        sage: b = M.alternating_form(4, name='B')
        sage: b[1,2,3,4] = 5
        sage: c = a.interior_product(b); c
        Alternating form i_A B of degree 2 on the Rank-4 free module M over the Integer Ring
        sage: c.display()
        i_A B = 20 e^1∧e^2 - 40 e^1∧e^3 - 10 e^1∧e^4 + 30 e^2∧e^3 + 50 e^2∧e^4 + 20 e^3∧e^4
        sage: c == a.contract(0, 1, b, 0, 1)
        True

    Python

        >>> from sage.all import *
        >>> b = M.alternating_form(Integer(4), name='B')
        >>> b[Integer(1),Integer(2),Integer(3),Integer(4)] = Integer(5)
        >>> c = a.interior_product(b); c
        Alternating form i_A B of degree 2 on the Rank-4 free module M over the Integer Ring
        >>> c.display()
        i_A B = 20 e^1∧e^2 - 40 e^1∧e^3 - 10 e^1∧e^4 + 30 e^2∧e^3 + 50 e^2∧e^4 + 20 e^3∧e^4
        >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1))
        True

    Case `p=2` and `q=2`:

    Sage

        sage: b = M.alternating_form(2)
        sage: b[1,2], b[1,3], b[1,4] = 6, 0, -2
        sage: b[2,3], b[2,4], b[3,4] = 2, 3, 4
        sage: c = a.interior_product(b); c
        48
        sage: c == a.contract(0, 1, b, 0, 1)
        True

    [Python]

        >>> from sage.all import *
        >>> b = M.alternating_form(Integer(2))
        >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(1),Integer(4)] = Integer(6), Integer(0), -Integer(2)
        >>> b[Integer(2),Integer(3)], b[Integer(2),Integer(4)], b[Integer(3),Integer(4)] = Integer(2), Integer(3), Integer(4)
        >>> c = a.interior_product(b); c
        48
        >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1))
        True

    Case `p=3` and `q=3`:

    Sage

        sage: a = M.alternating_contravariant_tensor(3, name='A')
        sage: a[1,2,3], a[1,2,4], a[1,3,4], a[2,3,4] = -3, 2, 8, -5
        sage: b = M.alternating_form(3, name='B')
        sage: b[1,2,3], b[1,2,4], b[1,3,4], b[2,3,4] = 3, -1, 2, 5
        sage: c = a.interior_product(b); c
        -120
        sage: c == a.contract(0, 1, 2, b, 0, 1, 2)
        True

    Python

        >>> from sage.all import *
        >>> a = M.alternating_contravariant_tensor(Integer(3), name='A')
        >>> a[Integer(1),Integer(2),Integer(3)], a[Integer(1),Integer(2),Integer(4)], a[Integer(1),Integer(3),Integer(4)], a[Integer(2),Integer(3),Integer(4)] = -Integer(3), Integer(2), Integer(8), -Integer(5)
        >>> b = M.alternating_form(Integer(3), name='B')
        >>> b[Integer(1),Integer(2),Integer(3)], b[Integer(1),Integer(2),Integer(4)], b[Integer(1),Integer(3),Integer(4)], b[Integer(2),Integer(3),Integer(4)] = Integer(3), -Integer(1), Integer(2), Integer(5)
        >>> c = a.interior_product(b); c
        -120
        >>> c == a.contract(Integer(0), Integer(1), Integer(2), b, Integer(0), Integer(1), Integer(2))
        True

    Case `p=3` and `q=4`:

    Sage

        sage: b = M.alternating_form(4, name='B')
        sage: b[1,2,3,4] = 5
        sage: c = a.interior_product(b); c
        Linear form i_A B on the Rank-4 free module M over the Integer Ring
        sage: c.display()
        i_A B = 150 e^1 + 240 e^2 - 60 e^3 - 90 e^4
        sage: c == a.contract(0, 1, 2, b, 0, 1, 2)
        True

    [Python]

        >>> from sage.all import *
        >>> b = M.alternating_form(Integer(4), name='B')
        >>> b[Integer(1),Integer(2),Integer(3),Integer(4)] = Integer(5)
        >>> c = a.interior_product(b); c
        Linear form i_A B on the Rank-4 free module M over the Integer Ring
        >>> c.display()
        i_A B = 150 e^1 + 240 e^2 - 60 e^3 - 90 e^4
        >>> c == a.contract(Integer(0), Integer(1), Integer(2), b, Integer(0), Integer(1), Integer(2))
        True

    Case `p=4` and `q=4`:

    Sage

        sage: a = M.alternating_contravariant_tensor(4, name='A')
        sage: a[1,2,3,4] = -2
        sage: c = a.interior_product(b); c
        -240
        sage: c == a.contract(0, 1, 2, 3, b, 0, 1, 2, 3)
        True

    Python

        >>> from sage.all import *
        >>> a = M.alternating_contravariant_tensor(Integer(4), name='A')
        >>> a[Integer(1),Integer(2),Integer(3),Integer(4)] = -Integer(2)
        >>> c = a.interior_product(b); c
        -240
        >>> c == a.contract(Integer(0), Integer(1), Integer(2), Integer(3), b, Integer(0), Integer(1), Integer(2), Integer(3))
        True

  wedge(other)

    Exterior product of `self` with the alternating contravariant tensor `other`.

    INPUT:

    - `other` – an alternating contravariant tensor

    OUTPUT:

    - instance of `AlternatingContrTensor` representing the exterior product `self ∧ other`

    EXAMPLES:

    Exterior product of two module elements:

    Sage

        sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
        sage: e = M.basis('e')
        sage: a = M([1,-3,4], basis=e, name='A')
        sage: b = M([2,-1,2], basis=e, name='B')
        sage: c = a.wedge(b) ; c
        Alternating contravariant tensor A∧B of degree 2 on the Rank-3
         free module M over the Integer Ring
        sage: c.display()
        A∧B = 5 e_0∧e_1 - 6 e_0∧e_2 - 2 e_1∧e_2
        sage: latex(c)
        A\wedge B
        sage: latex(c.display())
        A\wedge B = 5 e_{0}\wedge e_{1} -6 e_{0}\wedge e_{2}
         -2 e_{1}\wedge e_{2}

    Python

        >>> from sage.all import *
        >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M')
        >>> e = M.basis('e')
        >>> a = M([Integer(1),-Integer(3),Integer(4)], basis=e, name='A')
        >>> b = M([Integer(2),-Integer(1),Integer(2)], basis=e, name='B')
        >>> c = a.wedge(b) ; c
        Alternating contravariant tensor A∧B of degree 2 on the Rank-3
         free module M over the Integer Ring
        >>> c.display()
        A∧B = 5 e_0∧e_1 - 6 e_0∧e_2 - 2 e_1∧e_2
        >>> latex(c)
        A\wedge B
        >>> latex(c.display())
        A\wedge B = 5 e_{0}\wedge e_{1} -6 e_{0}\wedge e_{2}
         -2 e_{1}\wedge e_{2}

    Test of the computation:

    Sage

        sage: a.wedge(b) == a*b - b*a
        True

    [Python]

        >>> from sage.all import *
        >>> a.wedge(b) == a*b - b*a
        True

    Exterior product of a module element and an alternating contravariant tensor of degree 2:

    Sage

        sage: d = M([-1,2,4], basis=e, name='D')
        sage: s = d.wedge(c) ; s
        Alternating contravariant tensor D∧A∧B of degree 3 on the Rank-3
         free module M over the Integer Ring
        sage: s.display()
        D∧A∧B = 34 e_0∧e_1∧e_2

    Python

        >>> from sage.all import *
        >>> d = M([-Integer(1),Integer(2),Integer(4)], basis=e, name='D')
        >>> s = d.wedge(c) ; s
        Alternating contravariant tensor D∧A∧B of degree 3 on the Rank-3
         free module M over the Integer Ring
        >>> s.display()
        D∧A∧B = 34 e_0∧e_1∧e_2

    Test of the computation:

    Sage

        sage: s[0,1,2] == d[0]*c[1,2] + d[1]*c[2,0] + d[2]*c[0,1]
        True

    [Python]

        >>> from sage.all import *
        >>> s[Integer(0),Integer(1),Integer(2)] == d[Integer(0)]*c[Integer(1),Integer(2)] + d[Integer(1)]*c[Integer(2),Integer(0)] + d[Integer(2)]*c[Integer(0),Integer(1)]
        True

    Let us check that the exterior product is associative:

    Sage

        sage: d.wedge(a.wedge(b)) == (d.wedge(a)).wedge(b)
        True

    Python

        >>> from sage.all import *
        >>> d.wedge(a.wedge(b)) == (d.wedge(a)).wedge(b)
        True

    and that it is graded anticommutative:

    Sage

        sage: a.wedge(b) == - b.wedge(a)
        True
        sage: d.wedge(c) == c.wedge(d)
        True

    [Python]

        >>> from sage.all import *
        >>> a.wedge(b) == - b.wedge(a)
        True
        >>> d.wedge(c) == c.wedge(d)
        True