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