Alternating forms on free modules#
Given a free module \(M\) of finite rank over a commutative ring \(R\) and a positive integer \(p\), an alternating form of degree \(p\) on \(M\) is a map
that (i) is multilinear and (ii) vanishes whenever any of two of its arguments are equal. An alternating form of degree \(p\) is a tensor on \(M\) of type \((0,p)\).
Alternating forms are implemented via the class FreeModuleAltForm
,
which is a subclass of the generic tensor class
FreeModuleTensor
.
AUTHORS:
Eric Gourgoulhon, Michal Bejger (2014-2015): initial version
REFERENCES:
- class sage.tensor.modules.free_module_alt_form.FreeModuleAltForm(fmodule, degree, name=None, latex_name=None)[source]#
Bases:
FreeModuleTensor
Alternating form on a free module of finite rank over a commutative ring.
This is a Sage element class, the corresponding parent class being
ExtPowerDualFreeModule
.INPUT:
fmodule
– free module \(M\) of finite rank over a commutative ring \(R\), as an instance ofFiniteRankFreeModule
degree
– positive integer; the degree \(p\) of the alternating form (i.e. its tensor rank)name
– (default:None
) string; name given to the alternating formlatex_name
– (default:None
) string; LaTeX symbol to denote the alternating form; if none is provided,name
is used
EXAMPLES:
Alternating form of degree 2 on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: e = M.basis('e') sage: a = M.alternating_form(2, name='a') ; a Alternating form 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.ExtPowerDualFreeModule_with_category.element_class'> sage: a.parent() 2nd exterior power of the dual 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
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M', start_index=Integer(1)) >>> e = M.basis('e') >>> a = M.alternating_form(Integer(2), name='a') ; a Alternating form 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.ExtPowerDualFreeModule_with_category.element_class'> >>> a.parent() 2nd exterior power of the dual 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 form acting on the basis elements:
sage: a(e[1],e[2]) 4 sage: a(e[1],e[3]) 0 sage: a(e[2],e[3]) -3 sage: a(e[2],e[1]) -4
>>> from sage.all import * >>> a(e[Integer(1)],e[Integer(2)]) 4 >>> a(e[Integer(1)],e[Integer(3)]) 0 >>> a(e[Integer(2)],e[Integer(3)]) -3 >>> a(e[Integer(2)],e[Integer(1)]) -4
An alternating form of degree 1 is a linear form:
sage: b = M.linear_form('b') ; b Linear form b on 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)
>>> from sage.all import * >>> b = M.linear_form('b') ; b Linear form b on 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)
A linear form is a tensor of type \((0,1)\):
sage: b.tensor_type() (0, 1)
>>> from sage.all import * >>> b.tensor_type() (0, 1)
It is an element of the dual module:
sage: b.parent() Dual of the Rank-3 free module M over the Integer Ring sage: b.parent() is M.dual() True
>>> from sage.all import * >>> b.parent() Dual of the Rank-3 free module M over the Integer Ring >>> b.parent() is M.dual() True
The members of a dual basis are linear forms:
sage: e.dual_basis()[1] Linear form e^1 on the Rank-3 free module M over the Integer Ring sage: e.dual_basis()[2] Linear form e^2 on the Rank-3 free module M over the Integer Ring sage: e.dual_basis()[3] Linear form e^3 on the Rank-3 free module M over the Integer Ring
>>> from sage.all import * >>> e.dual_basis()[Integer(1)] Linear form e^1 on the Rank-3 free module M over the Integer Ring >>> e.dual_basis()[Integer(2)] Linear form e^2 on the Rank-3 free module M over the Integer Ring >>> e.dual_basis()[Integer(3)] Linear form e^3 on the Rank-3 free module M over the Integer Ring
Any linear form is expanded onto them:
sage: b.display(e) b = 2 e^1 - e^2 + 3 e^3
>>> from sage.all import * >>> b.display(e) b = 2 e^1 - e^2 + 3 e^3
In the above example, an equivalent writing would have been
b.display()
, since the basise
is the module’s default basis. A linear form maps module elements to ring elements:sage: v = M([1,1,1]) sage: b(v) 4 sage: b(v) in M.base_ring() True
>>> from sage.all import * >>> v = M([Integer(1),Integer(1),Integer(1)]) >>> b(v) 4 >>> b(v) in M.base_ring() True
Test of linearity:
sage: u = M([-5,-2,7]) sage: b(3*u - 4*v) == 3*b(u) - 4*b(v) True
>>> from sage.all import * >>> u = M([-Integer(5),-Integer(2),Integer(7)]) >>> b(Integer(3)*u - Integer(4)*v) == Integer(3)*b(u) - Integer(4)*b(v) True
The standard tensor operations apply to alternating forms, like the extraction of components with respect to a given basis:
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
>>> 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: c = b*b ; c Symmetric bilinear form b⊗b on the Rank-3 free module M over the Integer Ring sage: c.parent() Free module of type-(0,2) 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
>>> from sage.all import * >>> c = b*b ; c Symmetric bilinear form b⊗b on the Rank-3 free module M over the Integer Ring >>> c.parent() Free module of type-(0,2) 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: s = a.contract(v) ; s Linear form on the Rank-3 free module M over the Integer Ring sage: s.parent() Dual of the Rank-3 free module M over the Integer Ring sage: s.display(e) 4 e^1 - 7 e^2 + 3 e^3
>>> from sage.all import * >>> s = a.contract(v) ; s Linear form on the Rank-3 free module M over the Integer Ring >>> s.parent() Dual 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: s = 3*a + c ; s Type-(0,2) tensor on the Rank-3 free module M over the Integer Ring sage: s.parent() Free module of type-(0,2) 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
>>> from sage.all import * >>> s = Integer(3)*a + c ; s Type-(0,2) tensor on the Rank-3 free module M over the Integer Ring >>> s.parent() Free module of type-(0,2) 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: s = a - 2*a ; s Alternating form 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 dual of the Rank-3 free module M over the Integer Ring sage: s == -a True
>>> from sage.all import * >>> s = a - Integer(2)*a ; s Alternating form 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 dual of the Rank-3 free module M over the Integer Ring >>> s == -a True
An operation specific to alternating forms is of course the exterior product:
sage: s = a.wedge(b) ; s Alternating form a∧b of degree 3 on the Rank-3 free module M over the Integer Ring sage: s.parent() 3rd exterior power of the dual 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
>>> from sage.all import * >>> s = a.wedge(b) ; s Alternating form a∧b of degree 3 on the Rank-3 free module M over the Integer Ring >>> s.parent() 3rd exterior power of the dual 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 linear forms:
sage: s = b.wedge(b) ; s Alternating form zero of degree 2 on the Rank-3 free module M over the Integer Ring sage: s.display(e) zero = 0
>>> from sage.all import * >>> s = b.wedge(b) ; s Alternating form zero of degree 2 on the Rank-3 free module M over the Integer Ring >>> s.display(e) zero = 0
- degree()[source]#
Return the degree of
self
.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: a = M.alternating_form(2, name='a') sage: a.degree() 2
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> a = M.alternating_form(Integer(2), name='a') >>> a.degree() 2
- disp(basis=None, format_spec=None)[source]#
Display the alternating form
self
in terms of its expansion w.r.t. a given module basis.The expansion is actually performed onto exterior products of elements of the cobasis (dual basis) associated with
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 the alternating form is expanded; if none is provided, the module’s default basis is assumedformat_spec
– (default:None
) format specification passed toself._fmodule._output_formatter
to format the output
EXAMPLES:
Display of an alternating form of degree 1 (linear form) on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: e.dual_basis() Dual basis (e^0,e^1,e^2) on the Rank-3 free module M over the Integer Ring sage: a = M.linear_form('a', latex_name=r'\alpha') sage: a[:] = [1,-3,4] sage: a.display(e) a = e^0 - 3 e^1 + 4 e^2 sage: a.display() # a shortcut since e is M's default basis a = e^0 - 3 e^1 + 4 e^2 sage: latex(a.display()) # display in the notebook \alpha = e^{0} -3 e^{1} + 4 e^{2}
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> e.dual_basis() Dual basis (e^0,e^1,e^2) on the Rank-3 free module M over the Integer Ring >>> a = M.linear_form('a', latex_name=r'\alpha') >>> a[:] = [Integer(1),-Integer(3),Integer(4)] >>> a.display(e) a = e^0 - 3 e^1 + 4 e^2 >>> a.display() # a shortcut since e is M's default basis a = e^0 - 3 e^1 + 4 e^2 >>> latex(a.display()) # display in the notebook \alpha = e^{0} -3 e^{1} + 4 e^{2}
A shortcut is
disp()
:sage: a.disp() a = e^0 - 3 e^1 + 4 e^2
>>> from sage.all import * >>> a.disp() a = e^0 - 3 e^1 + 4 e^2
Display of an alternating form of degree 2 on a rank-3 free module:
sage: b = M.alternating_form(2, 'b', latex_name=r'\beta') sage: b[0,1], b[0,2], b[1,2] = 3, 2, -1 sage: b.display() b = 3 e^0∧e^1 + 2 e^0∧e^2 - e^1∧e^2 sage: latex(b.display()) # display in the notebook \beta = 3 e^{0}\wedge e^{1} + 2 e^{0}\wedge e^{2} -e^{1}\wedge e^{2}
>>> from sage.all import * >>> b = M.alternating_form(Integer(2), 'b', latex_name=r'\beta') >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(1),Integer(2)] = Integer(3), Integer(2), -Integer(1) >>> b.display() b = 3 e^0∧e^1 + 2 e^0∧e^2 - e^1∧e^2 >>> latex(b.display()) # display in the notebook \beta = 3 e^{0}\wedge e^{1} + 2 e^{0}\wedge e^{2} -e^{1}\wedge e^{2}
Display of an alternating form of degree 3 on a rank-3 free module:
sage: c = M.alternating_form(3, 'c') sage: c[0,1,2] = 4 sage: c.display() c = 4 e^0∧e^1∧e^2 sage: latex(c.display()) c = 4 e^{0}\wedge e^{1}\wedge e^{2}
>>> from sage.all import * >>> c = M.alternating_form(Integer(3), 'c') >>> c[Integer(0),Integer(1),Integer(2)] = Integer(4) >>> c.display() c = 4 e^0∧e^1∧e^2 >>> latex(c.display()) c = 4 e^{0}\wedge e^{1}\wedge e^{2}
Display of a vanishing alternating form:
sage: c[0,1,2] = 0 # the only independent component set to zero sage: c.is_zero() True sage: c.display() c = 0 sage: latex(c.display()) c = 0 sage: c[0,1,2] = 4 # value restored for what follows
>>> from sage.all import * >>> c[Integer(0),Integer(1),Integer(2)] = Integer(0) # the only independent component set to zero >>> c.is_zero() True >>> c.display() c = 0 >>> latex(c.display()) c = 0 >>> c[Integer(0),Integer(1),Integer(2)] = Integer(4) # value restored for what follows
Display in a basis which is not the default one:
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 = 4 f^0 + f^1 + 3 f^2 sage: a.disp(f) # shortcut notation a = 4 f^0 + f^1 + 3 f^2 sage: b.display(f) b = -2 f^0∧f^1 - f^0∧f^2 - 3 f^1∧f^2 sage: c.display(f) c = -4 f^0∧f^1∧f^2
>>> 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 = 4 f^0 + f^1 + 3 f^2 >>> a.disp(f) # shortcut notation a = 4 f^0 + f^1 + 3 f^2 >>> b.display(f) b = -2 f^0∧f^1 - f^0∧f^2 - 3 f^1∧f^2 >>> c.display(f) c = -4 f^0∧f^1∧f^2
The output format can be set via the argument
output_formatter
passed at the module construction:sage: N = FiniteRankFreeModule(QQ, 3, name='N', start_index=1, ....: output_formatter=Rational.numerical_approx) sage: e = N.basis('e') sage: b = N.alternating_form(2, 'b') sage: b[1,2], b[1,3], b[2,3] = 1/3, 5/2, 4 sage: b.display() # default format (53 bits of precision) b = 0.333333333333333 e^1∧e^2 + 2.50000000000000 e^1∧e^3 + 4.00000000000000 e^2∧e^3
>>> from sage.all import * >>> N = FiniteRankFreeModule(QQ, Integer(3), name='N', start_index=Integer(1), ... output_formatter=Rational.numerical_approx) >>> e = N.basis('e') >>> b = N.alternating_form(Integer(2), 'b') >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(2),Integer(3)] = Integer(1)/Integer(3), Integer(5)/Integer(2), Integer(4) >>> b.display() # default format (53 bits of precision) b = 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 methoddisplay()
:sage: b.display(format_spec=10) # 10 bits of precision b = 0.33 e^1∧e^2 + 2.5 e^1∧e^3 + 4.0 e^2∧e^3
>>> from sage.all import * >>> b.display(format_spec=Integer(10)) # 10 bits of precision b = 0.33 e^1∧e^2 + 2.5 e^1∧e^3 + 4.0 e^2∧e^3
Check that the bug reported in Issue #22520 is fixed:
sage: # needs sage.symbolic sage: M = FiniteRankFreeModule(SR, 2, name='M') sage: e = M.basis('e') sage: a = M.alternating_form(2) sage: a[0,1] = SR.var('t', domain='real') sage: a.display() t e^0∧e^1
>>> from sage.all import * >>> # needs sage.symbolic >>> M = FiniteRankFreeModule(SR, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.alternating_form(Integer(2)) >>> a[Integer(0),Integer(1)] = SR.var('t', domain='real') >>> a.display() t e^0∧e^1
- display(basis=None, format_spec=None)[source]#
Display the alternating form
self
in terms of its expansion w.r.t. a given module basis.The expansion is actually performed onto exterior products of elements of the cobasis (dual basis) associated with
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 the alternating form is expanded; if none is provided, the module’s default basis is assumedformat_spec
– (default:None
) format specification passed toself._fmodule._output_formatter
to format the output
EXAMPLES:
Display of an alternating form of degree 1 (linear form) on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: e.dual_basis() Dual basis (e^0,e^1,e^2) on the Rank-3 free module M over the Integer Ring sage: a = M.linear_form('a', latex_name=r'\alpha') sage: a[:] = [1,-3,4] sage: a.display(e) a = e^0 - 3 e^1 + 4 e^2 sage: a.display() # a shortcut since e is M's default basis a = e^0 - 3 e^1 + 4 e^2 sage: latex(a.display()) # display in the notebook \alpha = e^{0} -3 e^{1} + 4 e^{2}
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> e.dual_basis() Dual basis (e^0,e^1,e^2) on the Rank-3 free module M over the Integer Ring >>> a = M.linear_form('a', latex_name=r'\alpha') >>> a[:] = [Integer(1),-Integer(3),Integer(4)] >>> a.display(e) a = e^0 - 3 e^1 + 4 e^2 >>> a.display() # a shortcut since e is M's default basis a = e^0 - 3 e^1 + 4 e^2 >>> latex(a.display()) # display in the notebook \alpha = e^{0} -3 e^{1} + 4 e^{2}
A shortcut is
disp()
:sage: a.disp() a = e^0 - 3 e^1 + 4 e^2
>>> from sage.all import * >>> a.disp() a = e^0 - 3 e^1 + 4 e^2
Display of an alternating form of degree 2 on a rank-3 free module:
sage: b = M.alternating_form(2, 'b', latex_name=r'\beta') sage: b[0,1], b[0,2], b[1,2] = 3, 2, -1 sage: b.display() b = 3 e^0∧e^1 + 2 e^0∧e^2 - e^1∧e^2 sage: latex(b.display()) # display in the notebook \beta = 3 e^{0}\wedge e^{1} + 2 e^{0}\wedge e^{2} -e^{1}\wedge e^{2}
>>> from sage.all import * >>> b = M.alternating_form(Integer(2), 'b', latex_name=r'\beta') >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(1),Integer(2)] = Integer(3), Integer(2), -Integer(1) >>> b.display() b = 3 e^0∧e^1 + 2 e^0∧e^2 - e^1∧e^2 >>> latex(b.display()) # display in the notebook \beta = 3 e^{0}\wedge e^{1} + 2 e^{0}\wedge e^{2} -e^{1}\wedge e^{2}
Display of an alternating form of degree 3 on a rank-3 free module:
sage: c = M.alternating_form(3, 'c') sage: c[0,1,2] = 4 sage: c.display() c = 4 e^0∧e^1∧e^2 sage: latex(c.display()) c = 4 e^{0}\wedge e^{1}\wedge e^{2}
>>> from sage.all import * >>> c = M.alternating_form(Integer(3), 'c') >>> c[Integer(0),Integer(1),Integer(2)] = Integer(4) >>> c.display() c = 4 e^0∧e^1∧e^2 >>> latex(c.display()) c = 4 e^{0}\wedge e^{1}\wedge e^{2}
Display of a vanishing alternating form:
sage: c[0,1,2] = 0 # the only independent component set to zero sage: c.is_zero() True sage: c.display() c = 0 sage: latex(c.display()) c = 0 sage: c[0,1,2] = 4 # value restored for what follows
>>> from sage.all import * >>> c[Integer(0),Integer(1),Integer(2)] = Integer(0) # the only independent component set to zero >>> c.is_zero() True >>> c.display() c = 0 >>> latex(c.display()) c = 0 >>> c[Integer(0),Integer(1),Integer(2)] = Integer(4) # value restored for what follows
Display in a basis which is not the default one:
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 = 4 f^0 + f^1 + 3 f^2 sage: a.disp(f) # shortcut notation a = 4 f^0 + f^1 + 3 f^2 sage: b.display(f) b = -2 f^0∧f^1 - f^0∧f^2 - 3 f^1∧f^2 sage: c.display(f) c = -4 f^0∧f^1∧f^2
>>> 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 = 4 f^0 + f^1 + 3 f^2 >>> a.disp(f) # shortcut notation a = 4 f^0 + f^1 + 3 f^2 >>> b.display(f) b = -2 f^0∧f^1 - f^0∧f^2 - 3 f^1∧f^2 >>> c.display(f) c = -4 f^0∧f^1∧f^2
The output format can be set via the argument
output_formatter
passed at the module construction:sage: N = FiniteRankFreeModule(QQ, 3, name='N', start_index=1, ....: output_formatter=Rational.numerical_approx) sage: e = N.basis('e') sage: b = N.alternating_form(2, 'b') sage: b[1,2], b[1,3], b[2,3] = 1/3, 5/2, 4 sage: b.display() # default format (53 bits of precision) b = 0.333333333333333 e^1∧e^2 + 2.50000000000000 e^1∧e^3 + 4.00000000000000 e^2∧e^3
>>> from sage.all import * >>> N = FiniteRankFreeModule(QQ, Integer(3), name='N', start_index=Integer(1), ... output_formatter=Rational.numerical_approx) >>> e = N.basis('e') >>> b = N.alternating_form(Integer(2), 'b') >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(2),Integer(3)] = Integer(1)/Integer(3), Integer(5)/Integer(2), Integer(4) >>> b.display() # default format (53 bits of precision) b = 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 methoddisplay()
:sage: b.display(format_spec=10) # 10 bits of precision b = 0.33 e^1∧e^2 + 2.5 e^1∧e^3 + 4.0 e^2∧e^3
>>> from sage.all import * >>> b.display(format_spec=Integer(10)) # 10 bits of precision b = 0.33 e^1∧e^2 + 2.5 e^1∧e^3 + 4.0 e^2∧e^3
Check that the bug reported in Issue #22520 is fixed:
sage: # needs sage.symbolic sage: M = FiniteRankFreeModule(SR, 2, name='M') sage: e = M.basis('e') sage: a = M.alternating_form(2) sage: a[0,1] = SR.var('t', domain='real') sage: a.display() t e^0∧e^1
>>> from sage.all import * >>> # needs sage.symbolic >>> M = FiniteRankFreeModule(SR, Integer(2), name='M') >>> e = M.basis('e') >>> a = M.alternating_form(Integer(2)) >>> a[Integer(0),Integer(1)] = SR.var('t', domain='real') >>> a.display() t e^0∧e^1
- interior_product(alt_tensor)[source]#
Interior product with an alternating contravariant tensor.
If
self
is an alternating form \(A\) of degree \(p\) and \(B\) is an alternating contravariant tensor of degree \(q\geq p\) on the same free module, the interior product of \(A\) by \(B\) is the alternating contravariant tensor \(\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 asA.contract(0,..., p-1, B, 0,..., p-1)
(cf.contract()
), butinterior_product
is more efficient, the alternating character of \(A\) being not used to reduce the computation incontract()
INPUT:
alt_tensor
– alternating contravariant tensor \(B\) (instance ofAlternatingContrTensor
); the degree of \(B\) must be at least equal to the degree ofself
OUTPUT:
element of the base ring (case \(p=q\)) or
AlternatingContrTensor
(case \(p<q\)) representing the interior product \(\iota_A B\), where \(A\) isself
See also
interior_product()
for the interior product of an alternating contravariant tensor by an alternating formEXAMPLES:
Let us consider a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: e = M.basis('e')
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M', start_index=Integer(1)) >>> e = M.basis('e')
and various interior products on it, starting with a linear form (
p=1
) and a module element (q=1
):sage: a = M.linear_form(name='A') sage: a[:] = [-2, 4, 3] sage: b = M([3, 1, 5], basis=e, name='B') sage: c = a.interior_product(b); c 13 sage: c == a.contract(b) True
>>> from sage.all import * >>> a = M.linear_form(name='A') >>> a[:] = [-Integer(2), Integer(4), Integer(3)] >>> b = M([Integer(3), Integer(1), Integer(5)], basis=e, name='B') >>> c = a.interior_product(b); c 13 >>> c == a.contract(b) True
Case
p=1
andq=2
:sage: b = M.alternating_contravariant_tensor(2, name='B') sage: b[1,2], b[1,3], b[2,3] = 5, 2, 3 sage: c = a.interior_product(b); c Element i_A B of the Rank-3 free module M over the Integer Ring sage: c.display() i_A B = -26 e_1 - 19 e_2 + 8 e_3 sage: latex(c) \iota_{A} B sage: c == a.contract(b) True
>>> from sage.all import * >>> b = M.alternating_contravariant_tensor(Integer(2), name='B') >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(2),Integer(3)] = Integer(5), Integer(2), Integer(3) >>> c = a.interior_product(b); c Element i_A B of the Rank-3 free module M over the Integer Ring >>> c.display() i_A B = -26 e_1 - 19 e_2 + 8 e_3 >>> latex(c) \iota_{A} B >>> c == a.contract(b) True
Case
p=1
andq=3
:sage: b = M.alternating_contravariant_tensor(3, name='B') sage: b[1,2,3] = 5 sage: c = a.interior_product(b); c Alternating contravariant tensor i_A B of degree 2 on the Rank-3 free module M over the Integer Ring sage: c.display() i_A B = 15 e_1∧e_2 - 20 e_1∧e_3 - 10 e_2∧e_3 sage: c == a.contract(b) True
>>> from sage.all import * >>> b = M.alternating_contravariant_tensor(Integer(3), name='B') >>> b[Integer(1),Integer(2),Integer(3)] = Integer(5) >>> c = a.interior_product(b); c Alternating contravariant tensor i_A B of degree 2 on the Rank-3 free module M over the Integer Ring >>> c.display() i_A B = 15 e_1∧e_2 - 20 e_1∧e_3 - 10 e_2∧e_3 >>> c == a.contract(b) True
Case
p=2
andq=2
:sage: a = M.alternating_form(2, name='A') sage: a[1,2], a[1,3], a[2,3] = 2, -3, 1 sage: b = M.alternating_contravariant_tensor(2, name='B') sage: b[1,2], b[1,3], b[2,3] = 5, 2, 3 sage: c = a.interior_product(b); c 14 sage: c == a.contract(0, 1, b, 0, 1) # contraction on all indices of a True
>>> from sage.all import * >>> a = M.alternating_form(Integer(2), name='A') >>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(2),Integer(3)] = Integer(2), -Integer(3), Integer(1) >>> b = M.alternating_contravariant_tensor(Integer(2), name='B') >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(2),Integer(3)] = Integer(5), Integer(2), Integer(3) >>> c = a.interior_product(b); c 14 >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1)) # contraction on all indices of a True
Case
p=2
andq=3
:sage: b = M.alternating_contravariant_tensor(3, name='B') sage: b[1,2,3] = 5 sage: c = a.interior_product(b); c Element i_A B of the Rank-3 free module M over the Integer Ring sage: c.display() i_A B = 10 e_1 + 30 e_2 + 20 e_3 sage: c == a.contract(0, 1, b, 0, 1) True
>>> from sage.all import * >>> b = M.alternating_contravariant_tensor(Integer(3), name='B') >>> b[Integer(1),Integer(2),Integer(3)] = Integer(5) >>> c = a.interior_product(b); c Element i_A B of the Rank-3 free module M over the Integer Ring >>> c.display() i_A B = 10 e_1 + 30 e_2 + 20 e_3 >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1)) True
Case
p=3
andq=3
:sage: a = M.alternating_form(3, name='A') sage: a[1,2,3] = -2 sage: c = a.interior_product(b); c -60 sage: c == a.contract(0, 1, 2, b, 0, 1, 2) True
>>> from sage.all import * >>> a = M.alternating_form(Integer(3), name='A') >>> a[Integer(1),Integer(2),Integer(3)] = -Integer(2) >>> c = a.interior_product(b); c -60 >>> c == a.contract(Integer(0), Integer(1), Integer(2), b, Integer(0), Integer(1), Integer(2)) True
- wedge(other)[source]#
Exterior product of
self
with the alternating formother
.INPUT:
other
– an alternating form
OUTPUT:
instance of
FreeModuleAltForm
representing the exterior productself ∧ other
EXAMPLES:
Exterior product of two linear forms:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: a = M.linear_form('A') sage: a[:] = [1,-3,4] sage: b = M.linear_form('B') sage: b[:] = [2,-1,2] sage: c = a.wedge(b) ; c Alternating form 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}
>>> from sage.all import * >>> M = FiniteRankFreeModule(ZZ, Integer(3), name='M') >>> e = M.basis('e') >>> a = M.linear_form('A') >>> a[:] = [Integer(1),-Integer(3),Integer(4)] >>> b = M.linear_form('B') >>> b[:] = [Integer(2),-Integer(1),Integer(2)] >>> c = a.wedge(b) ; c Alternating form 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: a.wedge(b) == a*b - b*a True
>>> from sage.all import * >>> a.wedge(b) == a*b - b*a True
Exterior product of a linear form and an alternating form of degree 2:
sage: d = M.linear_form('D') sage: d[:] = [-1,2,4] sage: s = d.wedge(c) ; s Alternating form 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
>>> from sage.all import * >>> d = M.linear_form('D') >>> d[:] = [-Integer(1),Integer(2),Integer(4)] >>> s = d.wedge(c) ; s Alternating form 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: s[0,1,2] == d[0]*c[1,2] + d[1]*c[2,0] + d[2]*c[0,1] True
>>> 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: d.wedge(a.wedge(b)) == (d.wedge(a)).wedge(b) True
>>> from sage.all import * >>> d.wedge(a.wedge(b)) == (d.wedge(a)).wedge(b) True
and that it is graded anticommutative:
sage: a.wedge(b) == - b.wedge(a) True sage: d.wedge(c) == c.wedge(d) True
>>> from sage.all import * >>> a.wedge(b) == - b.wedge(a) True >>> d.wedge(c) == c.wedge(d) True