Morphisms of free modules¶
- AUTHORS:
William Stein: initial version
Miguel Marco (2010-06-19): added eigenvalues, eigenvectors and minpoly functions
- class sage.modules.free_module_morphism.BaseIsomorphism1D[source]¶
Bases:
Morphism
An isomorphism between a ring and a free rank-1 module over the ring.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: V, from_V, to_V = R.free_module(R) sage: from_V Isomorphism morphism: From: Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field
>>> from sage.all import * >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2) >>> V, from_V, to_V = R.free_module(R) >>> from_V Isomorphism morphism: From: Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field
- class sage.modules.free_module_morphism.BaseIsomorphism1D_from_FM(parent, basis=None)[source]¶
Bases:
BaseIsomorphism1D
An isomorphism to a ring from its 1-dimensional free module.
INPUT:
parent
– the homsetbasis
– (default: 1) an invertible element of the ring
EXAMPLES:
sage: R.<x> = QQ[[]] sage: V, from_V, to_V = R.free_module(R) sage: v = to_V(1+x); v (1 + x) sage: from_V(v) 1 + x sage: W, from_W, to_W = R.free_module(R, basis=(1-x)) sage: W is V True sage: w = to_W(1+x); w (1 - x^2) sage: from_W(w) 1 + x + O(x^20)
>>> from sage.all import * >>> R = QQ[['x']]; (x,) = R._first_ngens(1) >>> V, from_V, to_V = R.free_module(R) >>> v = to_V(Integer(1)+x); v (1 + x) >>> from_V(v) 1 + x >>> W, from_W, to_W = R.free_module(R, basis=(Integer(1)-x)) >>> W is V True >>> w = to_W(Integer(1)+x); w (1 - x^2) >>> from_W(w) 1 + x + O(x^20)
The basis vector has to be a unit so that the map is an isomorphism:
sage: W, from_W, to_W = R.free_module(R, basis=x) Traceback (most recent call last): ... ValueError: basis element must be a unit
>>> from sage.all import * >>> W, from_W, to_W = R.free_module(R, basis=x) Traceback (most recent call last): ... ValueError: basis element must be a unit
- class sage.modules.free_module_morphism.BaseIsomorphism1D_to_FM(parent, basis=None)[source]¶
Bases:
BaseIsomorphism1D
An isomorphism from a ring to its 1-dimensional free module.
INPUT:
parent
– the homsetbasis
– (default: 1) an invertible element of the ring
EXAMPLES:
sage: R = Zmod(8) sage: V, from_V, to_V = R.free_module(R) sage: v = to_V(2); v (2) sage: from_V(v) 2 sage: W, from_W, to_W = R.free_module(R, basis=3) sage: W is V True sage: w = to_W(2); w (6) sage: from_W(w) 2
>>> from sage.all import * >>> R = Zmod(Integer(8)) >>> V, from_V, to_V = R.free_module(R) >>> v = to_V(Integer(2)); v (2) >>> from_V(v) 2 >>> W, from_W, to_W = R.free_module(R, basis=Integer(3)) >>> W is V True >>> w = to_W(Integer(2)); w (6) >>> from_W(w) 2
The basis vector has to be a unit so that the map is an isomorphism:
sage: W, from_W, to_W = R.free_module(R, basis=4) Traceback (most recent call last): ... ValueError: basis element must be a unit
>>> from sage.all import * >>> W, from_W, to_W = R.free_module(R, basis=Integer(4)) Traceback (most recent call last): ... ValueError: basis element must be a unit
- class sage.modules.free_module_morphism.FreeModuleMorphism(parent, A, side='left')[source]¶
Bases:
MatrixMorphism
INPUT:
parent
– a homspace in a (sub) category of free modulesA
– matrixside
– side of the vectors acted on by the matrix (default:'left'
)
EXAMPLES:
sage: V = ZZ^3; W = span([[1,2,3], [-1,2,8]], ZZ) sage: phi = V.hom(matrix(ZZ, 3, [1..9])) sage: type(phi) <class 'sage.modules.free_module_morphism.FreeModuleMorphism'>
>>> from sage.all import * >>> V = ZZ**Integer(3); W = span([[Integer(1),Integer(2),Integer(3)], [-Integer(1),Integer(2),Integer(8)]], ZZ) >>> phi = V.hom(matrix(ZZ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9))))) >>> type(phi) <class 'sage.modules.free_module_morphism.FreeModuleMorphism'>
- change_ring(R)[source]¶
Change the ring over which this morphism is defined.
This changes the ring of the domain, codomain, and underlying matrix.
EXAMPLES:
sage: V0 = span([[0,0,1],[0,2,0]], ZZ); V1 = span([[1/2,0],[0,2]], ZZ) sage: W = span([[1,0],[0,6]], ZZ) sage: h = V0.hom([-3*V1.0 - 3*V1.1, -3*V1.0 - 3*V1.1]) sage: h.base_ring() Integer Ring sage: h Free module morphism defined by the matrix [-3 -3] [-3 -3]... sage: h.change_ring(QQ).base_ring() Rational Field sage: f = h.change_ring(QQ); f Vector space morphism represented by the matrix: [-3 -3] [-3 -3] Domain: Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [0 1 0] [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Rational Field Basis matrix: [1 0] [0 1] sage: f = h.change_ring(GF(7)); f Vector space morphism represented by the matrix: [4 4] [4 4] Domain: Vector space of degree 3 and dimension 2 over Finite Field of size 7 Basis matrix: [0 1 0] [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Finite Field of size 7 Basis matrix: [1 0] [0 1]
>>> from sage.all import * >>> V0 = span([[Integer(0),Integer(0),Integer(1)],[Integer(0),Integer(2),Integer(0)]], ZZ); V1 = span([[Integer(1)/Integer(2),Integer(0)],[Integer(0),Integer(2)]], ZZ) >>> W = span([[Integer(1),Integer(0)],[Integer(0),Integer(6)]], ZZ) >>> h = V0.hom([-Integer(3)*V1.gen(0) - Integer(3)*V1.gen(1), -Integer(3)*V1.gen(0) - Integer(3)*V1.gen(1)]) >>> h.base_ring() Integer Ring >>> h Free module morphism defined by the matrix [-3 -3] [-3 -3]... >>> h.change_ring(QQ).base_ring() Rational Field >>> f = h.change_ring(QQ); f Vector space morphism represented by the matrix: [-3 -3] [-3 -3] Domain: Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [0 1 0] [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Rational Field Basis matrix: [1 0] [0 1] >>> f = h.change_ring(GF(Integer(7))); f Vector space morphism represented by the matrix: [4 4] [4 4] Domain: Vector space of degree 3 and dimension 2 over Finite Field of size 7 Basis matrix: [0 1 0] [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Finite Field of size 7 Basis matrix: [1 0] [0 1]
- eigenspaces(extend=True)[source]¶
Compute a list of subspaces formed by eigenvectors of
self
.INPUT:
extend
– boolean (default:True
); determines if field extensions should be considered
OUTPUT: a list of pairs
(eigenvalue, eigenspace)
EXAMPLES:
sage: V = QQ^3 sage: h = V.hom([[1,0,0], [0,0,1], [0,-1,0]], V) sage: h.eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [1 0 0]), (-1*I, Vector space of degree 3 and dimension 1 over Algebraic Field Basis matrix: [ 0 1 1*I]), (1*I, Vector space of degree 3 and dimension 1 over Algebraic Field Basis matrix: [ 0 1 -1*I])] sage: h.eigenspaces(extend=False) # needs sage.rings.number_field [(1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [1 0 0])] sage: h = V.hom([[2,1,0], [0,2,0], [0,0,-1]], V) sage: h.eigenspaces() # needs sage.rings.number_field [(-1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [0 0 1]), (2, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [0 1 0])] sage: h = V.hom([[2,1,0], [0,2,0], [0,0,2]], V) sage: h.eigenspaces() # needs sage.rings.number_field [(2, Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [0 1 0] [0 0 1])]
>>> from sage.all import * >>> V = QQ**Integer(3) >>> h = V.hom([[Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(1)], [Integer(0),-Integer(1),Integer(0)]], V) >>> h.eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [1 0 0]), (-1*I, Vector space of degree 3 and dimension 1 over Algebraic Field Basis matrix: [ 0 1 1*I]), (1*I, Vector space of degree 3 and dimension 1 over Algebraic Field Basis matrix: [ 0 1 -1*I])] >>> h.eigenspaces(extend=False) # needs sage.rings.number_field [(1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [1 0 0])] >>> h = V.hom([[Integer(2),Integer(1),Integer(0)], [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),-Integer(1)]], V) >>> h.eigenspaces() # needs sage.rings.number_field [(-1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [0 0 1]), (2, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [0 1 0])] >>> h = V.hom([[Integer(2),Integer(1),Integer(0)], [Integer(0),Integer(2),Integer(0)], [Integer(0),Integer(0),Integer(2)]], V) >>> h.eigenspaces() # needs sage.rings.number_field [(2, Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [0 1 0] [0 0 1])]
sage: V = QQ^2; m = matrix(2, [1, 1, 0, 1]) sage: V.hom(m, side='right').eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [1 0])] sage: V.hom(m).eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [0 1])]
>>> from sage.all import * >>> V = QQ**Integer(2); m = matrix(Integer(2), [Integer(1), Integer(1), Integer(0), Integer(1)]) >>> V.hom(m, side='right').eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [1 0])] >>> V.hom(m).eigenspaces() # needs sage.rings.number_field [(1, Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [0 1])]
- eigenvalues(extend=True)[source]¶
Return a list with the eigenvalues of the endomorphism of vector spaces.
INPUT:
extend
– boolean (default:True
); decides if base field extensions should be considered or not
EXAMPLES:
We compute the eigenvalues of an endomorphism of \(\QQ^3\):
sage: V = QQ^3 sage: H = V.endomorphism_ring()([[1,-1,0], [-1,1,1], [0,3,1]]) sage: H.eigenvalues() # needs sage.rings.number_field [3, 1, -1]
>>> from sage.all import * >>> V = QQ**Integer(3) >>> H = V.endomorphism_ring()([[Integer(1),-Integer(1),Integer(0)], [-Integer(1),Integer(1),Integer(1)], [Integer(0),Integer(3),Integer(1)]]) >>> H.eigenvalues() # needs sage.rings.number_field [3, 1, -1]
Note the effect of the
extend
option:sage: V = QQ^2 sage: H = V.endomorphism_ring()([[0,-1], [1,0]]) sage: H.eigenvalues() # needs sage.rings.number_field [-1*I, 1*I] sage: H.eigenvalues(extend=False) # needs sage.libs.pari []
>>> from sage.all import * >>> V = QQ**Integer(2) >>> H = V.endomorphism_ring()([[Integer(0),-Integer(1)], [Integer(1),Integer(0)]]) >>> H.eigenvalues() # needs sage.rings.number_field [-1*I, 1*I] >>> H.eigenvalues(extend=False) # needs sage.libs.pari []
- eigenvectors(extend=True)[source]¶
Compute the subspace of eigenvectors of a given eigenvalue.
INPUT:
extend
– boolean (default:True
); decides if base field extensions should be considered or not
OUTPUT:
A sequence of tuples. Each tuple contains an eigenvalue, a sequence with a basis of the corresponding subspace of eigenvectors, and the algebraic multiplicity of the eigenvalue.
EXAMPLES:
sage: # needs sage.rings.number_field sage: V = (QQ^4).subspace([[0,2,1,4], [1,2,5,0], [1,1,1,1]]) sage: H = (V.Hom(V))(matrix(QQ, [[0,1,0], [-1,0,0], [0,0,3]])) sage: H.eigenvectors() [(3, [ (0, 0, 1, -6/7) ], 1), (-1*I, [ (1, 1*I, 0, -0.571428571428572? + 2.428571428571429?*I) ], 1), (1*I, [ (1, -1*I, 0, -0.571428571428572? - 2.428571428571429?*I) ], 1)] sage: H.eigenvectors(extend=False) [(3, [ (0, 0, 1, -6/7) ], 1)] sage: H1 = (V.Hom(V))(matrix(QQ, [[2,1,0],[0,2,0],[0,0,3]])) sage: H1.eigenvectors() [(3, [ (0, 0, 1, -6/7) ], 1), (2, [ (0, 1, 0, 17/7) ], 2)] sage: H1.eigenvectors(extend=False) [(3, [ (0, 0, 1, -6/7) ], 1), (2, [ (0, 1, 0, 17/7) ], 2)]
>>> from sage.all import * >>> # needs sage.rings.number_field >>> V = (QQ**Integer(4)).subspace([[Integer(0),Integer(2),Integer(1),Integer(4)], [Integer(1),Integer(2),Integer(5),Integer(0)], [Integer(1),Integer(1),Integer(1),Integer(1)]]) >>> H = (V.Hom(V))(matrix(QQ, [[Integer(0),Integer(1),Integer(0)], [-Integer(1),Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(3)]])) >>> H.eigenvectors() [(3, [ (0, 0, 1, -6/7) ], 1), (-1*I, [ (1, 1*I, 0, -0.571428571428572? + 2.428571428571429?*I) ], 1), (1*I, [ (1, -1*I, 0, -0.571428571428572? - 2.428571428571429?*I) ], 1)] >>> H.eigenvectors(extend=False) [(3, [ (0, 0, 1, -6/7) ], 1)] >>> H1 = (V.Hom(V))(matrix(QQ, [[Integer(2),Integer(1),Integer(0)],[Integer(0),Integer(2),Integer(0)],[Integer(0),Integer(0),Integer(3)]])) >>> H1.eigenvectors() [(3, [ (0, 0, 1, -6/7) ], 1), (2, [ (0, 1, 0, 17/7) ], 2)] >>> H1.eigenvectors(extend=False) [(3, [ (0, 0, 1, -6/7) ], 1), (2, [ (0, 1, 0, 17/7) ], 2)]
sage: V = QQ^2 sage: m = matrix(2, [1, 1, 0, 1]) sage: V.hom(m, side='right').eigenvectors() # needs sage.rings.number_field [(1, [ (1, 0) ], 2)] sage: V.hom(m).eigenvectors() # needs sage.rings.number_field [(1, [ (0, 1) ], 2)]
>>> from sage.all import * >>> V = QQ**Integer(2) >>> m = matrix(Integer(2), [Integer(1), Integer(1), Integer(0), Integer(1)]) >>> V.hom(m, side='right').eigenvectors() # needs sage.rings.number_field [(1, [ (1, 0) ], 2)] >>> V.hom(m).eigenvectors() # needs sage.rings.number_field [(1, [ (0, 1) ], 2)]
- inverse_image(V)[source]¶
Given a submodule V of the codomain of self, return the inverse image of V under self, i.e., the biggest submodule of the domain of
self
that maps into V.EXAMPLES:
We test computing inverse images over a field:
sage: V = QQ^3; W = span([[1,2,3], [-1,2,5/3]], QQ) sage: phi = V.hom(matrix(QQ, 3, [1..9])) sage: phi.rank() 2 sage: I = phi.inverse_image(W); I Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 0] [ 0 1 -1/2] sage: phi(I.0) in W True sage: phi(I.1) in W True sage: W = phi.image() sage: phi.inverse_image(W) == V True
>>> from sage.all import * >>> V = QQ**Integer(3); W = span([[Integer(1),Integer(2),Integer(3)], [-Integer(1),Integer(2),Integer(5)/Integer(3)]], QQ) >>> phi = V.hom(matrix(QQ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9))))) >>> phi.rank() 2 >>> I = phi.inverse_image(W); I Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 0] [ 0 1 -1/2] >>> phi(I.gen(0)) in W True >>> phi(I.gen(1)) in W True >>> W = phi.image() >>> phi.inverse_image(W) == V True
We test computing inverse images between two spaces embedded in different ambient spaces.:
sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ) sage: W = span([[1,0],[0,6]],ZZ) sage: h = V0.hom([-3*V1.0 - 3*V1.1, -3*V1.0 - 3*V1.1]) sage: h.inverse_image(W) Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [0 2 1] [0 0 2] sage: h(h.inverse_image(W)).is_submodule(W) True sage: h(h.inverse_image(W)).index_in(W) +Infinity sage: h(h.inverse_image(W)) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [ 3 12]
>>> from sage.all import * >>> V0 = span([[Integer(0),Integer(0),Integer(1)],[Integer(0),Integer(2),Integer(0)]],ZZ); V1 = span([[Integer(1)/Integer(2),Integer(0)],[Integer(0),Integer(2)]],ZZ) >>> W = span([[Integer(1),Integer(0)],[Integer(0),Integer(6)]],ZZ) >>> h = V0.hom([-Integer(3)*V1.gen(0) - Integer(3)*V1.gen(1), -Integer(3)*V1.gen(0) - Integer(3)*V1.gen(1)]) >>> h.inverse_image(W) Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [0 2 1] [0 0 2] >>> h(h.inverse_image(W)).is_submodule(W) True >>> h(h.inverse_image(W)).index_in(W) +Infinity >>> h(h.inverse_image(W)) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [ 3 12]
We test computing inverse images over the integers:
sage: V = QQ^3; W = V.span_of_basis([[2,2,3],[-1,2,5/3]], ZZ) sage: phi = W.hom([W.0, W.0 - W.1]) sage: Z = W.span([2*W.1]); Z Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 2 -4 -10/3] sage: Y = phi.inverse_image(Z); Y Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 6 0 8/3] sage: phi(Y) == Z True
>>> from sage.all import * >>> V = QQ**Integer(3); W = V.span_of_basis([[Integer(2),Integer(2),Integer(3)],[-Integer(1),Integer(2),Integer(5)/Integer(3)]], ZZ) >>> phi = W.hom([W.gen(0), W.gen(0) - W.gen(1)]) >>> Z = W.span([Integer(2)*W.gen(1)]); Z Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 2 -4 -10/3] >>> Y = phi.inverse_image(Z); Y Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 6 0 8/3] >>> phi(Y) == Z True
We test that Issue #24590 is resolved:
sage: A = FreeQuadraticModule(ZZ, 1, matrix([2])) sage: f = A.Hom(A).an_element() sage: f.inverse_image(A) Free module of degree 1 and rank 1 over Integer Ring Echelon basis matrix: [1]
>>> from sage.all import * >>> A = FreeQuadraticModule(ZZ, Integer(1), matrix([Integer(2)])) >>> f = A.Hom(A).an_element() >>> f.inverse_image(A) Free module of degree 1 and rank 1 over Integer Ring Echelon basis matrix: [1]
We test that it respects the
side
:sage: V = ZZ^2 sage: m = matrix(2, [1, 1, 0, 1]) sage: h = V.hom(m, side='right') sage: h Free module morphism defined as left-multiplication by the matrix [1 1] [0 1]... sage: SV = V.span([V.0]) sage: h.inverse_image(SV) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [1 0] sage: V.hom(m).inverse_image(SV) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [ 1 -1]
>>> from sage.all import * >>> V = ZZ**Integer(2) >>> m = matrix(Integer(2), [Integer(1), Integer(1), Integer(0), Integer(1)]) >>> h = V.hom(m, side='right') >>> h Free module morphism defined as left-multiplication by the matrix [1 1] [0 1]... >>> SV = V.span([V.gen(0)]) >>> h.inverse_image(SV) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [1 0] >>> V.hom(m).inverse_image(SV) Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: [ 1 -1]
- lift(x)[source]¶
Given an element of the image, return an element of the codomain that maps onto it.
Note that
lift
andpreimage_representative
are equivalent names for this method, with the latter suggesting that the return value is a coset representative of the domain modulo the kernel of the morphism.EXAMPLES:
sage: X = QQ**2 sage: V = X.span([[2, 0], [0, 8]], ZZ) sage: W = (QQ**1).span([[1/12]], ZZ) sage: f = V.hom([W([1/3]), W([1/2])], W) sage: l=f.lift([1/3]); l # random (8, -16) sage: f(l) (1/3) sage: f(f.lift([1/2])) (1/2) sage: f(f.lift([1/6])) (1/6) sage: f.lift([1/12]) Traceback (most recent call last): ... ValueError: element is not in the image sage: f.lift([1/24]) Traceback (most recent call last): ... TypeError: element [1/24] is not in free module
>>> from sage.all import * >>> X = QQ**Integer(2) >>> V = X.span([[Integer(2), Integer(0)], [Integer(0), Integer(8)]], ZZ) >>> W = (QQ**Integer(1)).span([[Integer(1)/Integer(12)]], ZZ) >>> f = V.hom([W([Integer(1)/Integer(3)]), W([Integer(1)/Integer(2)])], W) >>> l=f.lift([Integer(1)/Integer(3)]); l # random (8, -16) >>> f(l) (1/3) >>> f(f.lift([Integer(1)/Integer(2)])) (1/2) >>> f(f.lift([Integer(1)/Integer(6)])) (1/6) >>> f.lift([Integer(1)/Integer(12)]) Traceback (most recent call last): ... ValueError: element is not in the image >>> f.lift([Integer(1)/Integer(24)]) Traceback (most recent call last): ... TypeError: element [1/24] is not in free module
This works for vector spaces, too:
sage: V = VectorSpace(GF(3), 2) sage: W = VectorSpace(GF(3), 3) sage: f = V.hom([W.1, W.1 - W.0]) sage: f.lift(W.1) (1, 0) sage: f.lift(W.2) Traceback (most recent call last): ... ValueError: element is not in the image sage: w = W((17, -2, 0)) sage: f(f.lift(w)) == w True
>>> from sage.all import * >>> V = VectorSpace(GF(Integer(3)), Integer(2)) >>> W = VectorSpace(GF(Integer(3)), Integer(3)) >>> f = V.hom([W.gen(1), W.gen(1) - W.gen(0)]) >>> f.lift(W.gen(1)) (1, 0) >>> f.lift(W.gen(2)) Traceback (most recent call last): ... ValueError: element is not in the image >>> w = W((Integer(17), -Integer(2), Integer(0))) >>> f(f.lift(w)) == w True
This example illustrates the use of the
preimage_representative
as an equivalent name for this method.sage: V = ZZ^3 sage: W = ZZ^2 sage: w = vector(ZZ, [1,2]) sage: f = V.hom([w, w, w], W) sage: f.preimage_representative(vector(ZZ, [10, 20])) (0, 0, 10)
>>> from sage.all import * >>> V = ZZ**Integer(3) >>> W = ZZ**Integer(2) >>> w = vector(ZZ, [Integer(1),Integer(2)]) >>> f = V.hom([w, w, w], W) >>> f.preimage_representative(vector(ZZ, [Integer(10), Integer(20)])) (0, 0, 10)
sage: V = QQ^2; m = matrix(2, [1, 1, 0, 1]) sage: V.hom(m, side='right').lift(V.0 + V.1) (0, 1) sage: V.hom(m).lift(V.0 + V.1) (1, 0)
>>> from sage.all import * >>> V = QQ**Integer(2); m = matrix(Integer(2), [Integer(1), Integer(1), Integer(0), Integer(1)]) >>> V.hom(m, side='right').lift(V.gen(0) + V.gen(1)) (0, 1) >>> V.hom(m).lift(V.gen(0) + V.gen(1)) (1, 0)
- preimage_representative(x)[source]¶
Given an element of the image, return an element of the codomain that maps onto it.
Note that
lift
andpreimage_representative
are equivalent names for this method, with the latter suggesting that the return value is a coset representative of the domain modulo the kernel of the morphism.EXAMPLES:
sage: X = QQ**2 sage: V = X.span([[2, 0], [0, 8]], ZZ) sage: W = (QQ**1).span([[1/12]], ZZ) sage: f = V.hom([W([1/3]), W([1/2])], W) sage: l=f.lift([1/3]); l # random (8, -16) sage: f(l) (1/3) sage: f(f.lift([1/2])) (1/2) sage: f(f.lift([1/6])) (1/6) sage: f.lift([1/12]) Traceback (most recent call last): ... ValueError: element is not in the image sage: f.lift([1/24]) Traceback (most recent call last): ... TypeError: element [1/24] is not in free module
>>> from sage.all import * >>> X = QQ**Integer(2) >>> V = X.span([[Integer(2), Integer(0)], [Integer(0), Integer(8)]], ZZ) >>> W = (QQ**Integer(1)).span([[Integer(1)/Integer(12)]], ZZ) >>> f = V.hom([W([Integer(1)/Integer(3)]), W([Integer(1)/Integer(2)])], W) >>> l=f.lift([Integer(1)/Integer(3)]); l # random (8, -16) >>> f(l) (1/3) >>> f(f.lift([Integer(1)/Integer(2)])) (1/2) >>> f(f.lift([Integer(1)/Integer(6)])) (1/6) >>> f.lift([Integer(1)/Integer(12)]) Traceback (most recent call last): ... ValueError: element is not in the image >>> f.lift([Integer(1)/Integer(24)]) Traceback (most recent call last): ... TypeError: element [1/24] is not in free module
This works for vector spaces, too:
sage: V = VectorSpace(GF(3), 2) sage: W = VectorSpace(GF(3), 3) sage: f = V.hom([W.1, W.1 - W.0]) sage: f.lift(W.1) (1, 0) sage: f.lift(W.2) Traceback (most recent call last): ... ValueError: element is not in the image sage: w = W((17, -2, 0)) sage: f(f.lift(w)) == w True
>>> from sage.all import * >>> V = VectorSpace(GF(Integer(3)), Integer(2)) >>> W = VectorSpace(GF(Integer(3)), Integer(3)) >>> f = V.hom([W.gen(1), W.gen(1) - W.gen(0)]) >>> f.lift(W.gen(1)) (1, 0) >>> f.lift(W.gen(2)) Traceback (most recent call last): ... ValueError: element is not in the image >>> w = W((Integer(17), -Integer(2), Integer(0))) >>> f(f.lift(w)) == w True
This example illustrates the use of the
preimage_representative
as an equivalent name for this method.sage: V = ZZ^3 sage: W = ZZ^2 sage: w = vector(ZZ, [1,2]) sage: f = V.hom([w, w, w], W) sage: f.preimage_representative(vector(ZZ, [10, 20])) (0, 0, 10)
>>> from sage.all import * >>> V = ZZ**Integer(3) >>> W = ZZ**Integer(2) >>> w = vector(ZZ, [Integer(1),Integer(2)]) >>> f = V.hom([w, w, w], W) >>> f.preimage_representative(vector(ZZ, [Integer(10), Integer(20)])) (0, 0, 10)
sage: V = QQ^2; m = matrix(2, [1, 1, 0, 1]) sage: V.hom(m, side='right').lift(V.0 + V.1) (0, 1) sage: V.hom(m).lift(V.0 + V.1) (1, 0)
>>> from sage.all import * >>> V = QQ**Integer(2); m = matrix(Integer(2), [Integer(1), Integer(1), Integer(0), Integer(1)]) >>> V.hom(m, side='right').lift(V.gen(0) + V.gen(1)) (0, 1) >>> V.hom(m).lift(V.gen(0) + V.gen(1)) (1, 0)
- pushforward(x)[source]¶
Compute the image of a sub-module of the domain.
EXAMPLES:
sage: V = QQ^3; W = span([[1,2,3], [-1,2,5/3]], QQ) sage: phi = V.hom(matrix(QQ, 3, [1..9])) sage: phi.rank() 2 sage: phi(V) #indirect doctest Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 -1] [ 0 1 2]
>>> from sage.all import * >>> V = QQ**Integer(3); W = span([[Integer(1),Integer(2),Integer(3)], [-Integer(1),Integer(2),Integer(5)/Integer(3)]], QQ) >>> phi = V.hom(matrix(QQ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9))))) >>> phi.rank() 2 >>> phi(V) #indirect doctest Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 -1] [ 0 1 2]
We compute the image of a submodule of a ZZ-module embedded in a rational vector space:
sage: V = QQ^3; W = V.span_of_basis([[2,2,3], [-1,2,5/3]], ZZ) sage: phi = W.hom([W.0, W.0 - W.1]); phi Free module morphism defined by the matrix [ 1 0] [ 1 -1]... sage: phi(span([2*W.1], ZZ)) Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 6 0 8/3] sage: phi(2*W.1) (6, 0, 8/3)
>>> from sage.all import * >>> V = QQ**Integer(3); W = V.span_of_basis([[Integer(2),Integer(2),Integer(3)], [-Integer(1),Integer(2),Integer(5)/Integer(3)]], ZZ) >>> phi = W.hom([W.gen(0), W.gen(0) - W.gen(1)]); phi Free module morphism defined by the matrix [ 1 0] [ 1 -1]... >>> phi(span([Integer(2)*W.gen(1)], ZZ)) Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [ 6 0 8/3] >>> phi(Integer(2)*W.gen(1)) (6, 0, 8/3)
- sage.modules.free_module_morphism.is_FreeModuleMorphism(x)[source]¶
This function is deprecated.
EXAMPLES:
sage: V = ZZ^2; f = V.hom([V.1, -2*V.0]) sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(f) doctest:warning... DeprecationWarning: is_FreeModuleMorphism is deprecated; use isinstance(..., FreeModuleMorphism) or categories instead See https://github.com/sagemath/sage/issues/37731 for details. True sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(0) False
>>> from sage.all import * >>> V = ZZ**Integer(2); f = V.hom([V.gen(1), -Integer(2)*V.gen(0)]) >>> sage.modules.free_module_morphism.is_FreeModuleMorphism(f) doctest:warning... DeprecationWarning: is_FreeModuleMorphism is deprecated; use isinstance(..., FreeModuleMorphism) or categories instead See https://github.com/sagemath/sage/issues/37731 for details. True >>> sage.modules.free_module_morphism.is_FreeModuleMorphism(Integer(0)) False