Path: blob/master/sage/modules/free_quadratic_module.py
4056 views
r"""1Free quadratic modules23Sage supports computation with free quadratic modules over an arbitrary4commutative ring. Nontrivial functionality is available over $\Z$ and5fields. All free modules over an integral domain are equipped with an6embedding in an ambient vector space and an inner product, which you7can specify and change.89Create the free module of rank $n$ over an arbitrary commutative ring $R$10using the command \code{FreeModule(R,n)} with a given inner_product_matrix.1112The following example illustrates the creation of both a vector spaces13and a free module over the integers and a submodule of it. Use the functions14\code{FreeModule}, \code{span} and member functions of free modules15to create free modules. \emph{Do not use the FreeModule\_xxx constructors16directly.}1718EXAMPLES:19sage: M = Matrix(QQ,[[2,1,0],[1,2,1],[0,1,2]])20sage: V = VectorSpace(QQ,3,inner_product_matrix=M)21sage: type(V)22<class 'sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_field_with_category'>23sage: V.inner_product_matrix()24[2 1 0]25[1 2 1]26[0 1 2]27sage: W = V.subspace([[1,2,7], [1,1,0]])28sage: type(W)29<class 'sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_field_with_category'>30sage: W31Quadratic space of degree 3 and dimension 2 over Rational Field32Basis matrix:33[ 1 0 -7]34[ 0 1 7]35Inner product matrix:36[2 1 0]37[1 2 1]38[0 1 2]39sage: W.gram_matrix()40[ 100 -104]41[-104 114]4243TESTS:44sage: M = Matrix(QQ,[[2,1,0],[1,2,1],[0,1,2]])45sage: V = VectorSpace(QQ,3,inner_product_matrix = M)46sage: V == loads(dumps(V))47True48sage: W = QuadraticSpace(QQ,3,M)49sage: W == V50True5152AUTHORS:53--David Kohel (2008-06): First created (based on free_module.py)54"""5556#*****************************************************************************57#58# Copyright (C) 2008 David Kohel <[email protected]>59#60# Distributed under the terms of the GNU General Public License (GPL)61#62# http://www.gnu.org/licenses/63#64# All rights granted to distribute under the GPL, version 2,65# or (at your option) any later version of the license.66#67#*****************************************************************************6869# Python imports70import weakref7172# Sage imports737475import sage.matrix.matrix_space7677import sage.misc.latex as latex7879import sage.rings.principal_ideal_domain as principal_ideal_domain80import sage.rings.field as field81import sage.rings.integral_domain as integral_domain82import sage.rings.integer83import sage.structure.parent_gens as gens848586import free_module8788###############################################################################89#90# Constructor functions91#92###############################################################################93_cache = {}9495def FreeQuadraticModule(96base_ring, rank, inner_product_matrix, sparse=False, inner_product_ring=None):97r"""98Create the free quadratic module over the given commutative ring of the given rank.99100INPUT:101base_ring -- a commutative ring102rank -- a nonnegative integer103inner_product_matrix -- the inner product matrix104sparse -- bool; (default False)105inner_product_ring -- the inner product codomain ring; (default None)106107OUTPUT:108A free quadratic module (with given inner product matrix).109110\note{In \sage it is the case that there is only one dense and one111sparse free ambient quadratic module of rank $n$ over $R$ and given112inner product matrix.}113114115EXAMPLES:116117sage: M1 = FreeQuadraticModule(ZZ,2,inner_product_matrix=1)118sage: M1 is FreeModule(ZZ,2,inner_product_matrix=1)119True120sage: M1.inner_product_matrix()121[1 0]122[0 1]123sage: M1 == ZZ^2124True125sage: M1 is ZZ^2126False127sage: M2 = FreeQuadraticModule(ZZ,2,inner_product_matrix=[1,2,3,4])128sage: M2 is FreeQuadraticModule(ZZ,2,inner_product_matrix=[1,2,3,4])129True130sage: M2.inner_product_matrix()131[1 2]132[3 4]133sage: M3 = FreeModule(ZZ,2,inner_product_matrix=[[1,2],[3,4]])134sage: M3 is M2135True136"""137global _cache138rank = int(rank)139140if inner_product_matrix is None:141raise ValueError, "An inner_product_matrix must be specified."142143# In order to use coercion into the inner_product_ring we need to pass144# this ring into the vector classes.145if inner_product_ring is not None:146raise NotImplementedError, "An inner_product_ring can not currently be defined."147148inner_product_matrix = sage.matrix.matrix_space.MatrixSpace(base_ring, rank)(inner_product_matrix)149inner_product_matrix.set_immutable()150151key = (base_ring, rank, inner_product_matrix, sparse)152153if _cache.has_key(key):154M = _cache[key]()155if not (M is None):156return M157158if not base_ring.is_commutative():159raise TypeError, "base_ring must be a commutative ring"160161#elif not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class):162# M = RealDoubleQuadraticSpace_class(rank, inner_product_matrix=inner_product_matrix, sparse=False)163164#elif not sparse and isinstance(base_ring,sage.rings.complex_double.ComplexDoubleField_class):165# M = ComplexDoubleQuadraticSpace_class(rank, inner_product_matrix=inner_product_matrix, sparse=False)166167elif base_ring.is_field():168M = FreeQuadraticModule_ambient_field(169base_ring, rank, sparse=sparse, inner_product_matrix=inner_product_matrix)170171elif isinstance(base_ring, principal_ideal_domain.PrincipalIdealDomain):172M = FreeQuadraticModule_ambient_pid(173base_ring, rank, sparse=sparse, inner_product_matrix=inner_product_matrix)174175elif isinstance(base_ring, integral_domain.IntegralDomain) or base_ring.is_integral_domain():176M = FreeQuadraticModule_ambient_domain(177base_ring, rank, sparse=sparse, inner_product_matrix=inner_product_matrix)178else:179M = FreeQuadraticModule_ambient(180base_ring, rank, sparse=sparse, inner_product_matrix=inner_product_matrix)181182_cache[key] = weakref.ref(M)183return M184185def QuadraticSpace(K, dimension, inner_product_matrix, sparse=False):186"""187EXAMPLES:188The base can be complicated, as long as it is a field.189sage: F.<x> = FractionField(PolynomialRing(ZZ,'x'))190sage: D = diagonal_matrix([x,x-1,x+1])191sage: V = QuadraticSpace(F,3,D)192sage: V193Ambient quadratic space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x over Integer Ring194Inner product matrix:195[ x 0 0]196[ 0 x - 1 0]197[ 0 0 x + 1]198sage: V.basis()199[200(1, 0, 0),201(0, 1, 0),202(0, 0, 1)203]204205The base must be a field or a \code{TypeError} is raised.206207sage: QuadraticSpace(ZZ,5,identity_matrix(ZZ,2))208Traceback (most recent call last):209...210TypeError: Argument K (= Integer Ring) must be a field.211"""212if not K.is_field():213raise TypeError, "Argument K (= %s) must be a field." % K214if not sparse in (True,False):215raise TypeError, "Argument sparse (= %s) must be a boolean."%sparse216return FreeQuadraticModule(K, rank=dimension, inner_product_matrix=inner_product_matrix, sparse=sparse)217218InnerProductSpace = QuadraticSpace219220###############################################################################221#222# Base class for all free modules223#224###############################################################################225226def is_FreeQuadraticModule(M):227"""228Returns True if M is a free quadratic module.229230EXAMPLES:231sage: from sage.modules.free_quadratic_module import is_FreeQuadraticModule232sage: U = FreeModule(QQ,3)233sage: is_FreeQuadraticModule(U)234False235sage: V = FreeModule(QQ,3,inner_product_matrix=diagonal_matrix([1,1,1]))236sage: is_FreeQuadraticModule(V)237True238sage: W = FreeModule(QQ,3,inner_product_matrix=diagonal_matrix([2,3,3]))239sage: is_FreeQuadraticModule(W)240True241"""242return isinstance(M, FreeQuadraticModule_generic)243244class FreeQuadraticModule_generic(free_module.FreeModule_generic):245"""246Base class for all free quadratic modules.247"""248def __init__(self, base_ring, rank, degree, inner_product_matrix, sparse=False):249"""250Create the free module of given rank over the given base_ring.251252INPUT:253base_ring -- a commutative ring254rank -- a non-negative integer255256EXAMPLES:257sage: R = PolynomialRing(QQ,3,'x')258sage: FreeModule(R,3,inner_product_matrix=diagonal_matrix(list(R.gens())))259Ambient free quadratic module of rank 3 over the integral domain Multivariate Polynomial Ring in x0, x1, x2 over Rational Field260Inner product matrix:261[x0 0 0]262[ 0 x1 0]263[ 0 0 x2]264"""265free_module.FreeModule_generic.__init__(266self, base_ring=base_ring, rank=rank, degree=degree, sparse=sparse)267self._inner_product_matrix=inner_product_matrix268269def _dense_module(self):270"""271Creates a dense module with the same defining data as self.272273N.B. This function is for internal use only! See dense_module for use.274275EXAMPLES:276sage: A = diagonal_matrix([1,2,2])277sage: M = FreeModule(Integers(8),3,inner_product_matrix=A)278sage: S = FreeModule(Integers(8),3,inner_product_matrix=A,sparse=True)279sage: M is S._dense_module()280True281"""282A = self.ambient_module().dense_module()283return A.span(self.basis())284285def _sparse_module(self):286"""287Creates a sparse module with the same defining data as self.288289N.B. This function is for internal use only! See sparse_module for use.290291EXAMPLES:292sage: A = diagonal_matrix([1,2,2])293sage: M = FreeModule(Integers(8),3,inner_product_matrix=A)294sage: S = FreeModule(Integers(8),3,inner_product_matrix=A,sparse=True)295sage: M._sparse_module() is S296True297"""298A = self.ambient_module().sparse_module()299return A.span(self.basis())300301def ambient_module(self):302"""303Return the ambient module associated to this module.304305EXAMPLES:306sage: R.<x,y> = QQ[]307sage: M = FreeModule(R,2)308sage: M.ambient_module()309Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field310311sage: V = FreeModule(QQ, 4).span([[1,2,3,4], [1,0,0,0]]); V312Vector space of degree 4 and dimension 2 over Rational Field313Basis matrix:314[ 1 0 0 0]315[ 0 1 3/2 2]316sage: V.ambient_module()317Vector space of dimension 4 over Rational Field318"""319return FreeQuadraticModule(self.base_ring(), self.degree(), self.inner_product_matrix())320321def determinant(self):322"""323Return the determinant of this free module.324325EXAMPLES:326sage: M = FreeModule(ZZ, 3, inner_product_matrix=1)327sage: M.determinant()3281329sage: N = M.span([[1,2,3]])330sage: N.determinant()33114332sage: P = M.span([[1,2,3], [1,1,1]])333sage: P.determinant()3346335"""336return self.gram_matrix().determinant()337338def discriminant(self):339"""340Return the discriminant of this free module, defined to be (-1)^r341of the determinant, where r = n/2 (n even) or (n-1)/2 (n odd) for342a module of rank n.343344EXAMPLES:345sage: M = FreeModule(ZZ, 3)346sage: M.discriminant()3471348sage: N = M.span([[1,2,3]])349sage: N.discriminant()35014351sage: P = M.span([[1,2,3], [1,1,1]])352sage: P.discriminant()3536354"""355n = self.rank()356if n%2 == 0:357r = n//2358else:359r = (n-1)//2360return (-1)^r*self.gram_matrix().determinant()361362def gram_matrix(self):363"""364Return the gram matrix associated to this free module, defined to be365G = B*A*B.transpose(), where A is the inner product matrix (induced from366the ambient space), and B the basis matrix.367368EXAMPLES:369sage: V = VectorSpace(QQ,4)370sage: u = V([1/2,1/2,1/2,1/2])371sage: v = V([0,1,1,0])372sage: w = V([0,0,1,1])373sage: M = span([u,v,w], ZZ)374sage: M.inner_product_matrix() == V.inner_product_matrix()375True376sage: L = M.submodule_with_basis([u,v,w])377sage: L.inner_product_matrix() == M.inner_product_matrix()378True379sage: L.gram_matrix()380[1 1 1]381[1 2 1]382[1 1 2]383384"""385if self.is_ambient():386return self.inner_product_matrix()387else:388if self._gram_matrix is None:389A = self.inner_product_matrix()390B = self.basis_matrix()391self._gram_matrix = B*A*B.transpose()392return self._gram_matrix393394def inner_product_matrix(self):395"""396Return the inner product matrix associated to this module. By definition this397is the inner product matrix of the ambient space, hence may be of degree greater398than the rank of the module.399400N.B. The inner product does not have to be symmetric (see examples).401402TODO: Differentiate the image ring of the inner product from the base ring of403the module and/or ambient space. E.g. On an integral module over ZZ the inner404product pairing could naturally take values in ZZ, QQ, RR, or CC.405406EXAMPLES:407sage: M = FreeModule(ZZ, 3)408sage: M.inner_product_matrix()409[1 0 0]410[0 1 0]411[0 0 1]412413The inner product does not have to be symmetric or definite.414415sage: N = FreeModule(ZZ,2,inner_product_matrix=[[1,-1],[2,5]])416sage: N.inner_product_matrix()417[ 1 -1]418[ 2 5]419sage: u, v = N.basis()420sage: u.inner_product(v)421-1422sage: v.inner_product(u)4232424425The inner product matrix is defined with respect to the ambient space.426427sage: V = QQ^3428sage: u = V([1/2,1,1])429sage: v = V([1,1,1/2])430sage: M = span([u,v], ZZ)431sage: M.inner_product_matrix()432[1 0 0]433[0 1 0]434[0 0 1]435sage: M.inner_product_matrix() == V.inner_product_matrix()436True437sage: M.gram_matrix()438[ 1/2 -3/4]439[-3/4 13/4]440441"""442return self._inner_product_matrix443444def _inner_product_is_dot_product(self):445"""446Return whether or not the inner product on this module is induced by447the dot product on the ambient vector space. This is used internally448by the inner_product function for optimization.449450EXAMPLES:451sage: FreeModule(ZZ, 3)._inner_product_is_dot_product()452True453sage: FreeModule(ZZ, 3, inner_product_matrix=1)._inner_product_is_dot_product()454True455sage: FreeModule(ZZ, 2, inner_product_matrix=[1,0,-1,0])._inner_product_is_dot_product()456False457458sage: M = FreeModule(QQ, 3)459sage: M2 = M.span([[1,2,3]])460sage: M2._inner_product_is_dot_product()461True462"""463return self.inner_product_matrix() == 1464465466def _inner_product_is_diagonal(self):467"""468Return whether or not the inner product on this module is induced by469the dot product on the ambient vector space. This is used internally470by the inner_product function for optimization.471472N.B. The FreeModule classes have the identity inner product matrix,473while FreeQuadraticModules must have an inner_product_matrix, although474it can be diagonal.475476EXAMPLES:477sage: M0 = FreeModule(ZZ, 3, inner_product_matrix=1)478sage: M0._inner_product_is_diagonal()479True480sage: D = diagonal_matrix([3,5,7])481sage: M1 = FreeModule(ZZ, 3, inner_product_matrix=D)482sage: M1._inner_product_is_diagonal()483True484sage: A = Matrix([[2,1,0],[1,2,1],[0,1,2]])485sage: M2 = FreeModule(ZZ, 3, inner_product_matrix=A)486sage: M2._inner_product_is_diagonal()487False488sage: M3 = FreeModule(ZZ, 2, inner_product_matrix=[1,0,-1,0])489sage: M3._inner_product_is_diagonal()490False491492TODO: Actually use the diagonal form of the inner product.493"""494A = self.inner_product_matrix()495D = sage.matrix.constructor.diagonal_matrix([ A[i,i] for i in range(A.nrows()) ])496return A == D497498class FreeQuadraticModule_generic_pid(499free_module.FreeModule_generic_pid, FreeQuadraticModule_generic):500"""501Class of all free modules over a PID.502"""503def __init__(self, base_ring, rank, degree, inner_product_matrix, sparse=False):504"""505Create a free module over a PID.506507EXAMPLES:508sage: FreeModule(ZZ, 2, inner_product_matrix=Matrix([[2,1],[1,2]]))509Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring510Inner product matrix:511[2 1]512[1 2]513"""514free_module.FreeModule_generic_pid.__init__(515self, base_ring=base_ring, rank=rank, degree=degree, sparse=sparse)516#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix517self._inner_product_matrix = inner_product_matrix518519def span(self, gens, check=True, already_echelonized=False):520"""521Return the R-span of the given list of gens, where R522is the base ring of self. Note that this span need not523be a submodule of self, nor even of the ambient space.524It must, however, be contained in the ambient vector space, i.e.,525the ambient space tensored with the fraction field of R.526527EXAMPLES:528sage: V = FreeModule(ZZ,3)529sage: W = V.submodule([V.gen(0)])530sage: W.span([V.gen(1)])531Free module of degree 3 and rank 1 over Integer Ring532Echelon basis matrix:533[0 1 0]534sage: W.submodule([V.gen(1)])535Traceback (most recent call last):536...537ArithmeticError: Argument gens (= [(0, 1, 0)]) does not generate a submodule of self.538"""539return FreeQuadraticModule_submodule_pid(540self.ambient_module(), gens, inner_product_matrix=self.inner_product_matrix(),541check=check, already_echelonized=already_echelonized)542543def span_of_basis(self, basis, check=True, already_echelonized=False):544r"""545Return the free R-module with the given basis, where R546is the base ring of self. Note that this R-module need not547be a submodule of self, nor even of the ambient space. It548must, however, be contained in the ambient vector space, i.e.,549the ambient space tensored with the fraction field of R.550551EXAMPLES:552sage: M = FreeModule(ZZ,3)553sage: W = M.span_of_basis([M([1,2,3])])554555Next we create two free $\Z$-modules, neither of556which is a submodule of $W$.557sage: W.span_of_basis([M([2,4,0])])558Free module of degree 3 and rank 1 over Integer Ring559User basis matrix:560[2 4 0]561562The following module isn't even in the ambient space.563sage: Q = QQ564sage: W.span_of_basis([ Q('1/5')*M([1,2,0]), Q('1/7')*M([1,1,0]) ])565Free module of degree 3 and rank 2 over Integer Ring566User basis matrix:567[1/5 2/5 0]568[1/7 1/7 0]569570Of course the input basis vectors must be linearly independent.571572sage: W.span_of_basis([ [1,2,0], [2,4,0] ])573Traceback (most recent call last):574...575ValueError: The given basis vectors must be linearly independent.576"""577return FreeQuadraticModule_submodule_with_basis_pid(578self.ambient_module(), basis=basis, inner_product_matrix=self.inner_product_matrix(),579check=check, already_echelonized=already_echelonized)580581def zero_submodule(self):582"""583Return the zero submodule of this module.584585EXAMPLES:586sage: V = FreeModule(ZZ,2)587sage: V.zero_submodule()588Free module of degree 2 and rank 0 over Integer Ring589Echelon basis matrix:590[]591"""592return FreeQuadraticModule_submodule_pid(593self.ambient_module(), [], self.inner_product_matrix(), check=False)594595class FreeQuadraticModule_generic_field(596free_module.FreeModule_generic_field, FreeQuadraticModule_generic_pid):597"""598Base class for all free modules over fields.599"""600def __init__(self, base_field, dimension, degree, inner_product_matrix, sparse=False):601"""602Creates a vector space over a field.603604EXAMPLES:605sage: FreeModule(QQ, 2, inner_product_matrix=[[2,1],[1,2]])606Ambient quadratic space of dimension 2 over Rational Field607Inner product matrix:608[2 1]609[1 2]610sage: FreeModule(FiniteField(2), 7, inner_product_matrix=1)611Ambient quadratic space of dimension 7 over Finite Field of size 2612Inner product matrix:613[1 0 0 0 0 0 0]614[0 1 0 0 0 0 0]615[0 0 1 0 0 0 0]616[0 0 0 1 0 0 0]617[0 0 0 0 1 0 0]618[0 0 0 0 0 1 0]619[0 0 0 0 0 0 1]620"""621if not isinstance(base_field, field.Field):622raise TypeError, "The base_field (=%s) must be a field" % base_field623free_module.FreeModule_generic_field.__init__(624self, base_field=base_field, dimension=dimension, degree=degree, sparse=sparse)625#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix626self._inner_product_matrix = inner_product_matrix627628def span(self, gens, check=True, already_echelonized=False):629"""630Return the K-span of the given list of gens, where K is the631base field of self. Note that this span is a subspace of the632ambient vector space, but need not be a subspace of self.633634INPUT:635gens -- list of vectors636check -- bool (default: True): whether or not to coerce entries of gens637into base field638already_echelonized -- bool (default: False): set this if you know the gens639are already in echelon form640641EXAMPLES:642sage: V = VectorSpace(GF(7), 3)643sage: W = V.subspace([[2,3,4]]); W644Vector space of degree 3 and dimension 1 over Finite Field of size 7645Basis matrix:646[1 5 2]647sage: W.span([[1,1,1]])648Vector space of degree 3 and dimension 1 over Finite Field of size 7649Basis matrix:650[1 1 1]651"""652if free_module.is_FreeModule(gens):653gens = gens.gens()654if not isinstance(gens, (list, tuple)):655raise TypeError, "gens (=%s) must be a list or tuple"%gens656657return FreeQuadraticModule_submodule_field(658self.ambient_module(), gens,659inner_product_matrix=self.inner_product_matrix(),660check=check, already_echelonized=already_echelonized)661662def span_of_basis(self, basis, check=True, already_echelonized=False):663r"""664Return the free K-module with the given basis, where K665is the base field of self. Note that this span is666a subspace of the ambient vector space, but need667not be a subspace of self.668669INPUT:670basis -- list of vectors671check -- bool (default: True): whether or not to coerce entries of gens672into base field673already_echelonized -- bool (default: False): set this if you know the gens674are already in echelon form675676EXAMPLES:677sage: V = VectorSpace(GF(7), 3)678sage: W = V.subspace([[2,3,4]]); W679Vector space of degree 3 and dimension 1 over Finite Field of size 7680Basis matrix:681[1 5 2]682sage: W.span_of_basis([[2,2,2], [3,3,0]])683Vector space of degree 3 and dimension 2 over Finite Field of size 7684User basis matrix:685[2 2 2]686[3 3 0]687688The basis vectors must be linearly independent or an ArithmeticError exception689is raised.690sage: W.span_of_basis([[2,2,2], [3,3,3]])691Traceback (most recent call last):692...693ValueError: The given basis vectors must be linearly independent.694"""695return FreeQuadraticModule_submodule_with_basis_field(696self.ambient_module(), basis=basis,697inner_product_matrix=self.inner_product_matrix(),698check=check, already_echelonized=already_echelonized)699700###############################################################################701#702# Generic ambient free modules, i.e., of the form R^n for some commutative ring R.703#704###############################################################################705706class FreeQuadraticModule_ambient(707free_module.FreeModule_ambient, FreeQuadraticModule_generic):708"""709Ambient free module over a commutative ring.710"""711def __init__(self, base_ring, rank, inner_product_matrix, sparse=False):712"""713The free module of given rank over the given base_ring.714715INPUT:716base_ring -- a commutative ring717rank -- a non-negative integer718719EXAMPLES:720sage: FreeModule(ZZ, 4)721Ambient free module of rank 4 over the principal ideal domain Integer Ring722"""723free_module.FreeModule_ambient.__init__(self, base_ring=base_ring, rank=rank, sparse=sparse)724#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix725self._inner_product_matrix = inner_product_matrix726727def _repr_(self):728"""729The printing representation of self.730731EXAMPLES:732sage: R = ZZ.quo(12)733sage: M = R^12734sage: print M735Ambient free module of rank 12 over Ring of integers modulo 12736sage: print M._repr_()737Ambient free module of rank 12 over Ring of integers modulo 12738739The system representation can be overwritten, but leaves _repr_ unmodified.740741sage: M.rename('M')742sage: print M743M744sage: print M._repr_()745Ambient free module of rank 12 over Ring of integers modulo 12746747Sparse modules print this fact.748749sage: N = FreeModule(R,12,sparse=True)750sage: print N751Ambient sparse free module of rank 12 over Ring of integers modulo 12752"""753if self.is_sparse():754return "Ambient sparse free quadratic module of rank %s over %s\n" % ( self.rank(), self.base_ring() ) + \755"Inner product matrix:\n%s" % self.inner_product_matrix()756else:757return "Ambient free quadratic module of rank %s over %s\n" % ( self.rank(), self.base_ring() ) + \758"Inner product matrix:\n%s" % self.inner_product_matrix()759760def __cmp__(self, other):761"""762Compare self and other.763764Modules are ordered by their ambient spaces, then by765dimension, then in order by their echelon matrices.766767EXAMPLES:768We compare rank three free modules over the integers and rationals:769sage: QQ^3 < CC^3770True771sage: CC^3 < QQ^3772False773sage: CC^3 > QQ^3774True775sage: Q = QQ; Z = ZZ776sage: Q^3 > Z^3777True778sage: Q^3 < Z^3779False780sage: Z^3 < Q^3781True782sage: Z^3 > Q^3783False784sage: Q^3 == Z^3785False786sage: Q^3 == Q^3787True788789sage: V = span([[1,2,3], [5,6,7], [8,9,10]], QQ)790sage: V791Vector space of degree 3 and dimension 2 over Rational Field792Basis matrix:793[ 1 0 -1]794[ 0 1 2]795sage: A = QQ^3796sage: V < A797True798sage: A < V799False800"""801if self is other:802return 0803if not isinstance(other, free_module.FreeModule_generic):804return cmp(type(self), type(other))805if isinstance(other, free_module.FreeModule_ambient):806c = cmp(self.rank(), other.rank())807if c: return c808c = cmp(self.base_ring(), other.base_ring())809if not c:810return c811try:812if self.base_ring().is_subring(other.base_ring()):813return -1814elif other.base_ring().is_subring(self.base_ring()):815return 1816except NotImplementedError:817pass818return c819else: # now other is not ambient; it knows how to do the comparison.820return -other.__cmp__(self)821822def _latex_(self):823r"""824Return a latex representation of this ambient free quadratic module.825826EXAMPLES:827sage: latex(QQ^3) # indirect doctest828\Bold{Q}^{3}829830sage: A = GF(5)^20; latex(A)831\Bold{F}_{5}^{20}832833sage: A = PolynomialRing(QQ,3,'x')^20; latex(A)834(\Bold{Q}[x_{0}, x_{1}, x_{2}])^{20}835836sage: V = QuadraticSpace(QQ,3,inner_product_matrix=[[2,1,0],[1,4,1],[0,1,8]])837sage: latex(V)838None839"""840# How do we want to represent this object?841NotImplementedError842843def _dense_module(self):844"""845Creates a dense module with the same defining data as self.846847N.B. This function is for internal use only! See dense_module for use.848849EXAMPLES:850sage: A = diagonal_matrix([1,2,2])851sage: M = FreeModule(Integers(8),3,inner_product_matrix=A)852sage: S = FreeModule(Integers(8),3,inner_product_matrix=A,sparse=True)853sage: M is S._dense_module()854True855"""856return FreeQuadraticModule(base_ring=self.base_ring(), rank = self.rank(),857inner_product_matrix = self.inner_product_matrix(), sparse=False)858859def _sparse_module(self):860"""861Creates a sparse module with the same defining data as self.862863N.B. This function is for internal use only! See sparse_module for use.864865EXAMPLES:866sage: A = diagonal_matrix([1,2,2])867sage: M = FreeModule(Integers(8),3,inner_product_matrix=A)868sage: S = FreeModule(Integers(8),3,inner_product_matrix=A,sparse=True)869sage: M._sparse_module() is S870True871"""872return FreeQuadraticModule(base_ring = self.base_ring(), rank = self.rank(),873inner_product_matrix = self.inner_product_matrix(), sparse=True)874875###############################################################################876#877# Ambient free modules over an integral domain.878#879###############################################################################880881class FreeQuadraticModule_ambient_domain(882free_module.FreeModule_ambient_domain, FreeQuadraticModule_ambient):883"""884Ambient free quadratic module over an integral domain.885"""886def __init__(self, base_ring, rank, inner_product_matrix, sparse=False):887"""888EXAMPLES:889sage: FreeModule(PolynomialRing(GF(5),'x'), 3)890Ambient free module of rank 3 over the principal ideal domain891Univariate Polynomial Ring in x over Finite Field of size 5892"""893free_module.FreeModule_ambient.__init__(self, base_ring=base_ring, rank=rank, sparse=sparse)894#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix895self._inner_product_matrix = inner_product_matrix896897def _repr_(self):898"""899The printing representation of self.900901EXAMPLES:902sage: R = PolynomialRing(ZZ,'x')903sage: M = FreeModule(R,7)904sage: print M905Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring906sage: print M._repr_()907Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring908909The system representation can be overwritten, but leaves _repr_ unmodified.910911sage: M.rename('M')912sage: print M913M914sage: print M._repr_()915Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring916917Sparse modules print this fact.918919sage: N = FreeModule(R,7,sparse=True)920sage: print N921Ambient sparse free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring922923Here is a construction of a free quadratic module with generic symmetric inner product matrix.924925sage: R.<a,b,c> = PolynomialRing(QQ,3)926sage: M = FreeModule(R, 2, inner_product_matrix=[[2*a,b],[b,2*c]])927sage: M928Ambient free quadratic module of rank 2 over the integral domain Multivariate Polynomial Ring in a, b, c over Rational Field929Inner product matrix:930[2*a b]931[ b 2*c]932sage: M.determinant()933-b^2 + 4*a*c934"""935if self.is_sparse():936return "Ambient sparse free quadratic module of rank %s over the integral domain %s\n"%(937self.rank(), self.base_ring() ) + \938"Inner product matrix:\n%s" % self.inner_product_matrix()939else:940return "Ambient free quadratic module of rank %s over the integral domain %s\n"%(941self.rank(), self.base_ring() ) + \942"Inner product matrix:\n%s" % self.inner_product_matrix()943944def ambient_vector_space(self):945"""946Returns the ambient vector space, which is this free module tensored947with its fraction field.948949EXAMPLES:950sage: M = ZZ^3; M.ambient_vector_space()951Vector space of dimension 3 over Rational Field952"""953try:954return self.__ambient_vector_space955except AttributeError:956self.__ambient_vector_space = FreeQuadraticModule(957self.base_field(), self.rank(),958inner_product_matrix=self.inner_product_matrix(), sparse=self.is_sparse())959return self.__ambient_vector_space960961###############################################################################962#963# Ambient free modules over a principal ideal domain.964#965###############################################################################966967class FreeQuadraticModule_ambient_pid(968free_module.FreeModule_ambient_pid, FreeQuadraticModule_generic_pid, FreeQuadraticModule_ambient_domain):969"""970Ambient free quadratic module over a principal ideal domain.971"""972def __init__(self, base_ring, rank, inner_product_matrix, sparse=False):973"""974Create the ambient free module of given rank over the given975principal ideal domain976977INPUT:978base_ring -- a principal ideal domain979rank -- a non-negative integer980sparse -- bool (default: False)981inner_product_matrix -- bool (default: None)982983EXAMPLES:984sage: ZZ^3985Ambient free module of rank 3 over the principal ideal domain Integer Ring986sage: FreeModule(ZZ,3,inner_product_matrix=Matrix([[2,-1,0],[-1,2,-1],[0,-1,2]]))987Ambient free quadratic module of rank 3 over the principal ideal domain Integer Ring988Inner product matrix:989[ 2 -1 0]990[-1 2 -1]991[ 0 -1 2]992"""993free_module.FreeModule_ambient_pid.__init__(self, base_ring=base_ring, rank=rank, sparse=sparse)994#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix995self._inner_product_matrix = inner_product_matrix996997def _repr_(self):998"""999The printing representation of self.10001001EXAMPLES:1002sage: M = FreeModule(ZZ, 2, inner_product_matrix=[[2,-1],[-1,2]])1003sage: M1004Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring1005Inner product matrix:1006[ 2 -1]1007[-1 2]10081009Without a user specified inner product the class and printing is simpler.10101011sage: M = FreeModule(ZZ,7)1012sage: print M1013Ambient free module of rank 7 over the principal ideal domain Integer Ring1014sage: print M._repr_()1015Ambient free module of rank 7 over the principal ideal domain Integer Ring10161017The system representation can be overwritten, but leaves _repr_ unmodified.10181019sage: M.rename('M')1020sage: print M1021M1022sage: print M._repr_()1023Ambient free module of rank 7 over the principal ideal domain Integer Ring10241025Sparse modules print this fact.10261027sage: N = FreeModule(ZZ,7,sparse=True)1028sage: print N1029Ambient sparse free module of rank 7 over the principal ideal domain Integer Ring10301031"""1032if self.is_sparse():1033return "Ambient sparse free quadratic module of rank %s over the principal ideal domain %s\n"%(1034self.rank(), self.base_ring() ) + \1035"Inner product matrix:\n%s" % self.inner_product_matrix()1036else:1037return "Ambient free quadratic module of rank %s over the principal ideal domain %s\n"%(1038self.rank(), self.base_ring()) + \1039"Inner product matrix:\n%s" % self.inner_product_matrix()10401041###############################################################################1042#1043# Ambient free modules over a field (i.e., a vector space).1044#1045###############################################################################10461047class FreeQuadraticModule_ambient_field(1048free_module.FreeModule_ambient_field,1049FreeQuadraticModule_generic_field, FreeQuadraticModule_ambient_pid):10501051def __init__(self, base_field, dimension, inner_product_matrix, sparse=False):1052"""1053Create the ambient vector space of given dimension over the given field.10541055INPUT:1056base_field -- a field1057dimension -- a non-negative integer1058sparse -- bool (default: False)10591060EXAMPLES:1061sage: VectorSpace(QQ,3,inner_product_matrix=[[2,1,0],[1,2,0],[0,1,2]])1062Ambient quadratic space of dimension 3 over Rational Field1063Inner product matrix:1064[2 1 0]1065[1 2 0]1066[0 1 2]1067"""1068free_module.FreeModule_ambient_field.__init__(1069self, base_field=base_field, dimension=dimension, sparse=sparse)1070#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix1071self._inner_product_matrix = inner_product_matrix10721073def _repr_(self):1074"""1075The printing representation of self.10761077EXAMPLES:1078sage: V = FreeModule(QQ,7)1079sage: print V1080Vector space of dimension 7 over Rational Field1081sage: print V._repr_()1082Vector space of dimension 7 over Rational Field10831084The system representation can be overwritten, but leaves _repr_ unmodified.10851086sage: V.rename('V')1087sage: print V1088V1089sage: print V._repr_()1090Vector space of dimension 7 over Rational Field10911092Sparse modules print this fact.10931094sage: U = FreeModule(QQ,7,sparse=True)1095sage: print U1096Sparse vector space of dimension 7 over Rational Field1097"""1098if self.is_sparse():1099return "Ambient sparse free quadratic space of dimension %s over %s\n" % ( self.rank(), self.base_ring() ) + \1100"Inner product matrix:\n%s" % self.inner_product_matrix()1101else:1102return "Ambient quadratic space of dimension %s over %s\n" % ( self.rank(), self.base_ring() ) + \1103"Inner product matrix:\n%s" % self.inner_product_matrix()11041105###############################################################################1106#1107# R-Submodule of K^n where K is the fraction field of a principal ideal domain $R$.1108#1109###############################################################################11101111class FreeQuadraticModule_submodule_with_basis_pid(1112free_module.FreeModule_submodule_with_basis_pid, FreeQuadraticModule_generic_pid):1113"""1114An $R$-submodule of $K^n$ with distinguished basis, where $K$ is1115the fraction field of a principal ideal domain $R$.1116"""1117def __init__(self, ambient, basis, inner_product_matrix,1118check=True, echelonize=False, echelonized_basis=None, already_echelonized=False):1119"""1120Create a free module with basis over a PID.11211122EXAMPLES:11231124sage: A = diagonal_matrix([1,2,2])1125sage: M = FreeQuadraticModule(ZZ,3,inner_product_matrix=A)1126sage: W = M.span_of_basis([[1,2,3],[4,5,6]]); W1127Free quadratic module of degree 3 and rank 2 over Integer Ring1128Basis matrix:1129[1 2 3]1130[4 5 6]1131Inner product matrix:1132[1 0 0]1133[0 2 0]1134[0 0 2]11351136sage: W = M.span_of_basis([[1,2,3/2],[4,5,6]]); W1137Free quadratic module of degree 3 and rank 2 over Integer Ring1138Basis matrix:1139[ 1 2 3/2]1140[ 4 5 6]1141Inner product matrix:1142[1 0 0]1143[0 2 0]1144[0 0 2]1145"""1146free_module.FreeModule_submodule_with_basis_pid.__init__(1147self, ambient=ambient, basis=basis, check=check,1148echelonize=echelonize, echelonized_basis=echelonized_basis, already_echelonized=already_echelonized)1149#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix1150self._inner_product_matrix = inner_product_matrix11511152def _repr_(self):1153"""1154The printing representation of self.11551156EXAMPLES:1157sage: L = ZZ^81158sage: E = L.submodule_with_basis([ L.gen(i) - L.gen(0) for i in range(1,8) ])1159sage: E # indirect doctest1160Free module of degree 8 and rank 7 over Integer Ring1161User basis matrix:1162[-1 1 0 0 0 0 0 0]1163[-1 0 1 0 0 0 0 0]1164[-1 0 0 1 0 0 0 0]1165[-1 0 0 0 1 0 0 0]1166[-1 0 0 0 0 1 0 0]1167[-1 0 0 0 0 0 1 0]1168[-1 0 0 0 0 0 0 1]11691170sage: M = FreeModule(ZZ,8,sparse=True)1171sage: N = M.submodule_with_basis([ M.gen(i) - M.gen(0) for i in range(1,8) ])1172sage: N # indirect doctest1173Sparse free module of degree 8 and rank 7 over Integer Ring1174User basis matrix:1175[-1 1 0 0 0 0 0 0]1176[-1 0 1 0 0 0 0 0]1177[-1 0 0 1 0 0 0 0]1178[-1 0 0 0 1 0 0 0]1179[-1 0 0 0 0 1 0 0]1180[-1 0 0 0 0 0 1 0]1181[-1 0 0 0 0 0 0 1]1182"""1183if self.is_sparse():1184s = "Sparse free quadratic module of degree %s and rank %s over %s\n"%(1185self.degree(), self.rank(), self.base_ring()) + \1186"Basis matrix:\n%s\n" % self.basis_matrix() + \1187"Inner product matrix:\n%s" % self.inner_product_matrix()1188else:1189s = "Free quadratic module of degree %s and rank %s over %s\n"%(1190self.degree(), self.rank(), self.base_ring()) + \1191"Basis matrix:\n%s\n" % self.basis_matrix() + \1192"Inner product matrix:\n%s" % self.inner_product_matrix()1193return s11941195def __cmp__(self, other):1196r"""1197Compare self and other.11981199Modules are ordered by their ambient spaces, then by1200dimension, then in order by their echelon matrices.12011202NOTE: Use the \code{is_submodule} to determine if one module1203is a submodule of another.12041205EXAMPLES:1206First we compare two equal vector spaces.1207sage: V = span([[1,2,3], [5,6,7], [8,9,10]], QQ)1208sage: W = span([[5,6,7], [8,9,10]], QQ)1209sage: V == W1210True12111212Next we compare a one dimensional space to the two dimensional space1213defined above.1214sage: M = span([[5,6,7]], QQ)1215sage: V == M1216False1217sage: M < V1218True1219sage: V < M1220False12211222We compare a $\Z$-module to the one-dimensional space above.1223sage: V = span([[5,6,7]], ZZ).scale(1/11); V1224Free module of degree 3 and rank 1 over Integer Ring1225Echelon basis matrix:1226[5/11 6/11 7/11]1227sage: V < M1228True1229sage: M < V1230False1231"""1232if self is other:1233return 01234if not isinstance(other, free_module.FreeModule_generic):1235return cmp(type(self), type(other))1236c = cmp(self.ambient_vector_space(), other.ambient_vector_space())1237if c: return c1238c = cmp(self.dimension(), other.dimension())1239if c: return c1240# We use self.echelonized_basis_matrix() == other.echelonized_basis_matrix()1241# with the matrix to avoid a circular reference.1242return cmp(self.echelonized_basis_matrix(), other.echelonized_basis_matrix())12431244def _latex_(self):1245r"""1246Return latex representation of this free module.12471248EXAMPLES:1249sage: A = ZZ^31250sage: M = A.span_of_basis([[1,2,3],[4,5,6]])1251sage: M._latex_()1252'\\mathrm{RowSpan}_{\\Bold{Z}}\\left(\\begin{array}{rrr}\n1 & 2 & 3 \\\\\n4 & 5 & 6\n\\end{array}\\right)'1253"""1254return "\\mathrm{RowSpan}_{%s}%s"%(latex.latex(self.base_ring()), latex.latex(self.basis_matrix()))12551256def change_ring(self, R):1257"""1258Return the free module over R obtained by coercing each1259element of self into a vector over the fraction field of R,1260then taking the resulting R-module. Raises a TypeError1261if coercion is not possible.12621263INPUT:1264R -- a principal ideal domain12651266EXAMPLES:1267Changing rings preserves the inner product and the user basis:12681269sage: V = QQ^31270sage: W = V.subspace([[2, '1/2', 1]]); W1271Vector space of degree 3 and dimension 1 over Rational Field1272Basis matrix:1273[ 1 1/4 1/2]1274sage: W.change_ring(GF(7))1275Vector space of degree 3 and dimension 1 over Finite Field of size 71276Basis matrix:1277[1 2 4]12781279sage: N = FreeModule(ZZ, 2, inner_product_matrix=[[1,-1],[2,5]])1280sage: N.inner_product_matrix()1281[ 1 -1]1282[ 2 5]1283sage: Np = N.change_ring(RDF)1284sage: Np.inner_product_matrix()1285[ 1.0 -1.0]1286[ 2.0 5.0]1287"""1288if self.base_ring() is R:1289return self1290K = R.fraction_field()1291A = self.inner_product_matrix()1292V = QuadraticSpace(K, self.degree(), inner_product_matrix=A)1293B = [ V(b) for b in self.basis() ]1294M = FreeQuadraticModule(R, self.degree(), inner_product_matrix=A)1295if self.has_user_basis():1296return M.span_of_basis(B)1297else:1298return M.span(B)12991300class FreeQuadraticModule_submodule_pid(1301free_module.FreeModule_submodule_pid, FreeQuadraticModule_submodule_with_basis_pid):1302"""1303An $R$-submodule of $K^n$ where $K$ is the fraction field of a1304principal ideal domain $R$.13051306EXAMPLES:1307sage: M = ZZ^31308sage: W = M.span_of_basis([[1,2,3],[4,5,19]]); W1309Free module of degree 3 and rank 2 over Integer Ring1310User basis matrix:1311[ 1 2 3]1312[ 4 5 19]13131314We can save and load submodules and elements.1315sage: loads(W.dumps()) == W1316True1317sage: v = W.0 + W.11318sage: loads(v.dumps()) == v1319True1320"""1321def __init__(self, ambient, gens, inner_product_matrix, check=True, already_echelonized=False):1322"""1323Create an embedded free module over a PID.13241325EXAMPLES:1326sage: V = ZZ^31327sage: W = V.span([[1,2,3],[4,5,6]])1328sage: W1329Free module of degree 3 and rank 2 over Integer Ring1330Echelon basis matrix:1331[1 2 3]1332[0 3 6]1333"""1334free_module.FreeModule_submodule_pid.__init__(1335self, ambient=ambient, gens=gens, check=check, already_echelonized=already_echelonized)1336#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix1337self._inner_product_matrix = inner_product_matrix13381339def _repr_(self):1340"""1341The printing representation of self.13421343EXAMPLES:1344sage: M = FreeModule(ZZ,8,inner_product_matrix=1)1345sage: L = M.submodule([ M.gen(i) - M.gen(0) for i in range(1,8) ])1346sage: print L # indirect doctest1347Free module of degree 8 and rank 7 over Integer Ring1348Echelon basis matrix:1349[ 1 0 0 0 0 0 0 -1]1350[ 0 1 0 0 0 0 0 -1]1351[ 0 0 1 0 0 0 0 -1]1352[ 0 0 0 1 0 0 0 -1]1353[ 0 0 0 0 1 0 0 -1]1354[ 0 0 0 0 0 1 0 -1]1355[ 0 0 0 0 0 0 1 -1]1356"""1357if self.is_sparse():1358s = "Sparse free module of degree %s and rank %s over %s\n"%(1359self.degree(), self.rank(), self.base_ring()) + \1360"Echelon basis matrix:\n%s"%self.basis_matrix()1361else:1362s = "Free module of degree %s and rank %s over %s\n"%(1363self.degree(), self.rank(), self.base_ring()) + \1364"Echelon basis matrix:\n%s"%self.basis_matrix()1365return s13661367class FreeQuadraticModule_submodule_with_basis_field(1368free_module.FreeModule_submodule_with_basis_field,1369FreeQuadraticModule_generic_field, FreeQuadraticModule_submodule_with_basis_pid):1370"""1371An embedded vector subspace with a distinguished user basis.13721373EXAMPLES:1374sage: M = QQ^3; W = M.submodule_with_basis([[1,2,3], [4,5,19]]); W1375Vector space of degree 3 and dimension 2 over Rational Field1376User basis matrix:1377[ 1 2 3]1378[ 4 5 19]13791380Since this is an embedded vector subspace with a distinguished user1381basis possibly different than the echelonized basis, the1382echelon_coordinates() and user coordinates() do not agree:13831384sage: V = QQ^31385sage: W = V.submodule_with_basis([[1,2,3], [4,5,6]])1386sage: W1387Vector space of degree 3 and dimension 2 over Rational Field1388User basis matrix:1389[1 2 3]1390[4 5 6]13911392sage: v = V([1,5,9])1393sage: W.echelon_coordinates(v)1394[1, 5]1395sage: vector(QQ, W.echelon_coordinates(v)) * W.echelonized_basis_matrix()1396(1, 5, 9)13971398sage: v = V([1,5,9])1399sage: W.coordinates(v)1400[5, -1]1401sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()1402(1, 5, 9)14031404We can load and save submodules:14051406sage: loads(W.dumps()) == W1407True14081409sage: K.<x> = FractionField(PolynomialRing(QQ,'x'))1410sage: M = K^3; W = M.span_of_basis([[1,1,x]])1411sage: loads(W.dumps()) == W1412True1413"""1414def __init__(self, ambient, basis, inner_product_basis,1415check=True, echelonize=False, echelonized_basis=None, already_echelonized=False):1416"""1417Create a vector space with given basis.14181419EXAMPLES:1420sage: V = QQ^31421sage: W = V.span_of_basis([[1,2,3],[4,5,6]])1422sage: W1423Vector space of degree 3 and dimension 2 over Rational Field1424User basis matrix:1425[1 2 3]1426[4 5 6]1427"""1428free_module.FreeModule_submodule_with_basis_field.__init__(1429self, ambient=ambient, basis=basis, check=check,1430echelonize=echelonize, echelonized_basis=echelonized_basis, already_echelonized=already_echelonized)1431#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix1432self._inner_product_matrix = inner_product_matrix14331434def _repr_(self):1435"""1436The printing representation of self.14371438EXAMPLES:1439sage: V = VectorSpace(QQ,5)1440sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])1441sage: print U # indirect doctest1442Vector space of degree 5 and dimension 4 over Rational Field1443Basis matrix:1444[ 1 0 0 0 -1]1445[ 0 1 0 0 -1]1446[ 0 0 1 0 -1]1447[ 0 0 0 1 -1]1448sage: print U._repr_()1449Vector space of degree 5 and dimension 4 over Rational Field1450Basis matrix:1451[ 1 0 0 0 -1]1452[ 0 1 0 0 -1]1453[ 0 0 1 0 -1]1454[ 0 0 0 1 -1]14551456The system representation can be overwritten, but leaves _repr_ unmodified.14571458sage: U.rename('U')1459sage: print U1460U1461sage: print U._repr_()1462Vector space of degree 5 and dimension 4 over Rational Field1463Basis matrix:1464[ 1 0 0 0 -1]1465[ 0 1 0 0 -1]1466[ 0 0 1 0 -1]1467[ 0 0 0 1 -1]14681469Sparse vector spaces print this fact.14701471sage: V = VectorSpace(QQ,5,sparse=True)1472sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])1473sage: print U # indirect doctest1474Sparse vector space of degree 5 and dimension 4 over Rational Field1475Basis matrix:1476[ 1 0 0 0 -1]1477[ 0 1 0 0 -1]1478[ 0 0 1 0 -1]1479[ 0 0 0 1 -1]1480"""1481if self.is_sparse():1482return "Sparse quadratic space of degree %s and dimension %s over %s\n"%(1483self.degree(), self.dimension(), self.base_field()) + \1484"Basis matrix:\n%s"%self.basis_matrix() + \1485"Inner product matrix:\n%s" % self.inner_product_matrix()1486else:1487return "Quadratic space of degree %s and dimension %s over %s\n"%(1488self.degree(), self.dimension(), self.base_field()) + \1489"Basis matrix:\n%s\n"%self.basis_matrix() + \1490"Inner product matrix:\n%s" % self.inner_product_matrix()14911492class FreeQuadraticModule_submodule_field(1493free_module.FreeModule_submodule_field, FreeQuadraticModule_submodule_with_basis_field):1494"""1495An embedded vector subspace with echelonized basis.14961497EXAMPLES:14981499Since this is an embedded vector subspace with echelonized basis,1500the echelon_coordinates() and user coordinates() agree:15011502sage: V = QQ^31503sage: W = V.span([[1,2,3],[4,5,6]])1504sage: W1505Vector space of degree 3 and dimension 2 over Rational Field1506Basis matrix:1507[ 1 0 -1]1508[ 0 1 2]15091510sage: v = V([1,5,9])1511sage: W.echelon_coordinates(v)1512[1, 5]1513sage: vector(QQ, W.echelon_coordinates(v)) * W.basis_matrix()1514(1, 5, 9)15151516sage: v = V([1,5,9])1517sage: W.coordinates(v)1518[1, 5]1519sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()1520(1, 5, 9)1521"""1522def __init__(self, ambient, gens, inner_product_matrix, check=True, already_echelonized=False):1523"""1524Create an embedded vector subspace with echelonized basis.15251526EXAMPLES:1527sage: V = QQ^31528sage: W = V.span([[1,2,3],[4,5,6]])1529sage: W1530Vector space of degree 3 and dimension 2 over Rational Field1531Basis matrix:1532[ 1 0 -1]1533[ 0 1 2]1534"""1535free_module.FreeModule_submodule_field.__init__(1536self, ambient=ambient, gens=gens, check=check, already_echelonized=already_echelonized)1537#self._FreeQuadraticModule_generic_inner_product_matrix = inner_product_matrix1538self._inner_product_matrix = inner_product_matrix15391540def _repr_(self):1541"""1542The default printing representation of self.15431544EXAMPLES:1545sage: V = VectorSpace(QQ,5)1546sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])1547sage: print U # indirect doctest1548Vector space of degree 5 and dimension 4 over Rational Field1549Basis matrix:1550[ 1 0 0 0 -1]1551[ 0 1 0 0 -1]1552[ 0 0 1 0 -1]1553[ 0 0 0 1 -1]1554sage: print U._repr_()1555Vector space of degree 5 and dimension 4 over Rational Field1556Basis matrix:1557[ 1 0 0 0 -1]1558[ 0 1 0 0 -1]1559[ 0 0 1 0 -1]1560[ 0 0 0 1 -1]15611562The system representation can be overwritten, but leaves _repr_ unmodified.15631564sage: U.rename('U')1565sage: print U1566U1567sage: print U._repr_()1568Vector space of degree 5 and dimension 4 over Rational Field1569Basis matrix:1570[ 1 0 0 0 -1]1571[ 0 1 0 0 -1]1572[ 0 0 1 0 -1]1573[ 0 0 0 1 -1]15741575Sparse vector spaces print this fact.15761577sage: V = VectorSpace(QQ,5,sparse=True)1578sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])1579sage: print U # indirect doctest1580Sparse vector space of degree 5 and dimension 4 over Rational Field1581Basis matrix:1582[ 1 0 0 0 -1]1583[ 0 1 0 0 -1]1584[ 0 0 1 0 -1]1585[ 0 0 0 1 -1]1586"""1587if self.is_sparse():1588return "Sparse quadratic space of degree %s and dimension %s over %s\n"%(1589self.degree(), self.dimension(), self.base_field()) + \1590"Basis matrix:\n%s\n" % self.basis_matrix() + \1591"Inner product matrix:\n%s" % self.inner_product_matrix()1592else:1593return "Quadratic space of degree %s and dimension %s over %s\n"%(1594self.degree(), self.dimension(), self.base_field()) + \1595"Basis matrix:\n%s\n" % self.basis_matrix() + \1596"Inner product matrix:\n%s" % self.inner_product_matrix()15971598#class RealDoubleQuadraticSpace_class(free_module.RealDoubleVectorSpace_class, FreeQuadraticModule_ambient_field):1599# def __init__(self, dimension, inner_product_matrix, sparse=False):1600# if sparse:1601# raise NotImplementedError, "Sparse matrices over RDF not implemented yet"1602# free_module.RealDoubleVectorSpace_class.__init__(self, dimension=dimension, sparse=False)1603# self._inner_product_matrix = inner_product_matrix16041605#class ComplexDoubleQuadraticSpace_class(1606# free_module.ComplexDoubleVectorSpace_class, FreeQuadraticModule_generic): #FreeQuadraticModule_ambient_field):1607# def __init__(self, dimension, inner_product_matrix, sparse=False):1608# if sparse:1609# raise NotImplementedError, "Sparse matrices over CDF not implemented yet"1610# free_module.ComplexDoubleVectorSpace_class.__init__(self, dimension=dimension, sparse=False)1611# self._inner_product_matrix = inner_product_matrix16121613######################################################1614161516161617