Free quadratic modules¶
Sage supports computation with free quadratic modules over an arbitrary commutative ring. Nontrivial functionality is available over \(\ZZ\) and fields. All free modules over an integral domain are equipped with an embedding in an ambient vector space and an inner product, which you can specify and change.
Create the free module of rank \(n\) over an arbitrary commutative ring \(R\)
using the command FreeModule(R,n)
with a given inner_product_matrix.
The following example illustrates the creation of both a vector spaces
and a free module over the integers and a submodule of it. Use the functions
FreeModule
, span
and member functions of free modules
to create free modules. ‘’Do not use the FreeModule_xxx
constructors
directly.’‘
EXAMPLES:
sage: M = Matrix(QQ,[[2,1,0],[1,2,1],[0,1,2]])
sage: V = VectorSpace(QQ,3,inner_product_matrix=M)
sage: type(V)
<class 'sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_field_with_category'>
sage: V.inner_product_matrix()
[2 1 0]
[1 2 1]
[0 1 2]
sage: W = V.subspace([[1,2,7], [1,1,0]])
sage: type(W)
<class 'sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_field_with_category'>
sage: W
Quadratic space of degree 3 and dimension 2 over Rational Field
Basis matrix:
[ 1 0 -7]
[ 0 1 7]
Inner product matrix:
[2 1 0]
[1 2 1]
[0 1 2]
sage: W.gram_matrix()
[ 100 -104]
[-104 114]
AUTHORS:
David Kohel (2008-06): First created (based on free_module.py)
-
sage.modules.free_quadratic_module.
FreeQuadraticModule
(base_ring, rank, inner_product_matrix, sparse=False, inner_product_ring=None)¶ Create the free quadratic module over the given commutative ring of the given rank.
INPUT:
base_ring – a commutative ring
rank – a nonnegative integer
inner_product_matrix – the inner product matrix
sparse – bool; (default False)
inner_product_ring – the inner product codomain ring; (default None)
OUTPUT:
A free quadratic module (with given inner product matrix).
Note
In Sage it is the case that there is only one dense and one sparse free ambient quadratic module of rank \(n\) over \(R\) and given inner product matrix.
EXAMPLES:
sage: M2 = FreeQuadraticModule(ZZ,2,inner_product_matrix=[1,2,3,4]) sage: M2 is FreeQuadraticModule(ZZ,2,inner_product_matrix=[1,2,3,4]) True sage: M2.inner_product_matrix() [1 2] [3 4] sage: M3 = FreeModule(ZZ,2,inner_product_matrix=[[1,2],[3,4]]) sage: M3 is M2 True
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_ambient
(base_ring, rank, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_ambient
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic
Ambient free module over a commutative ring.
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_ambient_domain
(base_ring, rank, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_ambient_domain
,sage.modules.free_quadratic_module.FreeQuadraticModule_ambient
Ambient free quadratic module over an integral domain.
-
ambient_vector_space
()¶ Returns the ambient vector space, which is this free module tensored with its fraction field.
EXAMPLES:
sage: M = ZZ^3; M.ambient_vector_space() Vector space of dimension 3 over Rational Field
-
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_ambient_field
(base_field, dimension, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_ambient_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_pid
Create the ambient vector space of given dimension over the given field.
INPUT:
base_field – a field
dimension – a non-negative integer
sparse – bool (default: False)
EXAMPLES:
sage: VectorSpace(QQ,3,inner_product_matrix=[[2,1,0],[1,2,0],[0,1,2]]) Ambient quadratic space of dimension 3 over Rational Field Inner product matrix: [2 1 0] [1 2 0] [0 1 2]
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_ambient_pid
(base_ring, rank, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_ambient_pid
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic_pid
,sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_domain
Ambient free quadratic module over a principal ideal domain.
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_generic
(base_ring, rank, degree, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_generic
Base class for all free quadratic modules.
Modules are ordered by inclusion in the same ambient space.
-
ambient_module
()¶ Return the ambient module associated to this module.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: M = FreeModule(R,2) sage: M.ambient_module() Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field sage: V = FreeModule(QQ, 4).span([[1,2,3,4], [1,0,0,0]]); V Vector space of degree 4 and dimension 2 over Rational Field Basis matrix: [ 1 0 0 0] [ 0 1 3/2 2] sage: V.ambient_module() Vector space of dimension 4 over Rational Field
-
determinant
()¶ Return the determinant of this free module.
EXAMPLES:
sage: M = FreeModule(ZZ, 3, inner_product_matrix=1) sage: M.determinant() 1 sage: N = M.span([[1,2,3]]) sage: N.determinant() 14 sage: P = M.span([[1,2,3], [1,1,1]]) sage: P.determinant() 6
-
discriminant
()¶ Return the discriminant of this free module, defined to be (-1)^r of the determinant, where r = n/2 (n even) or (n-1)/2 (n odd) for a module of rank n.
EXAMPLES:
sage: M = FreeModule(ZZ, 3) sage: M.discriminant() 1 sage: N = M.span([[1,2,3]]) sage: N.discriminant() 14 sage: P = M.span([[1,2,3], [1,1,1]]) sage: P.discriminant() 6
-
gram_matrix
()¶ Return the gram matrix associated to this free module, defined to be G = B*A*B.transpose(), where A is the inner product matrix (induced from the ambient space), and B the basis matrix.
EXAMPLES:
sage: V = VectorSpace(QQ,4) sage: u = V([1/2,1/2,1/2,1/2]) sage: v = V([0,1,1,0]) sage: w = V([0,0,1,1]) sage: M = span([u,v,w], ZZ) sage: M.inner_product_matrix() == V.inner_product_matrix() True sage: L = M.submodule_with_basis([u,v,w]) sage: L.inner_product_matrix() == M.inner_product_matrix() True sage: L.gram_matrix() [1 1 1] [1 2 1] [1 1 2]
-
inner_product_matrix
()¶ Return the inner product matrix associated to this module. By definition this is the inner product matrix of the ambient space, hence may be of degree greater than the rank of the module.
N.B. The inner product does not have to be symmetric (see examples).
TODO: Differentiate the image ring of the inner product from the base ring of the module and/or ambient space. E.g. On an integral module over ZZ the inner product pairing could naturally take values in ZZ, QQ, RR, or CC.
EXAMPLES:
sage: M = FreeModule(ZZ, 3) sage: M.inner_product_matrix() [1 0 0] [0 1 0] [0 0 1]
The inner product does not have to be symmetric or definite:
sage: N = FreeModule(ZZ,2,inner_product_matrix=[[1,-1],[2,5]]) sage: N.inner_product_matrix() [ 1 -1] [ 2 5] sage: u, v = N.basis() sage: u.inner_product(v) -1 sage: v.inner_product(u) 2
The inner product matrix is defined with respect to the ambient space.
sage: V = QQ^3 sage: u = V([1/2,1,1]) sage: v = V([1,1,1/2]) sage: M = span([u,v], ZZ) sage: M.inner_product_matrix() [1 0 0] [0 1 0] [0 0 1] sage: M.inner_product_matrix() == V.inner_product_matrix() True sage: M.gram_matrix() [ 1/2 -3/4] [-3/4 13/4]
-
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_generic_field
(base_field, dimension, degree, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_generic_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic_pid
Base class for all free modules over fields.
-
span
(gens, check=True, already_echelonized=False)¶ Return the K-span of the given list of gens, where K is the base field of self. Note that this span is a subspace of the ambient vector space, but need not be a subspace of self.
INPUT:
gens – list of vectors
check – bool (default: True): whether or not to coerce entries of gens into base field
already_echelonized – bool (default: False): set this if you know the gens are already in echelon form
EXAMPLES:
sage: V = VectorSpace(GF(7), 3) sage: W = V.subspace([[2,3,4]]); W Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 5 2] sage: W.span([[1,1,1]]) Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 1 1]
-
span_of_basis
(basis, check=True, already_echelonized=False)¶ Return the free K-module with the given basis, where K is the base field of self. Note that this span is a subspace of the ambient vector space, but need not be a subspace of self.
INPUT:
basis – list of vectors
check – bool (default: True): whether or not to coerce entries of gens into base field
already_echelonized – bool (default: False): set this if you know the gens are already in echelon form
EXAMPLES:
sage: V = VectorSpace(GF(7), 3) sage: W = V.subspace([[2,3,4]]); W Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 5 2] sage: W.span_of_basis([[2,2,2], [3,3,0]]) Vector space of degree 3 and dimension 2 over Finite Field of size 7 User basis matrix: [2 2 2] [3 3 0]
The basis vectors must be linearly independent or a
ValueError
exception is raised:sage: W.span_of_basis([[2,2,2], [3,3,3]]) Traceback (most recent call last): ... ValueError: The given basis vectors must be linearly independent.
-
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_generic_pid
(base_ring, rank, degree, inner_product_matrix, sparse=False)¶ Bases:
sage.modules.free_module.FreeModule_generic_pid
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic
Class of all free modules over a PID.
-
span
(gens, check=True, already_echelonized=False)¶ Return the R-span of the given list of gens, where R is the base ring of self. Note that this span need not be a submodule of self, nor even of the ambient space. It must, however, be contained in the ambient vector space, i.e., the ambient space tensored with the fraction field of R.
EXAMPLES:
sage: V = FreeModule(ZZ,3) sage: W = V.submodule([V.gen(0)]) sage: W.span([V.gen(1)]) Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [0 1 0] sage: W.submodule([V.gen(1)]) Traceback (most recent call last): ... ArithmeticError: Argument gens (= [(0, 1, 0)]) does not generate a submodule of self.
-
span_of_basis
(basis, check=True, already_echelonized=False)¶ Return the free R-module with the given basis, where R is the base ring of self. Note that this R-module need not be a submodule of self, nor even of the ambient space. It must, however, be contained in the ambient vector space, i.e., the ambient space tensored with the fraction field of R.
EXAMPLES:
sage: M = FreeModule(ZZ,3) sage: W = M.span_of_basis([M([1,2,3])])
Next we create two free \(\ZZ\)-modules, neither of which is a submodule of \(W\):
sage: W.span_of_basis([M([2,4,0])]) Free module of degree 3 and rank 1 over Integer Ring User basis matrix: [2 4 0]
The following module is not even in the ambient space:
sage: Q = QQ sage: W.span_of_basis([ Q('1/5')*M([1,2,0]), Q('1/7')*M([1,1,0]) ]) Free module of degree 3 and rank 2 over Integer Ring User basis matrix: [1/5 2/5 0] [1/7 1/7 0]
Of course the input basis vectors must be linearly independent:
sage: W.span_of_basis([ [1,2,0], [2,4,0] ]) Traceback (most recent call last): ... ValueError: The given basis vectors must be linearly independent.
-
zero_submodule
()¶ Return the zero submodule of this module.
EXAMPLES:
sage: V = FreeModule(ZZ,2) sage: V.zero_submodule() Free module of degree 2 and rank 0 over Integer Ring Echelon basis matrix: []
-
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_submodule_field
(ambient, gens, inner_product_matrix, check=True, already_echelonized=False)¶ Bases:
sage.modules.free_module.FreeModule_submodule_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_with_basis_field
An embedded vector subspace with echelonized basis.
EXAMPLES:
Since this is an embedded vector subspace with echelonized basis, the echelon_coordinates() and user coordinates() agree:
sage: V = QQ^3 sage: W = V.span([[1,2,3],[4,5,6]]) sage: W Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 -1] [ 0 1 2] sage: v = V([1,5,9]) sage: W.echelon_coordinates(v) [1, 5] sage: vector(QQ, W.echelon_coordinates(v)) * W.basis_matrix() (1, 5, 9) sage: v = V([1,5,9]) sage: W.coordinates(v) [1, 5] sage: vector(QQ, W.coordinates(v)) * W.basis_matrix() (1, 5, 9)
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_submodule_pid
(ambient, gens, inner_product_matrix, check=True, already_echelonized=False)¶ Bases:
sage.modules.free_module.FreeModule_submodule_pid
,sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_with_basis_pid
An \(R\)-submodule of \(K^n\) where \(K\) is the fraction field of a principal ideal domain \(R\).
EXAMPLES:
sage: M = ZZ^3 sage: W = M.span_of_basis([[1,2,3],[4,5,19]]); W Free module of degree 3 and rank 2 over Integer Ring User basis matrix: [ 1 2 3] [ 4 5 19]
We can save and load submodules and elements:
sage: loads(W.dumps()) == W True sage: v = W.0 + W.1 sage: loads(v.dumps()) == v True
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_submodule_with_basis_field
(ambient, basis, inner_product_matrix, check=True, echelonize=False, echelonized_basis=None, already_echelonized=False)¶ Bases:
sage.modules.free_module.FreeModule_submodule_with_basis_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic_field
,sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_with_basis_pid
An embedded vector subspace with a distinguished user basis.
EXAMPLES:
sage: M = QQ^3; W = M.submodule_with_basis([[1,2,3], [4,5,19]]); W Vector space of degree 3 and dimension 2 over Rational Field User basis matrix: [ 1 2 3] [ 4 5 19]
Since this is an embedded vector subspace with a distinguished user basis possibly different than the echelonized basis, the
echelon_coordinates()
and usercoordinates()
do not agree:sage: V = QQ^3 sage: W = V.submodule_with_basis([[1,2,3], [4,5,6]]) sage: W Vector space of degree 3 and dimension 2 over Rational Field User basis matrix: [1 2 3] [4 5 6] sage: v = V([1,5,9]) sage: W.echelon_coordinates(v) [1, 5] sage: vector(QQ, W.echelon_coordinates(v)) * W.echelonized_basis_matrix() (1, 5, 9) sage: v = V([1,5,9]) sage: W.coordinates(v) [5, -1] sage: vector(QQ, W.coordinates(v)) * W.basis_matrix() (1, 5, 9)
We can load and save submodules:
sage: loads(W.dumps()) == W True sage: K.<x> = FractionField(PolynomialRing(QQ,'x')) sage: M = K^3; W = M.span_of_basis([[1,1,x]]) sage: loads(W.dumps()) == W True
-
class
sage.modules.free_quadratic_module.
FreeQuadraticModule_submodule_with_basis_pid
(ambient, basis, inner_product_matrix, check=True, echelonize=False, echelonized_basis=None, already_echelonized=False)¶ Bases:
sage.modules.free_module.FreeModule_submodule_with_basis_pid
,sage.modules.free_quadratic_module.FreeQuadraticModule_generic_pid
An \(R\)-submodule of \(K^n\) with distinguished basis, where \(K\) is the fraction field of a principal ideal domain \(R\).
Modules are ordered by inclusion.
EXAMPLES:
First we compare two equal vector spaces:
sage: A = FreeQuadraticModule(QQ,3,2*matrix.identity(3)) sage: V = A.span([[1,2,3], [5,6,7], [8,9,10]]) sage: W = A.span([[5,6,7], [8,9,10]]) sage: V == W True
Next we compare a one dimensional space to the two dimensional space defined above:
sage: M = A.span([[5,6,7]]) sage: V == M False sage: M < V True sage: V < M False
We compare a \(\ZZ\)-module to the one-dimensional space above:
sage: V = A.span([[5,6,7]]) sage: V = V.change_ring(ZZ).scale(1/11) sage: V < M True sage: M < V False
-
change_ring
(R)¶ Return the free module over R obtained by coercing each element of self into a vector over the fraction field of R, then taking the resulting R-module. Raises a TypeError if coercion is not possible.
INPUT:
R
– a principal ideal domain
EXAMPLES:
Changing rings preserves the inner product and the user basis:
sage: V = QQ^3 sage: W = V.subspace([[2, '1/2', 1]]); W Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [ 1 1/4 1/2] sage: W.change_ring(GF(7)) Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 2 4] sage: N = FreeModule(ZZ, 2, inner_product_matrix=[[1,-1],[2,5]]) sage: N.inner_product_matrix() [ 1 -1] [ 2 5] sage: Np = N.change_ring(RDF) sage: Np.inner_product_matrix() [ 1.0 -1.0] [ 2.0 5.0]
-
-
sage.modules.free_quadratic_module.
InnerProductSpace
(K, dimension, inner_product_matrix, sparse=False)¶ EXAMPLES:
The base can be complicated, as long as it is a field:
sage: F.<x> = FractionField(PolynomialRing(ZZ,'x')) sage: D = diagonal_matrix([x,x-1,x+1]) sage: V = QuadraticSpace(F,3,D) sage: V Ambient quadratic space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x over Integer Ring Inner product matrix: [ x 0 0] [ 0 x - 1 0] [ 0 0 x + 1] sage: V.basis() [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ]
The base must be a field or a
TypeError
is raised:sage: QuadraticSpace(ZZ,5,identity_matrix(ZZ,2)) Traceback (most recent call last): ... TypeError: Argument K (= Integer Ring) must be a field.
-
sage.modules.free_quadratic_module.
QuadraticSpace
(K, dimension, inner_product_matrix, sparse=False)¶ EXAMPLES:
The base can be complicated, as long as it is a field:
sage: F.<x> = FractionField(PolynomialRing(ZZ,'x')) sage: D = diagonal_matrix([x,x-1,x+1]) sage: V = QuadraticSpace(F,3,D) sage: V Ambient quadratic space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x over Integer Ring Inner product matrix: [ x 0 0] [ 0 x - 1 0] [ 0 0 x + 1] sage: V.basis() [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ]
The base must be a field or a
TypeError
is raised:sage: QuadraticSpace(ZZ,5,identity_matrix(ZZ,2)) Traceback (most recent call last): ... TypeError: Argument K (= Integer Ring) must be a field.
-
sage.modules.free_quadratic_module.
is_FreeQuadraticModule
(M)¶ Return True if \(M\) is a free quadratic module.
EXAMPLES:
sage: from sage.modules.free_quadratic_module import is_FreeQuadraticModule sage: U = FreeModule(QQ,3) sage: is_FreeQuadraticModule(U) False sage: V = FreeModule(QQ,3,inner_product_matrix=diagonal_matrix([1,1,1])) sage: is_FreeQuadraticModule(V) True sage: W = FreeModule(QQ,3,inner_product_matrix=diagonal_matrix([2,3,3])) sage: is_FreeQuadraticModule(W) True