Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modules/free_module.py
4036 views
1
r"""
2
Free modules
3
4
Sage supports computation with free modules over an arbitrary commutative ring.
5
Nontrivial functionality is available over `\ZZ`, fields, and some principal
6
ideal domains (e.g. `\QQ[x]` and rings of integers of number fields). All free
7
modules over an integral domain are equipped with an embedding in an ambient
8
vector space and an inner product, which you can specify and change.
9
10
Create the free module of rank `n` over an arbitrary commutative ring `R` using
11
the command ``FreeModule(R,n)``. Equivalently, ``R^n`` also creates that free
12
module.
13
14
The following example illustrates the creation of both a vector space and a
15
free module over the integers and a submodule of it. Use the functions
16
``FreeModule``, ``span`` and member functions of free modules to create free
17
modules. *Do not use the FreeModule_xxx constructors directly.*
18
19
EXAMPLES::
20
21
sage: V = VectorSpace(QQ,3)
22
sage: W = V.subspace([[1,2,7], [1,1,0]])
23
sage: W
24
Vector space of degree 3 and dimension 2 over Rational Field
25
Basis matrix:
26
[ 1 0 -7]
27
[ 0 1 7]
28
sage: C = VectorSpaces(FiniteField(7))
29
sage: C
30
Category of vector spaces over Finite Field of size 7
31
sage: C(W)
32
Vector space of degree 3 and dimension 2 over Finite Field of size 7
33
Basis matrix:
34
[1 0 0]
35
[0 1 0]
36
37
::
38
39
sage: M = ZZ^3
40
sage: C = VectorSpaces(FiniteField(7))
41
sage: C(M)
42
Vector space of dimension 3 over Finite Field of size 7
43
sage: W = M.submodule([[1,2,7], [8,8,0]])
44
sage: C(W)
45
Vector space of degree 3 and dimension 2 over Finite Field of size 7
46
Basis matrix:
47
[1 0 0]
48
[0 1 0]
49
50
We illustrate the exponent notation for creation of free modules.
51
52
::
53
54
sage: ZZ^4
55
Ambient free module of rank 4 over the principal ideal domain Integer Ring
56
sage: QQ^2
57
Vector space of dimension 2 over Rational Field
58
sage: RR^3
59
Vector space of dimension 3 over Real Field with 53 bits of precision
60
61
Base ring::
62
63
sage: R.<x,y> = QQ[]
64
sage: M = FreeModule(R,2)
65
sage: M.base_ring()
66
Multivariate Polynomial Ring in x, y over Rational Field
67
68
::
69
70
sage: VectorSpace(QQ, 10).base_ring()
71
Rational Field
72
73
TESTS: We intersect a zero-dimensional vector space with a
74
1-dimension submodule.
75
76
::
77
78
sage: V = (QQ^1).span([])
79
sage: W = ZZ^1
80
sage: V.intersection(W)
81
Free module of degree 1 and rank 0 over Integer Ring
82
Echelon basis matrix:
83
[]
84
85
We construct subspaces of real and complex double vector spaces and
86
verify that the element types are correct::
87
88
sage: V = FreeModule(RDF, 3); V
89
Vector space of dimension 3 over Real Double Field
90
sage: V.0
91
(1.0, 0.0, 0.0)
92
sage: type(V.0)
93
<type 'sage.modules.vector_real_double_dense.Vector_real_double_dense'>
94
sage: W = V.span([V.0]); W
95
Vector space of degree 3 and dimension 1 over Real Double Field
96
Basis matrix:
97
[1.0 0.0 0.0]
98
sage: type(W.0)
99
<type 'sage.modules.vector_real_double_dense.Vector_real_double_dense'>
100
sage: V = FreeModule(CDF, 3); V
101
Vector space of dimension 3 over Complex Double Field
102
sage: type(V.0)
103
<type 'sage.modules.vector_complex_double_dense.Vector_complex_double_dense'>
104
sage: W = V.span_of_basis([CDF.0 * V.1]); W
105
Vector space of degree 3 and dimension 1 over Complex Double Field
106
User basis matrix:
107
[ 0.0 1.0*I 0.0]
108
sage: type(W.0)
109
<type 'sage.modules.vector_complex_double_dense.Vector_complex_double_dense'>
110
111
Basis vectors are immutable::
112
113
sage: A = span([[1,2,3], [4,5,6]], ZZ)
114
sage: A.0
115
(1, 2, 3)
116
sage: A.0[0] = 5
117
Traceback (most recent call last):
118
...
119
ValueError: vector is immutable; please change a copy instead (use copy())
120
121
Among other things, this tests that we can save and load submodules
122
and elements::
123
124
sage: M = ZZ^3
125
sage: TestSuite(M).run()
126
sage: W = M.span_of_basis([[1,2,3],[4,5,19]])
127
sage: TestSuite(W).run()
128
sage: v = W.0 + W.1
129
sage: TestSuite(v).run()
130
131
AUTHORS:
132
133
- William Stein (2005, 2007)
134
135
- David Kohel (2007, 2008)
136
137
- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
138
139
- Simon King (2010-12): Trac #8800: Fixing a bug in ``denominator()``.
140
141
"""
142
143
###########################################################################
144
# Copyright (C) 2005, 2007 William Stein <[email protected]>
145
# Copyright (C) 2007, 2008 David Kohel <[email protected]>
146
#
147
# Distributed under the terms of the GNU General Public License (GPL)
148
#
149
# This code is distributed in the hope that it will be useful,
150
# but WITHOUT ANY WARRANTY; without even the implied warranty of
151
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
152
# General Public License for more details.
153
#
154
# The full text of the GPL is available at:
155
#
156
# http://www.gnu.org/licenses/
157
###########################################################################
158
159
# python imports
160
161
162
# Sage imports
163
import free_module_element
164
165
import module
166
167
import sage.matrix.matrix_space
168
169
import sage.misc.latex as latex
170
171
import sage.rings.commutative_ring as commutative_ring
172
import sage.rings.principal_ideal_domain as principal_ideal_domain
173
import sage.rings.field as field
174
import sage.rings.finite_rings.constructor as finite_field
175
import sage.rings.integral_domain as integral_domain
176
import sage.rings.ring as ring
177
import sage.rings.integer_ring
178
import sage.rings.rational_field
179
import sage.rings.finite_rings.integer_mod_ring
180
import sage.rings.infinity
181
import sage.rings.integer
182
import sage.structure.parent_gens as gens
183
from sage.categories.principal_ideal_domains import PrincipalIdealDomains
184
from sage.misc.randstate import current_randstate
185
from sage.structure.sequence import Sequence
186
187
from sage.structure.parent_gens import ParentWithGens
188
from sage.misc.cachefunc import cached_method
189
190
from warnings import warn
191
192
###############################################################################
193
#
194
# Constructor functions
195
#
196
###############################################################################
197
198
from sage.structure.factory import UniqueFactory
199
200
class FreeModuleFactory(UniqueFactory):
201
r"""
202
Create the free module over the given commutative ring of the given
203
rank.
204
205
INPUT:
206
207
208
- ``base_ring`` - a commutative ring
209
210
- ``rank`` - a nonnegative integer
211
212
- ``sparse`` - bool; (default False)
213
214
- ``inner_product_matrix`` - the inner product
215
matrix (default None)
216
217
218
OUTPUT: a free module
219
220
.. note::
221
222
In Sage it is the case that there is only one dense and one
223
sparse free ambient module of rank `n` over `R`.
224
225
EXAMPLES:
226
227
First we illustrate creating free modules over various base fields.
228
The base field affects the free module that is created. For
229
example, free modules over a field are vector spaces, and free
230
modules over a principal ideal domain are special in that more
231
functionality is available for them than for completely general
232
free modules.
233
234
::
235
236
sage: FreeModule(Integers(8),10)
237
Ambient free module of rank 10 over Ring of integers modulo 8
238
sage: FreeModule(QQ,10)
239
Vector space of dimension 10 over Rational Field
240
sage: FreeModule(ZZ,10)
241
Ambient free module of rank 10 over the principal ideal domain Integer Ring
242
sage: FreeModule(FiniteField(5),10)
243
Vector space of dimension 10 over Finite Field of size 5
244
sage: FreeModule(Integers(7),10)
245
Vector space of dimension 10 over Ring of integers modulo 7
246
sage: FreeModule(PolynomialRing(QQ,'x'),5)
247
Ambient free module of rank 5 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
248
sage: FreeModule(PolynomialRing(ZZ,'x'),5)
249
Ambient free module of rank 5 over the integral domain Univariate Polynomial Ring in x over Integer Ring
250
251
Of course we can make rank 0 free modules::
252
253
sage: FreeModule(RealField(100),0)
254
Vector space of dimension 0 over Real Field with 100 bits of precision
255
256
Next we create a free module with sparse representation of
257
elements. Functionality with sparse modules is *identical* to dense
258
modules, but they may use less memory and arithmetic may be faster
259
(or slower!).
260
261
::
262
263
sage: M = FreeModule(ZZ,200,sparse=True)
264
sage: M.is_sparse()
265
True
266
sage: type(M.0)
267
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
268
269
The default is dense.
270
271
::
272
273
sage: M = ZZ^200
274
sage: type(M.0)
275
<type 'sage.modules.vector_integer_dense.Vector_integer_dense'>
276
277
Note that matrices associated in some way to sparse free modules
278
are sparse by default::
279
280
sage: M = FreeModule(Integers(8), 2)
281
sage: A = M.basis_matrix()
282
sage: A.is_sparse()
283
False
284
sage: Ms = FreeModule(Integers(8), 2, sparse=True)
285
sage: M == Ms # as mathematical objects they are equal
286
True
287
sage: Ms.basis_matrix().is_sparse()
288
True
289
290
We can also specify an inner product matrix, which is used when
291
computing inner products of elements.
292
293
::
294
295
sage: A = MatrixSpace(ZZ,2)([[1,0],[0,-1]])
296
sage: M = FreeModule(ZZ,2,inner_product_matrix=A)
297
sage: v, w = M.gens()
298
sage: v.inner_product(w)
299
0
300
sage: v.inner_product(v)
301
1
302
sage: w.inner_product(w)
303
-1
304
sage: (v+2*w).inner_product(w)
305
-2
306
307
You can also specify the inner product matrix by giving anything
308
that coerces to an appropriate matrix. This is only useful if the
309
inner product matrix takes values in the base ring.
310
311
::
312
313
sage: FreeModule(ZZ,2,inner_product_matrix=1).inner_product_matrix()
314
[1 0]
315
[0 1]
316
sage: FreeModule(ZZ,2,inner_product_matrix=[1,2,3,4]).inner_product_matrix()
317
[1 2]
318
[3 4]
319
sage: FreeModule(ZZ,2,inner_product_matrix=[[1,2],[3,4]]).inner_product_matrix()
320
[1 2]
321
[3 4]
322
323
.. todo::
324
325
Refactor modules such that it only counts what category the base
326
ring belongs to, but not what is its Python class.
327
328
"""
329
def create_key(self, base_ring, rank, sparse=False, inner_product_matrix=None):
330
"""
331
TESTS::
332
333
sage: loads(dumps(ZZ^6)) is ZZ^6
334
True
335
sage: loads(dumps(RDF^3)) is RDF^3
336
True
337
338
TODO: replace the above by ``TestSuite(...).run()``, once
339
:meth:`_test_pickling` will test unique representation and not
340
only equality.
341
"""
342
rank = int(sage.rings.integer.Integer(rank))
343
344
if not (inner_product_matrix is None):
345
inner_product_matrix = sage.matrix.matrix_space.MatrixSpace(base_ring, rank)(inner_product_matrix)
346
inner_product_matrix.set_immutable()
347
348
return (base_ring, rank, sparse, inner_product_matrix)
349
350
def create_object(self, version, key):
351
352
base_ring, rank, sparse, inner_product_matrix = key
353
354
if inner_product_matrix is not None:
355
from free_quadratic_module import FreeQuadraticModule
356
return FreeQuadraticModule(base_ring, rank, inner_product_matrix=inner_product_matrix, sparse=sparse)
357
358
if not isinstance(sparse,bool):
359
raise TypeError, "Argument sparse (= %s) must be True or False" % sparse
360
361
if not (hasattr(base_ring,'is_commutative') and base_ring.is_commutative()):
362
warn("""You are constructing a free module
363
over a noncommutative ring. Sage does not have a concept
364
of left/right and both sided modules, so be careful.
365
It's also not guaranteed that all multiplications are
366
done from the right side.""")
367
368
# raise TypeError, "The base_ring must be a commutative ring."
369
370
try:
371
if not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class):
372
return RealDoubleVectorSpace_class(rank)
373
374
elif not sparse and isinstance(base_ring,sage.rings.complex_double.ComplexDoubleField_class):
375
return ComplexDoubleVectorSpace_class(rank)
376
377
elif base_ring.is_field():
378
return FreeModule_ambient_field(base_ring, rank, sparse=sparse)
379
380
elif isinstance(base_ring, principal_ideal_domain.PrincipalIdealDomain):
381
return FreeModule_ambient_pid(base_ring, rank, sparse=sparse)
382
383
elif isinstance(base_ring, sage.rings.number_field.order.Order) \
384
and base_ring.is_maximal() and base_ring.class_number() == 1:
385
return FreeModule_ambient_pid(base_ring, rank, sparse=sparse)
386
387
elif isinstance(base_ring, integral_domain.IntegralDomain) or base_ring.is_integral_domain():
388
return FreeModule_ambient_domain(base_ring, rank, sparse=sparse)
389
390
else:
391
return FreeModule_ambient(base_ring, rank, sparse=sparse)
392
except NotImplementedError:
393
return FreeModule_ambient(base_ring, rank, sparse=sparse)
394
395
396
FreeModule = FreeModuleFactory("FreeModule")
397
398
399
def VectorSpace(K, dimension, sparse=False, inner_product_matrix=None):
400
"""
401
EXAMPLES:
402
403
The base can be complicated, as long as it is a field.
404
405
::
406
407
sage: V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),3)
408
sage: V
409
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x over Integer Ring
410
sage: V.basis()
411
[
412
(1, 0, 0),
413
(0, 1, 0),
414
(0, 0, 1)
415
]
416
417
The base must be a field or a ``TypeError`` is raised.
418
419
::
420
421
sage: VectorSpace(ZZ,5)
422
Traceback (most recent call last):
423
...
424
TypeError: Argument K (= Integer Ring) must be a field.
425
"""
426
if not K.is_field():
427
raise TypeError, "Argument K (= %s) must be a field." % K
428
if not sparse in (True,False):
429
raise TypeError, "Argument sparse (= %s) must be a boolean."%sparse
430
return FreeModule(K, rank=dimension, sparse=sparse, inner_product_matrix=inner_product_matrix)
431
432
###############################################################################
433
#
434
# The span of vectors
435
#
436
###############################################################################
437
438
def span(gens, base_ring=None, check=True, already_echelonized=False):
439
r"""
440
Return the span of the vectors in ``gens`` using scalars from ``base_ring``.
441
442
INPUT:
443
444
- ``gens`` - a list of either vectors or lists of ring elements
445
used to generate the span
446
447
- ``base_ring`` - default: ``None`` - a principal ideal domain
448
for the ring of scalars
449
450
- ``check`` - default: ``True`` - passed to the ``span()`` method
451
of the ambient module
452
453
- ``already_echelonized`` - default: ``False`` - set to ``True``
454
if the vectors form the rows of a matrix in echelon form, in
455
order to skip the computation of an echelonized basis for the
456
span.
457
458
OUTPUT:
459
460
A module (or vector space) that is all the linear combinations of the
461
free module elements (or vectors) with scalars from the
462
ring (or field) given by ``base_ring``. See the examples below
463
describing behavior when the base ring is not specified and/or
464
the module elements are given as lists that do not carry
465
explicit base ring information.
466
467
EXAMPLES:
468
469
The vectors in the list of generators can be given as
470
lists, provided a base ring is specified and the elements of the list
471
are in the ring (or the fraction field of the ring). If the
472
base ring is a field, the span is a vector space. ::
473
474
sage: V = span([[1,2,5], [2,2,2]], QQ); V
475
Vector space of degree 3 and dimension 2 over Rational Field
476
Basis matrix:
477
[ 1 0 -3]
478
[ 0 1 4]
479
480
sage: span([V.gen(0)], QuadraticField(-7,'a'))
481
Vector space of degree 3 and dimension 1 over Number Field in a with defining polynomial x^2 + 7
482
Basis matrix:
483
[ 1 0 -3]
484
485
sage: span([[1,2,3], [2,2,2], [1,2,5]], GF(2))
486
Vector space of degree 3 and dimension 1 over Finite Field of size 2
487
Basis matrix:
488
[1 0 1]
489
490
If the base ring is not a field, then a module is created.
491
The entries of the vectors can lie outside the ring, if they
492
are in the fraction field of the ring. ::
493
494
sage: span([[1,2,5], [2,2,2]], ZZ)
495
Free module of degree 3 and rank 2 over Integer Ring
496
Echelon basis matrix:
497
[ 1 0 -3]
498
[ 0 2 8]
499
500
sage: span([[1,1,1], [1,1/2,1]], ZZ)
501
Free module of degree 3 and rank 2 over Integer Ring
502
Echelon basis matrix:
503
[ 1 0 1]
504
[ 0 1/2 0]
505
506
sage: R.<x> = QQ[]
507
sage: M= span( [[x, x^2+1], [1/x, x^3]], R); M
508
Free module of degree 2 and rank 2 over
509
Univariate Polynomial Ring in x over Rational Field
510
Echelon basis matrix:
511
[ 1/x x^3]
512
[ 0 x^5 - x^2 - 1]
513
sage: M.basis()[0][0].parent()
514
Fraction Field of Univariate Polynomial Ring in x over Rational Field
515
516
A base ring can be inferred if the generators are given as a
517
list of vectors. ::
518
519
sage: span([vector(QQ, [1,2,3]), vector(QQ, [4,5,6])])
520
Vector space of degree 3 and dimension 2 over Rational Field
521
Basis matrix:
522
[ 1 0 -1]
523
[ 0 1 2]
524
sage: span([vector(QQ, [1,2,3]), vector(ZZ, [4,5,6])])
525
Vector space of degree 3 and dimension 2 over Rational Field
526
Basis matrix:
527
[ 1 0 -1]
528
[ 0 1 2]
529
sage: span([vector(ZZ, [1,2,3]), vector(ZZ, [4,5,6])])
530
Free module of degree 3 and rank 2 over Integer Ring
531
Echelon basis matrix:
532
[1 2 3]
533
[0 3 6]
534
535
TESTS::
536
537
sage: span([[1,2,3], [2,2,2], [1,2/3,5]], ZZ)
538
Free module of degree 3 and rank 3 over Integer Ring
539
Echelon basis matrix:
540
[ 1 0 13]
541
[ 0 2/3 6]
542
[ 0 0 14]
543
sage: span([[1,2,3], [2,2,2], [1,2,QQ['x'].gen()]], ZZ)
544
Traceback (most recent call last):
545
...
546
ValueError: The elements of gens (= [[1, 2, 3], [2, 2, 2], [1, 2, x]]) must be defined over base_ring (= Integer Ring) or its field of fractions.
547
548
For backwards compatibility one can also give the base ring as the
549
first argument. ::
550
551
sage: span(QQ,[[1,2],[3,4]])
552
Vector space of degree 2 and dimension 2 over Rational Field
553
Basis matrix:
554
[1 0]
555
[0 1]
556
557
The base ring must be a principal ideal domain (PID). ::
558
559
sage: span([[1,2,3]], Integers(6))
560
Traceback (most recent call last):
561
...
562
TypeError: The base_ring (= Ring of integers modulo 6)
563
must be a principal ideal domain.
564
565
Fix :trac:`5575`::
566
567
sage: V = QQ^3
568
sage: span([V.0, V.1])
569
Vector space of degree 3 and dimension 2 over Rational Field
570
Basis matrix:
571
[1 0 0]
572
[0 1 0]
573
574
Improve error message from :trac:`12541`::
575
576
sage: span({0:vector([0,1])}, QQ)
577
Traceback (most recent call last):
578
...
579
TypeError: generators must be lists of ring elements
580
or free module elements!
581
"""
582
if ring.is_Ring(gens):
583
# we allow the old input format with first input the base_ring.
584
# Do we want to deprecate it?..
585
base_ring, gens = gens, base_ring
586
587
try:
588
if base_ring is None:
589
gens = Sequence(gens)
590
R = gens.universe().base_ring()
591
else:
592
gens = list(gens)
593
R = base_ring
594
except TypeError:
595
raise TypeError("generators must be given as an iterable structure!")
596
597
if R not in PrincipalIdealDomains():
598
raise TypeError("The base_ring (= %s) must be a principal ideal "
599
"domain." % R)
600
if len(gens) == 0:
601
return FreeModule(R, 0)
602
else:
603
x = gens[0]
604
if free_module_element.is_FreeModuleElement(x):
605
M = x.parent()
606
else:
607
try:
608
x = list(x)
609
except TypeError:
610
raise TypeError("generators must be lists of ring elements or "
611
"free module elements!")
612
M = FreeModule(R, len(x))
613
try:
614
gens = map(M, gens)
615
except TypeError:
616
R = R.fraction_field()
617
M = FreeModule(R, len(x))
618
try:
619
gens = map(M, gens)
620
except TypeError:
621
raise ValueError("The elements of gens (= %s) must be "
622
"defined over base_ring (= %s) or its "
623
"field of fractions." % (gens, base_ring))
624
return M.span(gens=gens, base_ring=base_ring, check=check,
625
already_echelonized=already_echelonized)
626
627
###############################################################################
628
#
629
# Base class for all free modules
630
#
631
###############################################################################
632
633
def is_FreeModule(M):
634
"""
635
Return True if M inherits from from FreeModule_generic.
636
637
EXAMPLES::
638
639
sage: from sage.modules.free_module import is_FreeModule
640
sage: V = ZZ^3
641
sage: is_FreeModule(V)
642
True
643
sage: W = V.span([ V.random_element() for i in range(2) ])
644
sage: is_FreeModule(W)
645
True
646
"""
647
return isinstance(M, FreeModule_generic)
648
649
class FreeModule_generic(module.Module_old):
650
"""
651
Base class for all free modules.
652
"""
653
def __init__(self, base_ring, rank, degree, sparse=False):
654
"""
655
Create the free module of given rank over the given base_ring.
656
657
INPUT:
658
659
660
- ``base_ring`` - a commutative ring
661
662
- ``rank`` - a non-negative integer
663
664
- ``degree`` - a non-negative integer
665
666
- ``sparse`` - bool (default: False)
667
668
669
EXAMPLES::
670
671
sage: PolynomialRing(QQ,3,'x')^3
672
Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
673
674
If ``base_ring`` is a field, then the constructed module is in
675
the category of vector spaces over that field; otherwise it is
676
in the category of all free modules over that ring::
677
678
sage: FreeModule(GF(7),3).category()
679
Category of vector spaces over Finite Field of size 7
680
sage: V = QQ^4; V.category()
681
Category of vector spaces over Rational Field
682
sage: V = GF(5)**20; V.category()
683
Category of vector spaces over Finite Field of size 5
684
sage: FreeModule(ZZ,3).category()
685
Category of modules with basis over Integer Ring
686
687
"""
688
if not base_ring.is_commutative():
689
warn("""You are constructing a free module
690
over a noncommutative ring. Sage does not have a concept
691
of left/right and both sided modules, so be careful.
692
It's also not guaranteed that all multiplications are
693
done from the right side.""")
694
rank = sage.rings.integer.Integer(rank)
695
if rank < 0:
696
raise ValueError, "rank (=%s) must be nonnegative"%rank
697
degree = sage.rings.integer.Integer(degree)
698
if degree < 0:
699
raise ValueError, "degree (=%s) must be nonnegative"%degree
700
from sage.categories.all import Fields, FreeModules, VectorSpaces
701
if base_ring in Fields():
702
category = VectorSpaces(base_ring)
703
else:
704
category = FreeModules(base_ring)
705
706
ParentWithGens.__init__(self, base_ring, category = category) # names aren't used anywhere.
707
self.__uses_ambient_inner_product = True
708
self.__rank = rank
709
self.__degree = degree
710
self.__is_sparse = sparse
711
self._gram_matrix = None
712
self.element_class()
713
714
def construction(self):
715
"""
716
The construction functor and base ring for self.
717
718
EXAMPLES::
719
720
sage: R = PolynomialRing(QQ,3,'x')
721
sage: V = R^5
722
sage: V.construction()
723
(VectorFunctor, Multivariate Polynomial Ring in x0, x1, x2 over Rational Field)
724
"""
725
from sage.categories.pushout import VectorFunctor
726
if hasattr(self,'_inner_product_matrix'):
727
return VectorFunctor(self.rank(), self.is_sparse(),self.inner_product_matrix()), self.base_ring()
728
return VectorFunctor(self.rank(), self.is_sparse()), self.base_ring()
729
730
# FIXME: what's the level of generality of FreeModuleHomspace?
731
# Should there be a category for free modules accepting it as hom space?
732
# See similar method for FreeModule_generic_field class
733
def _Hom_(self, Y, category):
734
from free_module_homspace import FreeModuleHomspace
735
return FreeModuleHomspace(self, Y, category)
736
737
def dense_module(self):
738
"""
739
Return corresponding dense module.
740
741
EXAMPLES:
742
743
We first illustrate conversion with ambient spaces::
744
745
sage: M = FreeModule(QQ,3)
746
sage: S = FreeModule(QQ,3, sparse=True)
747
sage: M.sparse_module()
748
Sparse vector space of dimension 3 over Rational Field
749
sage: S.dense_module()
750
Vector space of dimension 3 over Rational Field
751
sage: M.sparse_module() == S
752
True
753
sage: S.dense_module() == M
754
True
755
sage: M.dense_module() == M
756
True
757
sage: S.sparse_module() == S
758
True
759
760
Next we create a subspace::
761
762
sage: M = FreeModule(QQ,3, sparse=True)
763
sage: V = M.span([ [1,2,3] ] ); V
764
Sparse vector space of degree 3 and dimension 1 over Rational Field
765
Basis matrix:
766
[1 2 3]
767
sage: V.sparse_module()
768
Sparse vector space of degree 3 and dimension 1 over Rational Field
769
Basis matrix:
770
[1 2 3]
771
"""
772
if self.is_sparse():
773
return self._dense_module()
774
return self
775
776
def _dense_module(self):
777
"""
778
Creates a dense module with the same defining data as self.
779
780
N.B. This function is for internal use only! See dense_module for
781
use.
782
783
EXAMPLES::
784
785
sage: M = FreeModule(Integers(8),3)
786
sage: S = FreeModule(Integers(8),3, sparse=True)
787
sage: M is S._dense_module()
788
True
789
"""
790
A = self.ambient_module().dense_module()
791
return A.span(self.basis())
792
793
def sparse_module(self):
794
"""
795
Return the corresponding sparse module with the same defining
796
data.
797
798
EXAMPLES:
799
800
We first illustrate conversion with ambient spaces::
801
802
sage: M = FreeModule(Integers(8),3)
803
sage: S = FreeModule(Integers(8),3, sparse=True)
804
sage: M.sparse_module()
805
Ambient sparse free module of rank 3 over Ring of integers modulo 8
806
sage: S.dense_module()
807
Ambient free module of rank 3 over Ring of integers modulo 8
808
sage: M.sparse_module() is S
809
True
810
sage: S.dense_module() is M
811
True
812
sage: M.dense_module() is M
813
True
814
sage: S.sparse_module() is S
815
True
816
817
Next we convert a subspace::
818
819
sage: M = FreeModule(QQ,3)
820
sage: V = M.span([ [1,2,3] ] ); V
821
Vector space of degree 3 and dimension 1 over Rational Field
822
Basis matrix:
823
[1 2 3]
824
sage: V.sparse_module()
825
Sparse vector space of degree 3 and dimension 1 over Rational Field
826
Basis matrix:
827
[1 2 3]
828
"""
829
if self.is_sparse():
830
return self
831
return self._sparse_module()
832
833
def _sparse_module(self):
834
"""
835
Creates a sparse module with the same defining data as self.
836
837
N.B. This function is for internal use only! See sparse_module for
838
use.
839
840
EXAMPLES::
841
842
sage: M = FreeModule(Integers(8),3)
843
sage: S = FreeModule(Integers(8),3, sparse=True)
844
sage: M._sparse_module() is S
845
True
846
"""
847
A = self.ambient_module().sparse_module()
848
return A.span(self.basis())
849
850
def _an_element_impl(self):
851
"""
852
Returns an arbitrary element of a free module.
853
854
EXAMPLES::
855
856
sage: V = VectorSpace(QQ,2)
857
sage: V._an_element_impl()
858
(1, 0)
859
sage: U = V.submodule([[1,0]])
860
sage: U._an_element_impl()
861
(1, 0)
862
sage: W = V.submodule([])
863
sage: W._an_element_impl()
864
(0, 0)
865
"""
866
try:
867
return self.gen(0)
868
except ValueError:
869
return self(0)
870
871
def element_class(self):
872
"""
873
The class of elements for this free module.
874
875
EXAMPLES::
876
877
sage: M = FreeModule(ZZ,20,sparse=False)
878
sage: x = M.random_element()
879
sage: type(x)
880
<type 'sage.modules.vector_integer_dense.Vector_integer_dense'>
881
sage: M.element_class()
882
<type 'sage.modules.vector_integer_dense.Vector_integer_dense'>
883
sage: N = FreeModule(ZZ,20,sparse=True)
884
sage: y = N.random_element()
885
sage: type(y)
886
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
887
sage: N.element_class()
888
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
889
"""
890
try:
891
return self._element_class
892
except AttributeError:
893
pass
894
C = element_class(self.base_ring(), self.is_sparse())
895
self._element_class = C
896
return C
897
898
def __call__(self, x, coerce=True, copy=True, check=True):
899
r"""
900
Create an element of this free module from x.
901
902
The ``coerce`` and ``copy`` arguments are
903
passed on to the underlying element constructor. If
904
``check`` is ``True``, confirm that the
905
element specified by x does in fact lie in self.
906
907
.. note:::
908
909
In the case of an inexact base ring (i.e. RDF), we don't
910
verify that the element is in the subspace, even when
911
``check=True``, to account for numerical instability
912
issues.
913
914
EXAMPLE::
915
916
sage: M = ZZ^4
917
sage: M([1,-1,0,1])
918
(1, -1, 0, 1)
919
920
::
921
922
sage: N = M.submodule([[1,0,0,0], [0,1,1,0]])
923
sage: N([1,1,1,0])
924
(1, 1, 1, 0)
925
sage: N((3,-2,-2,0))
926
(3, -2, -2, 0)
927
sage: N((0,0,0,1))
928
Traceback (most recent call last):
929
...
930
TypeError: element (= (0, 0, 0, 1)) is not in free module
931
932
Beware that using check=False can create invalid results::
933
934
sage: N((0,0,0,1), check=False)
935
(0, 0, 0, 1)
936
sage: N((0,0,0,1), check=False) in N
937
True
938
"""
939
if isinstance(x, (int, long, sage.rings.integer.Integer)) and x==0:
940
return self.zero_vector()
941
elif isinstance(x, free_module_element.FreeModuleElement):
942
if x.parent() is self:
943
if copy:
944
return x.__copy__()
945
else:
946
return x
947
x = x.list()
948
if check and self.base_ring().is_exact():
949
if isinstance(self, FreeModule_ambient):
950
return self._element_class(self, x, coerce, copy)
951
try:
952
c = self.coordinates(x)
953
R = self.base_ring()
954
for d in c:
955
if d not in R:
956
raise ArithmeticError
957
except ArithmeticError:
958
raise TypeError, "element (= %s) is not in free module"%(x,)
959
return self._element_class(self, x, coerce, copy)
960
961
def is_submodule(self, other):
962
"""
963
Return True if self is a submodule of other.
964
965
EXAMPLES::
966
967
sage: M = FreeModule(ZZ,3)
968
sage: V = M.ambient_vector_space()
969
sage: X = V.span([[1/2,1/2,0],[1/2,0,1/2]], ZZ)
970
sage: Y = V.span([[1,1,1]], ZZ)
971
sage: N = X + Y
972
sage: M.is_submodule(X)
973
False
974
sage: M.is_submodule(Y)
975
False
976
sage: Y.is_submodule(M)
977
True
978
sage: N.is_submodule(M)
979
False
980
sage: M.is_submodule(N)
981
True
982
983
Since basis() is not implemented in general, submodule testing does
984
not work for all PID's. However, trivial cases are already used
985
(and useful) for coercion, e.g.
986
987
::
988
989
sage: QQ(1/2) * vector(ZZ['x']['y'],[1,2,3,4])
990
(1/2, 1, 3/2, 2)
991
sage: vector(ZZ['x']['y'],[1,2,3,4]) * QQ(1/2)
992
(1/2, 1, 3/2, 2)
993
"""
994
if not isinstance(other, FreeModule_generic):
995
return False
996
try:
997
if self.ambient_vector_space() != other.ambient_vector_space():
998
return False
999
if other == other.ambient_vector_space():
1000
return True
1001
except AttributeError:
1002
# Not all free modules have an ambient_vector_space.
1003
pass
1004
if other.rank() < self.rank():
1005
return False
1006
if self.base_ring() != other.base_ring():
1007
try:
1008
if not self.base_ring().is_subring(other.base_ring()):
1009
return False
1010
except NotImplementedError:
1011
return False
1012
for b in self.basis():
1013
if not (b in other):
1014
return False
1015
return True
1016
1017
1018
def _has_coerce_map_from_space(self, V):
1019
"""
1020
Return True if V canonically coerces to self.
1021
1022
EXAMPLES::
1023
1024
sage: V = QQ^3
1025
sage: V._has_coerce_map_from_space(V)
1026
True
1027
sage: W = V.span([[1,1,1]])
1028
sage: V._has_coerce_map_from_space(W)
1029
True
1030
sage: W._has_coerce_map_from_space(V)
1031
False
1032
sage: (Zmod(8)^3)._has_coerce_map_from_space(ZZ^3)
1033
True
1034
1035
TESTS:
1036
1037
Make sure ticket #3638 is fixed::
1038
1039
sage: vector(ZZ,[1,2,11])==vector(Zmod(8),[1,2,3])
1040
True
1041
"""
1042
try:
1043
return self.__has_coerce_map_from_space[V]
1044
except AttributeError:
1045
self.__has_coerce_map_from_space = {}
1046
except KeyError:
1047
pass
1048
if self.base_ring() is V.base_ring():
1049
h = V.is_submodule(self)
1050
elif not self.base_ring().has_coerce_map_from(V.base_ring()):
1051
self.__has_coerce_map_from_space[V] = False
1052
return False
1053
else:
1054
h = V.base_extend(self.base_ring()).is_submodule(self)
1055
self.__has_coerce_map_from_space[V] = h
1056
return h
1057
1058
def _coerce_impl(self, x):
1059
"""
1060
Canonical coercion of x into this free module.
1061
1062
EXAMPLES::
1063
1064
sage: V = QQ^5
1065
sage: x = V([0,4/3,8/3,4,16/3])
1066
sage: V._coerce_impl(x)
1067
(0, 4/3, 8/3, 4, 16/3)
1068
sage: V._coerce_impl([0,4/3,8/3,4,16/3])
1069
Traceback (most recent call last):
1070
...
1071
TypeError: Automatic coercion supported only for vectors or 0.
1072
"""
1073
if isinstance(x, (int, long, sage.rings.integer.Integer)) and x==0:
1074
return self.zero_vector()
1075
if isinstance(x, free_module_element.FreeModuleElement):
1076
# determining if the map exists is expensive the first time,
1077
# so we cache it.
1078
if self._has_coerce_map_from_space(x.parent()):
1079
return self(x)
1080
raise TypeError, "Automatic coercion supported only for vectors or 0."
1081
1082
def __contains__(self, v):
1083
r"""
1084
EXAMPLES:
1085
1086
We create the module `\ZZ^3`, and the submodule
1087
generated by one vector `(1,1,0)`, and check whether
1088
certain elements are in the submodule.
1089
1090
::
1091
1092
sage: R = FreeModule(ZZ, 3)
1093
sage: V = R.submodule([R.gen(0) + R.gen(1)])
1094
sage: R.gen(0) + R.gen(1) in V
1095
True
1096
sage: R.gen(0) + 2*R.gen(1) in V
1097
False
1098
1099
::
1100
1101
sage: w = (1/2)*(R.gen(0) + R.gen(1))
1102
sage: w
1103
(1/2, 1/2, 0)
1104
sage: w.parent()
1105
Vector space of dimension 3 over Rational Field
1106
sage: w in V
1107
False
1108
sage: V.coordinates(w)
1109
[1/2]
1110
"""
1111
if not isinstance(v, free_module_element.FreeModuleElement):
1112
return False
1113
if v.parent() is self:
1114
return True
1115
try:
1116
c = self.coordinates(v)
1117
except (ArithmeticError, TypeError):
1118
return False
1119
# Finally, check that each coordinate lies in the base ring.
1120
R = self.base_ring()
1121
if not self.base_ring().is_field():
1122
for a in c:
1123
try:
1124
b = R(a)
1125
except (TypeError, ValueError):
1126
return False
1127
except NotImplementedError:
1128
from sage.rings.all import ZZ
1129
print "bad " + str((R, R._element_constructor, R is ZZ, type(R)))
1130
return True
1131
1132
def __iter__(self):
1133
"""
1134
Return iterator over the elements of this free module.
1135
1136
EXAMPLES::
1137
1138
sage: V = VectorSpace(GF(4,'a'),2)
1139
sage: [x for x in V]
1140
[(0, 0), (a, 0), (a + 1, 0), (1, 0), (0, a), (a, a), (a + 1, a), (1, a), (0, a + 1), (a, a + 1), (a + 1, a + 1), (1, a + 1), (0, 1), (a, 1), (a + 1, 1), (1, 1)]
1141
1142
::
1143
1144
sage: W = V.subspace([V([1,1])])
1145
sage: print [x for x in W]
1146
[(0, 0), (a, a), (a + 1, a + 1), (1, 1)]
1147
1148
TESTS::
1149
1150
sage: V = VectorSpace(GF(2,'a'),2)
1151
sage: V.list()
1152
[(0, 0), (1, 0), (0, 1), (1, 1)]
1153
"""
1154
G = self.gens()
1155
if len(G) == 0:
1156
yield self(0)
1157
return
1158
R = self.base_ring()
1159
iters = [iter(R) for _ in range(len(G))]
1160
for x in iters: x.next() # put at 0
1161
zero = R(0)
1162
v = [zero for _ in range(len(G))]
1163
n = 0
1164
z = self(0)
1165
yield z
1166
while n < len(G):
1167
try:
1168
v[n] = iters[n].next()
1169
yield self.linear_combination_of_basis(v)
1170
n = 0
1171
except StopIteration:
1172
iters[n] = iter(R) # reset
1173
iters[n].next() # put at 0
1174
v[n] = zero
1175
n += 1
1176
1177
def cardinality(self):
1178
r"""
1179
Return the cardinality of the free module.
1180
1181
OUTPUT:
1182
1183
Either an integer or ``+Infinity``.
1184
1185
EXAMPLES::
1186
1187
sage: k.<a> = FiniteField(9)
1188
sage: V = VectorSpace(k,3)
1189
sage: V.cardinality()
1190
729
1191
sage: W = V.span([[1,2,1],[0,1,1]])
1192
sage: W.cardinality()
1193
81
1194
sage: R = IntegerModRing(12)
1195
sage: M = FreeModule(R,2)
1196
sage: M.cardinality()
1197
144
1198
sage: (QQ^3).cardinality()
1199
+Infinity
1200
"""
1201
return (self.base_ring().cardinality())**self.rank()
1202
1203
__len__ = cardinality # for backward compatibility
1204
1205
def ambient_module(self):
1206
"""
1207
Return the ambient module associated to this module.
1208
1209
EXAMPLES::
1210
1211
sage: R.<x,y> = QQ[]
1212
sage: M = FreeModule(R,2)
1213
sage: M.ambient_module()
1214
Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field
1215
1216
::
1217
1218
sage: V = FreeModule(QQ, 4).span([[1,2,3,4], [1,0,0,0]]); V
1219
Vector space of degree 4 and dimension 2 over Rational Field
1220
Basis matrix:
1221
[ 1 0 0 0]
1222
[ 0 1 3/2 2]
1223
sage: V.ambient_module()
1224
Vector space of dimension 4 over Rational Field
1225
"""
1226
return FreeModule(self.base_ring(), self.degree())
1227
1228
def base_extend(self, R):
1229
r"""
1230
Return the base extension of self to R. This is the same as
1231
``self.change_ring(R)`` except that a TypeError is
1232
raised if there is no canonical coerce map from the base ring of
1233
self to R.
1234
1235
INPUT:
1236
1237
1238
- ``R`` - ring
1239
1240
1241
EXAMPLES::
1242
1243
sage: V = ZZ^7
1244
sage: V.base_extend(QQ)
1245
Vector space of dimension 7 over Rational Field
1246
"""
1247
if R.has_coerce_map_from(self.base_ring()):
1248
return self.change_ring(R)
1249
raise TypeError, "Base extension of self (over '%s') to ring '%s' not defined."%(self.base_ring(),R)
1250
1251
def basis(self):
1252
"""
1253
Return the basis of this module.
1254
1255
EXAMPLES::
1256
1257
sage: FreeModule(Integers(12),3).basis()
1258
[
1259
(1, 0, 0),
1260
(0, 1, 0),
1261
(0, 0, 1)
1262
]
1263
"""
1264
raise NotImplementedError
1265
1266
def basis_matrix(self):
1267
"""
1268
Return the matrix whose rows are the basis for this free module.
1269
1270
EXAMPLES::
1271
1272
sage: FreeModule(Integers(12),3).basis_matrix()
1273
[1 0 0]
1274
[0 1 0]
1275
[0 0 1]
1276
1277
::
1278
1279
sage: M = FreeModule(GF(7),3).span([[2,3,4],[1,1,1]]); M
1280
Vector space of degree 3 and dimension 2 over Finite Field of size 7
1281
Basis matrix:
1282
[1 0 6]
1283
[0 1 2]
1284
sage: M.basis_matrix()
1285
[1 0 6]
1286
[0 1 2]
1287
1288
::
1289
1290
sage: M = FreeModule(GF(7),3).span_of_basis([[2,3,4],[1,1,1]]);
1291
sage: M.basis_matrix()
1292
[2 3 4]
1293
[1 1 1]
1294
"""
1295
try:
1296
return self.__basis_matrix
1297
except AttributeError:
1298
MAT = sage.matrix.matrix_space.MatrixSpace(self.base_ring(),
1299
len(self.basis()), self.degree(),
1300
sparse = self.is_sparse())
1301
if self.is_ambient():
1302
A = MAT.identity_matrix()
1303
else:
1304
A = MAT(self.basis())
1305
A.set_immutable()
1306
self.__basis_matrix = A
1307
return A
1308
1309
def echelonized_basis_matrix(self):
1310
"""
1311
The echelonized basis matrix (not implemented for this module).
1312
1313
This example works because M is an ambient module. Submodule
1314
creation should exist for generic modules.
1315
1316
EXAMPLES::
1317
1318
sage: R = IntegerModRing(12)
1319
sage: S.<x,y> = R[]
1320
sage: M = FreeModule(S,3)
1321
sage: M.echelonized_basis_matrix()
1322
[1 0 0]
1323
[0 1 0]
1324
[0 0 1]
1325
1326
TESTS::
1327
1328
sage: from sage.modules.free_module import FreeModule_generic
1329
sage: FreeModule_generic.echelonized_basis_matrix(M)
1330
Traceback (most recent call last):
1331
...
1332
NotImplementedError
1333
"""
1334
raise NotImplementedError
1335
1336
def matrix(self):
1337
"""
1338
Return the basis matrix of this module, which is the matrix whose
1339
rows are a basis for this module.
1340
1341
EXAMPLES::
1342
1343
sage: M = FreeModule(ZZ, 2)
1344
sage: M.matrix()
1345
[1 0]
1346
[0 1]
1347
sage: M.submodule([M.gen(0) + M.gen(1), M.gen(0) - 2*M.gen(1)]).matrix()
1348
[1 1]
1349
[0 3]
1350
"""
1351
return self.basis_matrix()
1352
1353
def direct_sum(self, other):
1354
"""
1355
Return the direct sum of self and other as a free module.
1356
1357
EXAMPLES::
1358
1359
sage: V = (ZZ^3).span([[1/2,3,5], [0,1,-3]]); V
1360
Free module of degree 3 and rank 2 over Integer Ring
1361
Echelon basis matrix:
1362
[1/2 0 14]
1363
[ 0 1 -3]
1364
sage: W = (ZZ^3).span([[1/2,4,2]]); W
1365
Free module of degree 3 and rank 1 over Integer Ring
1366
Echelon basis matrix:
1367
[1/2 4 2]
1368
sage: V.direct_sum(W)
1369
Free module of degree 6 and rank 3 over Integer Ring
1370
Echelon basis matrix:
1371
[1/2 0 14 0 0 0]
1372
[ 0 1 -3 0 0 0]
1373
[ 0 0 0 1/2 4 2]
1374
"""
1375
if not is_FreeModule(other):
1376
raise TypeError, "other must be a free module"
1377
if other.base_ring() != self.base_ring():
1378
raise TypeError, "base rins of self and other must be the same"
1379
return self.basis_matrix().block_sum(other.basis_matrix()).row_module(self.base_ring())
1380
1381
def coordinates(self, v, check=True):
1382
r"""
1383
Write `v` in terms of the basis for self.
1384
1385
INPUT:
1386
1387
1388
- ``v`` - vector
1389
1390
- ``check`` - bool (default: True); if True, also
1391
verify that v is really in self.
1392
1393
1394
OUTPUT: list
1395
1396
Returns a list `c` such that if `B` is the basis
1397
for self, then
1398
1399
.. math::
1400
1401
\sum c_i B_i = v.
1402
1403
1404
If `v` is not in self, raises an
1405
``ArithmeticError`` exception.
1406
1407
EXAMPLES::
1408
1409
sage: M = FreeModule(ZZ, 2); M0,M1=M.gens()
1410
sage: W = M.submodule([M0 + M1, M0 - 2*M1])
1411
sage: W.coordinates(2*M0-M1)
1412
[2, -1]
1413
"""
1414
return self.coordinate_vector(v, check=check).list()
1415
1416
def coordinate_vector(self, v, check=True):
1417
"""
1418
Return the vector whose coefficients give `v` as a linear
1419
combination of the basis for self.
1420
1421
INPUT:
1422
1423
1424
- ``v`` - vector
1425
1426
- ``check`` - bool (default: True); if True, also
1427
verify that v is really in self.
1428
1429
1430
OUTPUT: list
1431
1432
EXAMPLES::
1433
1434
sage: M = FreeModule(ZZ, 2); M0,M1=M.gens()
1435
sage: W = M.submodule([M0 + M1, M0 - 2*M1])
1436
sage: W.coordinate_vector(2*M0 - M1)
1437
(2, -1)
1438
"""
1439
raise NotImplementedError
1440
1441
def coordinate_module(self, V):
1442
r"""
1443
Suppose V is a submodule of self (or a module commensurable with
1444
self), and that self is a free module over `R` of rank
1445
`n`. Let `\phi` be the map from self to
1446
`R^n` that sends the basis vectors of self in order to the
1447
standard basis of `R^n`. This function returns the image
1448
`\phi(V)`.
1449
1450
.. warning::
1451
1452
If there is no integer `d` such that `dV` is a
1453
submodule of self, then this function will give total
1454
nonsense.
1455
1456
EXAMPLES:
1457
1458
We illustrate this function with some
1459
`\ZZ`-submodules of `\QQ^3`.
1460
1461
::
1462
1463
sage: V = (ZZ^3).span([[1/2,3,5], [0,1,-3]])
1464
sage: W = (ZZ^3).span([[1/2,4,2]])
1465
sage: V.coordinate_module(W)
1466
Free module of degree 2 and rank 1 over Integer Ring
1467
User basis matrix:
1468
[1 4]
1469
sage: V.0 + 4*V.1
1470
(1/2, 4, 2)
1471
1472
In this example, the coordinate module isn't even in
1473
`\ZZ^3`.
1474
1475
::
1476
1477
sage: W = (ZZ^3).span([[1/4,2,1]])
1478
sage: V.coordinate_module(W)
1479
Free module of degree 2 and rank 1 over Integer Ring
1480
User basis matrix:
1481
[1/2 2]
1482
1483
The following more elaborate example illustrates using this
1484
function to write a submodule in terms of integral cuspidal modular
1485
symbols::
1486
1487
sage: M = ModularSymbols(54)
1488
sage: S = M.cuspidal_subspace()
1489
sage: K = S.integral_structure(); K
1490
Free module of degree 19 and rank 8 over Integer Ring
1491
Echelon basis matrix:
1492
[ 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1493
...
1494
sage: L = M[0].integral_structure(); L
1495
Free module of degree 19 and rank 2 over Integer Ring
1496
Echelon basis matrix:
1497
[ 0 1 1 0 -2 1 -1 1 -1 -2 2 0 0 0 0 0 0 0 0]
1498
[ 0 0 3 0 -3 2 -1 2 -1 -4 2 -1 -2 1 2 0 0 -1 1]
1499
sage: K.coordinate_module(L)
1500
Free module of degree 8 and rank 2 over Integer Ring
1501
User basis matrix:
1502
[ 1 1 1 -1 1 -1 0 0]
1503
[ 0 3 2 -1 2 -1 -1 -2]
1504
sage: K.coordinate_module(L).basis_matrix() * K.basis_matrix()
1505
[ 0 1 1 0 -2 1 -1 1 -1 -2 2 0 0 0 0 0 0 0 0]
1506
[ 0 0 3 0 -3 2 -1 2 -1 -4 2 -1 -2 1 2 0 0 -1 1]
1507
"""
1508
if not is_FreeModule(V):
1509
raise ValueError, "V must be a free module"
1510
A = self.basis_matrix()
1511
A = A.matrix_from_columns(A.pivots()).transpose()
1512
B = V.basis_matrix()
1513
B = B.matrix_from_columns(self.basis_matrix().pivots()).transpose()
1514
S = A.solve_right(B).transpose()
1515
return (self.base_ring()**S.ncols()).span_of_basis(S.rows())
1516
1517
def degree(self):
1518
"""
1519
Return the degree of this free module. This is the dimension of the
1520
ambient vector space in which it is embedded.
1521
1522
EXAMPLES::
1523
1524
sage: M = FreeModule(ZZ, 10)
1525
sage: W = M.submodule([M.gen(0), 2*M.gen(3) - M.gen(0), M.gen(0) + M.gen(3)])
1526
sage: W.degree()
1527
10
1528
sage: W.rank()
1529
2
1530
"""
1531
return self.__degree
1532
1533
def dimension(self):
1534
"""
1535
Return the dimension of this free module.
1536
1537
EXAMPLES::
1538
1539
sage: M = FreeModule(FiniteField(19), 100)
1540
sage: W = M.submodule([M.gen(50)])
1541
sage: W.dimension()
1542
1
1543
"""
1544
return self.rank()
1545
1546
def discriminant(self):
1547
"""
1548
Return the discriminant of this free module.
1549
1550
EXAMPLES::
1551
1552
sage: M = FreeModule(ZZ, 3)
1553
sage: M.discriminant()
1554
1
1555
sage: W = M.span([[1,2,3]])
1556
sage: W.discriminant()
1557
14
1558
sage: W2 = M.span([[1,2,3], [1,1,1]])
1559
sage: W2.discriminant()
1560
6
1561
"""
1562
return self.gram_matrix().determinant()
1563
1564
def free_module(self):
1565
"""
1566
Return this free module. (This is used by the
1567
``FreeModule`` functor, and simply returns self.)
1568
1569
EXAMPLES::
1570
1571
sage: M = FreeModule(ZZ, 3)
1572
sage: M.free_module()
1573
Ambient free module of rank 3 over the principal ideal domain Integer Ring
1574
"""
1575
return self
1576
1577
def gen(self, i=0):
1578
"""
1579
Return ith generator for self, where i is between 0 and rank-1,
1580
inclusive.
1581
1582
INPUT:
1583
1584
1585
- ``i`` - an integer
1586
1587
1588
OUTPUT: i-th basis vector for self.
1589
1590
EXAMPLES::
1591
1592
sage: n = 5
1593
sage: V = QQ^n
1594
sage: B = [ V.gen(i) for i in range(n) ]
1595
sage: B
1596
[(1, 0, 0, 0, 0),
1597
(0, 1, 0, 0, 0),
1598
(0, 0, 1, 0, 0),
1599
(0, 0, 0, 1, 0),
1600
(0, 0, 0, 0, 1)]
1601
sage: V.gens() == tuple(B)
1602
True
1603
1604
TESTS::
1605
1606
sage: (QQ^3).gen(4/3)
1607
Traceback (most recent call last):
1608
...
1609
TypeError: rational is not an integer
1610
"""
1611
if i < 0 or i >= self.rank():
1612
raise ValueError, "Generator %s not defined."%i
1613
return self.basis()[i]
1614
1615
def gram_matrix(self):
1616
r"""
1617
Return the gram matrix associated to this free module, defined to
1618
be `G = B*A*B.transpose()`, where A is the inner product matrix
1619
(induced from the ambient space), and B the basis matrix.
1620
1621
EXAMPLES::
1622
1623
sage: V = VectorSpace(QQ,4)
1624
sage: u = V([1/2,1/2,1/2,1/2])
1625
sage: v = V([0,1,1,0])
1626
sage: w = V([0,0,1,1])
1627
sage: M = span([u,v,w], ZZ)
1628
sage: M.inner_product_matrix() == V.inner_product_matrix()
1629
True
1630
sage: L = M.submodule_with_basis([u,v,w])
1631
sage: L.inner_product_matrix() == M.inner_product_matrix()
1632
True
1633
sage: L.gram_matrix()
1634
[1 1 1]
1635
[1 2 1]
1636
[1 1 2]
1637
"""
1638
if self.is_ambient():
1639
return sage.matrix.matrix_space.MatrixSpace(self.base_ring(), self.degree(), sparse=True)(1)
1640
else:
1641
if self._gram_matrix is None:
1642
B = self.basis_matrix()
1643
self._gram_matrix = B*B.transpose()
1644
return self._gram_matrix
1645
1646
def has_user_basis(self):
1647
"""
1648
Return ``True`` if the basis of this free module is
1649
specified by the user, as opposed to being the default echelon
1650
form.
1651
1652
EXAMPLES::
1653
1654
sage: V = QQ^3
1655
sage: W = V.subspace([[2,'1/2', 1]])
1656
sage: W.has_user_basis()
1657
False
1658
sage: W = V.subspace_with_basis([[2,'1/2',1]])
1659
sage: W.has_user_basis()
1660
True
1661
"""
1662
return False
1663
1664
def inner_product_matrix(self):
1665
"""
1666
Return the default identity inner product matrix associated to this
1667
module.
1668
1669
By definition this is the inner product matrix of the ambient
1670
space, hence may be of degree greater than the rank of the module.
1671
1672
TODO: Differentiate the image ring of the inner product from the
1673
base ring of the module and/or ambient space. E.g. On an integral
1674
module over ZZ the inner product pairing could naturally take
1675
values in ZZ, QQ, RR, or CC.
1676
1677
EXAMPLES::
1678
1679
sage: M = FreeModule(ZZ, 3)
1680
sage: M.inner_product_matrix()
1681
[1 0 0]
1682
[0 1 0]
1683
[0 0 1]
1684
"""
1685
return sage.matrix.matrix_space.MatrixSpace(self.base_ring(), self.degree(), sparse=True)(1)
1686
1687
def _inner_product_is_dot_product(self):
1688
"""
1689
Return whether or not the inner product on this module is induced
1690
by the dot product on the ambient vector space. This is used
1691
internally by the inner_product function for optimization.
1692
1693
EXAMPLES::
1694
1695
sage: FreeModule(ZZ, 3)._inner_product_is_dot_product()
1696
True
1697
sage: FreeModule(ZZ, 3, inner_product_matrix=1)._inner_product_is_dot_product()
1698
True
1699
sage: FreeModule(ZZ, 2, inner_product_matrix=[1,0,-1,0])._inner_product_is_dot_product()
1700
False
1701
1702
::
1703
1704
sage: M = FreeModule(QQ, 3)
1705
sage: M2 = M.span([[1,2,3]])
1706
sage: M2._inner_product_is_dot_product()
1707
True
1708
"""
1709
return True
1710
1711
def is_ambient(self):
1712
"""
1713
Returns False since this is not an ambient free module.
1714
1715
EXAMPLES::
1716
1717
sage: M = FreeModule(ZZ, 3).span([[1,2,3]]); M
1718
Free module of degree 3 and rank 1 over Integer Ring
1719
Echelon basis matrix:
1720
[1 2 3]
1721
sage: M.is_ambient()
1722
False
1723
sage: M = (ZZ^2).span([[1,0], [0,1]])
1724
sage: M
1725
Free module of degree 2 and rank 2 over Integer Ring
1726
Echelon basis matrix:
1727
[1 0]
1728
[0 1]
1729
sage: M.is_ambient()
1730
False
1731
sage: M == M.ambient_module()
1732
True
1733
"""
1734
return False
1735
1736
def is_dense(self):
1737
"""
1738
Return ``True`` if the underlying representation of
1739
this module uses dense vectors, and False otherwise.
1740
1741
EXAMPLES::
1742
1743
sage: FreeModule(ZZ, 2).is_dense()
1744
True
1745
sage: FreeModule(ZZ, 2, sparse=True).is_dense()
1746
False
1747
"""
1748
return not self.is_sparse()
1749
1750
def is_full(self):
1751
"""
1752
Return ``True`` if the rank of this module equals its
1753
degree.
1754
1755
EXAMPLES::
1756
1757
sage: FreeModule(ZZ, 2).is_full()
1758
True
1759
sage: M = FreeModule(ZZ, 2).span([[1,2]])
1760
sage: M.is_full()
1761
False
1762
"""
1763
return self.rank() == self.degree()
1764
1765
def is_finite(self):
1766
"""
1767
Returns True if the underlying set of this free module is finite.
1768
1769
EXAMPLES::
1770
1771
sage: FreeModule(ZZ, 2).is_finite()
1772
False
1773
sage: FreeModule(Integers(8), 2).is_finite()
1774
True
1775
sage: FreeModule(ZZ, 0).is_finite()
1776
True
1777
"""
1778
return self.base_ring().is_finite() or self.rank() == 0
1779
1780
def is_sparse(self):
1781
"""
1782
Return ``True`` if the underlying representation of
1783
this module uses sparse vectors, and False otherwise.
1784
1785
EXAMPLES::
1786
1787
sage: FreeModule(ZZ, 2).is_sparse()
1788
False
1789
sage: FreeModule(ZZ, 2, sparse=True).is_sparse()
1790
True
1791
"""
1792
return self.__is_sparse
1793
1794
def ngens(self):
1795
"""
1796
Returns the number of basis elements of this free module.
1797
1798
EXAMPLES::
1799
1800
sage: FreeModule(ZZ, 2).ngens()
1801
2
1802
sage: FreeModule(ZZ, 0).ngens()
1803
0
1804
sage: FreeModule(ZZ, 2).span([[1,1]]).ngens()
1805
1
1806
"""
1807
try:
1808
return self.__ngens
1809
except AttributeError:
1810
self.__ngens = self.rank()
1811
return self.__ngens
1812
1813
def nonembedded_free_module(self):
1814
"""
1815
Returns an ambient free module that is isomorphic to this free
1816
module.
1817
1818
Thus if this free module is of rank `n` over a ring
1819
`R`, then this function returns `R^n`, as an
1820
ambient free module.
1821
1822
EXAMPLES::
1823
1824
sage: FreeModule(ZZ, 2).span([[1,1]]).nonembedded_free_module()
1825
Ambient free module of rank 1 over the principal ideal domain Integer Ring
1826
"""
1827
return FreeModule(self.base_ring(), self.rank())
1828
1829
def random_element(self, prob=1.0, *args, **kwds):
1830
"""
1831
Returns a random element of self.
1832
1833
INPUT:
1834
1835
1836
-- ``prob`` - float. Each coefficient will be set to zero with
1837
probability `1-prob`. Otherwise coefficients will be chosen
1838
randomly from base ring (and may be zero).
1839
1840
-- ``*args, **kwds`` - passed on to ``random_element()`` function
1841
of base ring.
1842
1843
1844
EXAMPLES::
1845
1846
sage: M = FreeModule(ZZ, 2).span([[1,1]])
1847
sage: M.random_element()
1848
(-1, -1)
1849
sage: M.random_element()
1850
(2, 2)
1851
sage: M.random_element()
1852
(1, 1)
1853
1854
Passes extra positional or keyword arguments through::
1855
1856
sage: M.random_element(5,10)
1857
(9, 9)
1858
1859
1860
"""
1861
rand = current_randstate().python_random().random
1862
R = self.base_ring()
1863
prob = float(prob)
1864
c = [0 if rand() > prob else R.random_element(*args, **kwds) for _ in range(self.rank())]
1865
return self.linear_combination_of_basis(c)
1866
1867
def rank(self):
1868
"""
1869
Return the rank of this free module.
1870
1871
EXAMPLES::
1872
1873
sage: FreeModule(Integers(6), 10000000).rank()
1874
10000000
1875
sage: FreeModule(ZZ, 2).span([[1,1], [2,2], [3,4]]).rank()
1876
2
1877
"""
1878
return self.__rank
1879
1880
def uses_ambient_inner_product(self):
1881
r"""
1882
Return ``True`` if the inner product on this module is
1883
the one induced by the ambient inner product.
1884
1885
EXAMPLES::
1886
1887
sage: M = FreeModule(ZZ, 2)
1888
sage: W = M.submodule([[1,2]])
1889
sage: W.uses_ambient_inner_product()
1890
True
1891
sage: W.inner_product_matrix()
1892
[1 0]
1893
[0 1]
1894
1895
::
1896
1897
sage: W.gram_matrix()
1898
[5]
1899
"""
1900
return self.__uses_ambient_inner_product
1901
1902
def zero_vector(self):
1903
"""
1904
Returns the zero vector in this free module.
1905
1906
EXAMPLES::
1907
1908
sage: M = FreeModule(ZZ, 2)
1909
sage: M.zero_vector()
1910
(0, 0)
1911
sage: M(0)
1912
(0, 0)
1913
sage: M.span([[1,1]]).zero_vector()
1914
(0, 0)
1915
sage: M.zero_submodule().zero_vector()
1916
(0, 0)
1917
"""
1918
# Do *not* cache this -- it must be computed fresh each time, since
1919
# it is is used by __call__ to make a new copy of the 0 element.
1920
1921
return self._element_class(self, 0)
1922
1923
@cached_method
1924
def zero(self):
1925
"""
1926
Returns the zero vector in this free module.
1927
1928
EXAMPLES::
1929
1930
sage: M = FreeModule(ZZ, 2)
1931
sage: M.zero()
1932
(0, 0)
1933
sage: M.span([[1,1]]).zero()
1934
(0, 0)
1935
sage: M.zero_submodule().zero()
1936
(0, 0)
1937
sage: M.zero_submodule().zero().is_mutable()
1938
False
1939
"""
1940
res = self._element_class(self, 0)
1941
res.set_immutable()
1942
return res
1943
1944
def _magma_init_(self, magma):
1945
"""
1946
EXAMPLES::
1947
1948
sage: magma(QQ^9) # optional - magma
1949
Full Vector space of degree 9 over Rational Field
1950
sage: (QQ^9)._magma_init_(magma) # optional - magma
1951
'RSpace(_sage_[...],9)'
1952
1953
::
1954
1955
sage: magma(Integers(8)^2) # optional - magma
1956
Full RSpace of degree 2 over IntegerRing(8)
1957
sage: magma(FreeModule(QQ['x'], 2)) # optional - magma
1958
Full RSpace of degree 2 over Univariate Polynomial Ring in x over Rational Field
1959
1960
::
1961
1962
sage: A = matrix([[1,0],[0,-1]])
1963
sage: M = FreeModule(ZZ,2,inner_product_matrix=A); M
1964
Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring
1965
Inner product matrix:
1966
[ 1 0]
1967
[ 0 -1]
1968
sage: M._magma_init_(magma) # optional - magma
1969
'RSpace(_sage_[...],2,_sage_ref...)'
1970
sage: m = magma(M); m # optional - magma
1971
Full RSpace of degree 2 over Integer Ring
1972
Inner Product Matrix:
1973
[ 1 0]
1974
[ 0 -1]
1975
sage: m.Type() # optional - magma
1976
ModTupRng
1977
sage: m.sage() # optional - magma
1978
Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring
1979
Inner product matrix:
1980
[ 1 0]
1981
[ 0 -1]
1982
sage: m.sage() is M # optional - magma
1983
True
1984
1985
Now over a field::
1986
1987
sage: N = FreeModule(QQ,2,inner_product_matrix=A); N
1988
Ambient quadratic space of dimension 2 over Rational Field
1989
Inner product matrix:
1990
[ 1 0]
1991
[ 0 -1]
1992
sage: n = magma(N); n # optional - magma
1993
Full Vector space of degree 2 over Rational Field
1994
Inner Product Matrix:
1995
[ 1 0]
1996
[ 0 -1]
1997
sage: n.Type() # optional - magma
1998
ModTupFld
1999
sage: n.sage() # optional - magma
2000
Ambient quadratic space of dimension 2 over Rational Field
2001
Inner product matrix:
2002
[ 1 0]
2003
[ 0 -1]
2004
sage: n.sage() is N # optional - magma
2005
True
2006
2007
How about some inexact fields::
2008
2009
sage: v = vector(RR, [1, pi, 5/6])
2010
sage: F = v.parent()
2011
sage: M = magma(F); M # optional - magma
2012
Full Vector space of degree 3 over Real field of precision 15
2013
sage: M.Type() # optional - magma
2014
ModTupFld
2015
sage: m = M.sage(); m # optional - magma
2016
Vector space of dimension 3 over Real Field with 53 bits of precision
2017
sage: m is F # optional - magma
2018
True
2019
2020
For interval fields, we can convert to Magma but there is no
2021
interval field in Magma so we cannot convert back::
2022
2023
sage: v = vector(RealIntervalField(100), [1, pi, 0.125])
2024
sage: F = v.parent()
2025
sage: M = magma(v.parent()); M # optional - magma
2026
Full Vector space of degree 3 over Real field of precision 30
2027
sage: M.Type() # optional - magma
2028
ModTupFld
2029
sage: m = M.sage(); m # optional - magma
2030
Vector space of dimension 3 over Real Field with 100 bits of precision
2031
sage: m is F # optional - magma
2032
False
2033
"""
2034
K = magma(self.base_ring())
2035
if not self._inner_product_is_dot_product():
2036
M = magma(self.inner_product_matrix())
2037
return "RSpace(%s,%s,%s)"%(K.name(), self.rank(), M._ref())
2038
else:
2039
return "RSpace(%s,%s)"%(K.name(), self.rank())
2040
2041
def _macaulay2_(self, macaulay2=None):
2042
r"""
2043
EXAMPLES::
2044
2045
sage: R = QQ^2
2046
sage: macaulay2(R) # optional
2047
2
2048
QQ
2049
"""
2050
if macaulay2 is None:
2051
from sage.interfaces.macaulay2 import macaulay2
2052
if self._inner_product_matrix:
2053
raise NotImplementedError
2054
else:
2055
return macaulay2(self.base_ring())**self.rank()
2056
2057
class FreeModule_generic_pid(FreeModule_generic):
2058
"""
2059
Base class for all free modules over a PID.
2060
"""
2061
def __init__(self, base_ring, rank, degree, sparse=False):
2062
"""
2063
Create a free module over a PID.
2064
2065
EXAMPLES::
2066
2067
sage: FreeModule(ZZ, 2)
2068
Ambient free module of rank 2 over the principal ideal domain Integer Ring
2069
sage: FreeModule(PolynomialRing(GF(7),'x'), 2)
2070
Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 7
2071
"""
2072
# The first check should go away once everything is categorized...
2073
if base_ring not in PrincipalIdealDomains():
2074
raise TypeError("The base_ring must be a principal ideal domain.")
2075
super(FreeModule_generic_pid, self).__init__(base_ring, rank, degree,
2076
sparse)
2077
2078
def scale(self, other):
2079
"""
2080
Return the product of this module by the number other, which is the
2081
module spanned by other times each basis vector.
2082
2083
EXAMPLES::
2084
2085
sage: M = FreeModule(ZZ, 3)
2086
sage: M.scale(2)
2087
Free module of degree 3 and rank 3 over Integer Ring
2088
Echelon basis matrix:
2089
[2 0 0]
2090
[0 2 0]
2091
[0 0 2]
2092
2093
::
2094
2095
sage: a = QQ('1/3')
2096
sage: M.scale(a)
2097
Free module of degree 3 and rank 3 over Integer Ring
2098
Echelon basis matrix:
2099
[1/3 0 0]
2100
[ 0 1/3 0]
2101
[ 0 0 1/3]
2102
"""
2103
if other == 0:
2104
return self.zero_submodule()
2105
if other == 1 or other == -1:
2106
return self
2107
return self.span([v*other for v in self.basis()])
2108
2109
def __radd__(self, other):
2110
"""
2111
EXAMPLES::
2112
2113
sage: int(0) + QQ^3
2114
Vector space of dimension 3 over Rational Field
2115
sage: sum([QQ^3, QQ^3])
2116
Vector space of degree 3 and dimension 3 over Rational Field
2117
Basis matrix:
2118
[1 0 0]
2119
[0 1 0]
2120
[0 0 1]
2121
"""
2122
if other == 0:
2123
return self
2124
else:
2125
raise TypeError
2126
2127
def __add__(self, other):
2128
r"""
2129
Return the sum of self and other, where both self and other must be
2130
submodules of the ambient vector space.
2131
2132
EXAMPLES:
2133
2134
We add two vector spaces::
2135
2136
sage: V = VectorSpace(QQ, 3)
2137
sage: W = V.subspace([V([1,1,0])])
2138
sage: W2 = V.subspace([V([1,-1,0])])
2139
sage: W + W2
2140
Vector space of degree 3 and dimension 2 over Rational Field
2141
Basis matrix:
2142
[1 0 0]
2143
[0 1 0]
2144
2145
We add two free `\ZZ`-modules.
2146
2147
::
2148
2149
sage: M = FreeModule(ZZ, 3)
2150
sage: W = M.submodule([M([1,0,2])])
2151
sage: W2 = M.submodule([M([2,0,-4])])
2152
sage: W + W2
2153
Free module of degree 3 and rank 2 over Integer Ring
2154
Echelon basis matrix:
2155
[1 0 2]
2156
[0 0 8]
2157
2158
We can also add free `\ZZ`-modules embedded
2159
non-integrally into an ambient space.
2160
2161
::
2162
2163
sage: V = VectorSpace(QQ, 3)
2164
sage: W = M.span([1/2*V.0 - 1/3*V.1])
2165
2166
Here the command ``M.span(...)`` creates the span of
2167
the indicated vectors over the base ring of `M`.
2168
2169
::
2170
2171
sage: W2 = M.span([1/3*V.0 + V.1])
2172
sage: W + W2
2173
Free module of degree 3 and rank 2 over Integer Ring
2174
Echelon basis matrix:
2175
[ 1/6 7/3 0]
2176
[ 0 11/3 0]
2177
2178
We add two modules over `\ZZ`::
2179
2180
sage: A = Matrix(ZZ, 3, 3, [3, 0, -1, 0, -2, 0, 0, 0, -2])
2181
sage: V = (A+2).kernel()
2182
sage: W = (A-3).kernel()
2183
sage: V+W
2184
Free module of degree 3 and rank 3 over Integer Ring
2185
Echelon basis matrix:
2186
[5 0 0]
2187
[0 1 0]
2188
[0 0 1]
2189
2190
We add a module to 0::
2191
2192
sage: ZZ^3 + 0
2193
Ambient free module of rank 3 over the principal ideal domain Integer Ring
2194
"""
2195
if not isinstance(other, FreeModule_generic):
2196
if other == 0:
2197
return self
2198
raise TypeError, "other (=%s) must be a free module"%other
2199
if not (self.ambient_vector_space() == other.ambient_vector_space()):
2200
raise TypeError, "ambient vector spaces must be equal"
2201
return self.span(self.basis() + other.basis())
2202
2203
2204
def base_field(self):
2205
"""
2206
Return the base field, which is the fraction field of the base ring
2207
of this module.
2208
2209
EXAMPLES::
2210
2211
sage: FreeModule(GF(3), 2).base_field()
2212
Finite Field of size 3
2213
sage: FreeModule(ZZ, 2).base_field()
2214
Rational Field
2215
sage: FreeModule(PolynomialRing(GF(7),'x'), 2).base_field()
2216
Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 7
2217
"""
2218
return self.base_ring().fraction_field()
2219
2220
def basis_matrix(self):
2221
"""
2222
Return the matrix whose rows are the basis for this free module.
2223
2224
EXAMPLES::
2225
2226
sage: M = FreeModule(QQ,2).span_of_basis([[1,-1],[1,0]]); M
2227
Vector space of degree 2 and dimension 2 over Rational Field
2228
User basis matrix:
2229
[ 1 -1]
2230
[ 1 0]
2231
sage: M.basis_matrix()
2232
[ 1 -1]
2233
[ 1 0]
2234
2235
See #3699:
2236
sage: K = FreeModule(ZZ, 2000)
2237
sage: I = K.basis_matrix()
2238
"""
2239
try:
2240
return self.__basis_matrix
2241
except AttributeError:
2242
MAT = sage.matrix.matrix_space.MatrixSpace(self.base_field(),
2243
len(self.basis()), self.degree(),
2244
sparse = self.is_sparse())
2245
if self.is_ambient():
2246
A = MAT.identity_matrix()
2247
else:
2248
A = MAT(self.basis())
2249
A.set_immutable()
2250
self.__basis_matrix = A
2251
return A
2252
2253
def index_in(self, other):
2254
"""
2255
Return the lattice index [other:self] of self in other, as an
2256
element of the base field. When self is contained in other, the
2257
lattice index is the usual index. If the index is infinite, then
2258
this function returns infinity.
2259
2260
EXAMPLES::
2261
2262
sage: L1 = span([[1,2]], ZZ)
2263
sage: L2 = span([[3,6]], ZZ)
2264
sage: L2.index_in(L1)
2265
3
2266
2267
Note that the free modules being compared need not be integral.
2268
2269
::
2270
2271
sage: L1 = span([['1/2','1/3'], [4,5]], ZZ)
2272
sage: L2 = span([[1,2], [3,4]], ZZ)
2273
sage: L2.index_in(L1)
2274
12/7
2275
sage: L1.index_in(L2)
2276
7/12
2277
sage: L1.discriminant() / L2.discriminant()
2278
49/144
2279
2280
The index of a lattice of infinite index is infinite.
2281
2282
::
2283
2284
sage: L1 = FreeModule(ZZ, 2)
2285
sage: L2 = span([[1,2]], ZZ)
2286
sage: L2.index_in(L1)
2287
+Infinity
2288
"""
2289
if not isinstance(other, FreeModule_generic):
2290
raise TypeError, "other must be a free module"
2291
2292
if self.ambient_vector_space() != other.ambient_vector_space():
2293
raise ArithmeticError, "self and other must be embedded in the same ambient space."
2294
2295
if self.base_ring() != other.base_ring():
2296
raise NotImplementedError, "lattice index only defined for modules over the same base ring."
2297
2298
if other.base_ring().is_field():
2299
if self == other:
2300
return sage.rings.integer.Integer(1)
2301
else:
2302
if self.is_subspace(other):
2303
return sage.rings.infinity.infinity
2304
raise ArithmeticError, "self must be contained in the vector space spanned by other."
2305
2306
try:
2307
C = [other.coordinates(b) for b in self.basis()]
2308
except ArithmeticError:
2309
raise
2310
2311
if self.rank() < other.rank():
2312
return sage.rings.infinity.infinity
2313
2314
a = sage.matrix.matrix_space.MatrixSpace(self.base_field(), self.rank())(C).determinant()
2315
if sage.rings.integer_ring.is_IntegerRing(self.base_ring()):
2316
return a.abs()
2317
elif isinstance(self.base_ring, sage.rings.number_field.order.Order):
2318
return self.base_ring().ideal(a).norm()
2319
else:
2320
raise NotImplementedError
2321
2322
def intersection(self, other):
2323
r"""
2324
Return the intersection of self and other.
2325
2326
EXAMPLES:
2327
2328
We intersect two submodules one of which is clearly
2329
contained in the other.
2330
2331
::
2332
2333
sage: A = ZZ^2
2334
sage: M1 = A.span([[1,1]])
2335
sage: M2 = A.span([[3,3]])
2336
sage: M1.intersection(M2)
2337
Free module of degree 2 and rank 1 over Integer Ring
2338
Echelon basis matrix:
2339
[3 3]
2340
sage: M1.intersection(M2) is M2
2341
True
2342
2343
We intersection two submodules of `\ZZ^3` of rank
2344
`2`, whose intersection has rank `1`.
2345
2346
::
2347
2348
sage: A = ZZ^3
2349
sage: M1 = A.span([[1,1,1], [1,2,3]])
2350
sage: M2 = A.span([[2,2,2], [1,0,0]])
2351
sage: M1.intersection(M2)
2352
Free module of degree 3 and rank 1 over Integer Ring
2353
Echelon basis matrix:
2354
[2 2 2]
2355
2356
We compute an intersection of two `\ZZ`-modules that
2357
are not submodules of `\ZZ^2`.
2358
2359
::
2360
2361
sage: A = ZZ^2
2362
sage: M1 = A.span([[1,2]]).scale(1/6)
2363
sage: M2 = A.span([[1,2]]).scale(1/15)
2364
sage: M1.intersection(M2)
2365
Free module of degree 2 and rank 1 over Integer Ring
2366
Echelon basis matrix:
2367
[1/3 2/3]
2368
2369
We intersect a `\ZZ`-module with a
2370
`\QQ`-vector space.
2371
2372
::
2373
2374
sage: A = ZZ^3
2375
sage: L = ZZ^3
2376
sage: V = QQ^3
2377
sage: W = L.span([[1/2,0,1/2]])
2378
sage: K = V.span([[1,0,1], [0,0,1]])
2379
sage: W.intersection(K)
2380
Free module of degree 3 and rank 1 over Integer Ring
2381
Echelon basis matrix:
2382
[1/2 0 1/2]
2383
sage: K.intersection(W)
2384
Free module of degree 3 and rank 1 over Integer Ring
2385
Echelon basis matrix:
2386
[1/2 0 1/2]
2387
2388
We intersect two modules over the ring of integers of a number field::
2389
2390
sage: L.<w> = NumberField(x^2 - x + 2)
2391
sage: OL = L.ring_of_integers()
2392
sage: V = L**3; W1 = V.span([[0,w/5,0], [1,0,-1/17]], OL); W2 = V.span([[0,(1-w)/5,0]], OL)
2393
sage: W1.intersection(W2)
2394
Free module of degree 3 and rank 1 over Maximal Order in Number Field in w with defining polynomial x^2 - x + 2
2395
Echelon basis matrix:
2396
[ 0 2/5 0]
2397
2398
"""
2399
if not isinstance(other, FreeModule_generic):
2400
raise TypeError, "other must be a free module"
2401
2402
if self.ambient_vector_space() != other.ambient_vector_space():
2403
raise ArithmeticError, "self and other must be embedded in the same ambient space."
2404
2405
if self.base_ring() != other.base_ring():
2406
if other.base_ring().is_field():
2407
return other.intersection(self)
2408
raise NotImplementedError, "intersection of modules over different base rings (neither a field) is not implemented."
2409
2410
# dispense with the three easy cases
2411
if self == self.ambient_vector_space() or other.is_submodule(self):
2412
return other
2413
elif other == other.ambient_vector_space() or self.is_submodule(other):
2414
return self
2415
elif self.rank() == 0 or other.rank() == 0:
2416
if self.base_ring().is_field():
2417
return other.zero_submodule()
2418
else:
2419
return self.zero_submodule()
2420
2421
# standard algorithm for computing intersection of general submodule
2422
if self.dimension() <= other.dimension():
2423
V1 = self; V2 = other
2424
else:
2425
V1 = other; V2 = self
2426
A1 = V1.basis_matrix()
2427
A2 = V2.basis_matrix()
2428
S = A1.stack(A2)
2429
K = S.integer_kernel(self.base_ring()).basis_matrix()
2430
n = int(V1.dimension())
2431
K = K.matrix_from_columns(range(n))
2432
B = K*A1
2433
return B.row_module(self.base_ring())
2434
2435
def is_submodule(self, other):
2436
"""
2437
True if this module is a submodule of other.
2438
2439
EXAMPLES::
2440
2441
sage: M = FreeModule(ZZ,2)
2442
sage: M.is_submodule(M)
2443
True
2444
sage: N = M.scale(2)
2445
sage: N.is_submodule(M)
2446
True
2447
sage: M.is_submodule(N)
2448
False
2449
sage: N = M.scale(1/2)
2450
sage: N.is_submodule(M)
2451
False
2452
sage: M.is_submodule(N)
2453
True
2454
"""
2455
if not isinstance(other, FreeModule_generic):
2456
return False
2457
if self.ambient_vector_space() != other.ambient_vector_space():
2458
return False
2459
if other == other.ambient_vector_space():
2460
return True
2461
if other.rank() < self.rank():
2462
return False
2463
if self.base_ring() != other.base_ring():
2464
try:
2465
if not self.base_ring().is_subring(other.base_ring()):
2466
return False
2467
except NotImplementedError:
2468
return False
2469
for b in self.basis():
2470
if not (b in other):
2471
return False
2472
return True
2473
2474
def zero_submodule(self):
2475
"""
2476
Return the zero submodule of this module.
2477
2478
EXAMPLES::
2479
2480
sage: V = FreeModule(ZZ,2)
2481
sage: V.zero_submodule()
2482
Free module of degree 2 and rank 0 over Integer Ring
2483
Echelon basis matrix:
2484
[]
2485
"""
2486
return self.submodule([], check=False, already_echelonized=True)
2487
2488
def denominator(self):
2489
"""
2490
The denominator of the basis matrix of self (i.e. the LCM of the
2491
coordinate entries with respect to the basis of the ambient
2492
space).
2493
2494
EXAMPLES::
2495
2496
sage: V = QQ^3
2497
sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ)
2498
sage: L
2499
Free module of degree 3 and rank 2 over Integer Ring
2500
Echelon basis matrix:
2501
[ 1/5 19/6 37/3]
2502
[ 0 23/6 46/3]
2503
sage: L.denominator()
2504
30
2505
"""
2506
return self.basis_matrix().denominator()
2507
2508
def index_in_saturation(self):
2509
r"""
2510
Return the index of this module in its saturation, i.e., its
2511
intersection with `R^n`.
2512
2513
EXAMPLES::
2514
2515
sage: W = span([[2,4,6]], ZZ)
2516
sage: W.index_in_saturation()
2517
2
2518
sage: W = span([[1/2,1/3]], ZZ)
2519
sage: W.index_in_saturation()
2520
1/6
2521
"""
2522
# TODO: There is probably a much faster algorithm in this case.
2523
return self.index_in(self.saturation())
2524
2525
def saturation(self):
2526
r"""
2527
Return the saturated submodule of `R^n` that spans the same
2528
vector space as self.
2529
2530
EXAMPLES:
2531
2532
We create a 1-dimensional lattice that is obviously not
2533
saturated and saturate it.
2534
2535
::
2536
2537
sage: L = span([[9,9,6]], ZZ); L
2538
Free module of degree 3 and rank 1 over Integer Ring
2539
Echelon basis matrix:
2540
[9 9 6]
2541
sage: L.saturation()
2542
Free module of degree 3 and rank 1 over Integer Ring
2543
Echelon basis matrix:
2544
[3 3 2]
2545
2546
We create a lattice spanned by two vectors, and saturate.
2547
Computation of discriminants shows that the index of lattice in its
2548
saturation is `3`, which is a prime of congruence between
2549
the two generating vectors.
2550
2551
::
2552
2553
sage: L = span([[1,2,3], [4,5,6]], ZZ)
2554
sage: L.saturation()
2555
Free module of degree 3 and rank 2 over Integer Ring
2556
Echelon basis matrix:
2557
[ 1 0 -1]
2558
[ 0 1 2]
2559
sage: L.discriminant()
2560
54
2561
sage: L.saturation().discriminant()
2562
6
2563
2564
Notice that the saturation of a non-integral lattice `L` is
2565
defined, but the result is integral hence does not contain
2566
`L`::
2567
2568
sage: L = span([['1/2',1,3]], ZZ)
2569
sage: L.saturation()
2570
Free module of degree 3 and rank 1 over Integer Ring
2571
Echelon basis matrix:
2572
[1 2 6]
2573
"""
2574
R = self.base_ring()
2575
if R.is_field():
2576
return self
2577
try:
2578
A, _ = self.basis_matrix()._clear_denom()
2579
S = A.saturation().row_space()
2580
except AttributeError:
2581
# fallback in case _clear_denom isn't written
2582
V = self.vector_space()
2583
A = self.ambient_module()
2584
S = V.intersection(A)
2585
# Return exactly self if it is already saturated.
2586
return self if self == S else S
2587
2588
def span(self, gens, base_ring=None, check=True, already_echelonized=False):
2589
"""
2590
Return the R-span of the given list of gens, where R = base_ring.
2591
The default R is the base ring of self. Note that this span need
2592
not be a submodule of self, nor even of the ambient space. It must,
2593
however, be contained in the ambient vector space, i.e., the
2594
ambient space tensored with the fraction field of R.
2595
2596
EXAMPLES::
2597
2598
sage: V = FreeModule(ZZ,3)
2599
sage: W = V.submodule([V.gen(0)])
2600
sage: W.span([V.gen(1)])
2601
Free module of degree 3 and rank 1 over Integer Ring
2602
Echelon basis matrix:
2603
[0 1 0]
2604
sage: W.submodule([V.gen(1)])
2605
Traceback (most recent call last):
2606
...
2607
ArithmeticError: Argument gens (= [(0, 1, 0)]) does not generate a submodule of self.
2608
sage: V.span([[1,0,0],[1/5,4,0],[6,3/4,0]])
2609
Free module of degree 3 and rank 2 over Integer Ring
2610
Echelon basis matrix:
2611
[1/5 0 0]
2612
[ 0 1/4 0]
2613
2614
2615
It also works with other things than integers::
2616
2617
sage: R.<x>=QQ[]
2618
sage: L=R^1
2619
sage: a=L.span([(1/x,)])
2620
sage: a
2621
Free module of degree 1 and rank 1 over Univariate Polynomial Ring in x over Rational Field
2622
Echelon basis matrix:
2623
[1/x]
2624
sage: b=L.span([(1/x,)])
2625
sage: a(b.gens()[0])
2626
(1/x)
2627
sage: L2 = R^2
2628
sage: L2.span([[(x^2+x)/(x^2-3*x+2),1/5],[(x^2+2*x)/(x^2-4*x+3),x]])
2629
Free module of degree 2 and rank 2 over Univariate Polynomial Ring in x over Rational Field
2630
Echelon basis matrix:
2631
[x/(x^3 - 6*x^2 + 11*x - 6) 2/15*x^2 - 17/75*x - 1/75]
2632
[ 0 x^3 - 11/5*x^2 - 3*x + 4/5]
2633
2634
Note that the ``base_ring`` can make a huge difference. We repeat the previous example over the fraction field of R and get a simpler vector space.::
2635
2636
sage: L2.span([[(x^2+x)/(x^2-3*x+2),1/5],[(x^2+2*x)/(x^2-4*x+3),x]],base_ring=R.fraction_field())
2637
Vector space of degree 2 and dimension 2 over Fraction Field of Univariate Polynomial Ring in x over Rational Field
2638
Basis matrix:
2639
[1 0]
2640
[0 1]
2641
"""
2642
if is_FreeModule(gens):
2643
gens = gens.gens()
2644
if base_ring is None or base_ring == self.base_ring():
2645
return FreeModule_submodule_pid(
2646
self.ambient_module(), gens, check=check, already_echelonized=already_echelonized)
2647
else:
2648
try:
2649
M = self.change_ring(base_ring)
2650
except TypeError:
2651
raise ValueError, "Argument base_ring (= %s) is not compatible "%base_ring + \
2652
"with the base field (= %s)." % self.base_field()
2653
try:
2654
return M.span(gens)
2655
except TypeError:
2656
raise ValueError, "Argument gens (= %s) is not compatible "%gens + \
2657
"with base_ring (= %s)."%base_ring
2658
2659
def submodule(self, gens, check=True, already_echelonized=False):
2660
r"""
2661
Create the R-submodule of the ambient vector space with given
2662
generators, where R is the base ring of self.
2663
2664
INPUT:
2665
2666
2667
- ``gens`` - a list of free module elements or a free
2668
module
2669
2670
- ``check`` - (default: True) whether or not to verify
2671
that the gens are in self.
2672
2673
2674
OUTPUT:
2675
2676
2677
- ``FreeModule`` - the submodule spanned by the
2678
vectors in the list gens. The basis for the subspace is always put
2679
in reduced row echelon form.
2680
2681
2682
EXAMPLES:
2683
2684
We create a submodule of `\ZZ^3`::
2685
2686
sage: M = FreeModule(ZZ, 3)
2687
sage: B = M.basis()
2688
sage: W = M.submodule([B[0]+B[1], 2*B[1]-B[2]])
2689
sage: W
2690
Free module of degree 3 and rank 2 over Integer Ring
2691
Echelon basis matrix:
2692
[ 1 1 0]
2693
[ 0 2 -1]
2694
2695
We create a submodule of a submodule.
2696
2697
::
2698
2699
sage: W.submodule([3*B[0] + 3*B[1]])
2700
Free module of degree 3 and rank 1 over Integer Ring
2701
Echelon basis matrix:
2702
[3 3 0]
2703
2704
We try to create a submodule that isn't really a submodule, which
2705
results in an ArithmeticError exception::
2706
2707
sage: W.submodule([B[0] - B[1]])
2708
Traceback (most recent call last):
2709
...
2710
ArithmeticError: Argument gens (= [(1, -1, 0)]) does not generate a submodule of self.
2711
2712
Next we create a submodule of a free module over the principal ideal
2713
domain `\QQ[x]`, which uses the general Hermite normal form functionality::
2714
2715
sage: R = PolynomialRing(QQ, 'x'); x = R.gen()
2716
sage: M = FreeModule(R, 3)
2717
sage: B = M.basis()
2718
sage: W = M.submodule([x*B[0], 2*B[1]- x*B[2]]); W
2719
Free module of degree 3 and rank 2 over Univariate Polynomial Ring in x over Rational Field
2720
Echelon basis matrix:
2721
[ x 0 0]
2722
[ 0 2 -x]
2723
sage: W.ambient_module()
2724
Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field
2725
"""
2726
if is_FreeModule(gens):
2727
gens = gens.gens()
2728
V = self.span(gens, check=check, already_echelonized=already_echelonized)
2729
if check:
2730
if not V.is_submodule(self):
2731
raise ArithmeticError, "Argument gens (= %s) does not generate a submodule of self."%gens
2732
return V
2733
2734
def span_of_basis(self, basis, base_ring=None, check=True, already_echelonized=False):
2735
r"""
2736
Return the free R-module with the given basis, where R is the base
2737
ring of self or user specified base_ring.
2738
2739
Note that this R-module need not be a submodule of self, nor even
2740
of the ambient space. It must, however, be contained in the ambient
2741
vector space, i.e., the ambient space tensored with the fraction
2742
field of R.
2743
2744
EXAMPLES::
2745
2746
sage: M = FreeModule(ZZ,3)
2747
sage: W = M.span_of_basis([M([1,2,3])])
2748
2749
Next we create two free `\ZZ`-modules, neither of
2750
which is a submodule of `W`.
2751
2752
::
2753
2754
sage: W.span_of_basis([M([2,4,0])])
2755
Free module of degree 3 and rank 1 over Integer Ring
2756
User basis matrix:
2757
[2 4 0]
2758
2759
The following module isn't in the ambient module `\ZZ^3`
2760
but is contained in the ambient vector space `\QQ^3`::
2761
2762
sage: V = M.ambient_vector_space()
2763
sage: W.span_of_basis([ V([1/5,2/5,0]), V([1/7,1/7,0]) ])
2764
Free module of degree 3 and rank 2 over Integer Ring
2765
User basis matrix:
2766
[1/5 2/5 0]
2767
[1/7 1/7 0]
2768
2769
Of course the input basis vectors must be linearly independent.
2770
2771
::
2772
2773
sage: W.span_of_basis([ [1,2,0], [2,4,0] ])
2774
Traceback (most recent call last):
2775
...
2776
ValueError: The given basis vectors must be linearly independent.
2777
"""
2778
if is_FreeModule(basis):
2779
basis = basis.gens()
2780
if base_ring is None or base_ring == self.base_ring():
2781
return FreeModule_submodule_with_basis_pid(
2782
self.ambient_module(), basis=basis, check=check,
2783
already_echelonized=already_echelonized)
2784
else:
2785
try:
2786
M = self.change_ring(base_ring)
2787
except TypeError:
2788
raise ValueError, "Argument base_ring (= %s) is not compatible "%base_ring + \
2789
"with the base ring (= %s)."%self.base_ring()
2790
try:
2791
return M.span_of_basis(basis)
2792
except TypeError:
2793
raise ValueError, "Argument gens (= %s) is not compatible "%basis + \
2794
"with base_ring (= %s)."%base_ring
2795
2796
def submodule_with_basis(self, basis, check=True, already_echelonized=False):
2797
"""
2798
Create the R-submodule of the ambient vector space with given
2799
basis, where R is the base ring of self.
2800
2801
INPUT:
2802
2803
2804
- ``basis`` - a list of linearly independent vectors
2805
2806
- ``check`` - whether or not to verify that each gen
2807
is in the ambient vector space
2808
2809
2810
OUTPUT:
2811
2812
2813
- ``FreeModule`` - the R-submodule with given basis
2814
2815
2816
EXAMPLES:
2817
2818
First we create a submodule of `\ZZ^3`::
2819
2820
sage: M = FreeModule(ZZ, 3)
2821
sage: B = M.basis()
2822
sage: N = M.submodule_with_basis([B[0]+B[1], 2*B[1]-B[2]])
2823
sage: N
2824
Free module of degree 3 and rank 2 over Integer Ring
2825
User basis matrix:
2826
[ 1 1 0]
2827
[ 0 2 -1]
2828
2829
A list of vectors in the ambient vector space may fail to generate
2830
a submodule.
2831
2832
::
2833
2834
sage: V = M.ambient_vector_space()
2835
sage: X = M.submodule_with_basis([ V(B[0]+B[1])/2, V(B[1]-B[2])/2])
2836
Traceback (most recent call last):
2837
...
2838
ArithmeticError: The given basis does not generate a submodule of self.
2839
2840
However, we can still determine the R-span of vectors in the
2841
ambient space, or over-ride the submodule check by setting check to
2842
False.
2843
2844
::
2845
2846
sage: X = V.span([ V(B[0]+B[1])/2, V(B[1]-B[2])/2 ], ZZ)
2847
sage: X
2848
Free module of degree 3 and rank 2 over Integer Ring
2849
Echelon basis matrix:
2850
[ 1/2 0 1/2]
2851
[ 0 1/2 -1/2]
2852
sage: Y = M.submodule([ V(B[0]+B[1])/2, V(B[1]-B[2])/2 ], check=False)
2853
sage: X == Y
2854
True
2855
2856
Next we try to create a submodule of a free module over the
2857
principal ideal domain `\QQ[x]`, using our general Hermite normal form implementation::
2858
2859
sage: R = PolynomialRing(QQ, 'x'); x = R.gen()
2860
sage: M = FreeModule(R, 3)
2861
sage: B = M.basis()
2862
sage: W = M.submodule_with_basis([x*B[0], 2*B[0]- x*B[2]]); W
2863
Free module of degree 3 and rank 2 over Univariate Polynomial Ring in x over Rational Field
2864
User basis matrix:
2865
[ x 0 0]
2866
[ 2 0 -x]
2867
"""
2868
V = self.span_of_basis(basis=basis, check=check, already_echelonized=already_echelonized)
2869
if check:
2870
if not V.is_submodule(self):
2871
raise ArithmeticError, "The given basis does not generate a submodule of self."
2872
return V
2873
2874
def vector_space_span(self, gens, check=True):
2875
r"""
2876
Create the vector subspace of the ambient vector space with given
2877
generators.
2878
2879
INPUT:
2880
2881
2882
- ``gens`` - a list of vector in self
2883
2884
- ``check`` - whether or not to verify that each gen
2885
is in the ambient vector space
2886
2887
2888
OUTPUT: a vector subspace
2889
2890
EXAMPLES:
2891
2892
We create a `2`-dimensional subspace of `\QQ^3`.
2893
2894
::
2895
2896
sage: V = VectorSpace(QQ, 3)
2897
sage: B = V.basis()
2898
sage: W = V.vector_space_span([B[0]+B[1], 2*B[1]-B[2]])
2899
sage: W
2900
Vector space of degree 3 and dimension 2 over Rational Field
2901
Basis matrix:
2902
[ 1 0 1/2]
2903
[ 0 1 -1/2]
2904
2905
We create a subspace of a vector space over
2906
`\QQ(i)`.
2907
2908
::
2909
2910
sage: R.<x> = QQ[]
2911
sage: K = NumberField(x^2 + 1, 'a'); a = K.gen()
2912
sage: V = VectorSpace(K, 3)
2913
sage: V.vector_space_span([2*V.gen(0) + 3*V.gen(2)])
2914
Vector space of degree 3 and dimension 1 over Number Field in a with defining polynomial x^2 + 1
2915
Basis matrix:
2916
[ 1 0 3/2]
2917
2918
We use the ``vector_space_span`` command to create a
2919
vector subspace of the ambient vector space of a submodule of
2920
`\ZZ^3`.
2921
2922
::
2923
2924
sage: M = FreeModule(ZZ,3)
2925
sage: W = M.submodule([M([1,2,3])])
2926
sage: W.vector_space_span([M([2,3,4])])
2927
Vector space of degree 3 and dimension 1 over Rational Field
2928
Basis matrix:
2929
[ 1 3/2 2]
2930
"""
2931
if is_FreeModule(gens):
2932
gens = gens.gens()
2933
return FreeModule_submodule_field(self.ambient_vector_space(), gens, check=check)
2934
2935
def vector_space_span_of_basis(self, basis, check=True):
2936
"""
2937
Create the vector subspace of the ambient vector space with given
2938
basis.
2939
2940
INPUT:
2941
2942
2943
- ``basis`` - a list of linearly independent vectors
2944
2945
- ``check`` - whether or not to verify that each gen
2946
is in the ambient vector space
2947
2948
2949
OUTPUT: a vector subspace with user-specified basis
2950
2951
EXAMPLES::
2952
2953
sage: V = VectorSpace(QQ, 3)
2954
sage: B = V.basis()
2955
sage: W = V.vector_space_span_of_basis([B[0]+B[1], 2*B[1]-B[2]])
2956
sage: W
2957
Vector space of degree 3 and dimension 2 over Rational Field
2958
User basis matrix:
2959
[ 1 1 0]
2960
[ 0 2 -1]
2961
"""
2962
return FreeModule_submodule_with_basis_field(self.ambient_vector_space(), basis, check=check)
2963
2964
def quotient(self, sub, check=True):
2965
"""
2966
Return the quotient of self by the given submodule sub.
2967
2968
INPUT:
2969
2970
- ``sub`` - a submodule of self, or something that can
2971
be turned into one via self.submodule(sub).
2972
2973
- ``check`` - (default: True) whether or not to check
2974
that sub is a submodule.
2975
2976
2977
EXAMPLES::
2978
2979
sage: A = ZZ^3; V = A.span([[1,2,3], [4,5,6]])
2980
sage: Q = V.quotient( [V.0 + V.1] ); Q
2981
Finitely generated module V/W over Integer Ring with invariants (0)
2982
"""
2983
# Calling is_subspace may be way too slow and repeat work done below.
2984
# It will be very desirable to somehow do this step better.
2985
if check and (not is_FreeModule(sub) or not sub.is_submodule(self)):
2986
try:
2987
sub = self.submodule(sub)
2988
except (TypeError, ArithmeticError):
2989
raise ArithmeticError, "sub must be a subspace of self"
2990
if self.base_ring() == sage.rings.integer_ring.ZZ:
2991
from fg_pid.fgp_module import FGP_Module
2992
return FGP_Module(self, sub, check=False)
2993
else:
2994
raise NotImplementedError, "quotients of modules over rings other than fields or ZZ is not fully implemented"
2995
2996
def __div__(self, sub, check=True):
2997
"""
2998
Return the quotient of self by the given submodule sub.
2999
3000
This just calls self.quotient(sub, check).
3001
3002
EXAMPLES::
3003
3004
sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]])
3005
sage: V1/W1
3006
Finitely generated module V/W over Integer Ring with invariants (2)
3007
sage: V2 = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W2 = V2.span([2*V2.0+4*V2.1, 9*V2.0+12*V2.1, 4*V2.2])
3008
sage: V2/W2
3009
Finitely generated module V/W over Integer Ring with invariants (4, 12)
3010
"""
3011
return self.quotient(sub, check)
3012
3013
class FreeModule_generic_field(FreeModule_generic_pid):
3014
"""
3015
Base class for all free modules over fields.
3016
"""
3017
def __init__(self, base_field, dimension, degree, sparse=False):
3018
"""
3019
Creates a vector space over a field.
3020
3021
EXAMPLES::
3022
3023
sage: FreeModule(QQ, 2)
3024
Vector space of dimension 2 over Rational Field
3025
sage: FreeModule(FiniteField(2), 7)
3026
Vector space of dimension 7 over Finite Field of size 2
3027
3028
We test that the issue at Trac #11166 is solved::
3029
3030
sage: from sage.modules.free_module import FreeModule_generic_field
3031
sage: FreeModule_generic_field(QQ, 5, 5)
3032
<class 'sage.modules.free_module.FreeModule_generic_field_with_category'>
3033
"""
3034
if not isinstance(base_field, field.Field):
3035
raise TypeError, "The base_field (=%s) must be a field"%base_field
3036
FreeModule_generic_pid.__init__(self, base_field, dimension, degree, sparse=sparse)
3037
3038
def _Hom_(self, Y, category):
3039
r"""
3040
Returns a homspace whose morphisms have this vector space as domain.
3041
3042
This is called by the general methods such as
3043
:meth:`sage.structure.parent.Parent.Hom` and
3044
:meth:`sage.structure.parent_base.ParentWithBase.Hom`.
3045
3046
INPUT:
3047
3048
- ``Y`` - a free module (or vector space) that will
3049
be the codomain of the morphisms in returned homspace
3050
- ``category`` - the category for the homspace
3051
3052
OUTPUT:
3053
3054
If ``Y`` is a free module over a field, in other words, a vector space,
3055
then this returns a space of homomorphisms between vector spaces,
3056
in other words a space of linear transformations.
3057
3058
If ``Y`` is a free module that is not a vector space, then
3059
the returned space contains homomorphisms between free modules.
3060
3061
EXAMPLES::
3062
3063
sage: V = QQ^2
3064
sage: W = QQ^3
3065
sage: H = V._Hom_(W, category=None)
3066
sage: type(H)
3067
<class 'sage.modules.vector_space_homspace.VectorSpaceHomspace_with_category'>
3068
sage: H
3069
Set of Morphisms (Linear Transformations) from Vector space of dimension 2 over Rational Field to Vector space of dimension 3 over Rational Field
3070
3071
sage: V = QQ^2
3072
sage: W = ZZ^3
3073
sage: H = V._Hom_(W, category=None)
3074
sage: type(H)
3075
<class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
3076
sage: H
3077
Set of Morphisms from Vector space of dimension 2 over Rational Field to Ambient free module of rank 3 over the principal ideal domain Integer Ring in Category of vector spaces over Rational Field
3078
"""
3079
if Y.base_ring().is_field():
3080
import vector_space_homspace
3081
return vector_space_homspace.VectorSpaceHomspace(self, Y, category)
3082
import free_module_homspace
3083
return free_module_homspace.FreeModuleHomspace(self, Y, category)
3084
3085
def scale(self, other):
3086
"""
3087
Return the product of self by the number other, which is the module
3088
spanned by other times each basis vector. Since self is a vector
3089
space this product equals self if other is nonzero, and is the zero
3090
vector space if other is 0.
3091
3092
EXAMPLES::
3093
3094
sage: V = QQ^4
3095
sage: V.scale(5)
3096
Vector space of dimension 4 over Rational Field
3097
sage: V.scale(0)
3098
Vector space of degree 4 and dimension 0 over Rational Field
3099
Basis matrix:
3100
[]
3101
3102
::
3103
3104
sage: W = V.span([[1,1,1,1]])
3105
sage: W.scale(2)
3106
Vector space of degree 4 and dimension 1 over Rational Field
3107
Basis matrix:
3108
[1 1 1 1]
3109
sage: W.scale(0)
3110
Vector space of degree 4 and dimension 0 over Rational Field
3111
Basis matrix:
3112
[]
3113
3114
::
3115
3116
sage: V = QQ^4; V
3117
Vector space of dimension 4 over Rational Field
3118
sage: V.scale(3)
3119
Vector space of dimension 4 over Rational Field
3120
sage: V.scale(0)
3121
Vector space of degree 4 and dimension 0 over Rational Field
3122
Basis matrix:
3123
[]
3124
"""
3125
if other == 0:
3126
return self.zero_submodule()
3127
return self
3128
3129
def __add__(self, other):
3130
"""
3131
Return the sum of self and other.
3132
3133
EXAMPLES::
3134
3135
sage: V = VectorSpace(QQ,3)
3136
sage: V0 = V.span([V.gen(0)])
3137
sage: V2 = V.span([V.gen(2)])
3138
sage: V0 + V2
3139
Vector space of degree 3 and dimension 2 over Rational Field
3140
Basis matrix:
3141
[1 0 0]
3142
[0 0 1]
3143
sage: QQ^3 + 0
3144
Vector space of dimension 3 over Rational Field
3145
"""
3146
if not isinstance(other, FreeModule_generic_field):
3147
if other == 0:
3148
return self
3149
raise TypeError, "other must be a Vector Space"
3150
V = self.ambient_vector_space()
3151
if V != other.ambient_vector_space():
3152
raise ArithmeticError, "self and other must have the same ambient space"
3153
return V.span(self.basis() + other.basis())
3154
3155
def echelonized_basis_matrix(self):
3156
"""
3157
Return basis matrix for self in row echelon form.
3158
3159
EXAMPLES::
3160
3161
sage: V = FreeModule(QQ, 3).span_of_basis([[1,2,3],[4,5,6]])
3162
sage: V.basis_matrix()
3163
[1 2 3]
3164
[4 5 6]
3165
sage: V.echelonized_basis_matrix()
3166
[ 1 0 -1]
3167
[ 0 1 2]
3168
"""
3169
try:
3170
return self.__echelonized_basis_matrix
3171
except AttributeError:
3172
pass
3173
self.__echelonized_basis_matrix = self.basis_matrix().echelon_form()
3174
return self.__echelonized_basis_matrix
3175
3176
def intersection(self, other):
3177
"""
3178
Return the intersection of self and other, which must be
3179
R-submodules of a common ambient vector space.
3180
3181
EXAMPLES::
3182
3183
sage: V = VectorSpace(QQ,3)
3184
sage: W1 = V.submodule([V.gen(0), V.gen(0) + V.gen(1)])
3185
sage: W2 = V.submodule([V.gen(1), V.gen(2)])
3186
sage: W1.intersection(W2)
3187
Vector space of degree 3 and dimension 1 over Rational Field
3188
Basis matrix:
3189
[0 1 0]
3190
sage: W2.intersection(W1)
3191
Vector space of degree 3 and dimension 1 over Rational Field
3192
Basis matrix:
3193
[0 1 0]
3194
sage: V.intersection(W1)
3195
Vector space of degree 3 and dimension 2 over Rational Field
3196
Basis matrix:
3197
[1 0 0]
3198
[0 1 0]
3199
sage: W1.intersection(V)
3200
Vector space of degree 3 and dimension 2 over Rational Field
3201
Basis matrix:
3202
[1 0 0]
3203
[0 1 0]
3204
sage: Z = V.submodule([])
3205
sage: W1.intersection(Z)
3206
Vector space of degree 3 and dimension 0 over Rational Field
3207
Basis matrix:
3208
[]
3209
"""
3210
if not isinstance(other, FreeModule_generic):
3211
raise TypeError, "other must be a free module"
3212
3213
if self.ambient_vector_space() != other.ambient_vector_space():
3214
raise ArithmeticError, "self and other must have the same ambient space."
3215
3216
if self.rank() == 0 or other.rank() == 0:
3217
if self.base_ring().is_field():
3218
return other.zero_submodule()
3219
else:
3220
return self.zero_submodule()
3221
3222
if self.base_ring() != other.base_ring():
3223
# Now other is over a ring R whose fraction field K is the base field of V = self.
3224
# We compute the intersection using the following algorithm:
3225
# 1. By explicitly computing the nullspace of the matrix whose rows
3226
# are a basis for self, we obtain the matrix over a linear map
3227
# phi: K^n ----> W
3228
# with kernel equal to V = self.
3229
# 2. Compute the kernel over R of Phi restricted to other. Do this
3230
# by clearing denominators, computing the kernel of a matrix with
3231
# entries in R, then restoring denominators to the answer.
3232
K = self.base_ring()
3233
R = other.base_ring()
3234
B = self.basis_matrix().transpose()
3235
W = B.kernel()
3236
phi = W.basis_matrix().transpose()
3237
3238
# To restrict phi to other, we multiply the basis matrix for other
3239
# by phi, thus computing the image of each basis vector.
3240
X = other.basis_matrix()
3241
psi = X * phi
3242
3243
# Now psi is a matrix that defines an R-module morphism from other to some
3244
# R-module, whose kernel defines the long sought for intersection of self and other.
3245
L = psi.integer_kernel()
3246
3247
# Finally the kernel of the intersection has basis the linear combinations of
3248
# the basis of other given by a basis for L.
3249
G = L.basis_matrix() * other.basis_matrix()
3250
return other.span(G.rows())
3251
3252
# dispense with the three easy cases
3253
if self == self.ambient_vector_space():
3254
return other
3255
elif other == other.ambient_vector_space():
3256
return self
3257
elif self.dimension() == 0 or other.dimension() == 0:
3258
return self.zero_submodule()
3259
3260
# standard algorithm for computing intersection of general subspaces
3261
if self.dimension() <= other.dimension():
3262
V1 = self; V2 = other
3263
else:
3264
V1 = other; V2 = self
3265
A1 = V1.basis_matrix()
3266
A2 = V2.basis_matrix()
3267
S = A1.stack(A2)
3268
K = S.kernel()
3269
n = int(V1.dimension())
3270
B = [A1.linear_combination_of_rows(v.list()[:n]) for v in K.basis()]
3271
return self.ambient_vector_space().submodule(B, check=False)
3272
3273
def is_subspace(self, other):
3274
"""
3275
True if this vector space is a subspace of other.
3276
3277
EXAMPLES::
3278
3279
sage: V = VectorSpace(QQ,3)
3280
sage: W = V.subspace([V.gen(0), V.gen(0) + V.gen(1)])
3281
sage: W2 = V.subspace([V.gen(1)])
3282
sage: W.is_subspace(V)
3283
True
3284
sage: W2.is_subspace(V)
3285
True
3286
sage: W.is_subspace(W2)
3287
False
3288
sage: W2.is_subspace(W)
3289
True
3290
"""
3291
return self.is_submodule(other)
3292
3293
def span(self, gens, base_ring=None, check=True, already_echelonized=False):
3294
"""
3295
Return the K-span of the given list of gens, where K is the
3296
base field of self or the user-specified base_ring. Note that
3297
this span is a subspace of the ambient vector space, but need
3298
not be a subspace of self.
3299
3300
INPUT:
3301
3302
3303
- ``gens`` - list of vectors
3304
3305
- ``check`` - bool (default: True): whether or not to
3306
coerce entries of gens into base field
3307
3308
- ``already_echelonized`` - bool (default: False):
3309
set this if you know the gens are already in echelon form
3310
3311
3312
EXAMPLES::
3313
3314
sage: V = VectorSpace(GF(7), 3)
3315
sage: W = V.subspace([[2,3,4]]); W
3316
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3317
Basis matrix:
3318
[1 5 2]
3319
sage: W.span([[1,1,1]])
3320
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3321
Basis matrix:
3322
[1 1 1]
3323
3324
TESTS::
3325
3326
sage: V = FreeModule(RDF,3)
3327
sage: W = V.submodule([V.gen(0)])
3328
sage: W.span([V.gen(1)], base_ring=GF(7))
3329
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3330
Basis matrix:
3331
[0 1 0]
3332
sage: v = V((1, pi, e)); v
3333
(1.0, 3.14159265359, 2.71828182846)
3334
sage: W.span([v], base_ring=GF(7))
3335
Traceback (most recent call last):
3336
...
3337
ValueError: Argument gens (= [(1.0, 3.14159265359, 2.71828182846)]) is not compatible with base_ring (= Finite Field of size 7).
3338
sage: W = V.submodule([v])
3339
sage: W.span([V.gen(2)], base_ring=GF(7))
3340
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3341
Basis matrix:
3342
[0 0 1]
3343
"""
3344
if is_FreeModule(gens):
3345
gens = gens.gens()
3346
if base_ring is None or base_ring == self.base_ring():
3347
return FreeModule_submodule_field(
3348
self.ambient_module(), gens=gens, check=check, already_echelonized=already_echelonized)
3349
else:
3350
try:
3351
M = self.ambient_module().change_ring(base_ring)
3352
except TypeError:
3353
raise ValueError, \
3354
"Argument base_ring (= %s) is not compatible with the base field (= %s)." % (base_ring, self.base_field() )
3355
try:
3356
return M.span(gens)
3357
except TypeError:
3358
raise ValueError, \
3359
"Argument gens (= %s) is not compatible with base_ring (= %s)." % (gens, base_ring)
3360
3361
def span_of_basis(self, basis, base_ring=None, check=True, already_echelonized=False):
3362
r"""
3363
Return the free K-module with the given basis, where K is the base
3364
field of self or user specified base_ring.
3365
3366
Note that this span is a subspace of the ambient vector space, but
3367
need not be a subspace of self.
3368
3369
INPUT:
3370
3371
3372
- ``basis`` - list of vectors
3373
3374
- ``check`` - bool (default: True): whether or not to
3375
coerce entries of gens into base field
3376
3377
- ``already_echelonized`` - bool (default: False):
3378
set this if you know the gens are already in echelon form
3379
3380
3381
EXAMPLES::
3382
3383
sage: V = VectorSpace(GF(7), 3)
3384
sage: W = V.subspace([[2,3,4]]); W
3385
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3386
Basis matrix:
3387
[1 5 2]
3388
sage: W.span_of_basis([[2,2,2], [3,3,0]])
3389
Vector space of degree 3 and dimension 2 over Finite Field of size 7
3390
User basis matrix:
3391
[2 2 2]
3392
[3 3 0]
3393
3394
The basis vectors must be linearly independent or an
3395
ArithmeticError exception is raised.
3396
3397
::
3398
3399
sage: W.span_of_basis([[2,2,2], [3,3,3]])
3400
Traceback (most recent call last):
3401
...
3402
ValueError: The given basis vectors must be linearly independent.
3403
"""
3404
if is_FreeModule(basis):
3405
basis = basis.gens()
3406
if base_ring is None:
3407
return FreeModule_submodule_with_basis_field(
3408
self.ambient_module(), basis=basis, check=check, already_echelonized=already_echelonized)
3409
else:
3410
try:
3411
M = self.change_ring(base_ring)
3412
except TypeError:
3413
raise ValueError, \
3414
"Argument base_ring (= %s) is not compatible with the base field (= %s)." % (
3415
base_ring, self.base_field() )
3416
try:
3417
return M.span_of_basis(basis)
3418
except TypeError:
3419
raise ValueError, \
3420
"Argument basis (= %s) is not compatible with base_ring (= %s)." % (basis, base_ring)
3421
3422
def subspace(self, gens, check=True, already_echelonized=False):
3423
"""
3424
Return the subspace of self spanned by the elements of gens.
3425
3426
INPUT:
3427
3428
3429
- ``gens`` - list of vectors
3430
3431
- ``check`` - bool (default: True) verify that gens
3432
are all in self.
3433
3434
- ``already_echelonized`` - bool (default: False) set
3435
to True if you know the gens are in Echelon form.
3436
3437
3438
EXAMPLES:
3439
3440
First we create a 1-dimensional vector subspace of an
3441
ambient `3`-dimensional space over the finite field of
3442
order `7`.
3443
3444
::
3445
3446
sage: V = VectorSpace(GF(7), 3)
3447
sage: W = V.subspace([[2,3,4]]); W
3448
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3449
Basis matrix:
3450
[1 5 2]
3451
3452
Next we create an invalid subspace, but it's allowed since
3453
``check=False``. This is just equivalent to computing
3454
the span of the element.
3455
3456
::
3457
3458
sage: W.subspace([[1,1,0]], check=False)
3459
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3460
Basis matrix:
3461
[1 1 0]
3462
3463
With ``check=True`` (the default) the mistake is
3464
correctly detected and reported with an
3465
``ArithmeticError`` exception.
3466
3467
::
3468
3469
sage: W.subspace([[1,1,0]], check=True)
3470
Traceback (most recent call last):
3471
...
3472
ArithmeticError: Argument gens (= [[1, 1, 0]]) does not generate a submodule of self.
3473
"""
3474
return self.submodule(gens, check=check, already_echelonized=already_echelonized)
3475
3476
def subspaces(self, dim):
3477
"""
3478
Iterate over all subspaces of dimension dim.
3479
3480
INPUT:
3481
3482
3483
- ``dim`` - int, dimension of subspaces to be
3484
generated
3485
3486
3487
EXAMPLE::
3488
3489
sage: V = VectorSpace(GF(3), 5)
3490
sage: len(list(V.subspaces(0)))
3491
1
3492
sage: len(list(V.subspaces(1)))
3493
121
3494
sage: len(list(V.subspaces(2)))
3495
1210
3496
sage: len(list(V.subspaces(3)))
3497
1210
3498
sage: len(list(V.subspaces(4)))
3499
121
3500
sage: len(list(V.subspaces(5)))
3501
1
3502
3503
::
3504
3505
sage: V = VectorSpace(GF(3), 5)
3506
sage: V = V.subspace([V([1,1,0,0,0]),V([0,0,1,1,0])])
3507
sage: list(V.subspaces(1))
3508
[Vector space of degree 5 and dimension 1 over Finite Field of size 3
3509
Basis matrix:
3510
[1 1 0 0 0],
3511
Vector space of degree 5 and dimension 1 over Finite Field of size 3
3512
Basis matrix:
3513
[1 1 1 1 0],
3514
Vector space of degree 5 and dimension 1 over Finite Field of size 3
3515
Basis matrix:
3516
[1 1 2 2 0],
3517
Vector space of degree 5 and dimension 1 over Finite Field of size 3
3518
Basis matrix:
3519
[0 0 1 1 0]]
3520
"""
3521
if not self.base_ring().is_finite():
3522
raise RuntimeError("Base ring must be finite.")
3523
# First, we select which columns will be pivots:
3524
from sage.combinat.subset import Subsets
3525
BASE = self.basis_matrix()
3526
for pivots in Subsets(range(self.dimension()), dim):
3527
MAT = sage.matrix.matrix_space.MatrixSpace(self.base_ring(), dim,
3528
self.dimension(), sparse = self.is_sparse())()
3529
free_positions = []
3530
for i in range(dim):
3531
MAT[i, pivots[i]] = 1
3532
for j in range(pivots[i]+1,self.dimension()):
3533
if j not in pivots:
3534
free_positions.append((i,j))
3535
# Next, we fill in those entries that are not
3536
# determined by the echelon form alone:
3537
num_free_pos = len(free_positions)
3538
ENTS = VectorSpace(self.base_ring(), num_free_pos)
3539
for v in ENTS:
3540
for k in range(num_free_pos):
3541
MAT[free_positions[k]] = v[k]
3542
# Finally, we have to multiply by the basis matrix
3543
# to take corresponding linear combinations of the basis
3544
yield self.subspace((MAT*BASE).rows())
3545
3546
def subspace_with_basis(self, gens, check=True, already_echelonized=False):
3547
"""
3548
Same as ``self.submodule_with_basis(...)``.
3549
3550
EXAMPLES:
3551
3552
We create a subspace with a user-defined basis.
3553
3554
::
3555
3556
sage: V = VectorSpace(GF(7), 3)
3557
sage: W = V.subspace_with_basis([[2,2,2], [1,2,3]]); W
3558
Vector space of degree 3 and dimension 2 over Finite Field of size 7
3559
User basis matrix:
3560
[2 2 2]
3561
[1 2 3]
3562
3563
We then create a subspace of the subspace with user-defined basis.
3564
3565
::
3566
3567
sage: W1 = W.subspace_with_basis([[3,4,5]]); W1
3568
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3569
User basis matrix:
3570
[3 4 5]
3571
3572
Notice how the basis for the same subspace is different if we
3573
merely use the ``subspace`` command.
3574
3575
::
3576
3577
sage: W2 = W.subspace([[3,4,5]]); W2
3578
Vector space of degree 3 and dimension 1 over Finite Field of size 7
3579
Basis matrix:
3580
[1 6 4]
3581
3582
Nonetheless the two subspaces are equal (as mathematical objects)::
3583
3584
sage: W1 == W2
3585
True
3586
"""
3587
return self.submodule_with_basis(gens, check=check, already_echelonized=already_echelonized)
3588
3589
def vector_space(self, base_field=None):
3590
"""
3591
Return the vector space associated to self. Since self is a vector
3592
space this function simply returns self, unless the base field is
3593
different.
3594
3595
EXAMPLES::
3596
3597
sage: V = span([[1,2,3]],QQ); V
3598
Vector space of degree 3 and dimension 1 over Rational Field
3599
Basis matrix:
3600
[1 2 3]
3601
sage: V.vector_space()
3602
Vector space of degree 3 and dimension 1 over Rational Field
3603
Basis matrix:
3604
[1 2 3]
3605
"""
3606
if base_field is None:
3607
return self
3608
return self.change_ring(base_field)
3609
3610
def zero_submodule(self):
3611
"""
3612
Return the zero submodule of self.
3613
3614
EXAMPLES::
3615
3616
sage: (QQ^4).zero_submodule()
3617
Vector space of degree 4 and dimension 0 over Rational Field
3618
Basis matrix:
3619
[]
3620
"""
3621
return self.zero_subspace()
3622
3623
def zero_subspace(self):
3624
"""
3625
Return the zero subspace of self.
3626
3627
EXAMPLES::
3628
3629
sage: (QQ^4).zero_subspace()
3630
Vector space of degree 4 and dimension 0 over Rational Field
3631
Basis matrix:
3632
[]
3633
"""
3634
return self.submodule([], check=False, already_echelonized=True)
3635
3636
def linear_dependence(self, vectors, zeros='left', check=True):
3637
r"""
3638
Returns a list of vectors giving relations of linear dependence for the input list of vectors.
3639
Can be used to check linear independence of a set of vectors.
3640
3641
INPUT:
3642
3643
- ``vectors`` - A list of vectors, all from the same vector space.
3644
- ``zeros`` - default: ``'left'`` - ``'left'`` or ``'right'`` as a general
3645
preference for where zeros are located in the returned coefficients
3646
- ``check`` - default: ``True`` - if ``True`` each item in the list ``vectors``
3647
is checked for membership in ``self``. Set to ``False`` if you
3648
can be certain the vectors come from the vector space.
3649
3650
OUTPUT:
3651
3652
Returns a list of vectors. The scalar entries of each vector provide
3653
the coefficients for a linear combination of the input vectors that
3654
will equal the zero vector in ``self``. Furthermore, the returned list
3655
is linearly independent in the vector space over the same base field
3656
with degree equal to the length of the list ``vectors``.
3657
3658
The linear independence of ``vectors`` is equivalent to the returned
3659
list being empty, so this provides a test - see the examples below.
3660
3661
The returned vectors are always independent, and with ``zeros`` set to
3662
``'left'`` they have 1's in their first non-zero entries and a qualitative
3663
disposition to having zeros in the low-index entries. With ``zeros`` set
3664
to ``'right'`` the situation is reversed with a qualitative disposition
3665
for zeros in the high-index entries.
3666
3667
If the vectors in ``vectors`` are made the rows of a matrix `V` and
3668
the returned vectors are made the rows of a matrix `R`, then the
3669
matrix product `RV` is a zero matrix of the proper size. And
3670
`R` is a matrix of full rank. This routine uses kernels of
3671
matrices to compute these relations of linear dependence,
3672
but handles all the conversions between sets of vectors
3673
and matrices. If speed is important, consider working with
3674
the appropriate matrices and kernels instead.
3675
3676
EXAMPLES:
3677
3678
We begin with two linearly independent vectors, and add three
3679
non-trivial linear combinations to the set. We illustrate
3680
both types of output and check a selected relation of linear
3681
dependence. ::
3682
3683
sage: v1 = vector(QQ, [2, 1, -4, 3])
3684
sage: v2 = vector(QQ, [1, 5, 2, -2])
3685
sage: V = QQ^4
3686
sage: V.linear_dependence([v1,v2])
3687
[
3688
<BLANKLINE>
3689
]
3690
3691
sage: v3 = v1 + v2
3692
sage: v4 = 3*v1 - 4*v2
3693
sage: v5 = -v1 + 2*v2
3694
sage: L = [v1, v2, v3, v4, v5]
3695
3696
sage: relations = V.linear_dependence(L, zeros='left')
3697
sage: relations
3698
[
3699
(1, 0, 0, -1, -2),
3700
(0, 1, 0, -1/2, -3/2),
3701
(0, 0, 1, -3/2, -7/2)
3702
]
3703
sage: v2 + (-1/2)*v4 + (-3/2)*v5
3704
(0, 0, 0, 0)
3705
3706
sage: relations = V.linear_dependence(L, zeros='right')
3707
sage: relations
3708
[
3709
(-1, -1, 1, 0, 0),
3710
(-3, 4, 0, 1, 0),
3711
(1, -2, 0, 0, 1)
3712
]
3713
sage: z = sum([relations[2][i]*L[i] for i in range(len(L))])
3714
sage: z == zero_vector(QQ, 4)
3715
True
3716
3717
A linearly independent set returns an empty list,
3718
a result that can be tested. ::
3719
3720
sage: v1 = vector(QQ, [0,1,-3])
3721
sage: v2 = vector(QQ, [4,1,0])
3722
sage: V = QQ^3
3723
sage: relations = V.linear_dependence([v1, v2]); relations
3724
[
3725
<BLANKLINE>
3726
]
3727
sage: relations == []
3728
True
3729
3730
Exact results result from exact fields. We start with three
3731
linearly independent vectors and add in two linear combinations
3732
to make a linearly dependent set of five vectors. ::
3733
3734
sage: F = FiniteField(17)
3735
sage: v1 = vector(F, [1, 2, 3, 4, 5])
3736
sage: v2 = vector(F, [2, 4, 8, 16, 15])
3737
sage: v3 = vector(F, [1, 0, 0, 0, 1])
3738
sage: (F^5).linear_dependence([v1, v2, v3]) == []
3739
True
3740
sage: L = [v1, v2, v3, 2*v1+v2, 3*v2+6*v3]
3741
sage: (F^5).linear_dependence(L)
3742
[
3743
(1, 0, 16, 8, 3),
3744
(0, 1, 2, 0, 11)
3745
]
3746
sage: v1 + 16*v3 + 8*(2*v1+v2) + 3*(3*v2+6*v3)
3747
(0, 0, 0, 0, 0)
3748
sage: v2 + 2*v3 + 11*(3*v2+6*v3)
3749
(0, 0, 0, 0, 0)
3750
sage: (F^5).linear_dependence(L, zeros='right')
3751
[
3752
(15, 16, 0, 1, 0),
3753
(0, 14, 11, 0, 1)
3754
]
3755
3756
TESTS:
3757
3758
With ``check=True`` (the default) a mismatch between vectors
3759
and the vector space is caught. ::
3760
3761
sage: v1 = vector(RR, [1,2,3])
3762
sage: v2 = vector(RR, [1,2,3,4])
3763
sage: (RR^3).linear_dependence([v1,v2], check=True)
3764
Traceback (most recent call last):
3765
...
3766
ValueError: vector (1.00000000000000, 2.00000000000000, 3.00000000000000, 4.00000000000000) is not an element of Vector space of dimension 3 over Real Field with 53 bits of precision
3767
3768
The ``zeros`` keyword is checked. ::
3769
3770
sage: (QQ^3).linear_dependence([vector(QQ,[1,2,3])], zeros='bogus')
3771
Traceback (most recent call last):
3772
...
3773
ValueError: 'zeros' keyword must be 'left' or 'right', not 'bogus'
3774
3775
An empty input set is linearly independent, vacuously. ::
3776
3777
sage: (QQ^3).linear_dependence([]) == []
3778
True
3779
"""
3780
if check:
3781
for v in vectors:
3782
if not v in self:
3783
raise ValueError('vector %s is not an element of %s' % (v, self))
3784
if zeros == 'left':
3785
basis = 'echelon'
3786
elif zeros == 'right':
3787
basis = 'pivot'
3788
else:
3789
raise ValueError("'zeros' keyword must be 'left' or 'right', not '%s'" % zeros)
3790
import sage.matrix.constructor
3791
A = sage.matrix.constructor.matrix(vectors) # as rows, so get left kernel
3792
return A.left_kernel(basis=basis).basis()
3793
3794
def __div__(self, sub, check=True):
3795
"""
3796
Return the quotient of self by the given subspace sub.
3797
3798
This just calls self.quotient(sub, check)
3799
3800
EXAMPLES::
3801
3802
sage: V = RDF^3; W = V.span([[1,0,-1], [1,-1,0]])
3803
sage: Q = V/W; Q
3804
Vector space quotient V/W of dimension 1 over Real Double Field where
3805
V: Vector space of dimension 3 over Real Double Field
3806
W: Vector space of degree 3 and dimension 2 over Real Double Field
3807
Basis matrix:
3808
[ 1.0 0.0 -1.0]
3809
[ 0.0 1.0 -1.0]
3810
sage: type(Q)
3811
<class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient_with_category'>
3812
sage: V([1,2,3])
3813
(1.0, 2.0, 3.0)
3814
sage: Q == V.quotient(W)
3815
True
3816
sage: Q(W.0)
3817
(0.0)
3818
"""
3819
return self.quotient(sub, check)
3820
3821
def quotient(self, sub, check=True):
3822
"""
3823
Return the quotient of self by the given subspace sub.
3824
3825
INPUT:
3826
3827
3828
- ``sub`` - a submodule of self, or something that can
3829
be turned into one via self.submodule(sub).
3830
3831
- ``check`` - (default: True) whether or not to check
3832
that sub is a submodule.
3833
3834
3835
EXAMPLES::
3836
3837
sage: A = QQ^3; V = A.span([[1,2,3], [4,5,6]])
3838
sage: Q = V.quotient( [V.0 + V.1] ); Q
3839
Vector space quotient V/W of dimension 1 over Rational Field where
3840
V: Vector space of degree 3 and dimension 2 over Rational Field
3841
Basis matrix:
3842
[ 1 0 -1]
3843
[ 0 1 2]
3844
W: Vector space of degree 3 and dimension 1 over Rational Field
3845
Basis matrix:
3846
[1 1 1]
3847
sage: Q(V.0 + V.1)
3848
(0)
3849
3850
We illustrate the the base rings must be the same::
3851
3852
sage: (QQ^2)/(ZZ^2)
3853
Traceback (most recent call last):
3854
...
3855
ValueError: base rings must be the same
3856
"""
3857
# Calling is_submodule may be way too slow and repeat work done below.
3858
# It will be very desirable to somehow do this step better.
3859
if is_FreeModule(sub) and self.base_ring() != sub.base_ring():
3860
raise ValueError, "base rings must be the same"
3861
if check and (not is_FreeModule(sub) or not sub.is_subspace(self)):
3862
try:
3863
sub = self.subspace(sub)
3864
except (TypeError, ArithmeticError):
3865
raise ArithmeticError, "sub must be a subspace of self"
3866
A, L = self.__quotient_matrices(sub)
3867
import quotient_module
3868
return quotient_module.FreeModule_ambient_field_quotient(self, sub, A, L)
3869
3870
def __quotient_matrices(self, sub):
3871
r"""
3872
This internal function is used by
3873
``self.quotient(...)``.
3874
3875
EXAMPLES::
3876
3877
sage: V = QQ^3; W = V.span([[1,0,-1], [1,-1,0]])
3878
sage: A, L = V._FreeModule_generic_field__quotient_matrices(W)
3879
sage: A
3880
[1]
3881
[1]
3882
[1]
3883
sage: L
3884
[1 0 0]
3885
3886
The quotient and lift maps are used to compute in the quotient and
3887
to lift::
3888
3889
sage: Q = V/W
3890
sage: Q(W.0)
3891
(0)
3892
sage: Q.lift_map()(Q.0)
3893
(1, 0, 0)
3894
sage: Q(Q.lift_map()(Q.0))
3895
(1)
3896
3897
An example in characteristic 5::
3898
3899
sage: A = GF(5)^2; B = A.span([[1,3]]); A / B
3900
Vector space quotient V/W of dimension 1 over Finite Field of size 5 where
3901
V: Vector space of dimension 2 over Finite Field of size 5
3902
W: Vector space of degree 2 and dimension 1 over Finite Field of size 5
3903
Basis matrix:
3904
[1 3]
3905
"""
3906
# 2. Find a basis C for a another submodule of self, so that
3907
# B + C is a basis for self.
3908
# 3. Then the quotient map is:
3909
# x |---> 'write in terms of basis for C and take the last m = #C-#B components.
3910
# 4. And a section of this map is:
3911
# x |---> corresponding linear combination of entries of last m entries
3912
# of the basis C.
3913
3914
# Step 1: Find bases for spaces
3915
B = sub.basis_matrix()
3916
S = self.basis_matrix()
3917
3918
n = self.dimension()
3919
m = n - sub.dimension()
3920
3921
# Step 2: Extend basis B to a basis for self.
3922
# We do this by simply finding the pivot rows of the matrix
3923
# whose rows are a basis for sub concatenated with a basis for
3924
# self.
3925
C = B.stack(S).transpose()
3926
A = C.matrix_from_columns(C.pivots()).transpose()
3927
3928
# Step 3: Compute quotient map
3929
# The quotient map is given by writing in terms of the above basis,
3930
# then taking the last #C columns
3931
3932
# Compute the matrix D "change of basis from S to A"
3933
# that writes each element of the basis
3934
# for self in terms of the basis of rows of A, i.e.,
3935
# want to find D such that
3936
# D * A = S
3937
# where D is a square n x n matrix.
3938
# Our algorithm is to note that D is determined if we just
3939
# replace both A and S by the submatrix got from their pivot
3940
# columns.
3941
P = A.pivots()
3942
AA = A.matrix_from_columns(P)
3943
SS = S.matrix_from_columns(P)
3944
D = SS * AA**(-1)
3945
3946
# Compute the image of each basis vector for self under the
3947
# map "write an element of self in terms of the basis A" then
3948
# take the last n-m components.
3949
Q = D.matrix_from_columns(range(n - m, n))
3950
3951
# Step 4. Section map
3952
# The lifting or section map
3953
Dinv = D**(-1)
3954
L = Dinv.matrix_from_rows(range(n - m, n))
3955
3956
return Q, L
3957
3958
def quotient_abstract(self, sub, check=True):
3959
r"""
3960
Returns an ambient free module isomorphic to the quotient space of
3961
self modulo sub, together with maps from self to the quotient, and
3962
a lifting map in the other direction.
3963
3964
Use ``self.quotient(sub)`` to obtain the quotient
3965
module as an object equipped with natural maps in both directions,
3966
and a canonical coercion.
3967
3968
INPUT:
3969
3970
3971
- ``sub`` - a submodule of self, or something that can
3972
be turned into one via self.submodule(sub).
3973
3974
- ``check`` - (default: True) whether or not to check
3975
that sub is a submodule.
3976
3977
3978
OUTPUT:
3979
3980
3981
- ``U`` - the quotient as an abstract *ambient* free
3982
module
3983
3984
- ``pi`` - projection map to the quotient
3985
3986
- ``lift`` - lifting map back from quotient
3987
3988
3989
EXAMPLES::
3990
3991
sage: V = GF(19)^3
3992
sage: W = V.span_of_basis([ [1,2,3], [1,0,1] ])
3993
sage: U,pi,lift = V.quotient_abstract(W)
3994
sage: pi(V.2)
3995
(18)
3996
sage: pi(V.0)
3997
(1)
3998
sage: pi(V.0 + V.2)
3999
(0)
4000
4001
Another example involving a quotient of one subspace by another.
4002
4003
::
4004
4005
sage: A = matrix(QQ,4,4,[0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0])
4006
sage: V = (A^3).kernel()
4007
sage: W = A.kernel()
4008
sage: U, pi, lift = V.quotient_abstract(W)
4009
sage: [pi(v) == 0 for v in W.gens()]
4010
[True]
4011
sage: [pi(lift(b)) == b for b in U.basis()]
4012
[True, True]
4013
"""
4014
# Calling is_subspace may be way too slow and repeat work done below.
4015
# It will be very desirable to somehow do this step better.
4016
if check and (not is_FreeModule(sub) or not sub.is_subspace(self)):
4017
try:
4018
sub = self.subspace(sub)
4019
except (TypeError, ArithmeticError):
4020
raise ArithmeticError, "sub must be a subspace of self"
4021
4022
A, L = self.__quotient_matrices(sub)
4023
quomap = self.hom(A)
4024
quo = quomap.codomain()
4025
liftmap = quo.Hom(self)(L)
4026
4027
return quomap.codomain(), quomap, liftmap
4028
4029
###############################################################################
4030
#
4031
# Generic ambient free modules, i.e., of the form R^n for some commutative ring R.
4032
#
4033
###############################################################################
4034
4035
class FreeModule_ambient(FreeModule_generic):
4036
"""
4037
Ambient free module over a commutative ring.
4038
"""
4039
def __init__(self, base_ring, rank, sparse=False):
4040
"""
4041
The free module of given rank over the given base_ring.
4042
4043
INPUT:
4044
4045
4046
- ``base_ring`` - a commutative ring
4047
4048
- ``rank`` - a non-negative integer
4049
4050
4051
EXAMPLES::
4052
4053
sage: FreeModule(ZZ, 4)
4054
Ambient free module of rank 4 over the principal ideal domain Integer Ring
4055
"""
4056
FreeModule_generic.__init__(self, base_ring, rank=rank, degree=rank, sparse=sparse)
4057
4058
def __hash__(self):
4059
"""
4060
The hash of self.
4061
4062
EXAMPLES::
4063
4064
sage: V = QQ^7
4065
sage: V.__hash__()
4066
153079684 # 32-bit
4067
-3713095619189944444 # 64-bit
4068
sage: U = QQ^7
4069
sage: U.__hash__()
4070
153079684 # 32-bit
4071
-3713095619189944444 # 64-bit
4072
sage: U is V
4073
True
4074
"""
4075
try:
4076
return hash((self.rank(), self.base_ring()))
4077
except AttributeError:
4078
# This is a fallback because sometimes hash is called during object
4079
# reconstruction (unpickle), and the above fields haven't been
4080
# filled in yet.
4081
return 0
4082
4083
def _dense_module(self):
4084
"""
4085
Creates a dense module with the same defining data as self.
4086
4087
N.B. This function is for internal use only! See dense_module for
4088
use.
4089
4090
EXAMPLES::
4091
4092
sage: M = FreeModule(Integers(8),3)
4093
sage: S = FreeModule(Integers(8),3, sparse=True)
4094
sage: M is S._dense_module()
4095
True
4096
"""
4097
return FreeModule(base_ring=self.base_ring(), rank = self.rank(), sparse=False)
4098
4099
def _sparse_module(self):
4100
"""
4101
Creates a sparse module with the same defining data as self.
4102
4103
N.B. This function is for internal use only! See sparse_module for
4104
use.
4105
4106
EXAMPLES::
4107
4108
sage: M = FreeModule(Integers(8),3)
4109
sage: S = FreeModule(Integers(8),3, sparse=True)
4110
sage: M._sparse_module() is S
4111
True
4112
"""
4113
return FreeModule(base_ring=self.base_ring(), rank = self.rank(), sparse=True)
4114
4115
def echelonized_basis_matrix(self):
4116
"""
4117
The echelonized basis matrix of self.
4118
4119
EXAMPLES::
4120
4121
sage: V = ZZ^4
4122
sage: W = V.submodule([ V.gen(i)-V.gen(0) for i in range(1,4) ])
4123
sage: W.basis_matrix()
4124
[ 1 0 0 -1]
4125
[ 0 1 0 -1]
4126
[ 0 0 1 -1]
4127
sage: W.echelonized_basis_matrix()
4128
[ 1 0 0 -1]
4129
[ 0 1 0 -1]
4130
[ 0 0 1 -1]
4131
sage: U = V.submodule_with_basis([ V.gen(i)-V.gen(0) for i in range(1,4) ])
4132
sage: U.basis_matrix()
4133
[-1 1 0 0]
4134
[-1 0 1 0]
4135
[-1 0 0 1]
4136
sage: U.echelonized_basis_matrix()
4137
[ 1 0 0 -1]
4138
[ 0 1 0 -1]
4139
[ 0 0 1 -1]
4140
"""
4141
return self.basis_matrix()
4142
4143
def __cmp__(self, other):
4144
"""
4145
Compare the free module self with other.
4146
4147
Modules are ordered by their ambient spaces, then by dimension,
4148
then in order by their echelon matrices.
4149
4150
EXAMPLES:
4151
4152
We compare rank three free modules over the integers and
4153
rationals::
4154
4155
sage: QQ^3 < CC^3
4156
True
4157
sage: CC^3 < QQ^3
4158
False
4159
sage: CC^3 > QQ^3
4160
True
4161
4162
::
4163
4164
sage: Q = QQ; Z = ZZ
4165
sage: Q^3 > Z^3
4166
True
4167
sage: Q^3 < Z^3
4168
False
4169
sage: Z^3 < Q^3
4170
True
4171
sage: Z^3 > Q^3
4172
False
4173
sage: Q^3 == Z^3
4174
False
4175
sage: Q^3 == Q^3
4176
True
4177
4178
::
4179
4180
sage: V = span([[1,2,3], [5,6,7], [8,9,10]], QQ)
4181
sage: V
4182
Vector space of degree 3 and dimension 2 over Rational Field
4183
Basis matrix:
4184
[ 1 0 -1]
4185
[ 0 1 2]
4186
sage: A = QQ^3
4187
sage: V < A
4188
True
4189
sage: A < V
4190
False
4191
"""
4192
if self is other:
4193
return 0
4194
if not isinstance(other, FreeModule_generic):
4195
return cmp(type(self), type(other))
4196
if isinstance(other, FreeModule_ambient):
4197
c = cmp(self.rank(), other.rank())
4198
if c: return c
4199
c = cmp(self.base_ring(), other.base_ring())
4200
if not c: return c
4201
try:
4202
if self.base_ring().is_subring(other.base_ring()):
4203
return -1
4204
elif other.base_ring().is_subring(self.base_ring()):
4205
return 1
4206
except NotImplementedError:
4207
pass
4208
return c
4209
else: # now other is not ambient; it knows how to do the comparison.
4210
return -other.__cmp__(self)
4211
4212
def _repr_(self):
4213
"""
4214
The printing representation of self.
4215
4216
EXAMPLES::
4217
4218
sage: R = ZZ.quo(12)
4219
sage: M = R^12
4220
sage: print M
4221
Ambient free module of rank 12 over Ring of integers modulo 12
4222
sage: print M._repr_()
4223
Ambient free module of rank 12 over Ring of integers modulo 12
4224
4225
The system representation can be overwritten, but leaves _repr_
4226
unmodified.
4227
4228
::
4229
4230
sage: M.rename('M')
4231
sage: print M
4232
M
4233
sage: print M._repr_()
4234
Ambient free module of rank 12 over Ring of integers modulo 12
4235
4236
Sparse modules print this fact.
4237
4238
::
4239
4240
sage: N = FreeModule(R,12,sparse=True)
4241
sage: print N
4242
Ambient sparse free module of rank 12 over Ring of integers modulo 12
4243
4244
(Now clean up again.)
4245
4246
::
4247
4248
sage: M.reset_name()
4249
sage: print M
4250
Ambient free module of rank 12 over Ring of integers modulo 12
4251
"""
4252
if self.is_sparse():
4253
return "Ambient sparse free module of rank %s over %s"%(self.rank(), self.base_ring())
4254
else:
4255
return "Ambient free module of rank %s over %s"%(self.rank(), self.base_ring())
4256
4257
def _latex_(self):
4258
r"""
4259
Return a latex representation of this ambient free module.
4260
4261
EXAMPLES::
4262
4263
sage: latex(QQ^3) # indirect doctest
4264
\Bold{Q}^{3}
4265
4266
::
4267
4268
sage: A = GF(5)^20
4269
sage: latex(A) # indiret doctest
4270
\Bold{F}_{5}^{20}
4271
4272
::
4273
4274
sage: A = PolynomialRing(QQ,3,'x') ^ 20
4275
sage: latex(A) #indirect doctest
4276
(\Bold{Q}[x_{0}, x_{1}, x_{2}])^{20}
4277
"""
4278
t = "%s"%latex.latex(self.base_ring())
4279
if t.find(" ") != -1:
4280
t = "(%s)"%t
4281
return "%s^{%s}"%(t, self.rank())
4282
4283
def is_ambient(self):
4284
"""
4285
Return ``True`` since this module is an ambient
4286
module.
4287
4288
EXAMPLES::
4289
4290
sage: A = QQ^5; A.is_ambient()
4291
True
4292
sage: A = (QQ^5).span([[1,2,3,4,5]]); A.is_ambient()
4293
False
4294
"""
4295
return True
4296
4297
def ambient_module(self):
4298
"""
4299
Return self, since self is ambient.
4300
4301
EXAMPLES::
4302
4303
sage: A = QQ^5; A.ambient_module()
4304
Vector space of dimension 5 over Rational Field
4305
sage: A = ZZ^5; A.ambient_module()
4306
Ambient free module of rank 5 over the principal ideal domain Integer Ring
4307
"""
4308
return self
4309
4310
def basis(self):
4311
"""
4312
Return a basis for this ambient free module.
4313
4314
OUTPUT:
4315
4316
4317
- ``Sequence`` - an immutable sequence with universe
4318
this ambient free module
4319
4320
4321
EXAMPLES::
4322
4323
sage: A = ZZ^3; B = A.basis(); B
4324
[
4325
(1, 0, 0),
4326
(0, 1, 0),
4327
(0, 0, 1)
4328
]
4329
sage: B.universe()
4330
Ambient free module of rank 3 over the principal ideal domain Integer Ring
4331
"""
4332
try:
4333
return self.__basis
4334
except AttributeError:
4335
ZERO = self(0)
4336
one = self.base_ring()(1)
4337
w = []
4338
for n in range(self.rank()):
4339
v = ZERO.__copy__()
4340
v[n] = one
4341
w.append(v)
4342
self.__basis = basis_seq(self, w)
4343
return self.__basis
4344
4345
def echelonized_basis(self):
4346
"""
4347
Return a basis for this ambient free module in echelon form.
4348
4349
EXAMPLES::
4350
4351
sage: A = ZZ^3; A.echelonized_basis()
4352
[
4353
(1, 0, 0),
4354
(0, 1, 0),
4355
(0, 0, 1)
4356
]
4357
"""
4358
return self.basis()
4359
4360
def change_ring(self, R):
4361
"""
4362
Return the ambient free module over R of the same rank as self.
4363
4364
EXAMPLES::
4365
4366
sage: A = ZZ^3; A.change_ring(QQ)
4367
Vector space of dimension 3 over Rational Field
4368
sage: A = ZZ^3; A.change_ring(GF(5))
4369
Vector space of dimension 3 over Finite Field of size 5
4370
4371
For ambient modules any change of rings is defined.
4372
4373
::
4374
4375
sage: A = GF(5)**3; A.change_ring(QQ)
4376
Vector space of dimension 3 over Rational Field
4377
"""
4378
if self.base_ring() == R:
4379
return self
4380
from free_quadratic_module import is_FreeQuadraticModule
4381
if is_FreeQuadraticModule(self):
4382
return FreeModule(R, self.rank(), inner_product_matrix=self.inner_product_matrix())
4383
else:
4384
return FreeModule(R, self.rank())
4385
4386
4387
def linear_combination_of_basis(self, v):
4388
"""
4389
Return the linear combination of the basis for self obtained from
4390
the elements of the list v.
4391
4392
INPUTS:
4393
4394
- ``v`` - list
4395
4396
EXAMPLES::
4397
4398
sage: V = span([[1,2,3], [4,5,6]], ZZ)
4399
sage: V
4400
Free module of degree 3 and rank 2 over Integer Ring
4401
Echelon basis matrix:
4402
[1 2 3]
4403
[0 3 6]
4404
sage: V.linear_combination_of_basis([1,1])
4405
(1, 5, 9)
4406
4407
This should raise an error if the resulting element is not in self::
4408
4409
sage: W = span([[2,4]], ZZ)
4410
sage: W.linear_combination_of_basis([1/2])
4411
Traceback (most recent call last):
4412
...
4413
TypeError: element (= [1, 2]) is not in free module
4414
"""
4415
return self(v)
4416
4417
def coordinate_vector(self, v, check=True):
4418
"""
4419
Write `v` in terms of the standard basis for self and
4420
return the resulting coefficients in a vector over the fraction
4421
field of the base ring.
4422
4423
Returns a vector `c` such that if `B` is the basis for self, then
4424
4425
.. math::
4426
4427
\sum c_i B_i = v.
4428
4429
If `v` is not in self, raises an ArithmeticError
4430
exception.
4431
4432
EXAMPLES::
4433
4434
sage: V = Integers(16)^3
4435
sage: v = V.coordinate_vector([1,5,9]); v
4436
(1, 5, 9)
4437
sage: v.parent()
4438
Ambient free module of rank 3 over Ring of integers modulo 16
4439
"""
4440
return self(v)
4441
4442
def echelon_coordinate_vector(self, v, check=True):
4443
r"""
4444
Same as ``self.coordinate_vector(v)``, since self is
4445
an ambient free module.
4446
4447
INPUT:
4448
4449
4450
- ``v`` - vector
4451
4452
- ``check`` - bool (default: True); if True, also
4453
verify that v is really in self.
4454
4455
4456
OUTPUT: list
4457
4458
EXAMPLES::
4459
4460
sage: V = QQ^4
4461
sage: v = V([-1/2,1/2,-1/2,1/2])
4462
sage: v
4463
(-1/2, 1/2, -1/2, 1/2)
4464
sage: V.coordinate_vector(v)
4465
(-1/2, 1/2, -1/2, 1/2)
4466
sage: V.echelon_coordinate_vector(v)
4467
(-1/2, 1/2, -1/2, 1/2)
4468
sage: W = V.submodule_with_basis([[1/2,1/2,1/2,1/2],[1,0,1,0]])
4469
sage: W.coordinate_vector(v)
4470
(1, -1)
4471
sage: W.echelon_coordinate_vector(v)
4472
(-1/2, 1/2)
4473
"""
4474
return self.coordinate_vector(v, check=check)
4475
4476
def echelon_coordinates(self, v, check=True):
4477
"""
4478
Returns the coordinate vector of v in terms of the echelon basis
4479
for self.
4480
4481
EXAMPLES::
4482
4483
sage: U = VectorSpace(QQ,3)
4484
sage: [ U.coordinates(v) for v in U.basis() ]
4485
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
4486
sage: [ U.echelon_coordinates(v) for v in U.basis() ]
4487
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
4488
sage: V = U.submodule([[1,1,0],[0,1,1]])
4489
sage: V
4490
Vector space of degree 3 and dimension 2 over Rational Field
4491
Basis matrix:
4492
[ 1 0 -1]
4493
[ 0 1 1]
4494
sage: [ V.coordinates(v) for v in V.basis() ]
4495
[[1, 0], [0, 1]]
4496
sage: [ V.echelon_coordinates(v) for v in V.basis() ]
4497
[[1, 0], [0, 1]]
4498
sage: W = U.submodule_with_basis([[1,1,0],[0,1,1]])
4499
sage: W
4500
Vector space of degree 3 and dimension 2 over Rational Field
4501
User basis matrix:
4502
[1 1 0]
4503
[0 1 1]
4504
sage: [ W.coordinates(v) for v in W.basis() ]
4505
[[1, 0], [0, 1]]
4506
sage: [ W.echelon_coordinates(v) for v in W.basis() ]
4507
[[1, 1], [0, 1]]
4508
"""
4509
return self.coordinates(v, check=check)
4510
4511
def random_element(self, prob=1.0, *args, **kwds):
4512
"""
4513
Returns a random element of self.
4514
4515
INPUT:
4516
4517
4518
- ``prob`` - float. Each coefficient will be set to zero with
4519
probability `1-prob`. Otherwise coefficients will be chosen
4520
randomly from base ring (and may be zero).
4521
4522
- ``*args, **kwds`` - passed on to random_element function of base
4523
ring.
4524
4525
4526
EXAMPLES::
4527
4528
sage: M = FreeModule(ZZ, 3)
4529
sage: M.random_element()
4530
(-1, 2, 1)
4531
sage: M.random_element()
4532
(-95, -1, -2)
4533
sage: M.random_element()
4534
(-12, 0, 0)
4535
4536
Passes extra positional or keyword arguments through::
4537
4538
sage: M.random_element(5,10)
4539
(5, 5, 5)
4540
4541
4542
::
4543
4544
sage: M = FreeModule(ZZ, 16)
4545
sage: M.random_element()
4546
(-6, 5, 0, 0, -2, 0, 1, -4, -6, 1, -1, 1, 1, -1, 1, -1)
4547
sage: M.random_element(prob=0.3)
4548
(0, 0, 0, 0, -3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -3)
4549
"""
4550
rand = current_randstate().python_random().random
4551
R = self.base_ring()
4552
v = self(0)
4553
prob = float(prob)
4554
for i in range(self.rank()):
4555
if rand() <= prob:
4556
v[i] = R.random_element(*args, **kwds)
4557
return v
4558
4559
4560
###############################################################################
4561
#
4562
# Ambient free modules over an integral domain.
4563
#
4564
###############################################################################
4565
4566
class FreeModule_ambient_domain(FreeModule_ambient):
4567
"""
4568
Ambient free module over an integral domain.
4569
"""
4570
def __init__(self, base_ring, rank, sparse=False):
4571
"""
4572
Create the ambient free module of given rank over the given
4573
integral domain.
4574
4575
EXAMPLES::
4576
4577
sage: FreeModule(PolynomialRing(GF(5),'x'), 3)
4578
Ambient free module of rank 3 over the principal ideal domain
4579
Univariate Polynomial Ring in x over Finite Field of size 5
4580
"""
4581
FreeModule_ambient.__init__(self, base_ring, rank, sparse)
4582
4583
def _repr_(self):
4584
"""
4585
The printing representation of self.
4586
4587
EXAMPLES::
4588
4589
sage: R = PolynomialRing(ZZ,'x')
4590
sage: M = FreeModule(R,7)
4591
sage: print M
4592
Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring
4593
sage: print M._repr_()
4594
Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring
4595
4596
The system representation can be overwritten, but leaves _repr_
4597
unmodified.
4598
4599
::
4600
4601
sage: M.rename('M')
4602
sage: print M
4603
M
4604
sage: print M._repr_()
4605
Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring
4606
4607
Sparse modules print this fact.
4608
4609
::
4610
4611
sage: N = FreeModule(R,7,sparse=True)
4612
sage: print N
4613
Ambient sparse free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring
4614
4615
(Now clean up again.)
4616
4617
::
4618
4619
sage: M.reset_name()
4620
sage: print M
4621
Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring
4622
"""
4623
if self.is_sparse():
4624
return "Ambient sparse free module of rank %s over the integral domain %s"%(
4625
self.rank(), self.base_ring())
4626
else:
4627
return "Ambient free module of rank %s over the integral domain %s"%(
4628
self.rank(), self.base_ring())
4629
4630
def base_field(self):
4631
"""
4632
Return the fraction field of the base ring of self.
4633
4634
EXAMPLES::
4635
4636
sage: M = ZZ^3; M.base_field()
4637
Rational Field
4638
sage: M = PolynomialRing(GF(5),'x')^3; M.base_field()
4639
Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 5
4640
"""
4641
return self.base_ring().fraction_field()
4642
4643
def ambient_vector_space(self):
4644
"""
4645
Returns the ambient vector space, which is this free module
4646
tensored with its fraction field.
4647
4648
EXAMPLES::
4649
4650
sage: M = ZZ^3;
4651
sage: V = M.ambient_vector_space(); V
4652
Vector space of dimension 3 over Rational Field
4653
4654
If an inner product on the module is specified, then this
4655
is preserved on the ambient vector space.
4656
4657
::
4658
4659
sage: N = FreeModule(ZZ,4,inner_product_matrix=1)
4660
sage: U = N.ambient_vector_space()
4661
sage: U
4662
Ambient quadratic space of dimension 4 over Rational Field
4663
Inner product matrix:
4664
[1 0 0 0]
4665
[0 1 0 0]
4666
[0 0 1 0]
4667
[0 0 0 1]
4668
sage: P = N.submodule_with_basis([[1,-1,0,0],[0,1,-1,0],[0,0,1,-1]])
4669
sage: P.gram_matrix()
4670
[ 2 -1 0]
4671
[-1 2 -1]
4672
[ 0 -1 2]
4673
sage: U == N.ambient_vector_space()
4674
True
4675
sage: U == V
4676
False
4677
"""
4678
try:
4679
return self.__ambient_vector_space
4680
except AttributeError:
4681
self.__ambient_vector_space = FreeModule(self.base_field(), self.rank(), sparse=self.is_sparse())
4682
return self.__ambient_vector_space
4683
4684
def coordinate_vector(self, v, check=True):
4685
"""
4686
Write `v` in terms of the standard basis for self and
4687
return the resulting coefficients in a vector over the fraction
4688
field of the base ring.
4689
4690
INPUT:
4691
4692
4693
- ``v`` - vector
4694
4695
- ``check`` - bool (default: True); if True, also
4696
verify that v is really in self.
4697
4698
4699
OUTPUT: list
4700
4701
Returns a vector `c` such that if `B` is the basis for self, then
4702
4703
.. math::
4704
4705
\sum c_i B_i = v.
4706
4707
If `v` is not in self, raises an ArithmeticError exception.
4708
4709
EXAMPLES::
4710
4711
sage: V = ZZ^3
4712
sage: v = V.coordinate_vector([1,5,9]); v
4713
(1, 5, 9)
4714
sage: v.parent()
4715
Vector space of dimension 3 over Rational Field
4716
"""
4717
return self.ambient_vector_space()(v)
4718
4719
def vector_space(self, base_field=None):
4720
"""
4721
Returns the vector space obtained from self by tensoring with the
4722
fraction field of the base ring and extending to the field.
4723
4724
EXAMPLES::
4725
4726
sage: M = ZZ^3; M.vector_space()
4727
Vector space of dimension 3 over Rational Field
4728
"""
4729
if base_field is None:
4730
R = self.base_ring()
4731
return self.change_ring(R.fraction_field())
4732
else:
4733
return self.change_ring(base_field)
4734
4735
###############################################################################
4736
#
4737
# Ambient free modules over a principal ideal domain.
4738
#
4739
###############################################################################
4740
4741
class FreeModule_ambient_pid(FreeModule_generic_pid, FreeModule_ambient_domain):
4742
"""
4743
Ambient free module over a principal ideal domain.
4744
"""
4745
def __init__(self, base_ring, rank, sparse=False):
4746
"""
4747
Create the ambient free module of given rank over the given
4748
principal ideal domain.
4749
4750
INPUT:
4751
4752
4753
- ``base_ring`` - a principal ideal domain
4754
4755
- ``rank`` - a non-negative integer
4756
4757
- ``sparse`` - bool (default: False)
4758
4759
4760
EXAMPLES::
4761
4762
sage: ZZ^3
4763
Ambient free module of rank 3 over the principal ideal domain Integer Ring
4764
"""
4765
FreeModule_ambient_domain.__init__(self, base_ring=base_ring, rank=rank, sparse=sparse)
4766
4767
def _repr_(self):
4768
"""
4769
The printing representation of self.
4770
4771
EXAMPLES::
4772
4773
sage: M = FreeModule(ZZ,7)
4774
sage: print M
4775
Ambient free module of rank 7 over the principal ideal domain Integer Ring
4776
sage: print M._repr_()
4777
Ambient free module of rank 7 over the principal ideal domain Integer Ring
4778
4779
The system representation can be overwritten, but leaves _repr_
4780
unmodified.
4781
4782
::
4783
4784
sage: M.rename('M')
4785
sage: print M
4786
M
4787
sage: print M._repr_()
4788
Ambient free module of rank 7 over the principal ideal domain Integer Ring
4789
4790
Sparse modules print this fact.
4791
4792
::
4793
4794
sage: N = FreeModule(ZZ,7,sparse=True)
4795
sage: print N
4796
Ambient sparse free module of rank 7 over the principal ideal domain Integer Ring
4797
4798
(Now clean up again.)
4799
4800
::
4801
4802
sage: M.reset_name()
4803
sage: print M
4804
Ambient free module of rank 7 over the principal ideal domain Integer Ring
4805
"""
4806
if self.is_sparse():
4807
return "Ambient sparse free module of rank %s over the principal ideal domain %s"%(
4808
self.rank(), self.base_ring())
4809
else:
4810
return "Ambient free module of rank %s over the principal ideal domain %s"%(
4811
self.rank(), self.base_ring())
4812
4813
4814
###############################################################################
4815
#
4816
# Ambient free modules over a field (i.e., a vector space).
4817
#
4818
###############################################################################
4819
4820
class FreeModule_ambient_field(FreeModule_generic_field, FreeModule_ambient_pid):
4821
"""
4822
4823
"""
4824
def __init__(self, base_field, dimension, sparse=False):
4825
"""
4826
Create the ambient vector space of given dimension over the given
4827
field.
4828
4829
INPUT:
4830
4831
4832
- ``base_field`` - a field
4833
4834
- ``dimension`` - a non-negative integer
4835
4836
- ``sparse`` - bool (default: False)
4837
4838
4839
EXAMPLES::
4840
4841
sage: QQ^3
4842
Vector space of dimension 3 over Rational Field
4843
"""
4844
FreeModule_ambient_pid.__init__(self, base_field, dimension, sparse=sparse)
4845
4846
def _repr_(self):
4847
"""
4848
The printing representation of self.
4849
4850
EXAMPLES::
4851
4852
sage: V = FreeModule(QQ,7)
4853
sage: print V
4854
Vector space of dimension 7 over Rational Field
4855
sage: print V._repr_()
4856
Vector space of dimension 7 over Rational Field
4857
4858
The system representation can be overwritten, but leaves _repr_
4859
unmodified.
4860
4861
::
4862
4863
sage: V.rename('V')
4864
sage: print V
4865
V
4866
sage: print V._repr_()
4867
Vector space of dimension 7 over Rational Field
4868
4869
Sparse modules print this fact.
4870
4871
::
4872
4873
sage: U = FreeModule(QQ,7,sparse=True)
4874
sage: print U
4875
Sparse vector space of dimension 7 over Rational Field
4876
4877
(Now clean up again.)
4878
4879
::
4880
4881
sage: V.reset_name()
4882
sage: print V
4883
Vector space of dimension 7 over Rational Field
4884
"""
4885
if self.is_sparse():
4886
return "Sparse vector space of dimension %s over %s"%(self.dimension(), self.base_ring())
4887
else:
4888
return "Vector space of dimension %s over %s"%(self.dimension(), self.base_ring())
4889
4890
def ambient_vector_space(self):
4891
"""
4892
Returns self as the ambient vector space.
4893
4894
EXAMPLES::
4895
4896
sage: M = QQ^3
4897
sage: M.ambient_vector_space()
4898
Vector space of dimension 3 over Rational Field
4899
"""
4900
return self
4901
4902
def base_field(self):
4903
"""
4904
Returns the base field of this vector space.
4905
4906
EXAMPLES::
4907
4908
sage: M = QQ^3
4909
sage: M.base_field()
4910
Rational Field
4911
"""
4912
return self.base_ring()
4913
4914
def __call__(self, e, coerce=True, copy=True, check=True):
4915
"""
4916
Create an element of this vector space.
4917
4918
EXAMPLE::
4919
4920
sage: k.<a> = GF(3^4)
4921
sage: VS = k.vector_space()
4922
sage: VS(a)
4923
(0, 1, 0, 0)
4924
"""
4925
try:
4926
k = e.parent()
4927
if finite_field.is_FiniteField(k) and k.base_ring() == self.base_ring() and k.degree() == self.degree():
4928
return self(e._vector_())
4929
except AttributeError:
4930
pass
4931
return FreeModule_generic_field.__call__(self,e)
4932
4933
###############################################################################
4934
#
4935
# R-Submodule of K^n where K is the fraction field of a principal ideal domain $R$.
4936
#
4937
###############################################################################
4938
4939
class FreeModule_submodule_with_basis_pid(FreeModule_generic_pid):
4940
r"""
4941
Construct a submodule of a free module over PID with a distiguished basis.
4942
4943
INPUT:
4944
4945
- ``ambient`` -- ambient free module over a principal ideal domain `R`,
4946
i.e. `R^n`;
4947
4948
- ``basis`` -- list of elements of `K^n`, where `K` is the fraction field
4949
of `R`. These elements must be linearly independent and will be used as
4950
the default basis of the constructed submodule;
4951
4952
- ``check`` -- (default: ``True``) if ``False``, correctness of the input
4953
will not be checked and type conversion may be omitted, use with care;
4954
4955
- ``echelonize`` -- (default:``False``) if ``True``, ``basis`` will be
4956
echelonized and the result will be used as the default basis of the
4957
constructed submodule;
4958
4959
- `` echelonized_basis`` -- (default: ``None``) if not ``None``, must be
4960
the echelonized basis spanning the same submodule as ``basis``;
4961
4962
- ``already_echelonized`` -- (default: ``False``) if ``True``, ``basis``
4963
must be already given in the echelonized form.
4964
4965
OUTPUT:
4966
4967
- `R`-submodule of `K^n` with the user-specified ``basis``.
4968
4969
EXAMPLES::
4970
4971
sage: M = ZZ^3
4972
sage: W = M.span_of_basis([[1,2,3],[4,5,6]]); W
4973
Free module of degree 3 and rank 2 over Integer Ring
4974
User basis matrix:
4975
[1 2 3]
4976
[4 5 6]
4977
4978
Now we create a submodule of the ambient vector space, rather than
4979
``M`` itself::
4980
4981
sage: W = M.span_of_basis([[1,2,3/2],[4,5,6]]); W
4982
Free module of degree 3 and rank 2 over Integer Ring
4983
User basis matrix:
4984
[ 1 2 3/2]
4985
[ 4 5 6]
4986
"""
4987
4988
def __init__(self, ambient, basis, check=True,
4989
echelonize=False, echelonized_basis=None, already_echelonized=False):
4990
r"""
4991
See :class:`FreeModule_submodule_with_basis_pid` for documentation.
4992
4993
TESTS::
4994
4995
sage: M = ZZ^3
4996
sage: W = M.span_of_basis([[1,2,3],[4,5,6]])
4997
sage: TestSuite(W).run()
4998
4999
We test that the issue at :trac:`9502` is solved::
5000
5001
sage: parent(W.basis()[0])
5002
Free module of degree 3 and rank 2 over Integer Ring
5003
User basis matrix:
5004
[1 2 3]
5005
[4 5 6]
5006
sage: parent(W.echelonized_basis()[0])
5007
Free module of degree 3 and rank 2 over Integer Ring
5008
User basis matrix:
5009
[1 2 3]
5010
[4 5 6]
5011
5012
Now we test that the issue introduced at :trac:`9502` and reported at
5013
:trac:`10250` is solved as well::
5014
5015
sage: V = (QQ^2).span_of_basis([[1,1]])
5016
sage: w = sqrt(2) * V([1,1])
5017
sage: 3 * w
5018
(3*sqrt(2), 3*sqrt(2))
5019
"""
5020
if not isinstance(ambient, FreeModule_ambient_pid):
5021
raise TypeError("ambient (=%s) must be ambient." % ambient)
5022
self.__ambient_module = ambient
5023
basis = list(basis)
5024
if check:
5025
V = ambient.ambient_vector_space()
5026
try:
5027
basis = [V(x) for x in basis]
5028
except TypeError:
5029
raise TypeError("each element of basis must be in "
5030
"the ambient vector space")
5031
if echelonize and not already_echelonized:
5032
basis = self._echelonized_basis(ambient, basis)
5033
R = ambient.base_ring()
5034
# The following is WRONG - we should call __init__ of
5035
# FreeModule_generic_pid. However, it leads to a bunch of errors.
5036
FreeModule_generic.__init__(self, R,
5037
rank=len(basis), degree=ambient.degree(),
5038
sparse=ambient.is_sparse())
5039
C = self.element_class()
5040
try:
5041
w = [C(self, x.list(), coerce=False, copy=True) for x in basis]
5042
except TypeError:
5043
C = element_class(R.fraction_field(), self.is_sparse())
5044
self._element_class = C
5045
w = [C(self, x.list(), coerce=False, copy=True) for x in basis]
5046
self.__basis = basis_seq(self, w)
5047
5048
if echelonize or already_echelonized:
5049
self.__echelonized_basis = self.__basis
5050
else:
5051
if echelonized_basis is None:
5052
echelonized_basis = self._echelonized_basis(ambient, basis)
5053
w = [C(self, x.list(), coerce=False, copy=True)
5054
for x in echelonized_basis]
5055
self.__echelonized_basis = basis_seq(self, w)
5056
if check and len(basis) != len(self.__echelonized_basis):
5057
raise ValueError("The given basis vectors must be linearly "
5058
"independent.")
5059
5060
def __hash__(self):
5061
"""
5062
The hash of self.
5063
5064
EXAMPLES::
5065
5066
sage: V = QQ^7
5067
sage: V.__hash__()
5068
153079684 # 32-bit
5069
-3713095619189944444 # 64-bit
5070
sage: U = QQ^7
5071
sage: U.__hash__()
5072
153079684 # 32-bit
5073
-3713095619189944444 # 64-bit
5074
sage: U is V
5075
True
5076
"""
5077
return hash(self.__basis)
5078
5079
def construction(self):
5080
"""
5081
Returns the functorial construction of self, namely, the subspace
5082
of the ambient module spanned by the given basis.
5083
5084
EXAMPLE::
5085
5086
sage: M = ZZ^3
5087
sage: W = M.span_of_basis([[1,2,3],[4,5,6]]); W
5088
Free module of degree 3 and rank 2 over Integer Ring
5089
User basis matrix:
5090
[1 2 3]
5091
[4 5 6]
5092
sage: c, V = W.construction()
5093
sage: c(V) == W
5094
True
5095
"""
5096
from sage.categories.pushout import SubspaceFunctor
5097
return SubspaceFunctor(self.basis()), self.ambient_module()
5098
5099
def echelonized_basis_matrix(self):
5100
"""
5101
Return basis matrix for self in row echelon form.
5102
5103
EXAMPLES::
5104
5105
sage: V = FreeModule(ZZ, 3).span_of_basis([[1,2,3],[4,5,6]])
5106
sage: V.basis_matrix()
5107
[1 2 3]
5108
[4 5 6]
5109
sage: V.echelonized_basis_matrix()
5110
[1 2 3]
5111
[0 3 6]
5112
"""
5113
try:
5114
return self.__echelonized_basis_matrix
5115
except AttributeError:
5116
pass
5117
self._echelonized_basis(self.ambient_module(), self.__basis)
5118
return self.__echelonized_basis_matrix
5119
5120
def _echelonized_basis(self, ambient, basis):
5121
"""
5122
Given the ambient space and a basis, constructs and caches the
5123
__echelonized_basis_matrix and returns its rows.
5124
5125
N.B. This function is for internal use only!
5126
5127
EXAMPLES::
5128
5129
sage: M = ZZ^3
5130
sage: N = M.submodule_with_basis([[1,1,0],[0,2,1]])
5131
sage: N._echelonized_basis(M,N.basis())
5132
[(1, 1, 0), (0, 2, 1)]
5133
sage: V = QQ^3
5134
sage: W = V.submodule_with_basis([[1,1,0],[0,2,1]])
5135
sage: W._echelonized_basis(V,W.basis())
5136
[(1, 0, -1/2), (0, 1, 1/2)]
5137
sage: V = SR^3
5138
sage: W = V.submodule_with_basis([[1,0,1]])
5139
sage: W._echelonized_basis(V,W.basis())
5140
[(1, 0, 1)]
5141
"""
5142
# Return the first rank rows (i.e., the nonzero rows).
5143
d = self._denominator(basis)
5144
MAT = sage.matrix.matrix_space.MatrixSpace(
5145
ambient.base_ring(), len(basis), ambient.degree(), sparse = ambient.is_sparse())
5146
if d != 1:
5147
basis = [x*d for x in basis]
5148
A = MAT(basis)
5149
E = A.echelon_form()
5150
if d != 1:
5151
E = E.matrix_over_field()*(~d) # divide out denominator
5152
r = E.rank()
5153
if r < E.nrows():
5154
E = E.matrix_from_rows(range(r))
5155
self.__echelonized_basis_matrix = E
5156
return E.rows()
5157
5158
def __cmp__(self, other):
5159
r"""
5160
Compare the free module self with other.
5161
5162
Modules are ordered by their ambient spaces, then by dimension,
5163
then in order by their echelon matrices.
5164
5165
.. note::
5166
5167
Use :meth:`is_submodule` to determine if one
5168
module is a submodule of another.
5169
5170
EXAMPLES:
5171
5172
First we compare two equal vector spaces.
5173
5174
::
5175
5176
sage: V = span([[1,2,3], [5,6,7], [8,9,10]], QQ)
5177
sage: W = span([[5,6,7], [8,9,10]], QQ)
5178
sage: V == W
5179
True
5180
5181
Next we compare a one dimensional space to the two dimensional
5182
space defined above.
5183
5184
::
5185
5186
sage: M = span([[5,6,7]], QQ)
5187
sage: V == M
5188
False
5189
sage: M < V
5190
True
5191
sage: V < M
5192
False
5193
5194
We compare a `\ZZ`-module to the one-dimensional
5195
space above.
5196
5197
::
5198
5199
sage: V = span([[5,6,7]], ZZ).scale(1/11); V
5200
Free module of degree 3 and rank 1 over Integer Ring
5201
Echelon basis matrix:
5202
[5/11 6/11 7/11]
5203
sage: V < M
5204
True
5205
sage: M < V
5206
False
5207
5208
We test that trac 5525 is fixed::
5209
5210
sage: A = (QQ^1).span([[1/3]],ZZ); B = (QQ^1).span([[1]],ZZ);
5211
sage: A.intersection(B)
5212
Free module of degree 1 and rank 1 over Integer Ring
5213
Echelon basis matrix:
5214
[1]
5215
5216
"""
5217
if self is other:
5218
return 0
5219
if not isinstance(other, FreeModule_generic):
5220
return cmp(type(self), type(other))
5221
c = cmp(self.ambient_vector_space(), other.ambient_vector_space())
5222
if c: return c
5223
c = cmp(self.dimension(), other.dimension())
5224
if c: return c
5225
c = cmp(self.base_ring(), other.base_ring())
5226
if c: return c
5227
# We use self.echelonized_basis_matrix() == other.echelonized_basis_matrix()
5228
# with the matrix to avoid a circular reference.
5229
return cmp(self.echelonized_basis_matrix(), other.echelonized_basis_matrix())
5230
5231
def _denominator(self, B):
5232
"""
5233
The LCM of the denominators of the given list B.
5234
5235
N.B.: This function is for internal use only!
5236
5237
EXAMPLES::
5238
5239
sage: V = QQ^3
5240
sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ)
5241
sage: L
5242
Free module of degree 3 and rank 2 over Integer Ring
5243
Echelon basis matrix:
5244
[ 1/5 19/6 37/3]
5245
[ 0 23/6 46/3]
5246
sage: L._denominator(L.echelonized_basis_matrix().list())
5247
30
5248
5249
"""
5250
if len(B) == 0:
5251
return 1
5252
d = B[0].denominator()
5253
from sage.rings.arith import lcm
5254
for x in B[1:]:
5255
d = lcm(d,x.denominator())
5256
return d
5257
5258
def _repr_(self):
5259
"""
5260
The printing representation of self.
5261
5262
EXAMPLES::
5263
5264
sage: L = ZZ^8
5265
sage: E = L.submodule_with_basis([ L.gen(i) - L.gen(0) for i in range(1,8) ])
5266
sage: E # indirect doctest
5267
Free module of degree 8 and rank 7 over Integer Ring
5268
User basis matrix:
5269
[-1 1 0 0 0 0 0 0]
5270
[-1 0 1 0 0 0 0 0]
5271
[-1 0 0 1 0 0 0 0]
5272
[-1 0 0 0 1 0 0 0]
5273
[-1 0 0 0 0 1 0 0]
5274
[-1 0 0 0 0 0 1 0]
5275
[-1 0 0 0 0 0 0 1]
5276
5277
::
5278
5279
sage: M = FreeModule(ZZ,8,sparse=True)
5280
sage: N = M.submodule_with_basis([ M.gen(i) - M.gen(0) for i in range(1,8) ])
5281
sage: N # indirect doctest
5282
Sparse free module of degree 8 and rank 7 over Integer Ring
5283
User basis matrix:
5284
[-1 1 0 0 0 0 0 0]
5285
[-1 0 1 0 0 0 0 0]
5286
[-1 0 0 1 0 0 0 0]
5287
[-1 0 0 0 1 0 0 0]
5288
[-1 0 0 0 0 1 0 0]
5289
[-1 0 0 0 0 0 1 0]
5290
[-1 0 0 0 0 0 0 1]
5291
"""
5292
if self.is_sparse():
5293
s = "Sparse free module of degree %s and rank %s over %s\n"%(
5294
self.degree(), self.rank(), self.base_ring()) + \
5295
"User basis matrix:\n%s"%self.basis_matrix()
5296
else:
5297
s = "Free module of degree %s and rank %s over %s\n"%(
5298
self.degree(), self.rank(), self.base_ring()) + \
5299
"User basis matrix:\n%s"%self.basis_matrix()
5300
return s
5301
5302
def _latex_(self):
5303
r"""
5304
Return latex representation of this free module.
5305
5306
EXAMPLES::
5307
5308
sage: A = ZZ^3
5309
sage: M = A.span_of_basis([[1,2,3],[4,5,6]])
5310
sage: M._latex_()
5311
'\\mathrm{RowSpan}_{\\Bold{Z}}\\left(\\begin{array}{rrr}\n1 & 2 & 3 \\\\\n4 & 5 & 6\n\\end{array}\\right)'
5312
"""
5313
return "\\mathrm{RowSpan}_{%s}%s"%(latex.latex(self.base_ring()), latex.latex(self.basis_matrix()))
5314
5315
def ambient_module(self):
5316
"""
5317
Return the ambient module related to the `R`-module self,
5318
which was used when creating this module, and is of the form
5319
`R^n`. Note that self need not be contained in the ambient
5320
module, though self will be contained in the ambient vector space.
5321
5322
EXAMPLES::
5323
5324
sage: A = ZZ^3
5325
sage: M = A.span_of_basis([[1,2,'3/7'],[4,5,6]])
5326
sage: M
5327
Free module of degree 3 and rank 2 over Integer Ring
5328
User basis matrix:
5329
[ 1 2 3/7]
5330
[ 4 5 6]
5331
sage: M.ambient_module()
5332
Ambient free module of rank 3 over the principal ideal domain Integer Ring
5333
sage: M.is_submodule(M.ambient_module())
5334
False
5335
"""
5336
return self.__ambient_module
5337
5338
def echelon_coordinates(self, v, check=True):
5339
r"""
5340
Write `v` in terms of the echelonized basis for self.
5341
5342
INPUT:
5343
5344
5345
- ``v`` - vector
5346
5347
- ``check`` - bool (default: True); if True, also
5348
verify that v is really in self.
5349
5350
5351
OUTPUT: list
5352
5353
Returns a list `c` such that if `B` is the basis
5354
for self, then
5355
5356
.. math::
5357
5358
\sum c_i B_i = v.
5359
5360
5361
If `v` is not in self, raises an
5362
``ArithmeticError`` exception.
5363
5364
EXAMPLES::
5365
5366
sage: A = ZZ^3
5367
sage: M = A.span_of_basis([[1,2,'3/7'],[4,5,6]])
5368
sage: M.coordinates([8,10,12])
5369
[0, 2]
5370
sage: M.echelon_coordinates([8,10,12])
5371
[8, -2]
5372
sage: B = M.echelonized_basis(); B
5373
[
5374
(1, 2, 3/7),
5375
(0, 3, -30/7)
5376
]
5377
sage: 8*B[0] - 2*B[1]
5378
(8, 10, 12)
5379
5380
We do an example with a sparse vector space::
5381
5382
sage: V = VectorSpace(QQ,5, sparse=True)
5383
sage: W = V.subspace_with_basis([[0,1,2,0,0], [0,-1,0,0,-1/2]])
5384
sage: W.echelonized_basis()
5385
[
5386
(0, 1, 0, 0, 1/2),
5387
(0, 0, 1, 0, -1/4)
5388
]
5389
sage: W.echelon_coordinates([0,0,2,0,-1/2])
5390
[0, 2]
5391
"""
5392
if not isinstance(v, free_module_element.FreeModuleElement):
5393
v = self.ambient_vector_space()(v)
5394
elif v.degree() != self.degree():
5395
raise ArithmeticError, "vector is not in free module"
5396
# Find coordinates of v with respect to rref basis.
5397
E = self.echelonized_basis_matrix()
5398
P = E.pivots()
5399
w = v.list_from_positions(P)
5400
# Next use the transformation matrix from the rref basis
5401
# to the echelon basis.
5402
T = self._rref_to_echelon_matrix()
5403
x = T.linear_combination_of_rows(w).list(copy=False)
5404
if not check:
5405
return x
5406
if v.parent() is self:
5407
return x
5408
lc = E.linear_combination_of_rows(x)
5409
if lc != v and list(lc) != list(v):
5410
raise ArithmeticError, "vector is not in free module"
5411
return x
5412
5413
def user_to_echelon_matrix(self):
5414
"""
5415
Return matrix that transforms a vector written with respect to the
5416
user basis of self to one written with respect to the echelon
5417
basis. The matrix acts from the right, as is usual in Sage.
5418
5419
EXAMPLES::
5420
5421
sage: A = ZZ^3
5422
sage: M = A.span_of_basis([[1,2,3],[4,5,6]])
5423
sage: M.echelonized_basis()
5424
[
5425
(1, 2, 3),
5426
(0, 3, 6)
5427
]
5428
sage: M.user_to_echelon_matrix()
5429
[ 1 0]
5430
[ 4 -1]
5431
5432
The vector `v=(5,7,9)` in `M` is `(1,1)`
5433
with respect to the user basis. Multiplying the above matrix on the
5434
right by this vector yields `(5,-1)`, which has components
5435
the coordinates of `v` with respect to the echelon basis.
5436
5437
::
5438
5439
sage: v0,v1 = M.basis(); v = v0+v1
5440
sage: e0,e1 = M.echelonized_basis()
5441
sage: v
5442
(5, 7, 9)
5443
sage: 5*e0 + (-1)*e1
5444
(5, 7, 9)
5445
"""
5446
try:
5447
return self.__user_to_echelon_matrix
5448
except AttributeError:
5449
if self.base_ring().is_field():
5450
self.__user_to_echelon_matrix = self._user_to_rref_matrix()
5451
else:
5452
rows = sum([self.echelon_coordinates(b,check=False) for b in self.basis()], [])
5453
M = sage.matrix.matrix_space.MatrixSpace(self.base_ring().fraction_field(),
5454
self.dimension(),
5455
sparse = self.is_sparse())
5456
self.__user_to_echelon_matrix = M(rows)
5457
return self.__user_to_echelon_matrix
5458
5459
5460
def echelon_to_user_matrix(self):
5461
"""
5462
Return matrix that transforms the echelon basis to the user basis
5463
of self. This is a matrix `A` such that if `v` is a
5464
vector written with respect to the echelon basis for self then
5465
`vA` is that vector written with respect to the user basis
5466
of self.
5467
5468
EXAMPLES::
5469
5470
sage: V = QQ^3
5471
sage: W = V.span_of_basis([[1,2,3],[4,5,6]])
5472
sage: W.echelonized_basis()
5473
[
5474
(1, 0, -1),
5475
(0, 1, 2)
5476
]
5477
sage: A = W.echelon_to_user_matrix(); A
5478
[-5/3 2/3]
5479
[ 4/3 -1/3]
5480
5481
The vector `(1,1,1)` has coordinates `v=(1,1)` with
5482
respect to the echelonized basis for self. Multiplying `vA`
5483
we find the coordinates of this vector with respect to the user
5484
basis.
5485
5486
::
5487
5488
sage: v = vector(QQ, [1,1]); v
5489
(1, 1)
5490
sage: v * A
5491
(-1/3, 1/3)
5492
sage: u0, u1 = W.basis()
5493
sage: (-u0 + u1)/3
5494
(1, 1, 1)
5495
"""
5496
try:
5497
return self.__echelon_to_user_matrix
5498
except AttributeError:
5499
self.__echelon_to_user_matrix = ~self.user_to_echelon_matrix()
5500
return self.__echelon_to_user_matrix
5501
5502
def _user_to_rref_matrix(self):
5503
"""
5504
Returns a transformation matrix from the user specified basis to row
5505
reduced echelon form, for this module over a PID.
5506
5507
Note: For internal use only! See user_to_echelon_matrix.
5508
5509
EXAMPLES::
5510
5511
sage: M = ZZ^3
5512
sage: N = M.submodule_with_basis([[1,1,0],[0,1,1]])
5513
sage: T = N.user_to_echelon_matrix(); T # indirect doctest
5514
[1 1]
5515
[0 1]
5516
sage: N.basis_matrix()
5517
[1 1 0]
5518
[0 1 1]
5519
sage: N.echelonized_basis_matrix()
5520
[ 1 0 -1]
5521
[ 0 1 1]
5522
sage: T * N.echelonized_basis_matrix() == N.basis_matrix()
5523
True
5524
"""
5525
try:
5526
return self.__user_to_rref_matrix
5527
except AttributeError:
5528
A = self.basis_matrix()
5529
P = self.echelonized_basis_matrix().pivots()
5530
T = A.matrix_from_columns(P)
5531
self.__user_to_rref_matrix = T
5532
return self.__user_to_rref_matrix
5533
5534
def _rref_to_user_matrix(self):
5535
"""
5536
Returns a transformation matrix from row reduced echelon form to
5537
the user specified basis, for this module over a PID.
5538
5539
Note: For internal use only! See user_to_echelon_matrix.
5540
5541
EXAMPLES::
5542
5543
sage: M = ZZ^3
5544
sage: N = M.submodule_with_basis([[1,1,0],[0,1,1]])
5545
sage: U = N.echelon_to_user_matrix(); U # indirect doctest
5546
[ 1 -1]
5547
[ 0 1]
5548
sage: N.echelonized_basis_matrix()
5549
[ 1 0 -1]
5550
[ 0 1 1]
5551
sage: N.basis_matrix()
5552
[1 1 0]
5553
[0 1 1]
5554
sage: U * N.basis_matrix() == N.echelonized_basis_matrix()
5555
True
5556
"""
5557
try:
5558
return self.__rref_to_user_matrix
5559
except AttributeError:
5560
self.__rref_to_user_matrix = ~self._user_to_rref_matrix()
5561
return self.__rref_to_user_matrix
5562
5563
def _echelon_to_rref_matrix(self):
5564
"""
5565
Returns a transformation matrix from the some matrix to the row
5566
reduced echelon form for this module over a PID.
5567
5568
Note: For internal use only! and not used!
5569
5570
EXAMPLES::
5571
5572
sage: M = ZZ^3
5573
sage: N = M.submodule_with_basis([[1,1,0],[1,1,2]])
5574
sage: N
5575
Free module of degree 3 and rank 2 over Integer Ring
5576
User basis matrix:
5577
[1 1 0]
5578
[1 1 2]
5579
sage: T = N._echelon_to_rref_matrix(); T
5580
[1 0]
5581
[0 2]
5582
sage: type(T)
5583
<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>
5584
sage: U = N._rref_to_echelon_matrix(); U
5585
[ 1 0]
5586
[ 0 1/2]
5587
sage: type(U)
5588
<type 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'>
5589
"""
5590
try:
5591
return self.__echelon_to_rref_matrix
5592
except AttributeError:
5593
A = self.echelonized_basis_matrix()
5594
T = A.matrix_from_columns(A.pivots())
5595
self.__echelon_to_rref_matrix = T
5596
return self.__echelon_to_rref_matrix
5597
5598
def _rref_to_echelon_matrix(self):
5599
"""
5600
Returns a transformation matrix from row reduced echelon form to
5601
some matrix for this module over a PID.
5602
5603
Note: For internal use only!
5604
5605
EXAMPLES::
5606
5607
sage: M = ZZ^3
5608
sage: N = M.submodule_with_basis([[1,1,0],[1,1,2]])
5609
sage: N
5610
Free module of degree 3 and rank 2 over Integer Ring
5611
User basis matrix:
5612
[1 1 0]
5613
[1 1 2]
5614
sage: T = N._echelon_to_rref_matrix(); T
5615
[1 0]
5616
[0 2]
5617
sage: type(T)
5618
<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>
5619
sage: U = N._rref_to_echelon_matrix(); U
5620
[ 1 0]
5621
[ 0 1/2]
5622
sage: type(U)
5623
<type 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'>
5624
"""
5625
try:
5626
return self.__rref_to_echelon_matrix
5627
except AttributeError:
5628
self.__rref_to_echelon_matrix = ~self._echelon_to_rref_matrix()
5629
return self.__rref_to_echelon_matrix
5630
5631
def vector_space(self, base_field=None):
5632
"""
5633
Return the vector space associated to this free module via tensor
5634
product with the fraction field of the base ring.
5635
5636
EXAMPLES::
5637
5638
sage: A = ZZ^3; A
5639
Ambient free module of rank 3 over the principal ideal domain Integer Ring
5640
sage: A.vector_space()
5641
Vector space of dimension 3 over Rational Field
5642
sage: M = A.span_of_basis([['1/3',2,'3/7'],[4,5,6]]); M
5643
Free module of degree 3 and rank 2 over Integer Ring
5644
User basis matrix:
5645
[1/3 2 3/7]
5646
[ 4 5 6]
5647
sage: M.vector_space()
5648
Vector space of degree 3 and dimension 2 over Rational Field
5649
User basis matrix:
5650
[1/3 2 3/7]
5651
[ 4 5 6]
5652
"""
5653
if base_field is None:
5654
K = self.base_ring().fraction_field()
5655
V = self.ambient_vector_space()
5656
return V.submodule_with_basis(self.basis())
5657
return self.change_ring(base_field)
5658
5659
def ambient_vector_space(self):
5660
"""
5661
Return the ambient vector space in which this free module is
5662
embedded.
5663
5664
EXAMPLES::
5665
5666
sage: M = ZZ^3; M.ambient_vector_space()
5667
Vector space of dimension 3 over Rational Field
5668
5669
::
5670
5671
sage: N = M.span_of_basis([[1,2,'1/5']])
5672
sage: N
5673
Free module of degree 3 and rank 1 over Integer Ring
5674
User basis matrix:
5675
[ 1 2 1/5]
5676
sage: M.ambient_vector_space()
5677
Vector space of dimension 3 over Rational Field
5678
sage: M.ambient_vector_space() is N.ambient_vector_space()
5679
True
5680
5681
If an inner product on the module is specified, then this
5682
is preserved on the ambient vector space.
5683
5684
::
5685
5686
sage: M = FreeModule(ZZ,4,inner_product_matrix=1)
5687
sage: V = M.ambient_vector_space()
5688
sage: V
5689
Ambient quadratic space of dimension 4 over Rational Field
5690
Inner product matrix:
5691
[1 0 0 0]
5692
[0 1 0 0]
5693
[0 0 1 0]
5694
[0 0 0 1]
5695
sage: N = M.submodule([[1,-1,0,0],[0,1,-1,0],[0,0,1,-1]])
5696
sage: N.gram_matrix()
5697
[2 1 1]
5698
[1 2 1]
5699
[1 1 2]
5700
sage: V == N.ambient_vector_space()
5701
True
5702
"""
5703
return self.ambient_module().ambient_vector_space()
5704
5705
def basis(self):
5706
"""
5707
Return the user basis for this free module.
5708
5709
EXAMPLES::
5710
5711
sage: V = ZZ^3
5712
sage: V.basis()
5713
[
5714
(1, 0, 0),
5715
(0, 1, 0),
5716
(0, 0, 1)
5717
]
5718
sage: M = V.span_of_basis([['1/8',2,1]])
5719
sage: M.basis()
5720
[
5721
(1/8, 2, 1)
5722
]
5723
"""
5724
return self.__basis
5725
5726
def change_ring(self, R):
5727
"""
5728
Return the free module over R obtained by coercing each element of
5729
self into a vector over the fraction field of R, then taking the
5730
resulting R-module. Raises a TypeError if coercion is not
5731
possible.
5732
5733
INPUT:
5734
5735
5736
- ``R`` - a principal ideal domain
5737
5738
5739
EXAMPLES::
5740
5741
sage: V = QQ^3
5742
sage: W = V.subspace([[2,'1/2', 1]])
5743
sage: W.change_ring(GF(7))
5744
Vector space of degree 3 and dimension 1 over Finite Field of size 7
5745
Basis matrix:
5746
[1 2 4]
5747
"""
5748
if self.base_ring() == R:
5749
return self
5750
K = R.fraction_field()
5751
V = VectorSpace(K, self.degree())
5752
B = [V(b) for b in self.basis()]
5753
M = FreeModule(R, self.degree())
5754
if self.has_user_basis():
5755
return M.span_of_basis(B)
5756
else:
5757
return M.span(B)
5758
5759
def coordinate_vector(self, v, check=True):
5760
"""
5761
Write `v` in terms of the user basis for self.
5762
5763
INPUT:
5764
5765
5766
- ``v`` - vector
5767
5768
- ``check`` - bool (default: True); if True, also
5769
verify that v is really in self.
5770
5771
5772
OUTPUT: list
5773
5774
Returns a vector `c` such that if `B` is the basis for self, then
5775
5776
.. math::
5777
5778
5779
If `v` is not in self, raises an ArithmeticError exception.
5780
5781
EXAMPLES::
5782
5783
sage: V = ZZ^3
5784
sage: M = V.span_of_basis([['1/8',2,1]])
5785
sage: M.coordinate_vector([1,16,8])
5786
(8)
5787
"""
5788
# First find the coordinates of v wrt echelon basis.
5789
w = self.echelon_coordinate_vector(v, check=check)
5790
# Next use transformation matrix from echelon basis to
5791
# user basis.
5792
T = self.echelon_to_user_matrix()
5793
return T.linear_combination_of_rows(w)
5794
5795
def echelonized_basis(self):
5796
"""
5797
Return the basis for self in echelon form.
5798
5799
EXAMPLES::
5800
5801
sage: V = ZZ^3
5802
sage: M = V.span_of_basis([['1/2',3,1], [0,'1/6',0]])
5803
sage: M.basis()
5804
[
5805
(1/2, 3, 1),
5806
(0, 1/6, 0)
5807
]
5808
sage: B = M.echelonized_basis(); B
5809
[
5810
(1/2, 0, 1),
5811
(0, 1/6, 0)
5812
]
5813
sage: V.span(B) == M
5814
True
5815
"""
5816
return self.__echelonized_basis
5817
5818
def echelon_coordinate_vector(self, v, check=True):
5819
"""
5820
Write `v` in terms of the user basis for self.
5821
5822
INPUT:
5823
5824
5825
- ``v`` - vector
5826
5827
- ``check`` - bool (default: True); if True, also
5828
verify that v is really in self.
5829
5830
Returns a list `c` such that if `B` is the echelonized basis
5831
for self, then
5832
5833
.. math::
5834
5835
\sum c_i B_i = v.
5836
5837
5838
If `v` is not in self, raises an ``ArithmeticError`` exception.
5839
5840
EXAMPLES::
5841
5842
sage: V = ZZ^3
5843
sage: M = V.span_of_basis([['1/2',3,1], [0,'1/6',0]])
5844
sage: B = M.echelonized_basis(); B
5845
[
5846
(1/2, 0, 1),
5847
(0, 1/6, 0)
5848
]
5849
sage: M.echelon_coordinate_vector(['1/2', 3, 1])
5850
(1, 18)
5851
"""
5852
return FreeModule(self.base_ring().fraction_field(), self.rank())(self.echelon_coordinates(v, check=check))
5853
5854
def has_user_basis(self):
5855
"""
5856
Return ``True`` if the basis of this free module is
5857
specified by the user, as opposed to being the default echelon
5858
form.
5859
5860
EXAMPLES::
5861
5862
sage: V = ZZ^3; V.has_user_basis()
5863
False
5864
sage: M = V.span_of_basis([[1,3,1]]); M.has_user_basis()
5865
True
5866
sage: M = V.span([[1,3,1]]); M.has_user_basis()
5867
False
5868
"""
5869
return True
5870
5871
def linear_combination_of_basis(self, v):
5872
"""
5873
Return the linear combination of the basis for self obtained from
5874
the coordinates of v.
5875
5876
INPUTS:
5877
5878
- ``v`` - list
5879
5880
EXAMPLES::
5881
5882
sage: V = span([[1,2,3], [4,5,6]], ZZ); V
5883
Free module of degree 3 and rank 2 over Integer Ring
5884
Echelon basis matrix:
5885
[1 2 3]
5886
[0 3 6]
5887
sage: V.linear_combination_of_basis([1,1])
5888
(1, 5, 9)
5889
5890
This should raise an error if the resulting element is not in self::
5891
5892
sage: W = (QQ**2).span([[2, 0], [0, 8]], ZZ)
5893
sage: W.linear_combination_of_basis([1, -1/2])
5894
Traceback (most recent call last):
5895
...
5896
TypeError: element (= [2, -4]) is not in free module
5897
"""
5898
R = self.base_ring()
5899
check = (not R.is_field()) and any([a not in R for a in list(v)])
5900
return self(self.basis_matrix().linear_combination_of_rows(v),
5901
check=check, copy=False, coerce=False)
5902
5903
5904
class FreeModule_submodule_pid(FreeModule_submodule_with_basis_pid):
5905
"""
5906
An `R`-submodule of `K^n` where `K` is the
5907
fraction field of a principal ideal domain `R`.
5908
5909
EXAMPLES::
5910
5911
sage: M = ZZ^3
5912
sage: W = M.span_of_basis([[1,2,3],[4,5,19]]); W
5913
Free module of degree 3 and rank 2 over Integer Ring
5914
User basis matrix:
5915
[ 1 2 3]
5916
[ 4 5 19]
5917
5918
Generic tests, including saving and loading submodules and elements::
5919
5920
sage: TestSuite(W).run()
5921
sage: v = W.0 + W.1
5922
sage: TestSuite(v).run()
5923
"""
5924
def __init__(self, ambient, gens, check=True, already_echelonized=False):
5925
"""
5926
Create an embedded free module over a PID.
5927
5928
EXAMPLES::
5929
5930
sage: V = ZZ^3
5931
sage: W = V.span([[1,2,3],[4,5,6]])
5932
sage: W
5933
Free module of degree 3 and rank 2 over Integer Ring
5934
Echelon basis matrix:
5935
[1 2 3]
5936
[0 3 6]
5937
"""
5938
FreeModule_submodule_with_basis_pid.__init__(self, ambient, basis=gens,
5939
echelonize=True, already_echelonized=already_echelonized)
5940
5941
def _repr_(self):
5942
"""
5943
The printing representation of self.
5944
5945
EXAMPLES::
5946
5947
sage: M = ZZ^8
5948
sage: L = M.submodule([ M.gen(i) - M.gen(0) for i in range(1,8) ])
5949
sage: print L # indirect doctest
5950
Free module of degree 8 and rank 7 over Integer Ring
5951
Echelon basis matrix:
5952
[ 1 0 0 0 0 0 0 -1]
5953
[ 0 1 0 0 0 0 0 -1]
5954
[ 0 0 1 0 0 0 0 -1]
5955
[ 0 0 0 1 0 0 0 -1]
5956
[ 0 0 0 0 1 0 0 -1]
5957
[ 0 0 0 0 0 1 0 -1]
5958
[ 0 0 0 0 0 0 1 -1]
5959
"""
5960
if self.is_sparse():
5961
s = "Sparse free module of degree %s and rank %s over %s\n"%(
5962
self.degree(), self.rank(), self.base_ring()) + \
5963
"Echelon basis matrix:\n%s"%self.basis_matrix()
5964
else:
5965
s = "Free module of degree %s and rank %s over %s\n"%(
5966
self.degree(), self.rank(), self.base_ring()) + \
5967
"Echelon basis matrix:\n%s"%self.basis_matrix()
5968
return s
5969
5970
def coordinate_vector(self, v, check=True):
5971
"""
5972
Write `v` in terms of the user basis for self.
5973
5974
INPUT:
5975
5976
5977
- ``v`` - vector
5978
5979
- ``check`` - bool (default: True); if True, also
5980
verify that v is really in self.
5981
5982
5983
OUTPUT: list
5984
5985
Returns a list `c` such that if `B` is the basis for self, then
5986
5987
.. math::
5988
5989
\sum c_i B_i = v.
5990
5991
5992
If `v` is not in self, raises an ``ArithmeticError`` exception.
5993
5994
EXAMPLES::
5995
5996
sage: V = ZZ^3
5997
sage: W = V.span_of_basis([[1,2,3],[4,5,6]])
5998
sage: W.coordinate_vector([1,5,9])
5999
(5, -1)
6000
"""
6001
return self.echelon_coordinate_vector(v, check=check)
6002
6003
def has_user_basis(self):
6004
r"""
6005
Return ``True`` if the basis of this free module is
6006
specified by the user, as opposed to being the default echelon
6007
form.
6008
6009
EXAMPLES::
6010
6011
sage: A = ZZ^3; A
6012
Ambient free module of rank 3 over the principal ideal domain Integer Ring
6013
sage: A.has_user_basis()
6014
False
6015
sage: W = A.span_of_basis([[2,'1/2',1]])
6016
sage: W.has_user_basis()
6017
True
6018
sage: W = A.span([[2,'1/2',1]])
6019
sage: W.has_user_basis()
6020
False
6021
"""
6022
return False
6023
6024
6025
class FreeModule_submodule_with_basis_field(FreeModule_generic_field, FreeModule_submodule_with_basis_pid):
6026
"""
6027
An embedded vector subspace with a distinguished user basis.
6028
6029
EXAMPLES::
6030
6031
sage: M = QQ^3; W = M.submodule_with_basis([[1,2,3], [4,5,19]]); W
6032
Vector space of degree 3 and dimension 2 over Rational Field
6033
User basis matrix:
6034
[ 1 2 3]
6035
[ 4 5 19]
6036
6037
Since this is an embedded vector subspace with a distinguished user
6038
basis possibly different than the echelonized basis, the
6039
echelon_coordinates() and user coordinates() do not agree::
6040
6041
sage: V = QQ^3
6042
6043
::
6044
6045
sage: W = V.submodule_with_basis([[1,2,3], [4,5,6]])
6046
sage: W
6047
Vector space of degree 3 and dimension 2 over Rational Field
6048
User basis matrix:
6049
[1 2 3]
6050
[4 5 6]
6051
6052
::
6053
6054
sage: v = V([1,5,9])
6055
sage: W.echelon_coordinates(v)
6056
[1, 5]
6057
sage: vector(QQ, W.echelon_coordinates(v)) * W.echelonized_basis_matrix()
6058
(1, 5, 9)
6059
6060
::
6061
6062
sage: v = V([1,5,9])
6063
sage: W.coordinates(v)
6064
[5, -1]
6065
sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()
6066
(1, 5, 9)
6067
6068
Generic tests, including saving and loading submodules and elements::
6069
6070
sage: TestSuite(W).run()
6071
6072
sage: K.<x> = FractionField(PolynomialRing(QQ,'x'))
6073
sage: M = K^3; W = M.span_of_basis([[1,1,x]])
6074
sage: TestSuite(W).run()
6075
"""
6076
def __init__(self, ambient, basis, check=True,
6077
echelonize=False, echelonized_basis=None, already_echelonized=False):
6078
"""
6079
Create a vector space with given basis.
6080
6081
EXAMPLES::
6082
6083
sage: V = QQ^3
6084
sage: W = V.span_of_basis([[1,2,3],[4,5,6]])
6085
sage: W
6086
Vector space of degree 3 and dimension 2 over Rational Field
6087
User basis matrix:
6088
[1 2 3]
6089
[4 5 6]
6090
"""
6091
FreeModule_submodule_with_basis_pid.__init__(
6092
self, ambient, basis=basis, check=check, echelonize=echelonize,
6093
echelonized_basis=echelonized_basis, already_echelonized=already_echelonized)
6094
6095
def _repr_(self):
6096
"""
6097
The printing representation of self.
6098
6099
EXAMPLES::
6100
6101
sage: V = VectorSpace(QQ,5)
6102
sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])
6103
sage: print U # indirect doctest
6104
Vector space of degree 5 and dimension 4 over Rational Field
6105
Basis matrix:
6106
[ 1 0 0 0 -1]
6107
[ 0 1 0 0 -1]
6108
[ 0 0 1 0 -1]
6109
[ 0 0 0 1 -1]
6110
sage: print U._repr_()
6111
Vector space of degree 5 and dimension 4 over Rational Field
6112
Basis matrix:
6113
[ 1 0 0 0 -1]
6114
[ 0 1 0 0 -1]
6115
[ 0 0 1 0 -1]
6116
[ 0 0 0 1 -1]
6117
6118
The system representation can be overwritten, but leaves _repr_
6119
unmodified.
6120
6121
::
6122
6123
sage: U.rename('U')
6124
sage: print U
6125
U
6126
sage: print U._repr_()
6127
Vector space of degree 5 and dimension 4 over Rational Field
6128
Basis matrix:
6129
[ 1 0 0 0 -1]
6130
[ 0 1 0 0 -1]
6131
[ 0 0 1 0 -1]
6132
[ 0 0 0 1 -1]
6133
6134
Sparse vector spaces print this fact.
6135
6136
::
6137
6138
sage: VV = VectorSpace(QQ,5,sparse=True)
6139
sage: UU = VV.submodule([ VV.gen(i) - VV.gen(0) for i in range(1,5) ])
6140
sage: print UU # indirect doctest
6141
Sparse vector space of degree 5 and dimension 4 over Rational Field
6142
Basis matrix:
6143
[ 1 0 0 0 -1]
6144
[ 0 1 0 0 -1]
6145
[ 0 0 1 0 -1]
6146
[ 0 0 0 1 -1]
6147
6148
(Now clean up again.)
6149
6150
::
6151
6152
sage: U.reset_name()
6153
sage: print U
6154
Vector space of degree 5 and dimension 4 over Rational Field
6155
Basis matrix:
6156
[ 1 0 0 0 -1]
6157
[ 0 1 0 0 -1]
6158
[ 0 0 1 0 -1]
6159
[ 0 0 0 1 -1]
6160
"""
6161
if self.is_sparse():
6162
return "Sparse vector space of degree %s and dimension %s over %s\n"%(
6163
self.degree(), self.dimension(), self.base_field()) + \
6164
"User basis matrix:\n%s"%self.basis_matrix()
6165
else:
6166
return "Vector space of degree %s and dimension %s over %s\n"%(
6167
self.degree(), self.dimension(), self.base_field()) + \
6168
"User basis matrix:\n%s"%self.basis_matrix()
6169
6170
def _denominator(self, B):
6171
"""
6172
Given a list (of field elements) returns 1 as the common
6173
denominator.
6174
6175
N.B.: This function is for internal use only!
6176
6177
EXAMPLES::
6178
6179
sage: U = QQ^3
6180
sage: U
6181
Vector space of dimension 3 over Rational Field
6182
sage: U.denominator()
6183
1
6184
sage: V = U.span([[1,1/2,1/3], [-1/5,2/3,3]])
6185
sage: V
6186
Vector space of degree 3 and dimension 2 over Rational Field
6187
Basis matrix:
6188
[ 1 0 -5/3]
6189
[ 0 1 4]
6190
sage: W = U.submodule_with_basis([[1,1/2,1/3], [-1/5,2/3,3]])
6191
sage: W
6192
Vector space of degree 3 and dimension 2 over Rational Field
6193
User basis matrix:
6194
[ 1 1/2 1/3]
6195
[-1/5 2/3 3]
6196
sage: W._denominator(W.echelonized_basis_matrix().list())
6197
1
6198
"""
6199
return 1
6200
6201
def _echelonized_basis(self, ambient, basis):
6202
"""
6203
Given the ambient space and a basis, constructs and caches the
6204
__echelonized_basis_matrix and returns its rows.
6205
6206
N.B. This function is for internal use only!
6207
6208
EXAMPLES::
6209
6210
sage: M = ZZ^3
6211
sage: N = M.submodule_with_basis([[1,1,0],[0,2,1]])
6212
sage: N._echelonized_basis(M,N.basis())
6213
[(1, 1, 0), (0, 2, 1)]
6214
sage: V = QQ^3
6215
sage: W = V.submodule_with_basis([[1,1,0],[0,2,1]])
6216
sage: W._echelonized_basis(V,W.basis())
6217
[(1, 0, -1/2), (0, 1, 1/2)]
6218
"""
6219
MAT = sage.matrix.matrix_space.MatrixSpace(
6220
base_ring=ambient.base_ring(),
6221
nrows=len(basis), ncols=ambient.degree(),
6222
sparse=ambient.is_sparse())
6223
A = MAT(basis)
6224
E = A.echelon_form()
6225
# Return the first rank rows (i.e., the nonzero rows).
6226
return E.rows()[:E.rank()]
6227
6228
def is_ambient(self):
6229
"""
6230
Return False since this is not an ambient module.
6231
6232
EXAMPLES::
6233
6234
sage: V = QQ^3
6235
sage: V.is_ambient()
6236
True
6237
sage: W = V.span_of_basis([[1,2,3],[4,5,6]])
6238
sage: W.is_ambient()
6239
False
6240
"""
6241
return False
6242
6243
6244
class FreeModule_submodule_field(FreeModule_submodule_with_basis_field):
6245
"""
6246
An embedded vector subspace with echelonized basis.
6247
6248
EXAMPLES:
6249
6250
Since this is an embedded vector subspace with echelonized basis,
6251
the echelon_coordinates() and user coordinates() agree::
6252
6253
sage: V = QQ^3
6254
sage: W = V.span([[1,2,3],[4,5,6]])
6255
sage: W
6256
Vector space of degree 3 and dimension 2 over Rational Field
6257
Basis matrix:
6258
[ 1 0 -1]
6259
[ 0 1 2]
6260
6261
::
6262
6263
sage: v = V([1,5,9])
6264
sage: W.echelon_coordinates(v)
6265
[1, 5]
6266
sage: vector(QQ, W.echelon_coordinates(v)) * W.basis_matrix()
6267
(1, 5, 9)
6268
sage: v = V([1,5,9])
6269
sage: W.coordinates(v)
6270
[1, 5]
6271
sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()
6272
(1, 5, 9)
6273
"""
6274
def __init__(self, ambient, gens, check=True, already_echelonized=False):
6275
"""
6276
Create an embedded vector subspace with echelonized basis.
6277
6278
EXAMPLES::
6279
6280
sage: V = QQ^3
6281
sage: W = V.span([[1,2,3],[4,5,6]])
6282
sage: W
6283
Vector space of degree 3 and dimension 2 over Rational Field
6284
Basis matrix:
6285
[ 1 0 -1]
6286
[ 0 1 2]
6287
"""
6288
if is_FreeModule(gens):
6289
gens = gens.gens()
6290
FreeModule_submodule_with_basis_field.__init__(self, ambient, basis=gens, check=check,
6291
echelonize=not already_echelonized, already_echelonized=already_echelonized)
6292
6293
def _repr_(self):
6294
"""
6295
The default printing representation of self.
6296
6297
EXAMPLES::
6298
6299
sage: V = VectorSpace(QQ,5)
6300
sage: U = V.submodule([ V.gen(i) - V.gen(0) for i in range(1,5) ])
6301
sage: print U # indirect doctest
6302
Vector space of degree 5 and dimension 4 over Rational Field
6303
Basis matrix:
6304
[ 1 0 0 0 -1]
6305
[ 0 1 0 0 -1]
6306
[ 0 0 1 0 -1]
6307
[ 0 0 0 1 -1]
6308
sage: print U._repr_()
6309
Vector space of degree 5 and dimension 4 over Rational Field
6310
Basis matrix:
6311
[ 1 0 0 0 -1]
6312
[ 0 1 0 0 -1]
6313
[ 0 0 1 0 -1]
6314
[ 0 0 0 1 -1]
6315
6316
The system representation can be overwritten, but leaves _repr_
6317
unmodified.
6318
6319
::
6320
6321
sage: U.rename('U')
6322
sage: print U
6323
U
6324
sage: print U._repr_()
6325
Vector space of degree 5 and dimension 4 over Rational Field
6326
Basis matrix:
6327
[ 1 0 0 0 -1]
6328
[ 0 1 0 0 -1]
6329
[ 0 0 1 0 -1]
6330
[ 0 0 0 1 -1]
6331
6332
Sparse vector spaces print this fact.
6333
6334
::
6335
6336
sage: VV = VectorSpace(QQ,5,sparse=True)
6337
sage: UU = VV.submodule([ VV.gen(i) - VV.gen(0) for i in range(1,5) ])
6338
sage: print UU # indirect doctest
6339
Sparse vector space of degree 5 and dimension 4 over Rational Field
6340
Basis matrix:
6341
[ 1 0 0 0 -1]
6342
[ 0 1 0 0 -1]
6343
[ 0 0 1 0 -1]
6344
[ 0 0 0 1 -1]
6345
6346
(Now clean up again.)
6347
6348
::
6349
6350
sage: U.reset_name()
6351
sage: print U
6352
Vector space of degree 5 and dimension 4 over Rational Field
6353
Basis matrix:
6354
[ 1 0 0 0 -1]
6355
[ 0 1 0 0 -1]
6356
[ 0 0 1 0 -1]
6357
[ 0 0 0 1 -1]
6358
"""
6359
if self.is_sparse():
6360
return "Sparse vector space of degree %s and dimension %s over %s\n"%(
6361
self.degree(), self.dimension(), self.base_field()) + \
6362
"Basis matrix:\n%s"%self.basis_matrix()
6363
else:
6364
return "Vector space of degree %s and dimension %s over %s\n"%(
6365
self.degree(), self.dimension(), self.base_field()) + \
6366
"Basis matrix:\n%s"%self.basis_matrix()
6367
6368
def echelon_coordinates(self, v, check=True):
6369
"""
6370
Write `v` in terms of the echelonized basis of self.
6371
6372
INPUT:
6373
6374
6375
- ``v`` - vector
6376
6377
- ``check`` - bool (default: True); if True, also
6378
verify that v is really in self.
6379
6380
6381
OUTPUT: list
6382
6383
Returns a list `c` such that if `B` is the basis for self, then
6384
6385
.. math::
6386
6387
\sum c_i B_i = v.
6388
6389
6390
If `v` is not in self, raises an ``ArithmeticError`` exception.
6391
6392
EXAMPLES::
6393
6394
sage: V = QQ^3
6395
sage: W = V.span([[1,2,3],[4,5,6]])
6396
sage: W
6397
Vector space of degree 3 and dimension 2 over Rational Field
6398
Basis matrix:
6399
[ 1 0 -1]
6400
[ 0 1 2]
6401
6402
::
6403
6404
sage: v = V([1,5,9])
6405
sage: W.echelon_coordinates(v)
6406
[1, 5]
6407
sage: vector(QQ, W.echelon_coordinates(v)) * W.basis_matrix()
6408
(1, 5, 9)
6409
"""
6410
if not isinstance(v, free_module_element.FreeModuleElement):
6411
v = self.ambient_vector_space()(v)
6412
if v.degree() != self.degree():
6413
raise ArithmeticError, "v (=%s) is not in self"%v
6414
E = self.echelonized_basis_matrix()
6415
P = E.pivots()
6416
if len(P) == 0:
6417
if check and v != 0:
6418
raise ArithmeticError, "vector is not in free module"
6419
return []
6420
w = v.list_from_positions(P)
6421
if not check:
6422
# It's really really easy.
6423
return w
6424
if v.parent() is self: # obvious that v is really in here.
6425
return w
6426
# the "linear_combination_of_rows" call dominates the runtime
6427
# of this function, in the check==False case when the parent
6428
# of v is not self.
6429
lc = E.linear_combination_of_rows(w)
6430
if lc != v:
6431
raise ArithmeticError, "vector is not in free module"
6432
return w
6433
6434
def coordinate_vector(self, v, check=True):
6435
"""
6436
Write `v` in terms of the user basis for self.
6437
6438
INPUT:
6439
6440
6441
- ``v`` - vector
6442
6443
- ``check`` - bool (default: True); if True, also
6444
verify that v is really in self.
6445
6446
6447
OUTPUT: list
6448
6449
Returns a list `c` such that if `B` is the basis for self, then
6450
6451
.. math::
6452
6453
\sum c_i B_i = v.
6454
6455
6456
If `v` is not in self, raises an ``ArithmeticError`` exception.
6457
6458
EXAMPLES::
6459
6460
sage: V = QQ^3
6461
sage: W = V.span([[1,2,3],[4,5,6]]); W
6462
Vector space of degree 3 and dimension 2 over Rational Field
6463
Basis matrix:
6464
[ 1 0 -1]
6465
[ 0 1 2]
6466
sage: v = V([1,5,9])
6467
sage: W.coordinate_vector(v)
6468
(1, 5)
6469
sage: W.coordinates(v)
6470
[1, 5]
6471
sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()
6472
(1, 5, 9)
6473
6474
::
6475
6476
sage: V = VectorSpace(QQ,5, sparse=True)
6477
sage: W = V.subspace([[0,1,2,0,0], [0,-1,0,0,-1/2]])
6478
sage: W.coordinate_vector([0,0,2,0,-1/2])
6479
(0, 2)
6480
"""
6481
return self.echelon_coordinate_vector(v, check=check)
6482
6483
def has_user_basis(self):
6484
"""
6485
Return ``True`` if the basis of this free module is
6486
specified by the user, as opposed to being the default echelon
6487
form.
6488
6489
EXAMPLES::
6490
6491
sage: V = QQ^3
6492
sage: W = V.subspace([[2,'1/2', 1]])
6493
sage: W.has_user_basis()
6494
False
6495
sage: W = V.subspace_with_basis([[2,'1/2',1]])
6496
sage: W.has_user_basis()
6497
True
6498
"""
6499
return False
6500
6501
def basis_seq(V, vecs):
6502
"""
6503
This converts a list vecs of vectors in V to an Sequence of
6504
immutable vectors.
6505
6506
Should it? I.e. in most other parts of the system the return type
6507
of basis or generators is a tuple.
6508
6509
EXAMPLES::
6510
6511
sage: V = VectorSpace(QQ,2)
6512
sage: B = V.gens()
6513
sage: B
6514
((1, 0), (0, 1))
6515
sage: v = B[0]
6516
sage: v[0] = 0 # immutable
6517
Traceback (most recent call last):
6518
...
6519
ValueError: vector is immutable; please change a copy instead (use copy())
6520
sage: sage.modules.free_module.basis_seq(V, V.gens())
6521
[
6522
(1, 0),
6523
(0, 1)
6524
]
6525
"""
6526
for z in vecs:
6527
z.set_immutable()
6528
return Sequence(vecs, universe=V, check = False, immutable=True, cr=True)
6529
6530
#class RealDoubleVectorSpace_class(FreeModule_ambient_field):
6531
# def __init__(self, dimension, sparse=False):
6532
# if sparse:
6533
# raise NotImplementedError, "Sparse matrices over RDF not implemented yet"
6534
# FreeModule_ambient_field.__init__(self, sage.rings.real_double.RDF, dimension, sparse=False)
6535
6536
#class ComplexDoubleVectorSpace_class(FreeModule_ambient_field):
6537
# def __init__(self, dimension, sparse=False):
6538
# if sparse:
6539
# raise NotImplementedError, "Sparse matrices over CDF not implemented yet"
6540
# FreeModule_ambient_field.__init__(self, sage.rings.complex_double.CDF, dimension, sparse=False)
6541
6542
6543
6544
6545
6546
6547
class RealDoubleVectorSpace_class(FreeModule_ambient_field):
6548
def __init__(self,n):
6549
FreeModule_ambient_field.__init__(self,sage.rings.real_double.RDF,n)
6550
6551
def coordinates(self,v):
6552
return v
6553
6554
class ComplexDoubleVectorSpace_class(FreeModule_ambient_field):
6555
def __init__(self,n):
6556
FreeModule_ambient_field.__init__(self,sage.rings.complex_double.CDF,n)
6557
6558
def coordinates(self,v):
6559
return v
6560
6561
6562
6563
######################################################
6564
6565
def element_class(R, is_sparse):
6566
"""
6567
The class of the vectors (elements of a free module) with base ring
6568
R and boolean is_sparse.
6569
6570
EXAMPLES::
6571
6572
sage: FF = FiniteField(2)
6573
sage: P = PolynomialRing(FF,'x')
6574
sage: sage.modules.free_module.element_class(QQ, is_sparse=True)
6575
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
6576
sage: sage.modules.free_module.element_class(QQ, is_sparse=False)
6577
<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
6578
sage: sage.modules.free_module.element_class(ZZ, is_sparse=True)
6579
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
6580
sage: sage.modules.free_module.element_class(ZZ, is_sparse=False)
6581
<type 'sage.modules.vector_integer_dense.Vector_integer_dense'>
6582
sage: sage.modules.free_module.element_class(FF, is_sparse=True)
6583
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
6584
sage: sage.modules.free_module.element_class(FF, is_sparse=False)
6585
<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'>
6586
sage: sage.modules.free_module.element_class(GF(7), is_sparse=False)
6587
<type 'sage.modules.vector_modn_dense.Vector_modn_dense'>
6588
sage: sage.modules.free_module.element_class(P, is_sparse=True)
6589
<type 'sage.modules.free_module_element.FreeModuleElement_generic_sparse'>
6590
sage: sage.modules.free_module.element_class(P, is_sparse=False)
6591
<type 'sage.modules.free_module_element.FreeModuleElement_generic_dense'>
6592
"""
6593
import sage.modules.vector_real_double_dense
6594
import sage.modules.vector_complex_double_dense
6595
6596
if sage.rings.integer_ring.is_IntegerRing(R) and not is_sparse:
6597
from vector_integer_dense import Vector_integer_dense
6598
return Vector_integer_dense
6599
elif sage.rings.rational_field.is_RationalField(R) and not is_sparse:
6600
from vector_rational_dense import Vector_rational_dense
6601
return Vector_rational_dense
6602
elif sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R) and not is_sparse:
6603
from vector_modn_dense import Vector_modn_dense, MAX_MODULUS
6604
from vector_mod2_dense import Vector_mod2_dense
6605
if R.order() == 2:
6606
return Vector_mod2_dense
6607
if R.order() < MAX_MODULUS:
6608
return Vector_modn_dense
6609
else:
6610
return free_module_element.FreeModuleElement_generic_dense
6611
elif sage.rings.real_double.is_RealDoubleField(R) and not is_sparse:
6612
return sage.modules.vector_real_double_dense.Vector_real_double_dense
6613
elif sage.rings.complex_double.is_ComplexDoubleField(R) and not is_sparse:
6614
return sage.modules.vector_complex_double_dense.Vector_complex_double_dense
6615
elif sage.symbolic.ring.is_SymbolicExpressionRing(R) and not is_sparse:
6616
return sage.modules.vector_symbolic_dense.Vector_symbolic_dense
6617
elif sage.symbolic.callable.is_CallableSymbolicExpressionRing(R) and not is_sparse:
6618
return sage.modules.vector_callable_symbolic_dense.Vector_callable_symbolic_dense
6619
else:
6620
if is_sparse:
6621
return free_module_element.FreeModuleElement_generic_sparse
6622
else:
6623
return free_module_element.FreeModuleElement_generic_dense
6624
raise NotImplementedError
6625
6626