Ticket #6099: trac_6099-rebased.patch
File trac_6099-rebased.patch, 58.8 KB (added by , 13 years ago) |
---|
-
doc/en/reference/homology.rst
# HG changeset patch # User J. H. Palmieri <palmieri@math.washington.edu> # Date 1259091902 28800 # Node ID e3035f8ac9b555085e66a6ec9722b46c22481283 # Parent 44f70d431d43e3dfaa1487641ee6864d5025fb06 rebased patch for 6099 diff -r 44f70d431d43 -r e3035f8ac9b5 doc/en/reference/homology.rst
a b 8 8 :maxdepth: 2 9 9 10 10 sage/homology/simplicial_complex 11 sage/homology/simplicial_complex_morphism 12 sage/homology/simplicial_complex_homset 11 13 sage/homology/chain_complex 14 sage/homology/chain_complex_morphism 15 sage/homology/chain_complex_homspace 12 16 sage/homology/examples -
sage/homology/all.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/all.py
a b 1 1 from chain_complex import ChainComplex 2 2 3 from chain_complex_morphism import ChainComplexMorphism 4 3 5 from simplicial_complex import SimplicialComplex 4 6 7 from simplicial_complex_morphism import SimplicialComplexMorphism 8 5 9 from examples import simplicial_complexes -
sage/homology/chain_complex.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/chain_complex.py
a b 338 338 EXAMPLES:: 339 339 340 340 sage: ChainComplex() 341 Chain complex with at most 0 nonzero terms over Integer Ring .341 Chain complex with at most 0 nonzero terms over Integer Ring 342 342 sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) 343 343 sage: C 344 Chain complex with at most 2 nonzero terms over Integer Ring .344 Chain complex with at most 2 nonzero terms over Integer Ring 345 345 sage: D = ChainComplex([matrix(ZZ, 2, 2, [0, 1, 0, 0]), matrix(ZZ, 2, 2, [0, 1, 0, 0])], base_ring=GF(2)); D 346 Chain complex with at most 3 nonzero terms over Finite Field of size 2 .346 Chain complex with at most 3 nonzero terms over Finite Field of size 2 347 347 sage: D == loads(dumps(D)) 348 348 True 349 349 … … 361 361 Defining the base ring implicitly:: 362 362 363 363 sage: ChainComplex([matrix(QQ, 3, 1), matrix(ZZ, 4, 3)]) 364 Chain complex with at most 2 nonzero terms over Rational Field .364 Chain complex with at most 2 nonzero terms over Rational Field 365 365 sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(ZZ, 4, 3)]) 366 Chain complex with at most 2 nonzero terms over Finite Field in a of size 5^3 .366 Chain complex with at most 2 nonzero terms over Finite Field in a of size 5^3 367 367 368 368 If the matrices are defined over incompatible rings, an error results:: 369 369 … … 389 389 EXAMPLES:: 390 390 391 391 sage: C = ChainComplex(); C 392 Chain complex with at most 0 nonzero terms over Integer Ring .392 Chain complex with at most 0 nonzero terms over Integer Ring 393 393 sage: D = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) 394 394 sage: D 395 Chain complex with at most 2 nonzero terms over Integer Ring .395 Chain complex with at most 2 nonzero terms over Integer Ring 396 396 """ 397 397 try: 398 398 deg = grading_group(degree) … … 874 874 import sage.categories.all 875 875 return sage.categories.all.ChainComplexes(self.base_ring()) 876 876 877 def _Hom_(self, other, category=None): 878 """ 879 Return the set of chain maps between chain complexes ``self`` 880 and ``other``. 881 882 EXAMPLES:: 883 884 sage: S = simplicial_complexes.Sphere(2) 885 sage: T = simplicial_complexes.Torus() 886 sage: C = S.chain_complex(augmented=True,cochain=True) 887 sage: D = T.chain_complex(augmented=True,cochain=True) 888 sage: Hom(C,D) # indirect doctest 889 Set of Morphisms from Chain complex with at most 4 nonzero terms over Integer Ring to Chain complex with at most 4 nonzero terms over Integer Ring in Category of chain complexes over Integer Ring 890 """ 891 from sage.homology.chain_complex_homspace import ChainComplexHomspace 892 return ChainComplexHomspace(self, other) 893 877 894 def _repr_(self): 878 895 """ 879 896 Print representation. … … 882 899 883 900 sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) 884 901 sage: C._repr_() 885 'Chain complex with at most 2 nonzero terms over Integer Ring .'902 'Chain complex with at most 2 nonzero terms over Integer Ring' 886 903 """ 887 904 diffs = filter(lambda mat: mat.nrows() + mat.ncols() > 0, 888 905 self._diff.values()) 889 906 string1 = "Chain complex with at most" 890 string2 = " %s nonzero terms over %s ." % (len(diffs),907 string2 = " %s nonzero terms over %s" % (len(diffs), 891 908 self._base_ring) 892 909 return string1 + string2 893 910 -
new file sage/homology/chain_complex_homspace.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/chain_complex_homspace.py
- + 1 r""" 2 Homspaces between chain complexes 3 4 Note that some significant functionality is lacking. Namely, the homspaces 5 are not actually modules over the base ring. It will be necessary to 6 enrich some of the structure of chain complexes for this to be naturally 7 available. On other hand, there are various overloaded operators. __mul__ 8 acts as composition. One can __add__, and one can __mul__ with a ring element 9 on the right. 10 11 EXAMPLES:: 12 13 sage: S = simplicial_complexes.Sphere(2) 14 sage: T = simplicial_complexes.Torus() 15 sage: C = S.chain_complex(augmented=True,cochain=True) 16 sage: D = T.chain_complex(augmented=True,cochain=True) 17 sage: G = Hom(C,D) 18 sage: G 19 Set of Morphisms from Chain complex with at most 4 nonzero terms over Integer Ring to Chain complex with at most 4 nonzero terms over Integer Ring in Category of chain complexes over Integer Ring 20 21 sage: S = simplicial_complexes.ChessboardComplex(3,3) 22 sage: H = Hom(S,S) 23 sage: i = H.identity() 24 sage: x = i.associated_chain_complex_morphism(augmented=True) 25 sage: x 26 Chain complex morphism from Chain complex with at most 4 nonzero terms over Integer Ring to Chain complex with at most 4 nonzero terms over Integer Ring 27 sage: x._matrix_dictionary 28 {0: [1 0 0 0 0 0 0 0 0] 29 [0 1 0 0 0 0 0 0 0] 30 [0 0 1 0 0 0 0 0 0] 31 [0 0 0 1 0 0 0 0 0] 32 [0 0 0 0 1 0 0 0 0] 33 [0 0 0 0 0 1 0 0 0] 34 [0 0 0 0 0 0 1 0 0] 35 [0 0 0 0 0 0 0 1 0] 36 [0 0 0 0 0 0 0 0 1], 1: [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 37 [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 38 [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 39 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 40 [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] 41 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] 42 [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] 43 [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] 44 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] 45 [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] 46 [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] 47 [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] 48 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] 49 [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] 50 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] 51 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] 52 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] 53 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1], 2: [1 0 0 0 0 0] 54 [0 1 0 0 0 0] 55 [0 0 1 0 0 0] 56 [0 0 0 1 0 0] 57 [0 0 0 0 1 0] 58 [0 0 0 0 0 1], -1: [1]} 59 60 sage: S = simplicial_complexes.Sphere(2) 61 sage: A = Hom(S,S) 62 sage: i = A.identity() 63 sage: x = i.associated_chain_complex_morphism() 64 sage: x 65 Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring to Chain complex with at most 3 nonzero terms over Integer Ring 66 sage: y = x*4 67 sage: z = y*y 68 sage: (y+z) 69 Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring to Chain complex with at most 3 nonzero terms over Integer Ring 70 sage: f = x._matrix_dictionary 71 sage: C = S.chain_complex() 72 sage: G = Hom(C,C) 73 sage: w = G(f) 74 sage: w==x 75 True 76 77 """ 78 79 #***************************************************************************** 80 # Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com> 81 # 82 # Distributed under the terms of the GNU General Public License (GPL) 83 # 84 # This code is distributed in the hope that it will be useful, 85 # but WITHOUT ANY WARRANTY; without even the implied warranty 86 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 87 # 88 # See the GNU General Public License for more details; the full text 89 # is available at: 90 # 91 # http://www.gnu.org/licenses/ 92 # 93 #***************************************************************************** 94 95 import sage.categories.homset 96 import sage.homology.chain_complex as chain_complex 97 import sage.homology.chain_complex_morphism as chain_complex_morphism 98 99 def is_ChainComplexHomspace(x): 100 """ 101 Returns True if and only if x is a morphism of chain complexes. 102 103 EXAMPLES:: 104 105 sage: from sage.homology.chain_complex_homspace import is_ChainComplexHomspace 106 sage: T = SimplicialComplex(17,[[1,2,3,4],[7,8,9]]) 107 sage: C = T.chain_complex(augmented=True,cochain=True) 108 sage: G = Hom(C,C) 109 sage: is_ChainComplexHomspace(G) 110 True 111 112 """ 113 return isinstance(x,ChainComplexHomspace) 114 115 class ChainComplexHomspace(sage.categories.homset.Homset): 116 """ 117 Class of homspaces of chain complex morphisms. 118 119 EXAMPLES:: 120 121 sage: T = SimplicialComplex(17,[[1,2,3,4],[7,8,9]]) 122 sage: C = T.chain_complex(augmented=True,cochain=True) 123 sage: G = Hom(C,C) 124 sage: G 125 Set of Morphisms from Chain complex with at most 5 nonzero terms over Integer Ring to Chain complex with at most 5 nonzero terms over Integer Ring in Category of chain complexes over Integer Ring 126 127 """ 128 def __call__(self, f): 129 """ 130 f is a dictionary of matrices in the basis of the chain complex. 131 132 EXAMPLES:: 133 134 sage: S = simplicial_complexes.Sphere(5) 135 sage: H = Hom(S,S) 136 sage: i = H.identity() 137 sage: C = S.chain_complex() 138 sage: G = Hom(C,C) 139 sage: x = i.associated_chain_complex_morphism() 140 sage: f = x._matrix_dictionary 141 sage: y = G(f) 142 sage: x==y 143 True 144 145 """ 146 return chain_complex_morphism.ChainComplexMorphism(f, self.domain(), self.codomain()) -
new file sage/homology/chain_complex_morphism.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/chain_complex_morphism.py
- + 1 r""" 2 Morphisms of chain complexes 3 4 AUTHORS: 5 6 - Benjamin Antieau <d.ben.antieau@gmail.com> (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 <d.ben.antieau@gmail.com> 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.homology.simplicial_complex as simplicial_complex 53 import sage.matrix.all as matrix 54 from sage.structure.sage_object import SageObject 55 from sage.rings.integer_ring import ZZ 56 57 def is_ChainComplexMorphism(x): 58 """ 59 Returns True if and only if x is a chain complex morphism. 60 61 EXAMPLES:: 62 63 sage: from sage.homology.chain_complex_morphism import is_ChainComplexMorphism 64 sage: S = simplicial_complexes.Sphere(14) 65 sage: H = Hom(S,S) 66 sage: i = H.identity() 67 sage: S = simplicial_complexes.Sphere(6) 68 sage: H = Hom(S,S) 69 sage: i = H.identity() 70 sage: x = i.associated_chain_complex_morphism() 71 sage: x # indirect doctest 72 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 73 sage: is_ChainComplexMorphism(x) 74 True 75 76 """ 77 return isinstance(x,ChainComplexMorphism) 78 79 class ChainComplexMorphism(SageObject): 80 """ 81 An element of this class is a morphism of chain complexes. 82 """ 83 def __init__(self,matrices,C,D): 84 """ 85 Create a morphism from a dictionary of matrices. 86 87 EXAMPLES:: 88 89 from sage.matrix.constructor import zero_matrix 90 sage: S = simplicial_complexes.Sphere(1) 91 sage: S 92 Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} 93 sage: C = S.chain_complex() 94 sage: C.differential() 95 {0: [], 1: [ 1 1 0] 96 [ 0 -1 -1] 97 [-1 0 1]} 98 sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)} 99 sage: G = Hom(C,C) 100 sage: x = G(f) 101 sage: x 102 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 103 sage: x._matrix_dictionary 104 {0: [0 0 0] 105 [0 0 0] 106 [0 0 0], 1: [0 0 0] 107 [0 0 0] 108 [0 0 0]} 109 110 """ 111 if C._grading_group != ZZ: 112 raise NotImplementedError, "Chain complex morphisms are not implemented over gradings other than ZZ." 113 d = C._degree 114 if d != D._degree: 115 raise ValueError, "Chain complex morphisms are not defined for chain complexes of different degrees." 116 if d != -1 and d != 1: 117 raise NotImplementedError, "Chain complex morphisms are not implemented for degrees besides -1 and 1." 118 dim_min = min(min(C.differential().keys()),min(D.differential().keys())) 119 dim_max = max(max(C.differential().keys()),max(D.differential().keys())) 120 if not C.base_ring()==D.base_ring(): 121 raise NotImplementedError, "Chain complex morphisms between chain complexes of different base rings are not implemented." 122 for i in range(dim_min,dim_max): 123 try: 124 matrices[i] 125 except KeyError: 126 matrices[i] = matrix.zero_matrix(C.base_ring(),D.differential()[i].ncols(),C.differential()[i].ncols(),sparse=True) 127 try: 128 matrices[i+1] 129 except KeyError: 130 matrices[i+1] = matrix.zero_matrix(C.base_ring(),D.differential()[i+1].ncols(),C.differential()[i+1].ncols(),sparse=True) 131 if d==-1: 132 if (i+1) in C.differential().keys() and (i+1) in D.differential().keys(): 133 if not matrices[i]*C.differential()[i+1]==D.differential()[i+1]*matrices[i+1]: 134 raise ValueError, "Matrices must define a chain complex morphism." 135 elif (i+1) in C.differential().keys(): 136 if not matrices[i]*C.differential()[i+1].is_zero(): 137 raise ValueError, "Matrices must define a chain complex morphism." 138 elif (i+1) in D.differential().keys(): 139 if not D.differential()[i+1]*matrices[i+1].is_zero(): 140 raise ValueError, "Matrices must define a chain complex morphism." 141 else: 142 if i in C.differential().keys() and i in D.differential().keys(): 143 if not matrices[i+1]*C.differential()[i]==D.differential()[i]*matrices[i]: 144 raise ValueError, "Matrices must define a chain complex morphism." 145 elif i in C.differential().keys(): 146 if not matrices[i+1]*C.differential()[i].is_zero(): 147 raise ValueError, "Matrices must define a chain complex morphism." 148 elif i in D.differential().keys(): 149 if not D.differential()[i]*matrices[i].is_zero(): 150 raise ValueError, "Matrices must define a chain complex morphism." 151 self._matrix_dictionary = matrices 152 self._domain = C 153 self._codomain = D 154 155 def __neg__(self): 156 """ 157 Returns -x. 158 159 EXAMPLES:: 160 161 sage: S = simplicial_complexes.Sphere(2) 162 sage: H = Hom(S,S) 163 sage: i = H.identity() 164 sage: x = i.associated_chain_complex_morphism() 165 sage: w = -x 166 sage: w._matrix_dictionary 167 {0: [-1 0 0 0] 168 [ 0 -1 0 0] 169 [ 0 0 -1 0] 170 [ 0 0 0 -1], 171 1: [-1 0 0 0 0 0] 172 [ 0 -1 0 0 0 0] 173 [ 0 0 -1 0 0 0] 174 [ 0 0 0 -1 0 0] 175 [ 0 0 0 0 -1 0] 176 [ 0 0 0 0 0 -1], 177 2: [-1 0 0 0] 178 [ 0 -1 0 0] 179 [ 0 0 -1 0] 180 [ 0 0 0 -1]} 181 182 """ 183 f = dict() 184 for i in self._matrix_dictionary.keys(): 185 f[i] = -self._matrix_dictionary[i] 186 return ChainComplexMorphism(f,self._domain,self._codomain) 187 188 def __add__(self,x): 189 """ 190 Returns self+x. 191 192 EXAMPLES:: 193 194 sage: S = simplicial_complexes.Sphere(2) 195 sage: H = Hom(S,S) 196 sage: i = H.identity() 197 sage: x = i.associated_chain_complex_morphism() 198 sage: z = x+x 199 sage: z._matrix_dictionary 200 {0: [2 0 0 0] 201 [0 2 0 0] 202 [0 0 2 0] 203 [0 0 0 2], 204 1: [2 0 0 0 0 0] 205 [0 2 0 0 0 0] 206 [0 0 2 0 0 0] 207 [0 0 0 2 0 0] 208 [0 0 0 0 2 0] 209 [0 0 0 0 0 2], 210 2: [2 0 0 0] 211 [0 2 0 0] 212 [0 0 2 0] 213 [0 0 0 2]} 214 215 """ 216 if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary.keys() != x._matrix_dictionary.keys(): 217 raise TypeError, "Unsupported operation." 218 f = dict() 219 for i in self._matrix_dictionary.keys(): 220 f[i] = self._matrix_dictionary[i] + x._matrix_dictionary[i] 221 return ChainComplexMorphism(f,self._domain,self._codomain) 222 223 def __mul__(self,x): 224 """ 225 Returns self*x if self and x are composable morphisms or if x is an element of the base_ring. 226 227 EXAMPLES:: 228 229 sage: S = simplicial_complexes.Sphere(2) 230 sage: H = Hom(S,S) 231 sage: i = H.identity() 232 sage: x = i.associated_chain_complex_morphism() 233 sage: y = x*2 234 sage: y._matrix_dictionary 235 {0: [2 0 0 0] 236 [0 2 0 0] 237 [0 0 2 0] 238 [0 0 0 2], 239 1: [2 0 0 0 0 0] 240 [0 2 0 0 0 0] 241 [0 0 2 0 0 0] 242 [0 0 0 2 0 0] 243 [0 0 0 0 2 0] 244 [0 0 0 0 0 2], 245 2: [2 0 0 0] 246 [0 2 0 0] 247 [0 0 2 0] 248 [0 0 0 2]} 249 sage: z = y*y 250 sage: z._matrix_dictionary 251 {0: [4 0 0 0] 252 [0 4 0 0] 253 [0 0 4 0] 254 [0 0 0 4], 255 1: [4 0 0 0 0 0] 256 [0 4 0 0 0 0] 257 [0 0 4 0 0 0] 258 [0 0 0 4 0 0] 259 [0 0 0 0 4 0] 260 [0 0 0 0 0 4], 261 2: [4 0 0 0] 262 [0 4 0 0] 263 [0 0 4 0] 264 [0 0 0 4]} 265 266 """ 267 if not isinstance(x,ChainComplexMorphism) or self._codomain != x._domain: 268 try: 269 y = self._domain.base_ring()(x) 270 except TypeError: 271 raise TypeError, "Multiplication is not defined." 272 f = dict() 273 for i in self._matrix_dictionary.keys(): 274 f[i] = self._matrix_dictionary[i] * y 275 return ChainComplexMorphism(f,self._domain,self._codomain) 276 f = dict() 277 for i in self._matrix_dictionary.keys(): 278 f[i] = x._matrix_dictionary[i]*self._matrix_dictionary[i] 279 return ChainComplexMorphism(f,self._domain,x._codomain) 280 281 def __rmul__(self,x): 282 """ 283 Returns x*self if x is an element of the base_ring. 284 285 EXAMPLES:: 286 287 sage: S = simplicial_complexes.Sphere(2) 288 sage: H = Hom(S,S) 289 sage: i = H.identity() 290 sage: x = i.associated_chain_complex_morphism() 291 sage: 2*x == x*2 292 True 293 sage: 3*x == x*2 294 False 295 """ 296 try: 297 y = self._domain.base_ring()(x) 298 except TypeError: 299 raise TypeError, "Multiplication is not defined." 300 f = dict() 301 for i in self._matrix_dictionary.keys(): 302 f[i] = y * self._matrix_dictionary[i] 303 return ChainComplexMorphism(f,self._domain,self._codomain) 304 305 def __sub__(self,x): 306 """ 307 Returns self-x. 308 309 EXAMPLES:: 310 311 sage: S = simplicial_complexes.Sphere(2) 312 sage: H = Hom(S,S) 313 sage: i = H.identity() 314 sage: x = i.associated_chain_complex_morphism() 315 sage: y = x-x 316 sage: y._matrix_dictionary 317 {0: [0 0 0 0] 318 [0 0 0 0] 319 [0 0 0 0] 320 [0 0 0 0], 321 1: [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 [0 0 0 0 0 0], 327 2: [0 0 0 0] 328 [0 0 0 0] 329 [0 0 0 0] 330 [0 0 0 0]} 331 332 """ 333 return self + (-x) 334 335 def __eq__(self,x): 336 """ 337 Returns True if and only if self==x. 338 339 EXAMPLES:: 340 341 sage: S = SimplicialComplex(3) 342 sage: H = Hom(S,S) 343 sage: i = H.identity() 344 sage: x = i.associated_chain_complex_morphism() 345 sage: x 346 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 347 sage: f = x._matrix_dictionary 348 sage: C = S.chain_complex() 349 sage: G = Hom(C,C) 350 sage: y = G(f) 351 sage: x==y 352 True 353 354 """ 355 if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary != x._matrix_dictionary: 356 return False 357 else: 358 return True 359 360 def _repr_(self): 361 """ 362 Returns the string representation of self. 363 364 EXAMPLES:: 365 366 sage: S = SimplicialComplex(3) 367 sage: H = Hom(S,S) 368 sage: i = H.identity() 369 sage: x = i.associated_chain_complex_morphism() 370 sage: x 371 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 372 sage: x._repr_() 373 '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' 374 375 """ 376 return "Chain complex morphism from " + self._domain._repr_() + " to " + self._codomain._repr_() -
sage/homology/simplicial_complex.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/simplicial_complex.py
a b 1179 1179 1180 1180 sage: circle = SimplicialComplex(2, [[0,1], [1,2], [0, 2]]) 1181 1181 sage: circle.chain_complex() 1182 Chain complex with at most 2 nonzero terms over Integer Ring .1182 Chain complex with at most 2 nonzero terms over Integer Ring 1183 1183 sage: circle.chain_complex()._latex_() 1184 1184 '\\Bold{Z}^{3} \\xrightarrow{d_{1}} \\Bold{Z}^{3}' 1185 1185 sage: circle.chain_complex(base_ring=QQ, augmented=True) 1186 Chain complex with at most 3 nonzero terms over Rational Field .1186 Chain complex with at most 3 nonzero terms over Rational Field 1187 1187 """ 1188 1188 # initialize subcomplex 1189 1189 if subcomplex is None: … … 1716 1716 faces.append(Simplex(list(f.set().difference(s.set())))) 1717 1717 return SimplicialComplex(self.vertices(), faces) 1718 1718 1719 def effective_vertices(self): 1720 """ 1721 The set of vertices belonging to some face. Returns a Simplex. 1722 1723 EXAMPLES:: 1724 1725 sage: S = SimplicialComplex(15) 1726 sage: S 1727 Simplicial complex with 16 vertices and facets {()} 1728 sage: S.effective_vertices() 1729 () 1730 1731 sage: S = SimplicialComplex(15,[[0,1,2,3],[6,7]]) 1732 sage: S 1733 Simplicial complex with 16 vertices and facets {(6, 7), (0, 1, 2, 3)} 1734 sage: S.effective_vertices() 1735 (0, 1, 2, 3, 6, 7) 1736 1737 sage: type(S.effective_vertices()) 1738 <class 'sage.homology.simplicial_complex.Simplex'> 1739 1740 """ 1741 try: 1742 v = self.faces()[0] 1743 except KeyError: 1744 return Simplex(-1) 1745 f = [] 1746 for i in v: 1747 f.append(i[0]) 1748 return Simplex(set(f)) 1749 1750 def generated_subcomplex(self,sub_vertex_set): 1751 """ 1752 Returns the largest sub-simplicial complex of self containing 1753 exactly ``sub_vertex_set`` as vertices. 1754 1755 EXAMPLES:: 1756 1757 sage: S = simplicial_complexes.Sphere(2) 1758 sage: S 1759 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 1760 sage: S.generated_subcomplex([0,1,2]) 1761 Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)} 1762 1763 """ 1764 if not self.vertices().set().issuperset(sub_vertex_set): 1765 raise TypeError, "input must be a subset of the vertex set." 1766 faces = [] 1767 for i in range(self.dimension()+1): 1768 for j in self.faces()[i]: 1769 if j.set().issubset(sub_vertex_set): 1770 faces.append(j) 1771 return SimplicialComplex(sub_vertex_set,faces,maximality_check=True) 1772 1719 1773 def _complement(self, simplex): 1720 1774 """ 1721 1775 Return the complement of a simplex in the vertex set of this … … 2252 2306 import sage.categories.all 2253 2307 return sage.categories.all.SimplicialComplexes() 2254 2308 2309 def _Hom_(self, other, category=None): 2310 """ 2311 Return the set of simplicial maps between simplicial complexes 2312 ``self`` and ``other``. 2313 2314 EXAMPLES:: 2315 2316 sage: S = simplicial_complexes.Sphere(1) 2317 sage: T = simplicial_complexes.Sphere(2) 2318 sage: H = Hom(S,T) # indirect doctest 2319 sage: H 2320 Set of Morphisms from Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} in Category of simplicial complexes 2321 sage: f = {0:0,1:1,2:3} 2322 sage: x = H(f) 2323 sage: x 2324 Simplicial complex morphism {0: 0, 1: 1, 2: 3} from Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 2325 """ 2326 from sage.homology.simplicial_complex_homset import SimplicialComplexHomset 2327 return SimplicialComplexHomset(self, other) 2328 2329 2255 2330 def _repr_(self): 2256 2331 """ 2257 2332 Print representation. If there are only a few vertices or -
new file sage/homology/simplicial_complex_homset.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/simplicial_complex_homset.py
- + 1 r""" 2 Homsets between simplicial complexes 3 4 EXAMPLES: 5 6 :: 7 8 sage: S = simplicial_complexes.Sphere(1) 9 sage: T = simplicial_complexes.Sphere(2) 10 sage: H = Hom(S,T) 11 sage: f = {0:0,1:1,2:3} 12 sage: x = H(f) 13 sage: x 14 Simplicial complex morphism {0: 0, 1: 1, 2: 3} from Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 15 sage: x.is_injective() 16 True 17 sage: x.is_surjective() 18 False 19 sage: x.image() 20 Simplicial complex with vertex set (0, 1, 3) and facets {(1, 3), (0, 3), (0, 1)} 21 sage: from sage.homology.simplicial_complex import Simplex 22 sage: s = Simplex([1,2]) 23 sage: x(s) 24 (1, 3) 25 26 TESTS:: 27 28 sage: S = simplicial_complexes.Sphere(1) 29 sage: T = simplicial_complexes.Sphere(2) 30 sage: H = Hom(S,T) 31 sage: loads(dumps(H))==H 32 True 33 34 """ 35 36 #***************************************************************************** 37 # Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com> 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.categories.homset 53 import sage.homology.simplicial_complex as simplicial_complex 54 import sage.homology.simplicial_complex_morphism as simplicial_complex_morphism 55 56 def is_SimplicialComplexHomset(x): 57 """ 58 Return True if and only if x is a simplicial complex homspace. 59 60 EXAMPLES:: 61 62 sage: H = Hom(SimplicialComplex(2),SimplicialComplex(3)) 63 sage: H 64 Set of Morphisms from Simplicial complex with vertex set (0, 1, 2) and facets {()} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {()} in Category of simplicial complexes 65 sage: from sage.homology.simplicial_complex_homset import is_SimplicialComplexHomset 66 sage: is_SimplicialComplexHomset(H) 67 True 68 """ 69 return isinstance(x, SimplicialComplexHomset) 70 71 class SimplicialComplexHomset(sage.categories.homset.Homset): 72 def __call__(self, f): 73 """ 74 INPUT: 75 f -- a dictionary with keys exactly the vertices of the domain and values vertices of the codomain 76 77 EXAMPLE:: 78 79 sage: S = simplicial_complexes.Sphere(3) 80 sage: T = simplicial_complexes.Sphere(2) 81 sage: f = {0:0,1:1,2:2,3:2,4:2} 82 sage: H = Hom(S,T) 83 sage: x = H(f) 84 sage: x 85 Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 2, 4: 2} from Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 86 87 88 """ 89 return simplicial_complex_morphism.SimplicialComplexMorphism(f,self.domain(),self.codomain()) 90 91 def diagonal_morphism(self,rename_vertices=True): 92 """ 93 Returns the diagonal morphism in Hom(S,SxS). 94 95 EXAMPLES:: 96 97 sage: S = simplicial_complexes.Sphere(2) 98 sage: H = Hom(S,S.product(S)) 99 sage: d = H.diagonal_morphism() 100 sage: d 101 Simplicial complex morphism {0: 'L0R0', 1: 'L1R1', 2: 'L2R2', 3: 'L3R3'} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with 16 vertices and 96 facets 102 103 sage: T = SimplicialComplex(3) 104 sage: U = T.product(T,rename_vertices = False) 105 sage: G = Hom(T,U) 106 sage: e = G.diagonal_morphism(rename_vertices = False) 107 sage: e 108 Simplicial complex morphism {0: (0, 0), 1: (1, 1), 2: (2, 2), 3: (3, 3)} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {()} to Simplicial complex with 16 vertices and facets {()} 109 110 """ 111 112 if self._codomain == self._domain.product(self._domain,rename_vertices=rename_vertices): 113 X = self._domain.product(self._domain,rename_vertices=rename_vertices) 114 f = dict() 115 if rename_vertices: 116 for i in self._domain.vertices().set(): 117 f[i] = "L"+str(i)+"R"+str(i) 118 else: 119 for i in self._domain.vertices().set(): 120 f[i] = (i,i) 121 return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,X) 122 else: 123 raise TypeError, "Diagonal morphism is only defined for Hom(X,XxX)." 124 125 def identity(self): 126 """ 127 Returns the identity morphism of Hom(S,S). 128 129 EXAMPLES:: 130 131 sage: S = simplicial_complexes.Sphere(2) 132 sage: H = Hom(S,S) 133 sage: i = H.identity() 134 sage: i.is_identity() 135 True 136 137 sage: T = SimplicialComplex(3,[[0,1]]) 138 sage: G = Hom(T,T) 139 sage: G.identity() 140 Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1)} 141 142 """ 143 if self.is_endomorphism_set(): 144 f = dict() 145 for i in self._domain.vertices().set(): 146 f[i]=i 147 return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain) 148 else: 149 raise TypeError, "Identity map is only defined for endomorphism sets." 150 151 def an_element(self): 152 """ 153 Returns a (non-random) element of self. 154 155 EXAMPLES:: 156 157 sage: S = simplicial_complexes.KleinBottle() 158 sage: T = simplicial_complexes.Sphere(5) 159 sage: H = Hom(S,T) 160 sage: x = H.an_element() 161 sage: x 162 Simplicial complex morphism {0: 0, 1: 0, 2: 0, 'R3': 0, 'L4': 0, 'L5': 0, 'L3': 0, 'R5': 0, 'R4': 0} from Simplicial complex with 9 vertices and 18 facets to Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 7 facets 163 164 """ 165 X_vertices = self._domain.vertices().set() 166 try: 167 i = self._codomain.vertices().set().__iter__().next() 168 except StopIteration: 169 if len(X_vertices) == 0: 170 return dict() 171 else: 172 raise TypeError, "There are no morphisms from a non-empty simplicial complex to an empty simplicial comples." 173 f = dict() 174 for x in X_vertices: 175 f[x]=i 176 return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain) -
new file sage/homology/simplicial_complex_morphism.py
diff -r 44f70d431d43 -r e3035f8ac9b5 sage/homology/simplicial_complex_morphism.py
- + 1 r""" 2 Morphisms of simplicial complexes 3 4 AUTHORS: 5 6 - Benjamin Antieau <d.ben.antieau@gmail.com> (2009.06) 7 8 This module implements morphisms of simplicial complexes. The input is given 9 by a dictionary on the vertex set or the effective vertex set of a simplicial complex. 10 The initialization checks that faces are sent to faces. 11 12 There is also the capability to create the fiber product of two morphisms with the same codomain. 13 14 EXAMPLES:: 15 16 sage: S = SimplicialComplex(5,[[0,2],[1,5],[3,4]]) 17 sage: H = Hom(S,S.product(S)) 18 sage: H.diagonal_morphism() 19 Simplicial complex morphism {0: 'L0R0', 1: 'L1R1', 2: 'L2R2', 3: 'L3R3', 4: 'L4R4', 5: 'L5R5'} from Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (1, 5), (0, 2)} to Simplicial complex with 36 vertices and 18 facets 20 21 sage: S = SimplicialComplex(5,[[0,2],[1,5],[3,4]]) 22 sage: T = SimplicialComplex(4,[[0,2],[1,3]]) 23 sage: f = {0:0,1:1,2:2,3:1,4:3,5:3} 24 sage: H = Hom(S,T) 25 sage: x = H(f) 26 sage: x.image() 27 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (0, 2)} 28 sage: x.is_surjective() 29 False 30 sage: x.is_injective() 31 False 32 sage: x.is_identity() 33 False 34 35 sage: S = simplicial_complexes.Sphere(2) 36 sage: H = Hom(S,S) 37 sage: i = H.identity() 38 sage: i.image() 39 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 40 sage: i.is_surjective() 41 True 42 sage: i.is_injective() 43 True 44 sage: i.is_identity() 45 True 46 47 sage: S = simplicial_complexes.Sphere(2) 48 sage: H = Hom(S,S) 49 sage: i = H.identity() 50 sage: j = i.fiber_product(i) 51 sage: j 52 Simplicial complex morphism {'L1R1': 1, 'L3R3': 3, 'L2R2': 2, 'L0R0': 0} from Simplicial complex with 4 vertices and 4 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 53 54 sage: S = simplicial_complexes.Sphere(2) 55 sage: T = S.product(SimplicialComplex(1,[[0,1]]),rename_vertices = False) 56 sage: H = Hom(T,S) 57 sage: T 58 Simplicial complex with 8 vertices and 12 facets 59 sage: T.vertices() 60 ((0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)) 61 sage: f = {(0, 0): 0, (0, 1): 0, (1, 0): 1, (1, 1): 1, (2, 0): 2, (2, 1): 2, (3, 0): 3, (3, 1): 3} 62 sage: x = H(f) 63 sage: U = simplicial_complexes.Sphere(1) 64 sage: G = Hom(U,S) 65 sage: U 66 Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} 67 sage: g = {0:0,1:1,2:2} 68 sage: y = G(g) 69 sage: z = y.fiber_product(x) 70 sage: z # this is the mapping path space 71 Simplicial complex morphism {'L2R(2, 0)': 2, 'L2R(2, 1)': 2, 'L0R(0, 0)': 0, 'L0R(0, 1)': 0, 'L1R(1, 0)': 1, 'L1R(1, 1)': 1} from Simplicial complex with 6 vertices and 6 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 72 73 74 """ 75 76 #***************************************************************************** 77 # Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com> 78 # 79 # Distributed under the terms of the GNU General Public License (GPL) 80 # 81 # This code is distributed in the hope that it will be useful, 82 # but WITHOUT ANY WARRANTY; without even the implied warranty 83 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 84 # 85 # See the GNU General Public License for more details; the full text 86 # is available at: 87 # 88 # http://www.gnu.org/licenses/ 89 # 90 #***************************************************************************** 91 92 import sage.homology.simplicial_complex as simplicial_complex 93 import sage.matrix.all as matrix 94 from sage.structure.sage_object import SageObject 95 from sage.rings.integer_ring import ZZ 96 from sage.homology.chain_complex_morphism import ChainComplexMorphism 97 from sage.combinat.permutation import Permutation 98 from sage.algebras.steenrod_algebra_element import convert_perm 99 100 def is_SimplicialComplexMorphism(x): 101 """ 102 Returns True if and only if x is a morphism of simplicial complexes. 103 104 EXAMPLES:: 105 106 sage: from sage.homology.simplicial_complex_morphism import is_SimplicialComplexMorphism 107 sage: S = SimplicialComplex(5,[[0,1],[3,4]]) 108 sage: H = Hom(S,S) 109 sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} 110 sage: x = H(f) 111 sage: is_SimplicialComplexMorphism(x) 112 True 113 114 """ 115 return isinstance(x,SimplicialComplexMorphism) 116 117 class SimplicialComplexMorphism(SageObject): 118 """ 119 An element of this class is a morphism of simplicial complexes. 120 """ 121 def __init__(self,f,X,Y): 122 """ 123 Input is a dictionary f, the domain, and the codomain. 124 125 One can define the dictionary either on the vertices of X or on the effective vertices of X (X.effective_vertices()). Note that this 126 difference does matter. For instance, it changes the result of the image method, and hence it changes the result of the is_surjective method as well. 127 This is because two SimplicialComplexes with the same faces but different vertex sets are not equal. 128 129 EXAMPLES:: 130 131 sage: S = SimplicialComplex(5,[[0,1],[3,4]]) 132 sage: H = Hom(S,S) 133 sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} 134 sage: g = {0:0,1:1,3:3,4:4} 135 sage: x = H(f) 136 sage: y = H(g) 137 sage: x==y 138 False 139 sage: x.image() 140 Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (0, 1)} 141 sage: y.image() 142 Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)} 143 sage: x.image()==y.image() 144 False 145 146 """ 147 if not isinstance(X,simplicial_complex.SimplicialComplex) or not isinstance(Y,simplicial_complex.SimplicialComplex): 148 raise ValueError, "X and Y must be SimplicialComplexes." 149 if not set(f.keys())==X._vertex_set.set() and not set(f.keys())==X.effective_vertices().set(): 150 raise ValueError, "f must be a dictionary from the vertex set of X to single values in the vertex set of Y." 151 dim = X.dimension() 152 Y_faces = Y.faces() 153 for k in range(dim+1): 154 for i in X.faces()[k]: 155 tup = i.tuple() 156 fi = [] 157 for j in tup: 158 fi.append(f[j]) 159 v = simplicial_complex.Simplex(set(fi)) 160 if not v in Y_faces[v.dimension()]: 161 raise ValueError, "f must be a dictionary from the vertices of X to the vertices of Y." 162 self._vertex_dictionary = f 163 self._domain = X 164 self._codomain = Y 165 166 def __eq__(self,x): 167 """ 168 Returns True if and only if self == x. 169 170 EXAMPLES:: 171 172 sage: S = simplicial_complexes.Sphere(2) 173 sage: H = Hom(S,S) 174 sage: i = H.identity() 175 sage: i 176 Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 177 sage: f = {0:0,1:1,2:2,3:2} 178 sage: j = H(f) 179 sage: i==j 180 False 181 182 sage: T = SimplicialComplex(3,[[1,2]]) 183 sage: T 184 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2)} 185 sage: G = Hom(T,T) 186 sage: k = G.identity() 187 sage: g = {0:0,1:1,2:2,3:3} 188 sage: l = G(g) 189 sage: k==l 190 True 191 192 """ 193 if not isinstance(x,SimplicialComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._vertex_dictionary != x._vertex_dictionary: 194 return False 195 else: 196 return True 197 198 def __call__(self,x,orientation=False): 199 """ 200 Input is a simplex of the domain. Output is the image simplex. 201 202 If optional argument ``orientation`` is True, return a pair 203 ``(image simplex, oriented)`` where ``oriented`` is 1 or `-1` 204 depending on whether the map preserves or reverses the 205 orientation of the image simplex. 206 207 EXAMPLES:: 208 209 sage: S = simplicial_complexes.Sphere(2) 210 sage: T = simplicial_complexes.Sphere(3) 211 sage: S 212 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 213 sage: T 214 Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets 215 sage: f = {0:0,1:1,2:2,3:3} 216 sage: H = Hom(S,T) 217 sage: x = H(f) 218 sage: from sage.homology.simplicial_complex import Simplex 219 sage: x(Simplex([0,2,3])) 220 (0, 2, 3) 221 222 An orientation-reversing example:: 223 224 sage: X = SimplicialComplex(1, [[0,1]]) 225 sage: g = Hom(X,X)({0:1, 1:0}) 226 sage: g(Simplex([0,1])) 227 (0, 1) 228 sage: g(Simplex([0,1]), orientation=True) 229 ((0, 1), -1) """ 230 dim = self._domain.dimension() 231 if not isinstance(x,simplicial_complex.Simplex) or x.dimension() > dim or not x in self._domain.faces()[x.dimension()]: 232 raise ValueError, "x must be a simplex of the source of f" 233 tup=x.tuple() 234 fx=[] 235 for j in tup: 236 fx.append(self._vertex_dictionary[j]) 237 if orientation: 238 if len(set(fx)) == len(tup): 239 oriented = Permutation(convert_perm(fx)).signature() 240 else: 241 oriented = 1 242 return (simplicial_complex.Simplex(set(fx)), oriented) 243 else: 244 return simplicial_complex.Simplex(set(fx)) 245 246 def _repr_(self): 247 """ 248 Print representation 249 250 EXAMPLES:: 251 252 sage: S = simplicial_complexes.Sphere(2) 253 sage: H = Hom(S,S) 254 sage: i = H.identity() 255 sage: i 256 Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 257 sage: i._repr_() 258 'Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}' 259 260 261 """ 262 return "Simplicial complex morphism " + str(self._vertex_dictionary) + " from " + self._domain._repr_() + " to " + self._codomain._repr_() 263 264 def associated_chain_complex_morphism(self,base_ring=ZZ,augmented=False,cochain=False): 265 """ 266 Returns the associated chain complex morphism of self. 267 268 EXAMPLES:: 269 270 sage: S = simplicial_complexes.Sphere(1) 271 sage: T = simplicial_complexes.Sphere(2) 272 sage: H = Hom(S,T) 273 sage: f = {0:0,1:1,2:2} 274 sage: x = H(f) 275 sage: x 276 Simplicial complex morphism {0: 0, 1: 1, 2: 2} from Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} 277 sage: a = x.associated_chain_complex_morphism() 278 sage: a 279 Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 3 nonzero terms over Integer Ring 280 sage: a._matrix_dictionary 281 {0: [0 0 0] 282 [0 1 0] 283 [0 0 1] 284 [1 0 0], 285 1: [0 0 0] 286 [0 1 0] 287 [0 0 0] 288 [1 0 0] 289 [0 0 0] 290 [0 0 1], 291 2: []} 292 sage: x.associated_chain_complex_morphism(augmented=True) 293 Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring to Chain complex with at most 4 nonzero terms over Integer Ring 294 sage: x.associated_chain_complex_morphism(cochain=True) 295 Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring to Chain complex with at most 2 nonzero terms over Integer Ring 296 sage: x.associated_chain_complex_morphism(augmented=True,cochain=True) 297 Chain complex morphism from Chain complex with at most 4 nonzero terms over Integer Ring to Chain complex with at most 3 nonzero terms over Integer Ring 298 sage: x.associated_chain_complex_morphism(base_ring=GF(11)) 299 Chain complex morphism from Chain complex with at most 2 nonzero terms over Finite Field of size 11 to Chain complex with at most 3 nonzero terms over Finite Field of size 11 300 301 Some simplicial maps which reverse the orientation of a few simplices:: 302 303 sage: g = {0:1, 1:2, 2:0} 304 sage: H(g).associated_chain_complex_morphism()._matrix_dictionary 305 {0: [0 0 0] 306 [1 0 0] 307 [0 1 0] 308 [0 0 1], 1: [ 0 0 0] 309 [-1 0 0] 310 [ 0 0 0] 311 [ 0 0 1] 312 [ 0 0 0] 313 [ 0 -1 0], 2: []} 314 315 sage: X = SimplicialComplex(1, [[0, 1]]) 316 sage: Hom(X,X)({0:1, 1:0}).associated_chain_complex_morphism()._matrix_dictionary 317 {0: [0 1] 318 [1 0], 1: [-1]} 319 """ 320 max_dim = max(self._domain.dimension(),self._codomain.dimension()) 321 min_dim = min(self._domain.dimension(),self._codomain.dimension()) 322 matrices = {} 323 if augmented is True: 324 m = matrix.Matrix(base_ring,1,1,1) 325 if not cochain: 326 matrices[-1] = m 327 else: 328 matrices[-1] = m.transpose() 329 for dim in range(min_dim+1): 330 X_faces = list(self._domain.faces()[dim]) 331 Y_faces = list(self._codomain.faces()[dim]) 332 num_faces_X = len(X_faces) 333 num_faces_Y = len(Y_faces) 334 mval = [0 for i in range(num_faces_X*num_faces_Y)] 335 for i in X_faces: 336 y, oriented = self(i, orientation=True) 337 if y.dimension() < dim: 338 pass 339 else: 340 mval[X_faces.index(i)+(Y_faces.index(y)*num_faces_X)] = oriented 341 m = matrix.Matrix(base_ring,num_faces_Y,num_faces_X,mval,sparse=True) 342 if not cochain: 343 matrices[dim] = m 344 else: 345 matrices[dim] = m.transpose() 346 for dim in range(min_dim+1,max_dim+1): 347 try: 348 l1 = len(self._codomain.faces()[dim]) 349 except KeyError: 350 l1 = 0 351 try: 352 l2 = len(self._domain.faces()[dim]) 353 except KeyError: 354 l2 = 0 355 m = matrix.zero_matrix(base_ring,l1,l2,sparse=True) 356 if not cochain: 357 matrices[dim] = m 358 else: 359 matrices[dim] = m.transpose() 360 if not cochain: 361 return ChainComplexMorphism(matrices,\ 362 self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\ 363 self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain)) 364 else: 365 return ChainComplexMorphism(matrices,\ 366 self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\ 367 self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain)) 368 369 def image(self): 370 """ 371 Computes the image simplicial complex of f. 372 373 EXAMPLES:: 374 375 sage: S = SimplicialComplex(3,[[0,1],[2,3]]) 376 sage: T = SimplicialComplex(1,[[0,1]]) 377 sage: f = {0:0,1:1,2:0,3:1} 378 sage: H = Hom(S,T) 379 sage: x = H(f) 380 sage: x.image() 381 Simplicial complex with vertex set (0, 1) and facets {(0, 1)} 382 383 sage: S = SimplicialComplex(2) 384 sage: H = Hom(S,S) 385 sage: i = H.identity() 386 sage: i.image() 387 Simplicial complex with vertex set (0, 1, 2) and facets {()} 388 sage: i.is_surjective() 389 True 390 sage: S = SimplicialComplex(5,[[0,1]]) 391 sage: T = SimplicialComplex(3,[[0,1]]) 392 sage: f = {0:0,1:1} 393 sage: g = {0:0,1:1,2:2,3:3,4:4,5:5} 394 sage: H = Hom(S,T) 395 sage: x = H(f) 396 sage: y = H(g) 397 sage: x == y 398 False 399 sage: x.image() 400 Simplicial complex with vertex set (0, 1) and facets {(0, 1)} 401 sage: y.image() 402 Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 1)} 403 404 """ 405 fa = [self(i) for i in self._domain.facets()] 406 return simplicial_complex.SimplicialComplex(set(self._vertex_dictionary.values()),fa,maximality_check=True) 407 408 def domain(self): 409 """ 410 Returns the domain of the morphism. 411 412 EXAMPLES:: 413 414 sage: S = SimplicialComplex(3,[[0,1],[2,3]]) 415 sage: T = SimplicialComplex(1,[[0,1]]) 416 sage: f = {0:0,1:1,2:0,3:1} 417 sage: H = Hom(S,T) 418 sage: x = H(f) 419 sage: x.domain() 420 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(2, 3), (0, 1)} 421 422 """ 423 return self._domain 424 425 def codomain(self): 426 """ 427 Returns the codomain of the morphism. 428 429 EXAMPLES:: 430 431 sage: S = SimplicialComplex(3,[[0,1],[2,3]]) 432 sage: T = SimplicialComplex(1,[[0,1]]) 433 sage: f = {0:0,1:1,2:0,3:1} 434 sage: H = Hom(S,T) 435 sage: x = H(f) 436 sage: x.codomain() 437 Simplicial complex with vertex set (0, 1) and facets {(0, 1)} 438 439 """ 440 return self._codomain 441 442 def is_surjective(self): 443 """ 444 Returns True if and only if self is surjective. 445 446 EXAMPLES:: 447 448 sage: S = SimplicialComplex(3,[(0,1,2)]) 449 sage: S 450 Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2)} 451 sage: T = SimplicialComplex(2,[(0,1)]) 452 sage: T 453 Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1)} 454 sage: H = Hom(S,T) 455 sage: x = H({0:0,1:1,2:1,3:2}) 456 sage: x.is_surjective() 457 True 458 459 sage: S = SimplicialComplex(3,[[0,1],[2,3]]) 460 sage: T = SimplicialComplex(1,[[0,1]]) 461 sage: f = {0:0,1:1,2:0,3:1} 462 sage: H = Hom(S,T) 463 sage: x = H(f) 464 sage: x.is_surjective() 465 True 466 467 """ 468 return self._codomain == self.image() 469 470 def is_injective(self): 471 """ 472 Returns True if and only if self is injective. 473 474 EXAMPLES:: 475 476 sage: S = simplicial_complexes.Sphere(1) 477 sage: T = simplicial_complexes.Sphere(2) 478 sage: U = simplicial_complexes.Sphere(3) 479 sage: H = Hom(T,S) 480 sage: G = Hom(T,U) 481 sage: f = {0:0,1:1,2:0,3:1} 482 sage: x = H(f) 483 sage: g = {0:0,1:1,2:2,3:3} 484 sage: y = G(g) 485 sage: x.is_injective() 486 False 487 sage: y.is_injective() 488 True 489 490 """ 491 v = [self._vertex_dictionary[i[0]] for i in self._domain.faces()[0]] 492 for i in v: 493 if v.count(i) > 1: 494 return False 495 return True 496 497 def is_identity(self): 498 """ 499 If x is an identity morphism, returns True. Otherwise, False. 500 501 EXAMPLES:: 502 503 sage: T = simplicial_complexes.Sphere(1) 504 sage: G = Hom(T,T) 505 sage: T 506 Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} 507 sage: j = G({0:0,1:1,2:2}) 508 sage: j.is_identity() 509 True 510 511 sage: S = simplicial_complexes.Sphere(2) 512 sage: T = simplicial_complexes.Sphere(3) 513 sage: H = Hom(S,T) 514 sage: f = {0:0,1:1,2:2,3:3} 515 sage: x = H(f) 516 sage: x 517 Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets 518 sage: x.is_identity() 519 False 520 521 """ 522 if self._domain != self._codomain: 523 return False 524 else: 525 f = dict() 526 for i in self._domain.vertices().set(): 527 f[i] = i 528 if self._vertex_dictionary != f: 529 return False 530 else: 531 return True 532 533 def fiber_product(self,other,rename_vertices = True): 534 """ 535 Fiber product of self and other. Both morphisms should have the same codomain. The method returns a morphism of simplicial complexes, which 536 is the morphism from the space of the fiber product to the codomain. 537 538 EXAMPLES:: 539 540 sage: S = SimplicialComplex(2,[[0,1],[1,2]]) 541 sage: T = SimplicialComplex(2,[[0,2]]) 542 sage: U = SimplicialComplex(1,[[0,1]]) 543 sage: H = Hom(S,U) 544 sage: G = Hom(T,U) 545 sage: f = {0:0,1:1,2:0} 546 sage: g = {0:0,1:1,2:1} 547 sage: x = H(f) 548 sage: y = G(g) 549 sage: z = x.fiber_product(y) 550 sage: z 551 Simplicial complex morphism {'L1R2': 1, 'L2R0': 0, 'L0R0': 0} from Simplicial complex with vertex set ('L0R0', 'L1R2', 'L2R0') and facets {('L2R0',), ('L0R0', 'L1R2')} to Simplicial complex with vertex set (0, 1) and facets {(0, 1)} 552 553 """ 554 if self._codomain != other._codomain: 555 raise ValueError, "self and other must have the same codomain." 556 X = self._domain.product(other._domain,rename_vertices = rename_vertices) 557 v = [] 558 f = dict() 559 eff1 = self._domain.effective_vertices() 560 eff2 = other._domain.effective_vertices() 561 for i in eff1: 562 for j in eff2: 563 if self(simplicial_complex.Simplex([i])) == other(simplicial_complex.Simplex([j])): 564 if rename_vertices: 565 v.append("L"+str(i)+"R"+str(j)) 566 f["L"+str(i)+"R"+str(j)] = self._vertex_dictionary[i] 567 else: 568 v.append((i,j)) 569 f[(i,j)] = self._vertex_dictionary[i] 570 return SimplicialComplexMorphism(f,X.generated_subcomplex(v),self._codomain)