Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/homology/chain_complex_morphism.py
4094 views
1
r"""
2
Morphisms of chain complexes
3
4
AUTHORS:
5
6
- Benjamin Antieau <[email protected]> (2009.06)
7
8
This module implements morphisms of chain complexes. The input is a dictionary whose
9
keys are in the grading group of the chain complex and whose values are matrix morphisms.
10
11
EXAMPLES::
12
13
from sage.matrix.constructor import zero_matrix
14
sage: S = simplicial_complexes.Sphere(1)
15
sage: S
16
Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
17
sage: C = S.chain_complex()
18
sage: C.differential()
19
{0: [], 1: [ 1 1 0]
20
[ 0 -1 -1]
21
[-1 0 1]}
22
sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
23
sage: G = Hom(C,C)
24
sage: x = G(f)
25
sage: x
26
Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 2 nonzero terms over Integer Ring
27
sage: x._matrix_dictionary
28
{0: [0 0 0]
29
[0 0 0]
30
[0 0 0], 1: [0 0 0]
31
[0 0 0]
32
[0 0 0]}
33
34
"""
35
36
#*****************************************************************************
37
# Copyright (C) 2009 D. Benjamin Antieau <[email protected]>
38
#
39
# Distributed under the terms of the GNU General Public License (GPL)
40
#
41
# This code is distributed in the hope that it will be useful,
42
# but WITHOUT ANY WARRANTY; without even the implied warranty
43
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
44
#
45
# See the GNU General Public License for more details; the full text
46
# is available at:
47
#
48
# http://www.gnu.org/licenses/
49
#
50
#*****************************************************************************
51
52
import sage.matrix.all as matrix
53
from sage.structure.sage_object import SageObject
54
from sage.rings.integer_ring import ZZ
55
56
def is_ChainComplexMorphism(x):
57
"""
58
Returns True if and only if x is a chain complex morphism.
59
60
EXAMPLES::
61
62
sage: from sage.homology.chain_complex_morphism import is_ChainComplexMorphism
63
sage: S = simplicial_complexes.Sphere(14)
64
sage: H = Hom(S,S)
65
sage: i = H.identity() # long time (8s on sage.math, 2011)
66
sage: S = simplicial_complexes.Sphere(6)
67
sage: H = Hom(S,S)
68
sage: i = H.identity()
69
sage: x = i.associated_chain_complex_morphism()
70
sage: x # indirect doctest
71
Chain complex morphism from Chain complex with at most 7 nonzero terms over Integer Ring to Chain complex with at most 7 nonzero terms over Integer Ring
72
sage: is_ChainComplexMorphism(x)
73
True
74
75
"""
76
return isinstance(x,ChainComplexMorphism)
77
78
class ChainComplexMorphism(SageObject):
79
"""
80
An element of this class is a morphism of chain complexes.
81
"""
82
def __init__(self,matrices,C,D):
83
"""
84
Create a morphism from a dictionary of matrices.
85
86
EXAMPLES::
87
88
from sage.matrix.constructor import zero_matrix
89
sage: S = simplicial_complexes.Sphere(1)
90
sage: S
91
Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
92
sage: C = S.chain_complex()
93
sage: C.differential()
94
{0: [], 1: [ 1 1 0]
95
[ 0 -1 -1]
96
[-1 0 1]}
97
sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
98
sage: G = Hom(C,C)
99
sage: x = G(f)
100
sage: x
101
Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 2 nonzero terms over Integer Ring
102
sage: x._matrix_dictionary
103
{0: [0 0 0]
104
[0 0 0]
105
[0 0 0], 1: [0 0 0]
106
[0 0 0]
107
[0 0 0]}
108
109
"""
110
if C._grading_group != ZZ:
111
raise NotImplementedError, "Chain complex morphisms are not implemented over gradings other than ZZ."
112
d = C._degree
113
if d != D._degree:
114
raise ValueError, "Chain complex morphisms are not defined for chain complexes of different degrees."
115
if d != -1 and d != 1:
116
raise NotImplementedError, "Chain complex morphisms are not implemented for degrees besides -1 and 1."
117
dim_min = min(min(C.differential().keys()),min(D.differential().keys()))
118
dim_max = max(max(C.differential().keys()),max(D.differential().keys()))
119
if not C.base_ring()==D.base_ring():
120
raise NotImplementedError, "Chain complex morphisms between chain complexes of different base rings are not implemented."
121
for i in range(dim_min,dim_max):
122
try:
123
matrices[i]
124
except KeyError:
125
matrices[i] = matrix.zero_matrix(C.base_ring(),D.differential()[i].ncols(),C.differential()[i].ncols(),sparse=True)
126
try:
127
matrices[i+1]
128
except KeyError:
129
matrices[i+1] = matrix.zero_matrix(C.base_ring(),D.differential()[i+1].ncols(),C.differential()[i+1].ncols(),sparse=True)
130
if d==-1:
131
if (i+1) in C.differential().keys() and (i+1) in D.differential().keys():
132
if not matrices[i]*C.differential()[i+1]==D.differential()[i+1]*matrices[i+1]:
133
raise ValueError, "Matrices must define a chain complex morphism."
134
elif (i+1) in C.differential().keys():
135
if not matrices[i]*C.differential()[i+1].is_zero():
136
raise ValueError, "Matrices must define a chain complex morphism."
137
elif (i+1) in D.differential().keys():
138
if not D.differential()[i+1]*matrices[i+1].is_zero():
139
raise ValueError, "Matrices must define a chain complex morphism."
140
else:
141
if i in C.differential().keys() and i in D.differential().keys():
142
if not matrices[i+1]*C.differential()[i]==D.differential()[i]*matrices[i]:
143
raise ValueError, "Matrices must define a chain complex morphism."
144
elif i in C.differential().keys():
145
if not matrices[i+1]*C.differential()[i].is_zero():
146
raise ValueError, "Matrices must define a chain complex morphism."
147
elif i in D.differential().keys():
148
if not D.differential()[i]*matrices[i].is_zero():
149
raise ValueError, "Matrices must define a chain complex morphism."
150
self._matrix_dictionary = matrices
151
self._domain = C
152
self._codomain = D
153
154
def __neg__(self):
155
"""
156
Returns -x.
157
158
EXAMPLES::
159
160
sage: S = simplicial_complexes.Sphere(2)
161
sage: H = Hom(S,S)
162
sage: i = H.identity()
163
sage: x = i.associated_chain_complex_morphism()
164
sage: w = -x
165
sage: w._matrix_dictionary
166
{0: [-1 0 0 0]
167
[ 0 -1 0 0]
168
[ 0 0 -1 0]
169
[ 0 0 0 -1],
170
1: [-1 0 0 0 0 0]
171
[ 0 -1 0 0 0 0]
172
[ 0 0 -1 0 0 0]
173
[ 0 0 0 -1 0 0]
174
[ 0 0 0 0 -1 0]
175
[ 0 0 0 0 0 -1],
176
2: [-1 0 0 0]
177
[ 0 -1 0 0]
178
[ 0 0 -1 0]
179
[ 0 0 0 -1]}
180
181
"""
182
f = dict()
183
for i in self._matrix_dictionary.keys():
184
f[i] = -self._matrix_dictionary[i]
185
return ChainComplexMorphism(f,self._domain,self._codomain)
186
187
def __add__(self,x):
188
"""
189
Returns self+x.
190
191
EXAMPLES::
192
193
sage: S = simplicial_complexes.Sphere(2)
194
sage: H = Hom(S,S)
195
sage: i = H.identity()
196
sage: x = i.associated_chain_complex_morphism()
197
sage: z = x+x
198
sage: z._matrix_dictionary
199
{0: [2 0 0 0]
200
[0 2 0 0]
201
[0 0 2 0]
202
[0 0 0 2],
203
1: [2 0 0 0 0 0]
204
[0 2 0 0 0 0]
205
[0 0 2 0 0 0]
206
[0 0 0 2 0 0]
207
[0 0 0 0 2 0]
208
[0 0 0 0 0 2],
209
2: [2 0 0 0]
210
[0 2 0 0]
211
[0 0 2 0]
212
[0 0 0 2]}
213
214
"""
215
if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary.keys() != x._matrix_dictionary.keys():
216
raise TypeError, "Unsupported operation."
217
f = dict()
218
for i in self._matrix_dictionary.keys():
219
f[i] = self._matrix_dictionary[i] + x._matrix_dictionary[i]
220
return ChainComplexMorphism(f,self._domain,self._codomain)
221
222
def __mul__(self,x):
223
"""
224
Returns self*x if self and x are composable morphisms or if x is an element of the base_ring.
225
226
EXAMPLES::
227
228
sage: S = simplicial_complexes.Sphere(2)
229
sage: H = Hom(S,S)
230
sage: i = H.identity()
231
sage: x = i.associated_chain_complex_morphism()
232
sage: y = x*2
233
sage: y._matrix_dictionary
234
{0: [2 0 0 0]
235
[0 2 0 0]
236
[0 0 2 0]
237
[0 0 0 2],
238
1: [2 0 0 0 0 0]
239
[0 2 0 0 0 0]
240
[0 0 2 0 0 0]
241
[0 0 0 2 0 0]
242
[0 0 0 0 2 0]
243
[0 0 0 0 0 2],
244
2: [2 0 0 0]
245
[0 2 0 0]
246
[0 0 2 0]
247
[0 0 0 2]}
248
sage: z = y*y
249
sage: z._matrix_dictionary
250
{0: [4 0 0 0]
251
[0 4 0 0]
252
[0 0 4 0]
253
[0 0 0 4],
254
1: [4 0 0 0 0 0]
255
[0 4 0 0 0 0]
256
[0 0 4 0 0 0]
257
[0 0 0 4 0 0]
258
[0 0 0 0 4 0]
259
[0 0 0 0 0 4],
260
2: [4 0 0 0]
261
[0 4 0 0]
262
[0 0 4 0]
263
[0 0 0 4]}
264
265
"""
266
if not isinstance(x,ChainComplexMorphism) or self._codomain != x._domain:
267
try:
268
y = self._domain.base_ring()(x)
269
except TypeError:
270
raise TypeError, "Multiplication is not defined."
271
f = dict()
272
for i in self._matrix_dictionary.keys():
273
f[i] = self._matrix_dictionary[i] * y
274
return ChainComplexMorphism(f,self._domain,self._codomain)
275
f = dict()
276
for i in self._matrix_dictionary.keys():
277
f[i] = x._matrix_dictionary[i]*self._matrix_dictionary[i]
278
return ChainComplexMorphism(f,self._domain,x._codomain)
279
280
def __rmul__(self,x):
281
"""
282
Returns x*self if x is an element of the base_ring.
283
284
EXAMPLES::
285
286
sage: S = simplicial_complexes.Sphere(2)
287
sage: H = Hom(S,S)
288
sage: i = H.identity()
289
sage: x = i.associated_chain_complex_morphism()
290
sage: 2*x == x*2
291
True
292
sage: 3*x == x*2
293
False
294
"""
295
try:
296
y = self._domain.base_ring()(x)
297
except TypeError:
298
raise TypeError, "Multiplication is not defined."
299
f = dict()
300
for i in self._matrix_dictionary.keys():
301
f[i] = y * self._matrix_dictionary[i]
302
return ChainComplexMorphism(f,self._domain,self._codomain)
303
304
def __sub__(self,x):
305
"""
306
Returns self-x.
307
308
EXAMPLES::
309
310
sage: S = simplicial_complexes.Sphere(2)
311
sage: H = Hom(S,S)
312
sage: i = H.identity()
313
sage: x = i.associated_chain_complex_morphism()
314
sage: y = x-x
315
sage: y._matrix_dictionary
316
{0: [0 0 0 0]
317
[0 0 0 0]
318
[0 0 0 0]
319
[0 0 0 0],
320
1: [0 0 0 0 0 0]
321
[0 0 0 0 0 0]
322
[0 0 0 0 0 0]
323
[0 0 0 0 0 0]
324
[0 0 0 0 0 0]
325
[0 0 0 0 0 0],
326
2: [0 0 0 0]
327
[0 0 0 0]
328
[0 0 0 0]
329
[0 0 0 0]}
330
331
"""
332
return self + (-x)
333
334
def __eq__(self,x):
335
"""
336
Returns True if and only if self==x.
337
338
EXAMPLES::
339
340
sage: S = SimplicialComplex(3)
341
sage: H = Hom(S,S)
342
sage: i = H.identity()
343
sage: x = i.associated_chain_complex_morphism()
344
sage: x
345
Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring to Chain complex with at most 0 nonzero terms over Integer Ring
346
sage: f = x._matrix_dictionary
347
sage: C = S.chain_complex()
348
sage: G = Hom(C,C)
349
sage: y = G(f)
350
sage: x==y
351
True
352
353
"""
354
if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary != x._matrix_dictionary:
355
return False
356
else:
357
return True
358
359
def _repr_(self):
360
"""
361
Returns the string representation of self.
362
363
EXAMPLES::
364
365
sage: S = SimplicialComplex(3)
366
sage: H = Hom(S,S)
367
sage: i = H.identity()
368
sage: x = i.associated_chain_complex_morphism()
369
sage: x
370
Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring to Chain complex with at most 0 nonzero terms over Integer Ring
371
sage: x._repr_()
372
'Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring to Chain complex with at most 0 nonzero terms over Integer Ring'
373
374
"""
375
return "Chain complex morphism from " + self._domain._repr_() + " to " + self._codomain._repr_()
376
377