-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathQuotientModule.class.st
165 lines (136 loc) · 4.7 KB
/
QuotientModule.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"
Quotient modules M/S (read ""M mod S"") of a given module M 'modulo' a submodule S, where both M and S are finite-rank free modules over a PID. These are the finitely-generated modules over a PID, presented as quotients of free modules.
The elements of a quotient module M/S are cosets S + x with x in M.
See QuotientSpace for quotients of vector spaces.
References:
https://en.wikipedia.org/wiki/Quotient_module
https://en.wikipedia.org/wiki/Quotient_space_(linear_algebra)
"
Class {
#name : #QuotientModule,
#superclass : #Module,
#category : #'Mathematics-Modules'
}
{ #category : #'instance creation' }
QuotientModule class >> base: aModule relations: aSubmodule [
^ self new base: aModule; relations: aSubmodule
]
{ #category : #'instance creation' }
QuotientModule class >> mod: aSubmodule [
^ self new relations: aSubmodule
]
{ #category : #operations }
QuotientModule >> annihilator [
"Answer the ideal of the scalars rings that annihilates all the elements in the receiver."
self isFinite ifFalse: [^ self scalars zeroIdeal].
^ self scalars * (self invariants inject: self scalars one into: [:result :each| result lcm: each])
]
{ #category : #accessing }
QuotientModule >> base [
^ self propertyAt: #base ifAbsentPut: [self relations ambient]
]
{ #category : #'accessing-private' }
QuotientModule >> base: aModule [
self propertyAt: #base put: aModule
]
{ #category : #private }
QuotientModule >> buildProjection [
"Answer the quotient map, the canonical projection from the base module to the quotient module, i.e. the mapping pi:M->M/N that assigns to every x in M the coset x+N."
| answer |
answer := self base to: self evaluating: [:each| self project: each].
answer name: Character pi asString.
answer properties
at: #kernel put: self relations;
at: #image put: self;
at: #rightInverse put: (self to: self base evaluating: [:each| each representative]).
^ answer
]
{ #category : #testing }
QuotientModule >> contains: anAffineSubspace [
^ anAffineSubspace direction = self relations
]
{ #category : #accessing }
QuotientModule >> generators [
^ self base generators collect: [:each| self project: each]
]
{ #category : #testing }
QuotientModule >> includes: anObject [
^ (anObject isKindOf: AffineSubspace) and: [self contains: anObject]
]
{ #category : #accessing }
QuotientModule >> invariants [
^ self matrix SNF
]
{ #category : #testing }
QuotientModule >> isFinite [
^ (self invariants includes: 0) not and: [self invariants isEmpty not]
]
{ #category : #testing }
QuotientModule >> isNoetherian [
"A module is called Noetherian if every submodule is finitely generated."
^ self base isNoetherian
]
{ #category : #testing }
QuotientModule >> isQuotient [
^ true
]
{ #category : #morphisms }
QuotientModule >> lifting [
"Answer the map from the receiver to the base module lifting the canonical projection."
^ self projection section
]
{ #category : #accessing }
QuotientModule >> matrix [
"Answer the relative matrix of the receiver."
^ Matrix rows: (self relations basis collect: [:each| (self base coordinatesOf: each) over: self scalars])
]
{ #category : #printing }
QuotientModule >> printOn: aStream [
aStream print: self base; nextPut: $/; print: self relations
]
{ #category : #morphisms }
QuotientModule >> project: anElement [
^ AffineSubspace representative: anElement direction: self relations
]
{ #category : #morphisms }
QuotientModule >> projection [
"Answer the natural projection, or quotient map, or canonical homomorphism. This takes elements from the base module or vector space to the corresponding coset (an affine subspace) in the quotient."
^ self propertyAt: #projection ifAbsentPut: [self buildProjection]
]
{ #category : #accessing }
QuotientModule >> relation [
^ EquivalenceRelation
on: self base
evaluating: [ :x :y | self relations includes: x - y ]
]
{ #category : #accessing }
QuotientModule >> relations [
^ self propertyAt: #relations
]
{ #category : #'accessing-private' }
QuotientModule >> relations: aSubmodule [
self propertyAt: #relations put: aSubmodule
]
{ #category : #accessing }
QuotientModule >> relators [
^ self relations generators
]
{ #category : #accessing }
QuotientModule >> scalars [
^ self relations scalars
]
{ #category : #operations }
QuotientModule >> span: aCollection [
"Answer the submodule spanned by the module elements in aCollection."
^ (self base span: (aCollection apply: self lifting)) apply: self projection
]
{ #category : #operations }
QuotientModule >> span: aCollection over: aRing [
"Answer the submodule spanned by the module elements in aCollection over aRing."
aRing = self scalars ifFalse: [^ DomainError signal].
^ self span: aCollection
]
{ #category : #elements }
QuotientModule >> zero [
^ self project: self base zero
]