diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index bcc7150186d..34c79da3006 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -347,10 +347,10 @@ def _universal_cover_dict(self): TESTS:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) - sage: RP2._universal_cover_dict() + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups + sage: RP2._universal_cover_dict() # optional - sage.groups (Finitely presented group < e | e^2 >, {f: e}) - sage: RP2.nondegenerate_simplices() + sage: RP2.nondegenerate_simplices() # optional - sage.groups [1, f, f * f] """ from sage.groups.free_group import FreeGroup @@ -393,14 +393,14 @@ def universal_cover_map(self): EXAMPLES:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) - sage: phi = RP2.universal_cover_map() - sage: phi + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups + sage: phi = RP2.universal_cover_map(); phi # optional - sage.groups Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices To: RP^2 - Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] --> [1, 1, f, f, f * f, f * f] - sage: phi.domain().face_data() + Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] + --> [1, 1, f, f, f * f, f * f] + sage: phi.domain().face_data() # optional - sage.groups {(1, 1): None, (1, e): None, (f, 1): ((1, e), (1, 1)), @@ -432,18 +432,20 @@ def covering_map(self, character): EXAMPLES:: sage: S1 = simplicial_sets.Sphere(1) - sage: W = S1.wedge(S1) - sage: G = CyclicPermutationGroup(3) - sage: a, b = W.n_cells(1) - sage: C = W.covering_map({a : G.gen(0), b : G.one()}) - sage: C + sage: W = S1.wedge(S1) # optional - sage.graphs + sage: G = CyclicPermutationGroup(3) # optional - sage.groups + sage: a, b = W.n_cells(1) # optional - sage.graphs + sage: C = W.covering_map({a : G.gen(0), b : G.one()}); C # optional - sage.graphs sage.groups Simplicial set morphism: From: Simplicial set with 9 non-degenerate simplices To: Wedge: (S^1 v S^1) - Defn: [(*, ()), (*, (1,2,3)), (*, (1,3,2)), (sigma_1, ()), (sigma_1, ()), (sigma_1, (1,2,3)), (sigma_1, (1,2,3)), (sigma_1, (1,3,2)), (sigma_1, (1,3,2))] --> [*, *, *, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1] - sage: C.domain() + Defn: [(*, ()), (*, (1,2,3)), (*, (1,3,2)), (sigma_1, ()), + (sigma_1, ()), (sigma_1, (1,2,3)), (sigma_1, (1,2,3)), + (sigma_1, (1,3,2)), (sigma_1, (1,3,2))] + --> [*, *, *, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1] + sage: C.domain() # optional - sage.graphs sage.groups Simplicial set with 9 non-degenerate simplices - sage: C.domain().face_data() + sage: C.domain().face_data() # optional - sage.graphs sage.groups {(*, ()): None, (*, (1,2,3)): None, (*, (1,3,2)): None, @@ -517,11 +519,11 @@ def cover(self, character): EXAMPLES:: sage: S1 = simplicial_sets.Sphere(1) - sage: W = S1.wedge(S1) - sage: G = CyclicPermutationGroup(3) - sage: (a, b) = W.n_cells(1) - sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2}) - sage: C.face_data() + sage: W = S1.wedge(S1) # optional - sage.graphs + sage: G = CyclicPermutationGroup(3) # optional - sage.groups + sage: (a, b) = W.n_cells(1) # optional - sage.graphs + sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2}) # optional - sage.graphs sage.groups + sage: C.face_data() # optional - sage.graphs sage.groups {(*, ()): None, (*, (1,2,3)): None, (*, (1,3,2)): None, @@ -531,9 +533,9 @@ def cover(self, character): (sigma_1, (1,2,3)): ((*, ()), (*, (1,2,3))), (sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))), (sigma_1, (1,3,2)): ((*, (1,2,3)), (*, (1,3,2)))} - sage: C.homology(1) + sage: C.homology(1) # optional - sage.graphs sage.groups sage.modules Z x Z x Z x Z - sage: C.fundamental_group() + sage: C.fundamental_group() # optional - sage.graphs sage.groups Finitely presented group < e0, e1, e2, e3 | > """ return self.covering_map(character).domain() @@ -546,11 +548,10 @@ def universal_cover(self): EXAMPLES:: - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) - sage: C = RP3.universal_cover() - sage: C + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.groups + sage: C = RP3.universal_cover(); C # optional - sage.groups Simplicial set with 8 non-degenerate simplices - sage: C.face_data() + sage: C.face_data() # optional - sage.groups {(1, 1): None, (1, e): None, (f, 1): ((1, e), (1, 1)), diff --git a/src/sage/features/standard.py b/src/sage/features/standard.py index f48f47f2614..54d1f804cef 100644 --- a/src/sage/features/standard.py +++ b/src/sage/features/standard.py @@ -30,6 +30,7 @@ def all_features(): JoinFeature('pplpy', (PythonModule('ppl'),), spkg='pplpy'), PythonModule('primecountpy', spkg='primecountpy'), PythonModule('ptyprocess', spkg='ptyprocess'), + PythonModule('pyparsing', spkg='pyparsing'), PythonModule('requests', spkg='requests'), PythonModule('scipy', spkg='scipy'), PythonModule('sympy', spkg='sympy')] diff --git a/src/sage/homology/algebraic_topological_model.py b/src/sage/homology/algebraic_topological_model.py index f89a1529dd9..aa539d90126 100644 --- a/src/sage/homology/algebraic_topological_model.py +++ b/src/sage/homology/algebraic_topological_model.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.graphs r""" Algebraic topological model for a cell complex @@ -100,8 +100,8 @@ def algebraic_topological_model(K, base_ring=None): sage: from sage.homology.algebraic_topological_model import algebraic_topological_model sage: RP2 = simplicial_complexes.RealProjectivePlane() - sage: phi, M = algebraic_topological_model(RP2, GF(2)) - sage: M.homology() + sage: phi, M = algebraic_topological_model(RP2, GF(2)) # optional - sage.rings.finite_rings + sage: M.homology() # optional - sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} @@ -123,7 +123,8 @@ def algebraic_topological_model(K, base_ring=None): 1 sage: phi.dual() Chain homotopy between: - Chain complex endomorphism of Chain complex with at most 3 nonzero terms over Rational Field + Chain complex endomorphism of + Chain complex with at most 3 nonzero terms over Rational Field and Chain complex morphism: From: Chain complex with at most 3 nonzero terms over Rational Field To: Chain complex with at most 3 nonzero terms over Rational Field @@ -369,8 +370,8 @@ def algebraic_topological_model_delta_complex(K, base_ring=None): sage: from sage.homology.algebraic_topological_model import algebraic_topological_model_delta_complex as AT_model sage: RP2 = simplicial_complexes.RealProjectivePlane() - sage: phi, M = AT_model(RP2, GF(2)) - sage: M.homology() + sage: phi, M = AT_model(RP2, GF(2)) # optional - sage.rings.finite_rings + sage: M.homology() # optional - sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index 08e9158e590..6b318dce6ee 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -62,7 +62,6 @@ from sage.matrix.constructor import matrix from sage.misc.latex import latex from sage.misc.superseded import deprecation -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.fast_arith import prime_range from sage.homology.homology_group import HomologyGroup @@ -85,7 +84,7 @@ def _latex_module(R, m): '\\Bold{Z}^{3}' sage: _latex_module(ZZ, 0) '0' - sage: _latex_module(GF(3), 1) + sage: _latex_module(GF(3), 1) # optional - sage.rings.finite_rings '\\Bold{F}_{3}^{1}' """ if m == 0: @@ -188,11 +187,11 @@ def ChainComplex(data=None, base_ring=None, grading_group=None, Chain complex with at most 2 nonzero terms over Integer Ring sage: m = matrix(ZZ, 2, 2, [0, 1, 0, 0]) - sage: D = ChainComplex([m, m], base_ring=GF(2)); D + sage: D = ChainComplex([m, m], base_ring=GF(2)); D # optional - sage.rings.finite_rings Chain complex with at most 3 nonzero terms over Finite Field of size 2 - sage: D == loads(dumps(D)) + sage: D == loads(dumps(D)) # optional - sage.rings.finite_rings True - sage: D.differential(0)==m, m.is_immutable(), D.differential(0).is_immutable() + sage: D.differential(0)==m, m.is_immutable(), D.differential(0).is_immutable() # optional - sage.rings.finite_rings (True, False, True) Note that when a chain complex is defined in Sage, new @@ -214,20 +213,21 @@ def ChainComplex(data=None, base_ring=None, grading_group=None, sage: ChainComplex([matrix(QQ, 3, 1), matrix(ZZ, 4, 3)]) Chain complex with at most 3 nonzero terms over Rational Field - sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(ZZ, 4, 3)]) + sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(ZZ, 4, 3)]) # optional - sage.rings.finite_rings Chain complex with at most 3 nonzero terms over Finite Field in a of size 5^3 If the matrices are defined over incompatible rings, an error results:: - sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(QQ, 4, 3)]) + sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(QQ, 4, 3)]) # optional - sage.rings.finite_rings Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Finite Field in a of size 5^3' and 'Rational Field' + TypeError: no common canonical parent for objects with parents: + 'Finite Field in a of size 5^3' and 'Rational Field' If the base ring is given explicitly but is not compatible with the matrices, an error results:: - sage: ChainComplex([matrix(GF(125, 'a'), 3, 1)], base_ring=QQ) + sage: ChainComplex([matrix(GF(125, 'a'), 3, 1)], base_ring=QQ) # optional - sage.rings.finite_rings Traceback (most recent call last): ... TypeError: unable to convert 0 to a rational @@ -335,14 +335,15 @@ def __init__(self, parent, vectors, check=True): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=GF(7)) - sage: C.category() + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, # optional - sage.rings.finite_rings + ....: base_ring=GF(7)) + sage: C.category() # optional - sage.rings.finite_rings Category of chain complexes over Finite Field of size 7 TESTS:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: TestSuite(c).run() """ # only nonzero vectors shall be stored, ensuring this is the @@ -360,7 +361,7 @@ def vector(self, degree): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([1, 2, 3]), 1:vector([4, 5])}) + sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])}) sage: c.vector(0) (1, 2, 3) sage: c.vector(1) @@ -382,9 +383,9 @@ def _repr_(self): sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) sage: C() Trivial chain - sage: C({0:vector([1, 2, 3])}) + sage: C({0: vector([1, 2, 3])}) Chain(0:(1, 2, 3)) - sage: c = C({0:vector([1, 2, 3]), 1:vector([4, 5])}); c + sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])}); c Chain with 2 nonzero terms over Integer Ring sage: c._repr_() 'Chain with 2 nonzero terms over Integer Ring' @@ -409,8 +410,9 @@ def _ascii_art_(self): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1:zero_matrix(1,2)}) - sage: c = C({0:vector([1, 2, 3]), 1:vector([4, 5])}) + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), + ....: 1: zero_matrix(1,2)}) + sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])}) sage: ascii_art(c) d_2 d_1 d_0 [1] d_-1 0 <---- [0] <---- [4] <---- [2] <----- 0 @@ -455,8 +457,9 @@ def _unicode_art_(self): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1:zero_matrix(1,2)}) - sage: c = C({0:vector([1, 2, 3]), 1:vector([4, 5])}) + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), + ....: 1: zero_matrix(1,2)}) + sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])}) sage: unicode_art(c) ⎛1⎞ d_2 d_1 ⎛4⎞ d_0 ⎜2⎟ d_-1 @@ -505,7 +508,7 @@ def is_cycle(self): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: c.is_cycle() True """ @@ -528,7 +531,7 @@ def is_boundary(self): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: c.is_boundary() False sage: z3 = C({1:(1, 0)}) @@ -553,7 +556,7 @@ def _add_(self, other): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: c + c Chain with 2 nonzero terms over Integer Ring sage: ascii_art(c + c) @@ -577,7 +580,7 @@ def _lmul_(self, scalar): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: 2 * c Chain with 2 nonzero terms over Integer Ring sage: 2 * c == c + c == c * 2 @@ -599,7 +602,7 @@ def __eq__(self, other): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: c == c True sage: c == C(0) @@ -616,7 +619,7 @@ def __ne__(self, other): EXAMPLES:: sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) - sage: c = C({0:vector([0, 1, 2]), 1:vector([3, 4])}) + sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])}) sage: c != c False sage: c != C(0) @@ -767,7 +770,7 @@ def rank(self, degree, ring=None): [2] sage: C.rank(0) 1 - sage: C.rank(0, ring=GF(2)) + sage: C.rank(0, ring=GF(2)) # optional - sage.rings.finite_rings 0 """ degree = self.grading_group()(degree) @@ -1075,9 +1078,12 @@ def __eq__(self, other): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=GF(2)) - sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]), 1: matrix(ZZ, 0, 2), 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices - sage: C == D + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, # optional - sage.rings.finite_rings + ....: base_ring=GF(2)) + sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]), # optional - sage.rings.finite_rings + ....: 1: matrix(ZZ, 0, 2), + ....: 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices + sage: C == D # optional - sage.rings.finite_rings True """ if not isinstance(other, ChainComplex_class) or self.base_ring() != other.base_ring(): @@ -1101,12 +1107,16 @@ def __ne__(self, other): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=GF(2)) - sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]), 1: matrix(ZZ, 0, 2), 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices - sage: C != D + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, # optional - sage.rings.finite_rings + ....: base_ring=GF(2)) + sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]), # optional - sage.rings.finite_rings + ....: 1: matrix(ZZ, 0, 2), + ....: 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices + sage: C != D # optional - sage.rings.finite_rings False - sage: E = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=ZZ) - sage: C != E + sage: E = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, + ....: base_ring=ZZ) + sage: C != E # optional - sage.rings.finite_rings True """ return not self == other @@ -1132,15 +1142,15 @@ def _homology_chomp(self, deg, base_ring, verbose, generators): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=GF(2)) - sage: C._homology_chomp(None, GF(2), False, False) # optional - CHomP + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}, base_ring=GF(2)) # optional - sage.rings.finite_rings + sage: C._homology_chomp(None, GF(2), False, False) # optional - CHomP # optional - sage.rings.finite_rings doctest:...: DeprecationWarning: the CHomP interface is deprecated; hence so is this function See https://github.com/sagemath/sage/issues/33777 for details. {0: Vector space of dimension 2 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2} sage: D = ChainComplex({0: matrix(ZZ,1,0,[]), 1: matrix(ZZ,1,1,[0]), ....: 2: matrix(ZZ,0,1,[])}) - sage: D._homology_chomp(None, GF(2), False, False) # optional - CHomP + sage: D._homology_chomp(None, GF(2), False, False) # optional - CHomP # optional - sage.rings.finite_rings {1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} """ @@ -1242,7 +1252,7 @@ def homology(self, deg=None, base_ring=None, generators=False, sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) sage: C.homology() {0: Z x Z, 1: Z x C3} - sage: C.homology(deg=1, base_ring = GF(3)) + sage: C.homology(deg=1, base_ring=GF(3)) # optional - sage.rings.finite_rings Vector space of dimension 2 over Finite Field of size 3 sage: D = ChainComplex({0: identity_matrix(ZZ, 4), 4: identity_matrix(ZZ, 30)}) sage: D.homology() @@ -1269,9 +1279,9 @@ def homology(self, deg=None, base_ring=None, generators=False, From a torus using a field:: - sage: T = simplicial_complexes.Torus() - sage: C_t = T.chain_complex() - sage: C_t.homology(base_ring=QQ, generators=True) + sage: T = simplicial_complexes.Torus() # optional - sage.graphs + sage: C_t = T.chain_complex() # optional - sage.graphs + sage: C_t.homology(base_ring=QQ, generators=True) # optional - sage.graphs {0: [(Vector space of dimension 1 over Rational Field, Chain(0:(0, 0, 0, 0, 0, 0, 1)))], 1: [(Vector space of dimension 1 over Rational Field, @@ -1450,8 +1460,8 @@ def betti(self, deg=None, base_ring=None): sage: C.betti() {0: 2, 1: 1} - sage: D = ChainComplex({0:matrix(GF(5), [[3, 1],[1, 2]])}) - sage: D.betti() + sage: D = ChainComplex({0: matrix(GF(5), [[3, 1],[1, 2]])}) # optional - sage.rings.finite_rings + sage: D.betti() # optional - sage.rings.finite_rings {0: 1, 1: 1} """ if base_ring is None: @@ -1489,7 +1499,7 @@ def torsion_list(self, max_prime, min_prime=2): ALGORITHM: - let `C` denote the chain complex. Let `P` equal + Let `C` denote the chain complex. Let `P` equal ``max_prime``. Compute the mod `P` homology of `C`, and use this as the base-line computation: the assumption is that this is isomorphic to the integral homology tensored with @@ -1502,18 +1512,21 @@ def torsion_list(self, max_prime, min_prime=2): sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) sage: C.homology() {0: Z x Z, 1: Z x C3} - sage: C.torsion_list(11) + sage: C.torsion_list(11) # optional - sage.rings.finite_rings [(3, [1])] sage: C = ChainComplex([matrix(ZZ, 1, 1, [2]), matrix(ZZ, 1, 1), matrix(1, 1, [3])]) sage: C.homology(1) C2 sage: C.homology(3) C3 - sage: C.torsion_list(5) + sage: C.torsion_list(5) # optional - sage.rings.finite_rings [(2, [1]), (3, [3])] """ if self.base_ring() != ZZ: raise NotImplementedError('only implemented for base ring the integers') + + from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF + answer = [] torsion_free = self.betti(base_ring=GF(max_prime)) for p in prime_range(min_prime, max_prime): @@ -1549,11 +1562,11 @@ def _Hom_(self, other, category=None): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: T = simplicial_complexes.Torus() - sage: C = S.chain_complex(augmented=True,cochain=True) - sage: D = T.chain_complex(augmented=True,cochain=True) - sage: Hom(C,D) # indirect doctest + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: T = simplicial_complexes.Torus() # optional - sage.graphs + sage: C = S.chain_complex(augmented=True, cochain=True) # optional - sage.graphs + sage: D = T.chain_complex(augmented=True, cochain=True) # optional - sage.graphs + sage: Hom(C, D) # indirect doctest # optional - sage.graphs 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 @@ -1615,25 +1628,25 @@ def shift(self, n=1): EXAMPLES:: - sage: S1 = simplicial_complexes.Sphere(1).chain_complex() - sage: S1.shift(1).differential(2) == -S1.differential(1) + sage: S1 = simplicial_complexes.Sphere(1).chain_complex() # optional - sage.graphs + sage: S1.shift(1).differential(2) == -S1.differential(1) # optional - sage.graphs True - sage: S1.shift(2).differential(3) == S1.differential(1) + sage: S1.shift(2).differential(3) == S1.differential(1) # optional - sage.graphs True - sage: S1.shift(3).homology(4) + sage: S1.shift(3).homology(4) # optional - sage.graphs Z For cochain complexes, shifting goes in the other direction. Topologically, this makes sense if we grade the cochain complex for a space negatively:: - sage: T = simplicial_complexes.Torus() - sage: co_T = T.chain_complex()._flip_() - sage: co_T.homology() + sage: T = simplicial_complexes.Torus() # optional - sage.graphs + sage: co_T = T.chain_complex()._flip_() # optional - sage.graphs + sage: co_T.homology() # optional - sage.graphs {-2: Z, -1: Z x Z, 0: Z} - sage: co_T.degree_of_differential() + sage: co_T.degree_of_differential() # optional - sage.graphs 1 - sage: co_T.shift(2).homology() + sage: co_T.shift(2).homology() # optional - sage.graphs {-4: Z, -3: Z x Z, -2: Z} You can achieve the same result by tensoring (on the left, to @@ -1641,7 +1654,7 @@ def shift(self, n=1): ``-n * deg``, if ``deg`` is the degree of the differential:: sage: C = ChainComplex({-2: matrix(ZZ, 0, 1)}) - sage: C.tensor(co_T).homology() + sage: C.tensor(co_T).homology() # optional - sage.graphs {-4: Z, -3: Z x Z, -2: Z} """ deg = self.degree_of_differential() diff --git a/src/sage/homology/chain_complex_homspace.py b/src/sage/homology/chain_complex_homspace.py index 5679b275a82..0d2d82a8bba 100644 --- a/src/sage/homology/chain_complex_homspace.py +++ b/src/sage/homology/chain_complex_homspace.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.graphs (because all doctests use SimplicialComplex) r""" Homspaces between chain complexes @@ -12,70 +13,73 @@ sage: S = simplicial_complexes.Sphere(2) sage: T = simplicial_complexes.Torus() - sage: C = S.chain_complex(augmented=True,cochain=True) - sage: D = T.chain_complex(augmented=True,cochain=True) - sage: G = Hom(C,D) - sage: G - 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 - - sage: S = simplicial_complexes.ChessboardComplex(3,3) + sage: C = S.chain_complex(augmented=True, cochain=True) + sage: D = T.chain_complex(augmented=True, cochain=True) + sage: G = Hom(C, D); G + 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 + + sage: S = simplicial_complexes.ChessboardComplex(3, 3) sage: H = Hom(S,S) sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism(augmented=True) - sage: x + sage: x = i.associated_chain_complex_morphism(augmented=True); x 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 + To: Chain complex with at most 4 nonzero terms over Integer Ring sage: x._matrix_dictionary - {-1: [1], 0: [1 0 0 0 0 0 0 0 0] - [0 1 0 0 0 0 0 0 0] - [0 0 1 0 0 0 0 0 0] - [0 0 0 1 0 0 0 0 0] - [0 0 0 0 1 0 0 0 0] - [0 0 0 0 0 1 0 0 0] - [0 0 0 0 0 0 1 0 0] - [0 0 0 0 0 0 0 1 0] - [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] - [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] - [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] - [0 1 0 0 0 0] - [0 0 1 0 0 0] - [0 0 0 1 0 0] - [0 0 0 0 1 0] - [0 0 0 0 0 1]} + {-1: [1], + 0: [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 1 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 1 0 0] + [0 0 0 0 0 0 0 1 0] + [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] + [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] + [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] + [0 1 0 0 0 0] + [0 0 1 0 0 0] + [0 0 0 1 0 0] + [0 0 0 0 1 0] + [0 0 0 0 0 1]} sage: S = simplicial_complexes.Sphere(2) - sage: A = Hom(S,S) + sage: A = Hom(S, S) sage: i = A.identity() - sage: x = i.associated_chain_complex_morphism() - sage: x + sage: x = i.associated_chain_complex_morphism(); x 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 sage: y = x*4 sage: z = y*y - sage: (y+z) + sage: y + z 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 sage: f = x._matrix_dictionary sage: C = S.chain_complex() - sage: G = Hom(C,C) + sage: G = Hom(C, C) sage: w = G(f) sage: w == x True @@ -111,7 +115,7 @@ def is_ChainComplexHomspace(x): sage: from sage.homology.chain_complex_homspace import is_ChainComplexHomspace sage: T = SimplicialComplex([[1,2,3,4],[7,8,9]]) sage: C = T.chain_complex(augmented=True, cochain=True) - sage: G = Hom(C,C) + sage: G = Hom(C, C) sage: is_ChainComplexHomspace(G) True @@ -127,9 +131,12 @@ class ChainComplexHomspace(sage.categories.homset.Homset): sage: T = SimplicialComplex([[1,2,3,4],[7,8,9]]) sage: C = T.chain_complex(augmented=True, cochain=True) - sage: G = Hom(C,C) + sage: G = Hom(C, C) sage: G - 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 + 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 """ def __call__(self, f): @@ -139,10 +146,10 @@ def __call__(self, f): EXAMPLES:: sage: S = simplicial_complexes.Sphere(5) - sage: H = Hom(S,S) + sage: H = Hom(S, S) sage: i = H.identity() sage: C = S.chain_complex() - sage: G = Hom(C,C) + sage: G = Hom(C, C) sage: x = i.associated_chain_complex_morphism() sage: f = x._matrix_dictionary sage: y = G(f) diff --git a/src/sage/homology/chain_complex_morphism.py b/src/sage/homology/chain_complex_morphism.py index b049b534e0b..085530fea9d 100644 --- a/src/sage/homology/chain_complex_morphism.py +++ b/src/sage/homology/chain_complex_morphism.py @@ -14,25 +14,25 @@ EXAMPLES:: - sage: S = simplicial_complexes.Sphere(1) - sage: S + sage: S = simplicial_complexes.Sphere(1); S # optional - sage.graphs Minimal triangulation of the 1-sphere - sage: C = S.chain_complex() - sage: C.differential() + sage: C = S.chain_complex() # optional - sage.graphs + sage: C.differential() # optional - sage.graphs {0: [], 1: [-1 -1 0] [ 1 0 -1] [ 0 1 1], 2: []} - sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)} - sage: G = Hom(C,C) - sage: x = G(f) - sage: x - Chain complex endomorphism of Chain complex with at most 2 nonzero terms over Integer Ring - sage: x._matrix_dictionary + sage: f = {0: zero_matrix(ZZ,3,3), 1: zero_matrix(ZZ,3,3)} + sage: G = Hom(C, C) # optional - sage.graphs + sage: x = G(f); x # optional - sage.graphs + Chain complex endomorphism of + Chain complex with at most 2 nonzero terms over Integer Ring + sage: x._matrix_dictionary # optional - sage.graphs {0: [0 0 0] - [0 0 0] - [0 0 0], 1: [0 0 0] - [0 0 0] - [0 0 0]} + [0 0 0] + [0 0 0], + 1: [0 0 0] + [0 0 0] + [0 0 0]} """ #***************************************************************************** @@ -64,18 +64,18 @@ def is_ChainComplexMorphism(x): EXAMPLES:: sage: from sage.homology.chain_complex_morphism import is_ChainComplexMorphism - sage: S = simplicial_complexes.Sphere(14) - sage: H = Hom(S,S) - sage: i = H.identity() # long time (8s on sage.math, 2011) - sage: S = simplicial_complexes.Sphere(6) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: x # indirect doctest + sage: S = simplicial_complexes.Sphere(14) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # long time (8s on sage.math, 2011) # optional - sage.graphs + sage: S = simplicial_complexes.Sphere(6) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: x # indirect doctest # optional - sage.graphs 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 - sage: is_ChainComplexMorphism(x) + sage: is_ChainComplexMorphism(x) # optional - sage.graphs True """ return isinstance(x, ChainComplexMorphism) @@ -91,32 +91,34 @@ def __init__(self, matrices, C, D, check=True): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(1) - sage: S + sage: S = simplicial_complexes.Sphere(1); S # optional - sage.graphs Minimal triangulation of the 1-sphere - sage: C = S.chain_complex() - sage: C.differential() - {0: [], 1: [-1 -1 0] - [ 1 0 -1] - [ 0 1 1], 2: []} + sage: C = S.chain_complex() # optional - sage.graphs + sage: C.differential() # optional - sage.graphs + {0: [], + 1: [-1 -1 0] + [ 1 0 -1] + [ 0 1 1], + 2: []} sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)} - sage: G = Hom(C,C) - sage: x = G(f) - sage: x - Chain complex endomorphism of Chain complex with at most 2 nonzero terms over Integer Ring - sage: x._matrix_dictionary + sage: G = Hom(C,C) # optional - sage.graphs + sage: x = G(f); x # optional - sage.graphs + Chain complex endomorphism of + Chain complex with at most 2 nonzero terms over Integer Ring + sage: x._matrix_dictionary # optional - sage.graphs {0: [0 0 0] - [0 0 0] - [0 0 0], 1: [0 0 0] - [0 0 0] - [0 0 0]} + [0 0 0] + [0 0 0], + 1: [0 0 0] + [0 0 0] + [0 0 0]} Check that the bug in :trac:`13220` has been fixed:: - sage: X = simplicial_complexes.Simplex(1) - sage: Y = simplicial_complexes.Simplex(0) - sage: g = Hom(X,Y)({0:0, 1:0}) - sage: g.associated_chain_complex_morphism() + sage: X = simplicial_complexes.Simplex(1) # optional - sage.graphs + sage: Y = simplicial_complexes.Simplex(0) # optional - sage.graphs + sage: g = Hom(X,Y)({0: 0, 1: 0}) # optional - sage.graphs + sage: g.associated_chain_complex_morphism() # optional - sage.graphs Chain complex morphism: From: Chain complex with at most 2 nonzero terms over Integer Ring To: Chain complex with at most 1 nonzero terms over Integer Ring @@ -189,7 +191,7 @@ def __init__(self, matrices, C, D, check=True): def in_degree(self, n): """ - The matrix representing this morphism in degree n + The matrix representing this morphism in degree `n`. INPUT: @@ -264,24 +266,24 @@ def dual(self): EXAMPLES:: - sage: X = simplicial_complexes.Simplex(1) - sage: Y = simplicial_complexes.Simplex(0) - sage: g = Hom(X,Y)({0:0, 1:0}) - sage: f = g.associated_chain_complex_morphism() - sage: f.in_degree(0) + sage: X = simplicial_complexes.Simplex(1) # optional - sage.graphs + sage: Y = simplicial_complexes.Simplex(0) # optional - sage.graphs + sage: g = Hom(X,Y)({0:0, 1:0}) # optional - sage.graphs + sage: f = g.associated_chain_complex_morphism() # optional - sage.graphs + sage: f.in_degree(0) # optional - sage.graphs [1 1] - sage: f.dual() + sage: f.dual() # optional - sage.graphs Chain complex morphism: From: Chain complex with at most 1 nonzero terms over Integer Ring - To: Chain complex with at most 2 nonzero terms over Integer Ring - sage: f.dual().in_degree(0) + To: Chain complex with at most 2 nonzero terms over Integer Ring + sage: f.dual().in_degree(0) # optional - sage.graphs [1] [1] - sage: ascii_art(f.domain()) + sage: ascii_art(f.domain()) # optional - sage.graphs [-1] [ 1] 0 <-- C_0 <----- C_1 <-- 0 - sage: ascii_art(f.dual().codomain()) + sage: ascii_art(f.dual().codomain()) # optional - sage.graphs [-1 1] 0 <-- C_1 <-------- C_0 <-- 0 """ @@ -295,26 +297,26 @@ def __neg__(self): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: w = -x - sage: w._matrix_dictionary + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: w = -x # optional - sage.graphs + sage: w._matrix_dictionary # optional - sage.graphs {0: [-1 0 0 0] - [ 0 -1 0 0] - [ 0 0 -1 0] - [ 0 0 0 -1], + [ 0 -1 0 0] + [ 0 0 -1 0] + [ 0 0 0 -1], 1: [-1 0 0 0 0 0] - [ 0 -1 0 0 0 0] - [ 0 0 -1 0 0 0] - [ 0 0 0 -1 0 0] - [ 0 0 0 0 -1 0] - [ 0 0 0 0 0 -1], + [ 0 -1 0 0 0 0] + [ 0 0 -1 0 0 0] + [ 0 0 0 -1 0 0] + [ 0 0 0 0 -1 0] + [ 0 0 0 0 0 -1], 2: [-1 0 0 0] - [ 0 -1 0 0] - [ 0 0 -1 0] - [ 0 0 0 -1]} + [ 0 -1 0 0] + [ 0 0 -1 0] + [ 0 0 0 -1]} """ f = dict() @@ -328,26 +330,26 @@ def __add__(self,x): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: z = x+x - sage: z._matrix_dictionary + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: z = x+x # optional - sage.graphs + sage: z._matrix_dictionary # optional - sage.graphs {0: [2 0 0 0] - [0 2 0 0] - [0 0 2 0] - [0 0 0 2], + [0 2 0 0] + [0 0 2 0] + [0 0 0 2], 1: [2 0 0 0 0 0] - [0 2 0 0 0 0] - [0 0 2 0 0 0] - [0 0 0 2 0 0] - [0 0 0 0 2 0] - [0 0 0 0 0 2], + [0 2 0 0 0 0] + [0 0 2 0 0 0] + [0 0 0 2 0 0] + [0 0 0 0 2 0] + [0 0 0 0 0 2], 2: [2 0 0 0] - [0 2 0 0] - [0 0 2 0] - [0 0 0 2]} + [0 2 0 0] + [0 0 2 0] + [0 0 0 2]} """ if not isinstance(x, ChainComplexMorphism) or self.codomain() != x.codomain() or self.domain() != x.domain() or self._matrix_dictionary.keys() != x._matrix_dictionary.keys(): raise TypeError("unsupported operation") @@ -363,42 +365,42 @@ def __mul__(self, x): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: y = x*2 - sage: y._matrix_dictionary + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: y = x*2 # optional - sage.graphs + sage: y._matrix_dictionary # optional - sage.graphs {0: [2 0 0 0] - [0 2 0 0] - [0 0 2 0] - [0 0 0 2], + [0 2 0 0] + [0 0 2 0] + [0 0 0 2], 1: [2 0 0 0 0 0] - [0 2 0 0 0 0] - [0 0 2 0 0 0] - [0 0 0 2 0 0] - [0 0 0 0 2 0] - [0 0 0 0 0 2], + [0 2 0 0 0 0] + [0 0 2 0 0 0] + [0 0 0 2 0 0] + [0 0 0 0 2 0] + [0 0 0 0 0 2], 2: [2 0 0 0] - [0 2 0 0] - [0 0 2 0] - [0 0 0 2]} - sage: z = y*y - sage: z._matrix_dictionary + [0 2 0 0] + [0 0 2 0] + [0 0 0 2]} + sage: z = y*y # optional - sage.graphs + sage: z._matrix_dictionary # optional - sage.graphs {0: [4 0 0 0] - [0 4 0 0] - [0 0 4 0] - [0 0 0 4], + [0 4 0 0] + [0 0 4 0] + [0 0 0 4], 1: [4 0 0 0 0 0] - [0 4 0 0 0 0] - [0 0 4 0 0 0] - [0 0 0 4 0 0] - [0 0 0 0 4 0] - [0 0 0 0 0 4], + [0 4 0 0 0 0] + [0 0 4 0 0 0] + [0 0 0 4 0 0] + [0 0 0 0 4 0] + [0 0 0 0 0 4], 2: [4 0 0 0] - [0 4 0 0] - [0 0 4 0] - [0 0 0 4]} + [0 4 0 0] + [0 0 4 0] + [0 0 0 4]} TESTS: @@ -449,13 +451,13 @@ def __rmul__(self,x): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: 2*x == x*2 + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: 2*x == x*2 # optional - sage.graphs True - sage: 3*x == x*2 + sage: 3*x == x*2 # optional - sage.graphs False """ try: @@ -473,12 +475,12 @@ def __sub__(self,x): EXAMPLES:: - sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: y = x-x - sage: y._matrix_dictionary + sage: S = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: y = x - x # optional - sage.graphs + sage: y._matrix_dictionary # optional - sage.graphs {0: [0 0 0 0] [0 0 0 0] [0 0 0 0] @@ -502,19 +504,18 @@ def __eq__(self,x): EXAMPLES:: - sage: S = SimplicialComplex(is_mutable=False) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: x + sage: S = SimplicialComplex(is_mutable=False) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism(); x # optional - sage.graphs Chain complex morphism: From: Trivial chain complex over Integer Ring To: Trivial chain complex over Integer Ring - sage: f = x._matrix_dictionary - sage: C = S.chain_complex() - sage: G = Hom(C,C) - sage: y = G(f) - sage: x == y + sage: f = x._matrix_dictionary # optional - sage.graphs + sage: C = S.chain_complex() # optional - sage.graphs + sage: G = Hom(C,C) # optional - sage.graphs + sage: y = G(f) # optional - sage.graphs + sage: x == y # optional - sage.graphs True """ return isinstance(x,ChainComplexMorphism) \ @@ -524,36 +525,36 @@ def __eq__(self,x): def is_identity(self): """ - True if this is the identity map. + Return ``True`` if this is the identity map. EXAMPLES:: - sage: S = SimplicialComplex(is_mutable=False) - sage: H = Hom(S,S) - sage: i = H.identity() - sage: x = i.associated_chain_complex_morphism() - sage: x.is_identity() + sage: S = SimplicialComplex(is_mutable=False) # optional - sage.graphs + sage: H = Hom(S,S) # optional - sage.graphs + sage: i = H.identity() # optional - sage.graphs + sage: x = i.associated_chain_complex_morphism() # optional - sage.graphs + sage: x.is_identity() # optional - sage.graphs True """ return self.to_matrix().is_one() def is_surjective(self): """ - True if this map is surjective. + Return ``True`` if this map is surjective. EXAMPLES:: - sage: S1 = simplicial_complexes.Sphere(1) - sage: H = Hom(S1, S1) - sage: flip = H({0:0, 1:2, 2:1}) - sage: flip.associated_chain_complex_morphism().is_surjective() + sage: S1 = simplicial_complexes.Sphere(1) # optional - sage.graphs + sage: H = Hom(S1, S1) # optional - sage.graphs + sage: flip = H({0:0, 1:2, 2:1}) # optional - sage.graphs + sage: flip.associated_chain_complex_morphism().is_surjective() # optional - sage.graphs True - sage: pt = simplicial_complexes.Simplex(0) - sage: inclusion = Hom(pt, S1)({0:2}) - sage: inclusion.associated_chain_complex_morphism().is_surjective() + sage: pt = simplicial_complexes.Simplex(0) # optional - sage.graphs + sage: inclusion = Hom(pt, S1)({0:2}) # optional - sage.graphs + sage: inclusion.associated_chain_complex_morphism().is_surjective() # optional - sage.graphs False - sage: inclusion.associated_chain_complex_morphism(cochain=True).is_surjective() + sage: inclusion.associated_chain_complex_morphism(cochain=True).is_surjective() # optional - sage.graphs True """ m = self.to_matrix() @@ -561,21 +562,21 @@ def is_surjective(self): def is_injective(self): """ - True if this map is injective. + Return ``True`` if this map is injective. EXAMPLES:: - sage: S1 = simplicial_complexes.Sphere(1) - sage: H = Hom(S1, S1) - sage: flip = H({0:0, 1:2, 2:1}) - sage: flip.associated_chain_complex_morphism().is_injective() + sage: S1 = simplicial_complexes.Sphere(1) # optional - sage.graphs + sage: H = Hom(S1, S1) # optional - sage.graphs + sage: flip = H({0:0, 1:2, 2:1}) # optional - sage.graphs + sage: flip.associated_chain_complex_morphism().is_injective() # optional - sage.graphs True - sage: pt = simplicial_complexes.Simplex(0) - sage: inclusion = Hom(pt, S1)({0:2}) - sage: inclusion.associated_chain_complex_morphism().is_injective() + sage: pt = simplicial_complexes.Simplex(0) # optional - sage.graphs + sage: inclusion = Hom(pt, S1)({0:2}) # optional - sage.graphs + sage: inclusion.associated_chain_complex_morphism().is_injective() # optional - sage.graphs True - sage: inclusion.associated_chain_complex_morphism(cochain=True).is_injective() + sage: inclusion.associated_chain_complex_morphism(cochain=True).is_injective() # optional - sage.graphs False """ return self.to_matrix().right_nullity() == 0 diff --git a/src/sage/homology/chain_homotopy.py b/src/sage/homology/chain_homotopy.py index afeaee2430c..326f512b305 100644 --- a/src/sage/homology/chain_homotopy.py +++ b/src/sage/homology/chain_homotopy.py @@ -121,7 +121,8 @@ def __init__(self, matrices, f, g=None): `f - (H \partial + \partial H)`. :: sage: from sage.homology.chain_homotopy import ChainHomotopy - sage: C = ChainComplex({1: matrix(ZZ, 1, 2, (1,0)), 2: matrix(ZZ, 2, 1, (0, 2))}, degree_of_differential=-1) + sage: C = ChainComplex({1: matrix(ZZ, 1, 2, (1,0)), 2: matrix(ZZ, 2, 1, (0, 2))}, + ....: degree_of_differential=-1) sage: D = ChainComplex({2: matrix(ZZ, 1, 1, (6,))}, degree_of_differential=-1) sage: f_d = {1: matrix(ZZ, 1, 2, (0,3)), 2: identity_matrix(ZZ, 1)} sage: f = Hom(C,D)(f_d) @@ -212,15 +213,23 @@ def is_algebraic_gradient_vector_field(self): `\ZZ` in degree 0. Two chain maps `C \to C` will be chain homotopic as long as they agree in degree 0. :: - sage: f = Hom(C,C)({0: identity_matrix(ZZ, 1), 1: matrix(ZZ, 1, 1, [3]), 2: matrix(ZZ, 1, 1, [3])}) - sage: g = Hom(C,C)({0: identity_matrix(ZZ, 1), 1: matrix(ZZ, 1, 1, [2]), 2: matrix(ZZ, 1, 1, [2])}) - sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), 1: zero_matrix(ZZ, 1), 2: identity_matrix(ZZ, 1)}, f, g) + sage: f = Hom(C,C)({0: identity_matrix(ZZ, 1), + ....: 1: matrix(ZZ, 1, 1, [3]), + ....: 2: matrix(ZZ, 1, 1, [3])}) + sage: g = Hom(C,C)({0: identity_matrix(ZZ, 1), + ....: 1: matrix(ZZ, 1, 1, [2]), + ....: 2: matrix(ZZ, 1, 1, [2])}) + sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), + ....: 1: zero_matrix(ZZ, 1), + ....: 2: identity_matrix(ZZ, 1)}, f, g) sage: H.is_algebraic_gradient_vector_field() True A chain homotopy which is not an algebraic gradient vector field:: - sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), 1: identity_matrix(ZZ, 1), 2: identity_matrix(ZZ, 1)}, f, g) + sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), + ....: 1: identity_matrix(ZZ, 1), + ....: 2: identity_matrix(ZZ, 1)}, f, g) sage: H.is_algebraic_gradient_vector_field() False """ @@ -251,9 +260,15 @@ def is_homology_gradient_vector_field(self): sage: from sage.homology.chain_homotopy import ChainHomotopy sage: C = ChainComplex({0: zero_matrix(ZZ, 1), 1: identity_matrix(ZZ, 1)}) - sage: f = Hom(C,C)({0: identity_matrix(ZZ, 1), 1: matrix(ZZ, 1, 1, [3]), 2: matrix(ZZ, 1, 1, [3])}) - sage: g = Hom(C,C)({0: identity_matrix(ZZ, 1), 1: matrix(ZZ, 1, 1, [2]), 2: matrix(ZZ, 1, 1, [2])}) - sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), 1: zero_matrix(ZZ, 1), 2: identity_matrix(ZZ, 1)}, f, g) + sage: f = Hom(C,C)({0: identity_matrix(ZZ, 1), + ....: 1: matrix(ZZ, 1, 1, [3]), + ....: 2: matrix(ZZ, 1, 1, [3])}) + sage: g = Hom(C,C)({0: identity_matrix(ZZ, 1), + ....: 1: matrix(ZZ, 1, 1, [2]), + ....: 2: matrix(ZZ, 1, 1, [2])}) + sage: H = ChainHomotopy({0: zero_matrix(ZZ, 0, 1), + ....: 1: zero_matrix(ZZ, 1), + ....: 2: identity_matrix(ZZ, 1)}, f, g) sage: H.is_homology_gradient_vector_field() True """ @@ -281,8 +296,8 @@ def in_degree(self, n): EXAMPLES:: sage: from sage.homology.chain_homotopy import ChainHomotopy - sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 - sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 + sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 + sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 sage: f = Hom(C, D)({}) sage: H = ChainHomotopy({1: matrix(ZZ, 1, 2, (3,1))}, f, f) sage: H.in_degree(1) @@ -316,8 +331,8 @@ def dual(self): EXAMPLES:: sage: from sage.homology.chain_homotopy import ChainHomotopy - sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 - sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 + sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 + sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 sage: f = Hom(C, D)({}) sage: H = ChainHomotopy({1: matrix(ZZ, 1, 2, (3,1))}, f, f) sage: H.in_degree(1) @@ -336,8 +351,8 @@ def __hash__(self): TESTS:: sage: from sage.homology.chain_homotopy import ChainHomotopy - sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 - sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 + sage: C = ChainComplex({1: matrix(ZZ, 0, 2)}) # one nonzero term in degree 1 + sage: D = ChainComplex({0: matrix(ZZ, 0, 1)}) # one nonzero term in degree 0 sage: f = Hom(C, D)({}) sage: H = ChainHomotopy({1: matrix(ZZ, 1, 2, (3,1))}, f, f) sage: hash(H) # random @@ -347,7 +362,7 @@ def __hash__(self): def _repr_(self): """ - String representation + String representation. EXAMPLES:: @@ -403,7 +418,9 @@ class ChainContraction(ChainHomotopy): sage: pi = Hom(C,D)({0: identity_matrix(ZZ, 1)}) sage: iota = Hom(D,C)({0: identity_matrix(ZZ, 1)}) - sage: H = ChainContraction({0: zero_matrix(ZZ, 0, 1), 1: zero_matrix(ZZ, 1), 2: identity_matrix(ZZ, 1)}, pi, iota) + sage: H = ChainContraction({0: zero_matrix(ZZ, 0, 1), + ....: 1: zero_matrix(ZZ, 1), + ....: 2: identity_matrix(ZZ, 1)}, pi, iota) """ def __init__(self, matrices, pi, iota): r""" @@ -488,20 +505,20 @@ def pi(self): EXAMPLES:: - sage: S2 = simplicial_complexes.Sphere(2) - sage: phi, M = S2.algebraic_topological_model(QQ) - sage: phi.pi() + sage: S2 = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: phi, M = S2.algebraic_topological_model(QQ) # optional - sage.graphs + sage: phi.pi() # optional - sage.graphs Chain complex morphism: From: Chain complex with at most 3 nonzero terms over Rational Field To: Chain complex with at most 3 nonzero terms over Rational Field - sage: phi.pi().in_degree(0) # Every vertex represents a homology class. + sage: phi.pi().in_degree(0) # Every vertex represents a homology class. # optional - sage.graphs [1 1 1 1] - sage: phi.pi().in_degree(1) # No homology in degree 1. + sage: phi.pi().in_degree(1) # No homology in degree 1. # optional - sage.graphs [] The degree 2 homology generator is detected on a single simplex:: - sage: phi.pi().in_degree(2) + sage: phi.pi().in_degree(2) # optional - sage.graphs [0 0 0 1] """ return self._pi @@ -512,16 +529,16 @@ def iota(self): EXAMPLES:: - sage: S2 = simplicial_complexes.Sphere(2) - sage: phi, M = S2.algebraic_topological_model(QQ) - sage: phi.iota() + sage: S2 = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: phi, M = S2.algebraic_topological_model(QQ) # optional - sage.graphs + sage: phi.iota() # optional - sage.graphs Chain complex morphism: From: Chain complex with at most 3 nonzero terms over Rational Field To: Chain complex with at most 3 nonzero terms over Rational Field Lifting the degree zero homology class gives a single vertex:: - sage: phi.iota().in_degree(0) + sage: phi.iota().in_degree(0) # optional - sage.graphs [0] [0] [0] @@ -530,7 +547,7 @@ def iota(self): Lifting the degree two homology class gives the signed sum of all of the 2-simplices:: - sage: phi.iota().in_degree(2) + sage: phi.iota().in_degree(2) # optional - sage.graphs [-1] [ 1] [-1] @@ -546,9 +563,9 @@ def dual(self): EXAMPLES:: - sage: S2 = simplicial_complexes.Sphere(2) - sage: phi, M = S2.algebraic_topological_model(QQ) - sage: phi.iota() + sage: S2 = simplicial_complexes.Sphere(2) # optional - sage.graphs + sage: phi, M = S2.algebraic_topological_model(QQ) # optional - sage.graphs + sage: phi.iota() # optional - sage.graphs Chain complex morphism: From: Chain complex with at most 3 nonzero terms over Rational Field To: Chain complex with at most 3 nonzero terms over Rational Field @@ -557,22 +574,22 @@ def dual(self): but the degree zero cohomology class needs to be detected on every vertex, and vice versa for degree 2:: - sage: phi.iota().in_degree(0) + sage: phi.iota().in_degree(0) # optional - sage.graphs [0] [0] [0] [1] - sage: phi.dual().iota().in_degree(0) + sage: phi.dual().iota().in_degree(0) # optional - sage.graphs [1] [1] [1] [1] - sage: phi.iota().in_degree(2) + sage: phi.iota().in_degree(2) # optional - sage.graphs [-1] [ 1] [-1] [ 1] - sage: phi.dual().iota().in_degree(2) + sage: phi.dual().iota().in_degree(2) # optional - sage.graphs [0] [0] [0] diff --git a/src/sage/homology/chains.py b/src/sage/homology/chains.py index 7bd375f35fd..86e2eaec897 100644 --- a/src/sage/homology/chains.py +++ b/src/sage/homology/chains.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.graphs (because all doctests use the catalogs simplicial_complexes, cubical_complexes) r""" Chains and cochains diff --git a/src/sage/homology/free_resolution.py b/src/sage/homology/free_resolution.py index 424086d283e..c7ea0da39cc 100644 --- a/src/sage/homology/free_resolution.py +++ b/src/sage/homology/free_resolution.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.singular r""" Free resolutions @@ -17,29 +18,25 @@ sage: from sage.homology.free_resolution import FreeResolution sage: S. = PolynomialRing(QQ) sage: m = matrix(S, 1, [z^2 - y*w, y*z - x*w, y^2 - x*z]).transpose() - sage: r = FreeResolution(m, name='S') - sage: r + sage: r = FreeResolution(m, name='S'); r S^1 <-- S^3 <-- S^2 <-- 0 sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.free_resolution() - sage: r + sage: r = I.free_resolution(); r S^1 <-- S^3 <-- S^2 <-- 0 :: sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 An example of a minimal free resolution from [CLO2005]_:: sage: R. = QQ[] sage: I = R.ideal([y*z - x*w, y^3 - x^2*z, x*z^2 - y^2*w, z^3 - y*w^2]) - sage: r = I.free_resolution() - sage: r + sage: r = I.free_resolution(); r S^1 <-- S^4 <-- S^4 <-- S^1 <-- 0 sage: len(r) 3 @@ -66,8 +63,6 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.libs.singular.singular import si2sa_resolution -from sage.libs.singular.function import singular_function from sage.misc.lazy_attribute import lazy_attribute from sage.misc.abstract_method import abstract_method from sage.misc.classcall_metaclass import ClasscallMetaclass @@ -298,12 +293,13 @@ def target(self): sage: r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: r.target() - Quotient module by Submodule of Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - Generated by the rows of the matrix: - [-z^2 + y*w] - [ y*z - x*w] - [-y^2 + x*z] + Quotient module by + Submodule of Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Generated by the rows of the matrix: + [-z^2 + y*w] + [ y*z - x*w] + [-y^2 + x*z] """ return self.differential(0).codomain() @@ -337,13 +333,14 @@ class FiniteFreeResolution(FreeResolution): sage: r.differential(0) Coercion map: From: Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - To: Quotient module by Submodule of Ambient free module of rank 1 - over the integral domain Multivariate Polynomial Ring in x, y, z, w over Rational Field - Generated by the rows of the matrix: - [-z^2 + y*w] - [ y*z - x*w] - [-y^2 + x*z] + Multivariate Polynomial Ring in x, y, z, w over Rational Field + To: Quotient module by + Submodule of Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Generated by the rows of the matrix: + [-z^2 + y*w] + [ y*z - x*w] + [-y^2 + x*z] """ @lazy_attribute def _length(self): @@ -373,8 +370,7 @@ def _repr_(self): sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 """ s = self._repr_module(0) @@ -393,8 +389,7 @@ def __len__(self): sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: len(r) 2 @@ -413,8 +408,7 @@ def __getitem__(self, i): sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: r.target() Quotient module by Submodule of Ambient free module of rank 1 over the integral domain @@ -450,38 +444,38 @@ def differential(self, i): sage: r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: r.differential(3) - Free module morphism defined by the matrix - [] - Domain: Ambient free module of rank 0 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - Codomain: Ambient free module of rank 2 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field + Free module morphism defined by the matrix [] + Domain: Ambient free module of rank 0 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Codomain: Ambient free module of rank 2 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field sage: r.differential(2) Free module morphism defined as left-multiplication by the matrix - [-y x] - [ z -y] - [-w z] - Domain: Ambient free module of rank 2 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - Codomain: Ambient free module of rank 3 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field + [-y x] + [ z -y] + [-w z] + Domain: Ambient free module of rank 2 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Codomain: Ambient free module of rank 3 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field sage: r.differential(1) Free module morphism defined as left-multiplication by the matrix - [z^2 - y*w y*z - x*w y^2 - x*z] - Domain: Ambient free module of rank 3 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - Codomain: Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field + [z^2 - y*w y*z - x*w y^2 - x*z] + Domain: Ambient free module of rank 3 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Codomain: Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field sage: r.differential(0) Coercion map: From: Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - To: Quotient module by Submodule of Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - Generated by the rows of the matrix: - [-z^2 + y*w] - [ y*z - x*w] - [-y^2 + x*z] + Multivariate Polynomial Ring in x, y, z, w over Rational Field + To: Quotient module by + Submodule of Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Generated by the rows of the matrix: + [-z^2 + y*w] + [ y*z - x*w] + [-y^2 + x*z] """ if i < 0: raise IndexError('invalid index') @@ -516,8 +510,7 @@ def matrix(self, i): sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: r.matrix(3) [] @@ -572,9 +565,10 @@ def _initial_differential(self): sage: r._initial_differential Coercion map: From: Ambient free module of rank 1 over the integral domain - Multivariate Polynomial Ring in x, y, z, w over Rational Field - To: Quotient module by Submodule of Ambient free module of rank 1 - over the integral domain Multivariate Polynomial Ring in x, y, z, w over Rational Field + Multivariate Polynomial Ring in x, y, z, w over Rational Field + To: Quotient module by + Submodule of Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field Generated by the rows of the matrix: [-z^2 + y*w] [ y*z - x*w] @@ -646,15 +640,13 @@ class FiniteFreeResolution_free_module(FiniteFreeResolution): sage: M = R^3 sage: v = M([x^2, 2*x^2, 3*x^2]) sage: w = M([0, x, 2*x]) - sage: S = M.submodule([v, w]) - sage: S + sage: S = M.submodule([v, w]); S Free module of degree 3 and rank 2 over Univariate Polynomial Ring in x over Rational Field - Echelon basis matrix: - [ x^2 2*x^2 3*x^2] - [ 0 x 2*x] - sage: res = S.free_resolution() - sage: res + Echelon basis matrix: + [ x^2 2*x^2 3*x^2] + [ 0 x 2*x] + sage: res = S.free_resolution(); res S^3 <-- S^2 <-- 0 sage: ascii_art(res.chain_complex()) [ x^2 0] @@ -664,8 +656,7 @@ class FiniteFreeResolution_free_module(FiniteFreeResolution): sage: R. = PolynomialRing(QQ) sage: I = R.ideal([x^4 + 3*x^2 + 2]) - sage: res = I.free_resolution() - sage: res + sage: res = I.free_resolution(); res S^1 <-- S^1 <-- 0 """ @lazy_attribute @@ -680,8 +671,7 @@ def _maps(self): sage: v = M([x^2, 2*x^2, 3*x^2]) sage: w = M([0, x, 2*x]) sage: S = M.submodule([v, w]) - sage: res = S.free_resolution() - sage: res + sage: res = S.free_resolution(); res S^3 <-- S^2 <-- 0 sage: ascii_art(res.chain_complex()) [ x^2 0] @@ -705,8 +695,7 @@ def _maps(self): sage: M = matrix([[x^2, 2], ....: [3*x^2, 5], ....: [5*x^2, 4]]) - sage: res = FreeResolution(M.transpose()) - sage: res + sage: res = FreeResolution(M.transpose()); res S^3 <-- S^2 <-- 0 sage: res._m() [ 1 0] @@ -721,8 +710,7 @@ def _maps(self): An overdetermined system over a PID:: - sage: res = FreeResolution(M) - sage: res + sage: res = FreeResolution(M); res S^2 <-- S^2 <-- 0 sage: res._m() [x^2 0] @@ -776,8 +764,7 @@ class FiniteFreeResolution_singular(FiniteFreeResolution): sage: from sage.homology.free_resolution import FreeResolution sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = FreeResolution(I) - sage: r + sage: r = FreeResolution(I); r S^1 <-- S^3 <-- S^2 <-- 0 sage: len(r) 2 @@ -797,8 +784,7 @@ class FiniteFreeResolution_singular(FiniteFreeResolution): the initial differential:: sage: m = matrix(S, 1, [z^2 - y*w, y*z - x*w, y^2 - x*z]).transpose() - sage: r = FreeResolution(m, name='S') - sage: r + sage: r = FreeResolution(m, name='S'); r S^1 <-- S^3 <-- S^2 <-- 0 sage: r.matrix(1) [z^2 - y*w y*z - x*w y^2 - x*z] @@ -806,15 +792,13 @@ class FiniteFreeResolution_singular(FiniteFreeResolution): An additional construction is using a submodule of a free module:: sage: M = m.image() - sage: r = FreeResolution(M, name='S') - sage: r + sage: r = FreeResolution(M, name='S'); r S^1 <-- S^3 <-- S^2 <-- 0 A nonhomogeneous ideal:: sage: I = S.ideal([z^2 - y*w, y*z - x*w, y^2 - x]) - sage: R = FreeResolution(I) - sage: R + sage: R = FreeResolution(I); R S^1 <-- S^3 <-- S^3 <-- S^1 <-- 0 sage: R.matrix(2) [ y*z - x*w y^2 - x 0] @@ -866,6 +850,9 @@ def _maps(self): [z^2 - y*w y*z - x*w y^2 - x*z], [-w z] ] """ + from sage.libs.singular.singular import si2sa_resolution + from sage.libs.singular.function import singular_function + # This ensures the first component of the Singular resolution to be a # module, like the later components. This is important when the # components are converted to Sage modules. diff --git a/src/sage/homology/graded_resolution.py b/src/sage/homology/graded_resolution.py index d9aa9e11119..58fa8285fd7 100644 --- a/src/sage/homology/graded_resolution.py +++ b/src/sage/homology/graded_resolution.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.singular r""" Graded free resolutions @@ -24,16 +25,16 @@ sage: d = r.differential(2) sage: d Free module morphism defined as left-multiplication by the matrix - [ y x] - [-z -y] - [ w z] - Domain: Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring - in x, y, z, w over Rational Field - Codomain: Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring - in x, y, z, w over Rational Field + [ y x] + [-z -y] + [ w z] + Domain: Ambient free module of rank 2 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field + Codomain: Ambient free module of rank 3 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field sage: d.image() - Submodule of Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring - in x, y, z, w over Rational Field + Submodule of Ambient free module of rank 3 over the integral domain + Multivariate Polynomial Ring in x, y, z, w over Rational Field Generated by the rows of the matrix: [ y -z w] [ x -y z] @@ -47,7 +48,8 @@ sage: S. = QQ[] sage: phi = S.hom([s, s*t, s*t^2, s*t^3]) sage: I = phi.kernel(); I - Ideal (c^2 - b*d, b*c - a*d, b^2 - a*c) of Multivariate Polynomial Ring in a, b, c, d over Rational Field + Ideal (c^2 - b*d, b*c - a*d, b^2 - a*c) of + Multivariate Polynomial Ring in a, b, c, d over Rational Field sage: P3 = ProjectiveSpace(S) sage: C = P3.subscheme(I) # twisted cubic curve sage: r = I.graded_free_resolution(degrees=[(1,0), (1,1), (1,2), (1,3)]) @@ -73,8 +75,6 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.libs.singular.singular import si2sa_resolution_graded -from sage.libs.singular.function import singular_function from sage.misc.lazy_attribute import lazy_attribute from sage.structure.element import Matrix from sage.modules.free_module_element import vector @@ -124,8 +124,7 @@ def __init__(self, module, degrees=None, shifts=None, name='S', **kwds): sage: M = matrix([[x^2, 2*x^2], ....: [3*x^2, 5*x^2], ....: [5*x^2, 4*x^2]]) - sage: res = FreeResolution(M, graded=True) - sage: res + sage: res = FreeResolution(M, graded=True); res S(0)⊕S(0) <-- S(-2)⊕S(-2) <-- 0 sage: res._res_shifts [[2, 2]] @@ -327,8 +326,7 @@ class GradedFiniteFreeResolution_free_module(GradedFiniteFreeResolution, FiniteF sage: R. = QQ[] sage: M = matrix([[x^3, 3*x^3, 5*x^3], ....: [0, x, 2*x]]) - sage: res = FreeResolution(M, graded=True) - sage: res + sage: res = FreeResolution(M, graded=True); res S(0)⊕S(0)⊕S(0) <-- S(-3)⊕S(-1) <-- 0 """ def __init__(self, module, degrees=None, *args, **kwds): @@ -363,8 +361,7 @@ def _maps(self): sage: R. = QQ[] sage: M = matrix([[x^3, 3*x^3, 5*x^3], ....: [0, x, 2*x]]) - sage: res = FreeResolution(M, graded=True) - sage: res + sage: res = FreeResolution(M, graded=True); res S(0)⊕S(0)⊕S(0) <-- S(-3)⊕S(-1) <-- 0 sage: res._maps [ @@ -376,8 +373,7 @@ def _maps(self): [[3, 1]] sage: I = R.ideal([x^4]) - sage: res = I.graded_free_resolution(shifts=[1], degrees=[2]) - sage: res + sage: res = I.graded_free_resolution(shifts=[1], degrees=[2]); res S(-1) <-- S(-9) <-- 0 sage: res._maps [[x^4]] @@ -473,8 +469,7 @@ class GradedFiniteFreeResolution_singular(GradedFiniteFreeResolution, FiniteFree sage: S. = PolynomialRing(QQ) sage: I = S.ideal([y*w - z^2, -x*w + y*z, x*z - y^2]) - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-2)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3) <-- 0 sage: len(r) 2 @@ -482,8 +477,7 @@ class GradedFiniteFreeResolution_singular(GradedFiniteFreeResolution, FiniteFree sage: I = S.ideal([z^2 - y*w, y*z - x*w, y - x]) sage: I.is_homogeneous() True - sage: r = I.graded_free_resolution() - sage: r + sage: r = I.graded_free_resolution(); r S(0) <-- S(-1)⊕S(-2)⊕S(-2) <-- S(-3)⊕S(-3)⊕S(-4) <-- S(-5) <-- 0 """ def __init__(self, module, degrees=None, shifts=None, name='S', algorithm='heuristic', **kwds): @@ -521,6 +515,9 @@ def _maps(self): sage: r._res_shifts [[2, 2, 2], [3, 3]] """ + from sage.libs.singular.singular import si2sa_resolution_graded + from sage.libs.singular.function import singular_function + #cdef int i, j, k, ncols, nrows #cdef list res_shifts, prev_shifts, new_shifts diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index f372a08e0e8..05af2b6cbce 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.combinat (because all doctests use FreeAlgebra, SymmetricGroupAlgebra, etc.) """ Hochschild Complexes """ diff --git a/src/sage/homology/homology_group.py b/src/sage/homology/homology_group.py index 0b27087a362..5948d206371 100644 --- a/src/sage/homology/homology_group.py +++ b/src/sage/homology/homology_group.py @@ -32,13 +32,13 @@ class HomologyGroup_class(AdditiveAbelianGroup_fixed_gens): EXAMPLES:: sage: from sage.homology.homology_group import HomologyGroup - sage: G = AbelianGroup(5, [5,5,7,8,9]); G + sage: G = AbelianGroup(5, [5,5,7,8,9]); G # optional - sage.groups Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9 sage: H = HomologyGroup(5, ZZ, [5,5,7,8,9]); H C5 x C5 x C7 x C8 x C9 - sage: G == loads(dumps(G)) + sage: G == loads(dumps(G)) # optional - sage.groups True - sage: AbelianGroup(4) + sage: AbelianGroup(4) # optional - sage.groups Multiplicative Abelian group isomorphic to Z x Z x Z x Z sage: HomologyGroup(4, ZZ) Z x Z x Z x Z @@ -156,11 +156,11 @@ def HomologyGroup(n, base_ring, invfac=None): EXAMPLES:: sage: from sage.homology.homology_group import HomologyGroup - sage: G = AbelianGroup(5, [5,5,7,8,9]); G + sage: G = AbelianGroup(5, [5,5,7,8,9]); G # optional - sage.groups Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9 sage: H = HomologyGroup(5, ZZ, [5,5,7,8,9]); H C5 x C5 x C7 x C8 x C9 - sage: AbelianGroup(4) + sage: AbelianGroup(4) # optional - sage.groups Multiplicative Abelian group isomorphic to Z x Z x Z x Z sage: HomologyGroup(4, ZZ) Z x Z x Z x Z diff --git a/src/sage/homology/homology_morphism.py b/src/sage/homology/homology_morphism.py index 7dfd5fc8b08..9cd1c7a4a82 100644 --- a/src/sage/homology/homology_morphism.py +++ b/src/sage/homology/homology_morphism.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.graphs (because all doctests use the catalog simplicial_complexes) r""" Induced morphisms on homology @@ -27,12 +28,19 @@ # - associated_chain_complex_morphism # Once this is done, the code here ought to work without modification. +import itertools + from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis from sage.categories.graded_modules_with_basis import GradedModulesWithBasis from sage.categories.morphism import Morphism from sage.categories.homset import Hom from sage.rings.rational_field import QQ -from sage.topology.simplicial_complex import SimplicialComplex + +try: + from sage.topology.simplicial_complex import SimplicialComplex +except ImportError: + SimplicialComplex = () + class InducedHomologyMorphism(Morphism): r""" @@ -61,12 +69,13 @@ class InducedHomologyMorphism(Morphism): sage: f = H({0:0, 1:2, 2:1}) # f switches two vertices sage: f_star = f.induced_homology_morphism(QQ, cohomology=True) sage: f_star - Graded algebra endomorphism of Cohomology ring of Minimal triangulation of the 1-sphere over Rational Field + Graded algebra endomorphism of + Cohomology ring of Minimal triangulation of the 1-sphere over Rational Field Defn: induced by: - Simplicial complex endomorphism of Minimal triangulation of the 1-sphere - Defn: 0 |--> 0 - 1 |--> 2 - 2 |--> 1 + Simplicial complex endomorphism of Minimal triangulation of the 1-sphere + Defn: 0 |--> 0 + 1 |--> 2 + 2 |--> 1 sage: f_star.to_matrix(1) [-1] sage: f_star.to_matrix() @@ -86,7 +95,7 @@ class in the torus, we can define a map `S^1 \to T` inducing an sage: Hom(S1, T)({0:0, 1:2, 2:5}) Simplicial complex morphism: From: Minimal triangulation of the 1-sphere - To: Minimal triangulation of the torus + To: Minimal triangulation of the torus Defn: 0 |--> 0 1 |--> 2 2 |--> 5 @@ -180,7 +189,7 @@ def __init__(self, map, base_ring=None, cohomology=False): def base_ring(self): """ - The base ring for this map + The base ring for this map. EXAMPLES:: @@ -189,7 +198,7 @@ def base_ring(self): sage: id = H.identity() sage: id.induced_homology_morphism(QQ).base_ring() Rational Field - sage: id.induced_homology_morphism(GF(13)).base_ring() + sage: id.induced_homology_morphism(GF(13)).base_ring() # optional - sage.rings.finite_rings Finite Field of size 13 """ return self._base_ring @@ -234,14 +243,13 @@ def to_matrix(self, deg=None): mat = mat.transpose() H_domain, H_codomain = H_codomain, H_domain if deg is None: - import numpy as np betti_domain = [H_domain.free_module_rank(n) for n in range(domain.dimension()+1)] betti_codomain = [H_codomain.free_module_rank(n) for n in range(codomain.dimension()+1)] # Compute cumulative sums of Betti numbers to get subdivisions: - row_subdivs = list(np.cumsum(betti_codomain[:-1])) - col_subdivs = list(np.cumsum(betti_domain[:-1])) + row_subdivs = list(itertools.accumulate(betti_codomain[:-1])) + col_subdivs = list(itertools.accumulate(betti_domain[:-1])) mat.subdivide(row_subdivs, col_subdivs) return mat @@ -304,7 +312,7 @@ def __eq__(self, other): sage: g = Hom(S1, K)({0: 0, 1:0, 2:0}) sage: f.induced_homology_morphism(QQ) == g.induced_homology_morphism(QQ) True - sage: f.induced_homology_morphism(QQ) == g.induced_homology_morphism(GF(2)) + sage: f.induced_homology_morphism(QQ) == g.induced_homology_morphism(GF(2)) # optional - sage.rings.finite_rings False sage: id = Hom(K, K).identity() # different domain sage: f.induced_homology_morphism(QQ) == id.induced_homology_morphism(QQ) @@ -320,7 +328,7 @@ def __eq__(self, other): def is_identity(self): """ - True if this is the identity map on (co)homology. + Return ``True`` if this is the identity map on (co)homology. EXAMPLES:: @@ -339,7 +347,7 @@ def is_identity(self): def is_surjective(self): """ - True if this map is surjective on (co)homology. + Return ``True`` if this map is surjective on (co)homology. EXAMPLES:: @@ -357,7 +365,7 @@ def is_surjective(self): def is_injective(self): """ - True if this map is injective on (co)homology. + Return ``True`` if this map is injective on (co)homology. EXAMPLES:: diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 63a80657917..fd5e2fbdc0d 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -1,4 +1,5 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.graphs (because all doctests use the catalogs simplicial_complexes, cubical_complexes) + """ Homology and cohomology with a basis @@ -30,8 +31,13 @@ from sage.categories.modules import Modules from sage.combinat.free_module import CombinatorialFreeModule from sage.sets.family import Family -from sage.topology.simplicial_complex import SimplicialComplex -from sage.topology.simplicial_set import SimplicialSet_arbitrary + +try: + from sage.topology.simplicial_complex import SimplicialComplex + from sage.topology.simplicial_set import SimplicialSet_arbitrary +except ImportError: + SimplicialComplex = SimplicialSet_arbitrary = () + class HomologyVectorSpaceWithBasis(CombinatorialFreeModule): r""" diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 24379a7ca7b..1b40ed49d40 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -48,7 +48,6 @@ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.misc.abstract_method import abstract_method -from sage.homology.chains import Chains, Cochains class GenericCellComplex(SageObject): @@ -509,21 +508,22 @@ def homology(self, dim=None, base_ring=ZZ, subcomplex=None, {0: 0, 1: C2, 2: 0} sage: P.homology(reduced=False) {0: Z, 1: C2, 2: 0} - sage: P.homology(base_ring=GF(2)) + sage: P.homology(base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: S7 = delta_complexes.Sphere(7) - sage: S7.homology(7) + sage: S7.homology(7) # optional - sage.modules Z - sage: cubical_complexes.KleinBottle().homology(1, base_ring=GF(2)) + sage: cubical_complexes.KleinBottle().homology(1, base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 2 over Finite Field of size 2 Sage can compute generators of homology groups:: sage: S2 = simplicial_complexes.Sphere(2) - sage: S2.homology(dim=2, generators=True, base_ring=GF(2)) - [(Vector space of dimension 1 over Finite Field of size 2, (0, 1, 2) + (0, 1, 3) + (0, 2, 3) + (1, 2, 3))] + sage: S2.homology(dim=2, generators=True, base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings + [(Vector space of dimension 1 over Finite Field of size 2, + (0, 1, 2) + (0, 1, 3) + (0, 2, 3) + (1, 2, 3))] When generators are computed, Sage returns a pair for each dimension: the group and the list of generators. For @@ -532,14 +532,15 @@ def homology(self, dim=None, base_ring=ZZ, subcomplex=None, complexes, each generator is a linear combination of cubes:: sage: S2_cub = cubical_complexes.Sphere(2) - sage: S2_cub.homology(dim=2, generators=True) + sage: S2_cub.homology(dim=2, generators=True) # optional - sage.modules [(Z, - [0,0] x [0,1] x [0,1] - [0,1] x [0,0] x [0,1] + [0,1] x [0,1] x [0,0] - [0,1] x [0,1] x [1,1] + [0,1] x [1,1] x [0,1] - [1,1] x [0,1] x [0,1])] + [0,0] x [0,1] x [0,1] - [0,1] x [0,0] x [0,1] + [0,1] x [0,1] x [0,0] + - [0,1] x [0,1] x [1,1] + [0,1] x [1,1] x [0,1] - [1,1] x [0,1] x [0,1])] Similarly for simpicial sets:: sage: S = simplicial_sets.Sphere(2) - sage: S.homology(generators=True) + sage: S.homology(generators=True) # optional - sage.modules {0: [], 1: 0, 2: [(Z, sigma_2)]} """ from sage.topology.cubical_complex import CubicalComplex @@ -623,28 +624,32 @@ def cohomology(self, dim=None, base_ring=ZZ, subcomplex=None, 0 sage: circle.cohomology(1) Z - sage: P2 = SimplicialComplex([[0,1,2], [0,2,3], [0,1,5], [0,4,5], [0,3,4], [1,2,4], [1,3,4], [1,3,5], [2,3,5], [2,4,5]]) # projective plane - sage: P2.cohomology(2) + + Projective plane:: + + sage: P2 = SimplicialComplex([[0,1,2], [0,2,3], [0,1,5], [0,4,5], [0,3,4], + ....: [1,2,4], [1,3,4], [1,3,5], [2,3,5], [2,4,5]]) + sage: P2.cohomology(2) # optional - sage.modules C2 - sage: P2.cohomology(2, base_ring=GF(2)) + sage: P2.cohomology(2, base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 1 over Finite Field of size 2 - sage: P2.cohomology(2, base_ring=GF(3)) + sage: P2.cohomology(2, base_ring=GF(3)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 0 over Finite Field of size 3 - sage: cubical_complexes.KleinBottle().cohomology(2) + sage: cubical_complexes.KleinBottle().cohomology(2) # optional - sage.modules C2 Relative cohomology:: sage: T = SimplicialComplex([[0,1]]) sage: U = SimplicialComplex([[0], [1]]) - sage: T.cohomology(1, subcomplex=U) + sage: T.cohomology(1, subcomplex=U) # optional - sage.modules Z A `\Delta`-complex example:: sage: s5 = delta_complexes.Sphere(5) - sage: s5.cohomology(base_ring=GF(7))[5] + sage: s5.cohomology(base_ring=GF(7))[5] # optional - sage.modules sage.rings.finite_rings Vector space of dimension 1 over Finite Field of size 7 """ return self.homology(dim=dim, cohomology=True, base_ring=base_ring, @@ -775,6 +780,8 @@ def n_chains(self, n, base_ring=ZZ, cochains=False): sage: list(simplicial_complexes.Sphere(2).n_chains(1, QQ, cochains=True).basis()) [\chi_(0, 1), \chi_(0, 2), \chi_(0, 3), \chi_(1, 2), \chi_(1, 3), \chi_(2, 3)] """ + from sage.homology.chains import Chains, Cochains + n_cells = tuple(self._n_cells_sorted(n)) if cochains: return Cochains(self, n, n_cells, base_ring) @@ -836,25 +843,26 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): EXAMPLES:: sage: K = simplicial_complexes.KleinBottle() - sage: H = K.homology_with_basis(QQ); H + sage: H = K.homology_with_basis(QQ); H # optional - sage.modules Homology module of Minimal triangulation of the Klein bottle over Rational Field - sage: sorted(H.basis(), key=str) + sage: sorted(H.basis(), key=str) # optional - sage.modules [h_{0,0}, h_{1,0}] - sage: H = K.homology_with_basis(GF(2)); H + sage: H = K.homology_with_basis(GF(2)); H # optional - sage.modules sage.rings.finite_rings Homology module of Minimal triangulation of the Klein bottle over Finite Field of size 2 - sage: sorted(H.basis(), key=str) + sage: sorted(H.basis(), key=str) # optional - sage.modules sage.rings.finite_rings [h_{0,0}, h_{1,0}, h_{1,1}, h_{2,0}] The homology is constructed as a graded object, so for example, you can ask for the basis in a single degree:: - sage: H.basis(1) + sage: H.basis(1) # optional - sage.modules sage.rings.finite_rings Finite family {(1, 0): h_{1,0}, (1, 1): h_{1,1}} + sage: S3 = delta_complexes.Sphere(3) - sage: H = S3.homology_with_basis(QQ, cohomology=True) - sage: list(H.basis(3)) + sage: H = S3.homology_with_basis(QQ, cohomology=True) # optional - sage.modules + sage: list(H.basis(3)) # optional - sage.modules [h^{3,0}] """ from sage.homology.homology_vector_space_with_basis import HomologyVectorSpaceWithBasis @@ -899,10 +907,10 @@ def cohomology_ring(self, base_ring=QQ): over Rational Field sage: sorted(H.basis(), key=str) [h^{0,0}, h^{1,0}] - sage: H = K.cohomology_ring(GF(2)); H + sage: H = K.cohomology_ring(GF(2)); H # optional - sage.rings.finite_rings Cohomology ring of Minimal triangulation of the Klein bottle over Finite Field of size 2 - sage: sorted(H.basis(), key=str) + sage: sorted(H.basis(), key=str) # optional - sage.rings.finite_rings [h^{0,0}, h^{1,0}, h^{1,1}, h^{2,0}] sage: X = delta_complexes.SurfaceOfGenus(2) @@ -933,12 +941,12 @@ def cohomology_ring(self, base_ring=QQ): Cohomology operations:: - sage: RP2 = simplicial_complexes.RealProjectivePlane() - sage: K = RP2.suspension() - sage: K.set_immutable() - sage: y = K.cohomology_ring(GF(2)).basis()[2,0]; y + sage: RP2 = simplicial_complexes.RealProjectivePlane() # optional - sage.groups + sage: K = RP2.suspension() # optional - sage.graphs sage.groups + sage: K.set_immutable() # optional - sage.graphs sage.groups + sage: y = K.cohomology_ring(GF(2)).basis()[2,0]; y # optional - sage.graphs sage.groups sage.rings.finite_rings h^{2,0} - sage: y.Sq(1) + sage: y.Sq(1) # optional - sage.graphs sage.groups sage.rings.finite_rings h^{3,0} To compute the cohomology ring, the complex must be @@ -1031,13 +1039,13 @@ def face_poset(self): EXAMPLES:: - sage: P = SimplicialComplex([[0, 1], [1,2], [2,3]]).face_poset(); P + sage: P = SimplicialComplex([[0, 1], [1,2], [2,3]]).face_poset(); P # optional - sage.combinat sage.graphs Finite poset containing 7 elements - sage: sorted(P.list()) + sage: sorted(P.list()) # optional - sage.combinat sage.graphs [(0,), (0, 1), (1,), (1, 2), (2,), (2, 3), (3,)] sage: S2 = cubical_complexes.Sphere(2) - sage: S2.face_poset() + sage: S2.face_poset() # optional - sage.combinat sage.graphs Finite poset containing 26 elements """ from sage.combinat.posets.posets import Poset @@ -1079,27 +1087,26 @@ def is_connected(self): EXAMPLES:: - sage: V = SimplicialComplex([[0,1,2],[3]]) - sage: V + sage: V = SimplicialComplex([[0,1,2],[3]]); V Simplicial complex with vertex set (0, 1, 2, 3) and facets {(3,), (0, 1, 2)} - sage: V.is_connected() + sage: V.is_connected() # optional - sage.graphs False sage: X = SimplicialComplex([[0,1,2]]) - sage: X.is_connected() + sage: X.is_connected() # optional - sage.graphs True sage: U = simplicial_complexes.ChessboardComplex(3,3) - sage: U.is_connected() + sage: U.is_connected() # optional - sage.graphs True sage: W = simplicial_complexes.Sphere(3) - sage: W.is_connected() + sage: W.is_connected() # optional - sage.graphs True sage: S = SimplicialComplex([[0,1],[2,3]]) - sage: S.is_connected() + sage: S.is_connected() # optional - sage.graphs False - sage: cubical_complexes.Sphere(0).is_connected() + sage: cubical_complexes.Sphere(0).is_connected() # optional - sage.graphs False - sage: cubical_complexes.Sphere(2).is_connected() + sage: cubical_complexes.Sphere(2).is_connected() # optional - sage.graphs True """ return self.graph().is_connected() diff --git a/src/sage/topology/cubical_complex.py b/src/sage/topology/cubical_complex.py index 0ce508ec2c1..227dfbe8219 100644 --- a/src/sage/topology/cubical_complex.py +++ b/src/sage/topology/cubical_complex.py @@ -26,7 +26,8 @@ `(0,2)` to `(0,3)` to `(1,3)` to `(1,2)` to `(0,2)`. In Sage, this is done with the following command:: - sage: S1 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]), ([0,1], [2,2]), ([1,1], [2,3])]); S1 + sage: S1 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]), + ....: ([0,1], [2,2]), ([1,1], [2,3])]); S1 Cubical complex with 4 vertices and 8 cubes The argument to ``CubicalComplex`` is a list of the maximal "cubes" in @@ -47,7 +48,8 @@ sage: S1.homology() {0: 0, 1: Z} - sage: X = CubicalComplex([([0,0], [2,3], [2]), ([0,1], [3,3], [2]), ([0,1], [2,2], [2]), ([1,1], [2,3], [2])]) + sage: X = CubicalComplex([([0,0], [2,3], [2]), ([0,1], [3,3], [2]), + ....: ([0,1], [2,2], [2]), ([1,1], [2,3], [2])]) sage: X.homology() {0: 0, 1: Z} @@ -771,8 +773,8 @@ class :class:`Cube`, or lists or tuples suitable for conversion to A "circle" (four edges connecting the vertices (0,2), (0,3), (1,2), and (1,3)):: - sage: S1 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]), ([0,1], [2,2]), ([1,1], [2,3])]) - sage: S1 + sage: S1 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]), + ....: ([0,1], [2,2]), ([1,1], [2,3])]); S1 Cubical complex with 4 vertices and 8 cubes sage: S1.homology() {0: 0, 1: Z} @@ -832,12 +834,12 @@ class :class:`Cube`, or lists or tuples suitable for conversion to Cubical complex with 16 vertices and 64 cubes sage: T.chain_complex() Chain complex with at most 3 nonzero terms over Integer Ring - sage: T.homology(base_ring=QQ) + sage: T.homology(base_ring=QQ) # optional - sage.modules {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 2 over Rational Field, 2: Vector space of dimension 1 over Rational Field} sage: RP2 = cubical_complexes.RealProjectivePlane() - sage: RP2.cohomology(dim=[1, 2], base_ring=GF(2)) + sage: RP2.cohomology(dim=[1, 2], base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings {1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} @@ -1330,7 +1332,7 @@ def graph(self): EXAMPLES:: - sage: cubical_complexes.Sphere(2).graph() + sage: cubical_complexes.Sphere(2).graph() # optional - sage.graphs Graph on 8 vertices """ from sage.graphs.graph import Graph @@ -1549,12 +1551,12 @@ def connected_sum(self, other): sage: T = cubical_complexes.Torus() sage: S2 = cubical_complexes.Sphere(2) - sage: T.connected_sum(S2).cohomology() == T.cohomology() + sage: T.connected_sum(S2).cohomology() == T.cohomology() # optional - sage.modules True sage: RP2 = cubical_complexes.RealProjectivePlane() - sage: T.connected_sum(RP2).homology(1) + sage: T.connected_sum(RP2).homology(1) # optional - sage.modules Z x Z x C2 - sage: RP2.connected_sum(RP2).connected_sum(RP2).homology(1) + sage: RP2.connected_sum(RP2).connected_sum(RP2).homology(1) # optional - sage.modules Z x Z x C2 """ # connected_sum: first check whether the complexes are pure @@ -1670,14 +1672,14 @@ def algebraic_topological_model(self, base_ring=None): EXAMPLES:: sage: RP2 = cubical_complexes.RealProjectivePlane() - sage: phi, M = RP2.algebraic_topological_model(GF(2)) - sage: M.homology() + sage: phi, M = RP2.algebraic_topological_model(GF(2)) # optional - sage.rings.finite_rings + sage: M.homology() # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: T = cubical_complexes.Torus() sage: phi, M = T.algebraic_topological_model(QQ) - sage: M.homology() + sage: M.homology() # optional - sage.modules {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 2 over Rational Field, 2: Vector space of dimension 1 over Rational Field} diff --git a/src/sage/topology/delta_complex.py b/src/sage/topology/delta_complex.py index 012b92e351d..d4430d074b0 100644 --- a/src/sage/topology/delta_complex.py +++ b/src/sage/topology/delta_complex.py @@ -944,22 +944,22 @@ def product(self, other): sage: K = delta_complexes.KleinBottle() sage: X = K.product(K) - sage: X.homology(1) + sage: X.homology(1) # optional - sage.modules Z x Z x C2 x C2 - sage: X.homology(2) + sage: X.homology(2) # optional - sage.modules Z x C2 x C2 x C2 - sage: X.homology(3) + sage: X.homology(3) # optional - sage.modules C2 - sage: X.homology(4) + sage: X.homology(4) # optional - sage.modules 0 - sage: X.homology(base_ring=GF(2)) + sage: X.homology(base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 4 over Finite Field of size 2, 2: Vector space of dimension 6 over Finite Field of size 2, 3: Vector space of dimension 4 over Finite Field of size 2, 4: Vector space of dimension 1 over Finite Field of size 2} sage: S1 = delta_complexes.Sphere(1) - sage: K.product(S1).homology() == S1.product(K).homology() + sage: K.product(S1).homology() == S1.product(K).homology() # optional - sage.modules True sage: S1.product(S1) == delta_complexes.Torus() True @@ -1063,7 +1063,7 @@ def disjoint_union(self, right): sage: S1 = delta_complexes.Sphere(1) sage: S2 = delta_complexes.Sphere(2) - sage: S1.disjoint_union(S2).homology() + sage: S1.disjoint_union(S2).homology() # optional - sage.modules {0: Z, 1: Z, 2: Z} """ dim = max(self.dimension(), right.dimension()) @@ -1095,7 +1095,7 @@ def wedge(self, right): sage: S1 = delta_complexes.Sphere(1) sage: S2 = delta_complexes.Sphere(2) - sage: S1.wedge(S2).homology() + sage: S1.wedge(S2).homology() # optional - sage.modules {0: 0, 1: Z, 2: Z} """ data = self.disjoint_union(right).cells() @@ -1146,14 +1146,14 @@ def connected_sum(self, other): sage: T = delta_complexes.Torus() sage: S2 = delta_complexes.Sphere(2) - sage: T.connected_sum(S2).cohomology() == T.cohomology() + sage: T.connected_sum(S2).cohomology() == T.cohomology() # optional - sage.modules True sage: RP2 = delta_complexes.RealProjectivePlane() - sage: T.connected_sum(RP2).homology(1) + sage: T.connected_sum(RP2).homology(1) # optional - sage.modules Z x Z x C2 - sage: T.connected_sum(RP2).homology(2) + sage: T.connected_sum(RP2).homology(2) # optional - sage.modules 0 - sage: RP2.connected_sum(RP2).connected_sum(RP2).homology(1) + sage: RP2.connected_sum(RP2).connected_sum(RP2).homology(1) # optional - sage.modules Z x Z x C2 """ if not self.dimension() == other.dimension(): @@ -1272,7 +1272,7 @@ def elementary_subdivision(self, idx=-1): Delta complex with 2 vertices and 13 simplices sage: X.elementary_subdivision() Delta complex with 3 vertices and 19 simplices - sage: X.homology() == T.homology() + sage: X.homology() == T.homology() # optional - sage.modules True """ pi = self._epi_from_standard_simplex(idx=idx) @@ -1453,7 +1453,7 @@ def face_poset(self): EXAMPLES:: sage: T = delta_complexes.Torus() - sage: T.face_poset() + sage: T.face_poset() # optional - sage.combinat sage.graphs Finite poset containing 6 elements """ from sage.combinat.posets.posets import Poset @@ -1581,14 +1581,14 @@ def algebraic_topological_model(self, base_ring=None): EXAMPLES:: sage: RP2 = delta_complexes.RealProjectivePlane() - sage: phi, M = RP2.algebraic_topological_model(GF(2)) - sage: M.homology() + sage: phi, M = RP2.algebraic_topological_model(GF(2)) # optional - sage.rings.finite_rings + sage: M.homology() # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: T = delta_complexes.Torus() sage: phi, M = T.algebraic_topological_model(QQ) - sage: M.homology() + sage: M.homology() # optional - sage.modules {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 2 over Rational Field, 2: Vector space of dimension 1 over Rational Field} @@ -1649,7 +1649,7 @@ def Sphere(self,n): EXAMPLES:: - sage: delta_complexes.Sphere(4).cohomology(4, base_ring=GF(3)) + sage: delta_complexes.Sphere(4).cohomology(4, base_ring=GF(3)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 1 over Finite Field of size 3 """ if n == 1: @@ -1682,13 +1682,13 @@ def RealProjectivePlane(self): EXAMPLES:: sage: P = delta_complexes.RealProjectivePlane() - sage: P.cohomology(1) + sage: P.cohomology(1) # optional - sage.modules 0 - sage: P.cohomology(2) + sage: P.cohomology(2) # optional - sage.modules C2 - sage: P.cohomology(dim=1, base_ring=GF(2)) + sage: P.cohomology(dim=1, base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 1 over Finite Field of size 2 - sage: P.cohomology(dim=2, base_ring=GF(2)) + sage: P.cohomology(dim=2, base_ring=GF(2)) # optional - sage.modules sage.rings.finite_rings Vector space of dimension 1 over Finite Field of size 2 """ return DeltaComplex((((), ()), ((1, 0), (1, 0), (0, 0)), @@ -1744,9 +1744,9 @@ def SurfaceOfGenus(self, g, orientable=True): sage: delta_complexes.SurfaceOfGenus(1, orientable=False) Delta complex with 2 vertices and 8 simplices - sage: delta_complexes.SurfaceOfGenus(3, orientable=False).homology(1) + sage: delta_complexes.SurfaceOfGenus(3, orientable=False).homology(1) # optional - sage.modules Z x Z x C2 - sage: delta_complexes.SurfaceOfGenus(3, orientable=False).homology(2) + sage: delta_complexes.SurfaceOfGenus(3, orientable=False).homology(2) # optional - sage.modules 0 Compare to simplicial complexes:: @@ -1757,7 +1757,7 @@ def SurfaceOfGenus(self, g, orientable=True): sage: simpl_g4 = simplicial_complexes.SurfaceOfGenus(4) sage: simpl_g4.f_vector() [1, 19, 75, 50] - sage: delta_g4.homology() == simpl_g4.homology() + sage: delta_g4.homology() == simpl_g4.homology() # optional - sage.modules True """ try: diff --git a/src/sage/topology/filtered_simplicial_complex.py b/src/sage/topology/filtered_simplicial_complex.py index a8193680b29..c7bf66a66cb 100644 --- a/src/sage/topology/filtered_simplicial_complex.py +++ b/src/sage/topology/filtered_simplicial_complex.py @@ -16,25 +16,26 @@ EXAMPLES:: sage: FilteredSimplicialComplex([([0], 0), ([1], 0), ([0, 1], 1)]) - Filtered complex on vertex set (0, 1) and with simplices ((0,) : 0), ((1,) : 0), ((0, 1) : 1) + Filtered complex on vertex set (0, 1) and + with simplices ((0,) : 0), ((1,) : 0), ((0, 1) : 1) Sage can compute persistent homology of simplicial complexes:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 0), ([0, 1], 1)]) - sage: X.persistence_intervals(0) + sage: X.persistence_intervals(0) # optional - sage.modules sage.rings.finite_rings [(0, 1), (0, +Infinity)] FilteredSimplicialComplex objects are mutable. Filtration values can be set with the ``filtration`` method as follows:: sage: X = FilteredSimplicialComplex() # returns an empty complex - sage: X.persistence_intervals(1) + sage: X.persistence_intervals(1) # optional - sage.modules sage.rings.finite_rings [] sage: X.filtration(Simplex([0, 2]), 0) # recursively adds faces sage: X.filtration(Simplex([0, 1]), 0) sage: X.filtration(Simplex([1, 2]), 0) sage: X.filtration(Simplex([0, 1, 2]), 1) # closes the circle - sage: X.persistence_intervals(1) + sage: X.persistence_intervals(1) # optional - sage.modules sage.rings.finite_rings [(0, 1)] The filtration value of a simplex can be accessed as well with the @@ -359,7 +360,8 @@ def prune(self, threshold): sage: a.insert([0, 2], 2) sage: b = a.prune(1) sage: b - Filtered complex on vertex set (0, 1) and with simplices ((0,) : 0), ((1,) : 1), ((0, 1) : 1) + Filtered complex on vertex set (0, 1) and + with simplices ((0,) : 0), ((1,) : 1), ((0, 1) : 1) """ result_complex = FilteredSimplicialComplex() for s in self._filtration_dict: @@ -394,7 +396,7 @@ def _persistent_homology(self, field=2, strict=True, verbose=False): EXAMPLES:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 0), ([0,1], 2)]) - sage: X._persistent_homology()[0] + sage: X._persistent_homology()[0] # optional - sage.modules sage.rings.finite_rings [(0, 2), (0, +Infinity)] Some homology elements may have a lifespan or persistence of 0. @@ -402,7 +404,7 @@ def _persistent_homology(self, field=2, strict=True, verbose=False): sage: X = FilteredSimplicialComplex() sage: X.insert([0,1],1) # opens a hole and closes it instantly - sage: X._persistent_homology(strict=False)[0] + sage: X._persistent_homology(strict=False)[0] # optional - sage.modules sage.rings.finite_rings [(1, 1), (1, +Infinity)] REFERENCES: @@ -417,11 +419,11 @@ def _persistent_homology(self, field=2, strict=True, verbose=False): ....: ([1, 2], 1), ([0, 3], 2), ([2, 3], 2), ([0, 2], 3), ....: ([0, 1, 2], 4), ([0, 2, 3], 5)] sage: X = FilteredSimplicialComplex(l) - sage: X.persistence_intervals(0) + sage: X.persistence_intervals(0) # optional - sage.modules sage.rings.finite_rings [(0, 1), (1, 2), (0, +Infinity)] - sage: X.persistence_intervals(1) + sage: X.persistence_intervals(1) # optional - sage.modules sage.rings.finite_rings [(3, 4), (2, 5)] - sage: X.persistence_intervals(0, strict=False) + sage: X.persistence_intervals(0, strict=False) # optional - sage.modules sage.rings.finite_rings [(0, 1), (1, 1), (1, 2), (0, +Infinity)] """ # first, order the simplices in lexico order @@ -507,18 +509,18 @@ def _add_interval(self, s, t, intervals): TESTS:: sage: X = FilteredSimplicialComplex([([0], 0), ([1, 2], 10)]) - sage: int_list = X._persistent_homology() - sage: int_list[0] + sage: int_list = X._persistent_homology() # optional - sage.modules sage.rings.finite_rings + sage: int_list[0] # optional - sage.modules sage.rings.finite_rings [(0, +Infinity), (10, +Infinity)] - sage: X._add_interval(Simplex([0]), Simplex([1, 2]),int_list) - sage: int_list[0] + sage: X._add_interval(Simplex([0]), Simplex([1, 2]), int_list) # optional - sage.modules sage.rings.finite_rings + sage: int_list[0] # optional - sage.modules sage.rings.finite_rings [(0, +Infinity), (10, +Infinity), (0, 10)] Infinite interval:: sage: int_list2 = [[],[]] - sage: X._add_interval(Simplex([1, 2]), None, int_list2) - sage: int_list2[1] + sage: X._add_interval(Simplex([1, 2]), None, int_list2) # optional - sage.modules sage.rings.finite_rings + sage: int_list2[1] # optional - sage.modules sage.rings.finite_rings [(10, +Infinity)] """ # figure out dimension of homology element @@ -552,12 +554,12 @@ def _remove_pivot_rows(self, s, simplices): sage: l = [([0], 0), ([1], 0), ([2], 1), ([3], 1), ([0, 1], 1), ([1, 2], 1), ....: ([0, 3], 2), ([2, 3], 2), ([0, 2], 3), ([0, 1, 2], 4)] sage: X = FilteredSimplicialComplex(l) - sage: X._persistent_homology() + sage: X._persistent_homology() # optional - sage.modules sage.rings.finite_rings [[(0, 1), (1, 2), (0, +Infinity)], [(3, 4), (2, +Infinity)], []] - sage: X._remove_pivot_rows(Simplex([0,1,2]), list(X._filtration_dict)) + sage: X._remove_pivot_rows(Simplex([0,1,2]), list(X._filtration_dict)) # optional - sage.modules sage.rings.finite_rings 0 sage: X.insert([0,2,3],5) - sage: X._remove_pivot_rows(Simplex([0,2,3]), list(X._filtration_dict)) + sage: X._remove_pivot_rows(Simplex([0,2,3]), list(X._filtration_dict)) # optional - sage.modules sage.rings.finite_rings B[(2, 3)] """ d = self._chaingroup() @@ -603,12 +605,12 @@ def _max_index(self, d): TESTS:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 5), ([0, 1], 18), ([0, 2, 3], 32)]) - sage: X._persistent_homology() + sage: X._persistent_homology() # optional - sage.modules sage.rings.finite_rings [[(5, 18), (0, +Infinity)], [], []] - sage: a = X._chaingroup(Simplex([0, 1])) - sage: b = X._chaingroup(Simplex([0, 3])) - sage: d = a + b - sage: X._max_index(d) + sage: a = X._chaingroup(Simplex([0, 1])) # optional - sage.modules sage.rings.finite_rings + sage: b = X._chaingroup(Simplex([0, 3])) # optional - sage.modules sage.rings.finite_rings + sage: d = a + b # optional - sage.modules sage.rings.finite_rings + sage: X._max_index(d) # optional - sage.modules sage.rings.finite_rings 6 """ currmax = -1 @@ -637,7 +639,7 @@ def persistence_intervals(self, dimension, field=2, strict=True, verbose=None): EXAMPLES:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 1), ([0,1], 2)]) - sage: X.persistence_intervals(0) + sage: X.persistence_intervals(0) # optional - sage.modules sage.rings.finite_rings [(1, 2), (0, +Infinity)] """ if verbose is None: @@ -672,16 +674,16 @@ def betti_number(self, k, a, b, field=2, strict=True, verbose=None): EXAMPLES:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 0), ([0,1], 2)]) - sage: X.betti_number(0, 0.5, 1) + sage: X.betti_number(0, 0.5, 1) # optional - sage.modules sage.rings.finite_rings 2 - sage: X.betti_number(0, 1.5, 1) + sage: X.betti_number(0, 1.5, 1) # optional - sage.modules sage.rings.finite_rings 1 If an element vanishes at time ``a + b`` exactly, it does not count towards the Betti number:: sage: X = FilteredSimplicialComplex([([0], 0), ([1], 0), ([0,1], 2)]) - sage: X.betti_number(0, 1.5, 0.5) + sage: X.betti_number(0, 1.5, 0.5) # optional - sage.modules sage.rings.finite_rings 1 """ if verbose is None: diff --git a/src/sage/topology/simplicial_complex.py b/src/sage/topology/simplicial_complex.py index 9f3412543ec..207702727c9 100644 --- a/src/sage/topology/simplicial_complex.py +++ b/src/sage/topology/simplicial_complex.py @@ -82,7 +82,8 @@ Simplicial complex with vertex set () and facets {()} sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [3,0]]) sage: X - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1), (0, 3), (1, 2), (2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1), (0, 3), (1, 2), (2, 3)} Sage can perform a number of operations on simplicial complexes, such as the join and the product, and it can also compute homology:: @@ -91,7 +92,7 @@ sage: T = S.product(S) # torus sage: T Simplicial complex with 9 vertices and 18 facets - sage: T.homology() # this computes reduced homology + sage: T.homology() # this computes reduced homology # optional - sage.modules {0: 0, 1: Z x Z, 2: Z} sage: T.euler_characteristic() 0 @@ -173,8 +174,6 @@ from sage.misc.latex import latex from sage.misc.superseded import deprecation from sage.matrix.constructor import matrix -from sage.homology.chain_complex import ChainComplex -from sage.graphs.graph import Graph from functools import total_ordering from itertools import combinations, chain lazy_import('sage.categories.simplicial_complexes', 'SimplicialComplexes') @@ -895,7 +894,7 @@ class SimplicialComplex(Parent, GenericCellComplex): Cubical complex with 16 vertices and 64 cubes sage: Ts = SimplicialComplex(Tc); Ts Simplicial complex with 16 vertices and 32 facets - sage: Ts.homology() + sage: Ts.homology() # optional - sage.modules {0: 0, 1: Z x Z, 2: Z} In the situation where the first argument is a simplicial complex @@ -1474,12 +1473,12 @@ def g_vector(self): EXAMPLES:: - sage: S3 = simplicial_complexes.Sphere(3).barycentric_subdivision() - sage: S3.f_vector() + sage: S3 = simplicial_complexes.Sphere(3).barycentric_subdivision() # optional - sage.combinat sage.graphs + sage: S3.f_vector() # optional - sage.combinat sage.graphs [1, 30, 150, 240, 120] - sage: S3.h_vector() + sage: S3.h_vector() # optional - sage.combinat sage.graphs [1, 26, 66, 26, 1] - sage: S3.g_vector() + sage: S3.g_vector() # optional - sage.combinat sage.graphs [1, 25, 40] """ d = self.dimension() @@ -1601,14 +1600,14 @@ def F_triangle(self, S): EXAMPLES:: sage: cs = simplicial_complexes.Torus() - sage: cs.F_triangle(cs.facets()[0]) + sage: cs.F_triangle(cs.facets()[0]) # optional - sage.combinat F: x^3 + 9*x^2*y + 3*x*y^2 + y^3 + 6*x^2 + 12*x*y + 3*y^2 + 4*x + 3*y + 1 TESTS:: sage: S = SimplicialComplex([]) - sage: S.F_triangle(S.facets()[0]) + sage: S.F_triangle(S.facets()[0]) # optional - sage.combinat F: 1 """ x, y = polygens(ZZ, 'x, y') @@ -1626,8 +1625,8 @@ def posi(f): def flip_graph(self): """ - If ``self`` is pure, then it returns the flip graph of ``self``, - otherwise, it returns ``None``. + If ``self`` is pure, return the flip graph of ``self``, + otherwise, return ``None``. The flip graph of a pure simplicial complex is the (undirected) graph with vertices being the facets, such that two facets are joined by @@ -1638,29 +1637,29 @@ def flip_graph(self): EXAMPLES:: sage: S0 = simplicial_complexes.Sphere(0) - sage: G = S0.flip_graph() - sage: G.vertices(sort=True); G.edges(sort=True, labels=False) + sage: G = S0.flip_graph() # optional - sage.graphs + sage: G.vertices(sort=True); G.edges(sort=True, labels=False) # optional - sage.graphs [(0,), (1,)] [((0,), (1,))] - sage: G = (S0.wedge(S0)).flip_graph() - sage: G.vertices(sort=True); G.edges(sort=True, labels=False) + sage: G = (S0.wedge(S0)).flip_graph() # optional - sage.graphs + sage: G.vertices(sort=True); G.edges(sort=True, labels=False) # optional - sage.graphs [(0,), ('L1',), ('R1',)] [((0,), ('L1',)), ((0,), ('R1',)), (('L1',), ('R1',))] sage: S1 = simplicial_complexes.Sphere(1) sage: S2 = simplicial_complexes.Sphere(2) - sage: G = (S1.wedge(S1)).flip_graph() - sage: len(G.vertices(sort=False)) + sage: G = (S1.wedge(S1)).flip_graph() # optional - sage.graphs + sage: len(G.vertices(sort=False)) # optional - sage.graphs 6 - sage: len(G.edges(sort=False)) + sage: len(G.edges(sort=False)) # optional - sage.graphs 10 - sage: (S1.wedge(S2)).flip_graph() is None + sage: (S1.wedge(S2)).flip_graph() is None # optional - sage.graphs True - sage: G = S2.flip_graph() - sage: G.vertices(sort=True); G.edges(sort=True, labels=False) + sage: G = S2.flip_graph() # optional - sage.graphs + sage: G.vertices(sort=True); G.edges(sort=True, labels=False) # optional - sage.graphs [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)] [((0, 1, 2), (0, 1, 3)), ((0, 1, 2), (0, 2, 3)), @@ -1669,13 +1668,15 @@ def flip_graph(self): ((0, 1, 3), (1, 2, 3)), ((0, 2, 3), (1, 2, 3))] - sage: T = simplicial_complexes.Torus() - sage: G = T.suspension(4).flip_graph() - sage: len(G.vertices(sort=False)); len(G.edges(sort=False, labels=False)) + sage: T = simplicial_complexes.Torus() # optional - sage.graphs + sage: G = T.suspension(4).flip_graph() # optional - sage.graphs + sage: len(G.vertices(sort=False)); len(G.edges(sort=False, labels=False)) # optional - sage.graphs 46 161 """ from collections import defaultdict + from sage.graphs.graph import Graph + if not self.is_pure(): return None d = self.dimension() @@ -1699,7 +1700,7 @@ def flip_graph(self): def is_pseudomanifold(self): """ - Return True if self is a pseudomanifold. + Return True if ``self`` is a pseudomanifold. A pseudomanifold is a simplicial complex with the following properties: @@ -1720,20 +1721,20 @@ def is_pseudomanifold(self): EXAMPLES:: sage: S0 = simplicial_complexes.Sphere(0) - sage: S0.is_pseudomanifold() + sage: S0.is_pseudomanifold() # optional - sage.graphs True - sage: (S0.wedge(S0)).is_pseudomanifold() + sage: (S0.wedge(S0)).is_pseudomanifold() # optional - sage.graphs False sage: S1 = simplicial_complexes.Sphere(1) sage: S2 = simplicial_complexes.Sphere(2) - sage: (S1.wedge(S1)).is_pseudomanifold() + sage: (S1.wedge(S1)).is_pseudomanifold() # optional - sage.graphs False - sage: (S1.wedge(S2)).is_pseudomanifold() + sage: (S1.wedge(S2)).is_pseudomanifold() # optional - sage.graphs False - sage: S2.is_pseudomanifold() + sage: S2.is_pseudomanifold() # optional - sage.graphs True sage: T = simplicial_complexes.Torus() - sage: T.suspension(4).is_pseudomanifold() + sage: T.suspension(4).is_pseudomanifold() # optional - sage.graphs True """ if not self.is_pure(): @@ -1795,7 +1796,7 @@ def product(self, right, rename_vertices=True, is_mutable=True): sage: T = S.product(S) # torus sage: T Simplicial complex with 9 vertices and 18 facets - sage: T.homology() + sage: T.homology() # optional - sage.modules {0: 0, 1: Z x Z, 2: Z} These can get large pretty quickly:: @@ -1858,7 +1859,8 @@ def join(self, right, rename_vertices=True, is_mutable=True): sage: S.join(T) Simplicial complex with vertex set ('L0', 'L1', 'R2', 'R3') and 4 facets sage: S.join(T, rename_vertices=False) - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2), (0, 3), (1, 2), (1, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) + and facets {(0, 2), (0, 3), (1, 2), (1, 3)} The notation '*' may be used, as well:: @@ -1938,8 +1940,8 @@ def suspension(self, n=1, is_mutable=True): sage: S0 = SimplicialComplex([[0], [1]]) sage: S0.suspension() == simplicial_complexes.Sphere(1) True - sage: S3 = S0.suspension(3) # the 3-sphere - sage: S3.homology() + sage: S3 = S0.suspension(3) # the 3-sphere # optional - sage.graphs + sage: S3.homology() # optional - sage.graphs sage.modules {0: 0, 1: 0, 2: 0, 3: Z} For pseudomanifolds, the complex constructed here will be @@ -2000,7 +2002,7 @@ def disjoint_union(self, right, rename_vertices=True, is_mutable=True): sage: S1 = simplicial_complexes.Sphere(1) sage: S2 = simplicial_complexes.Sphere(2) - sage: S1.disjoint_union(S2).homology() + sage: S1.disjoint_union(S2).homology() # optional - sage.modules {0: Z, 1: Z, 2: Z} """ facets = [] @@ -2040,7 +2042,7 @@ def wedge(self, right, rename_vertices=True, is_mutable=True): sage: S1 = simplicial_complexes.Sphere(1) sage: S2 = simplicial_complexes.Sphere(2) - sage: S1.wedge(S2).homology() + sage: S1.wedge(S2).homology() # optional - sage.modules {0: 0, 1: Z, 2: Z} """ left_vertices = list(self.vertices()) @@ -2108,11 +2110,11 @@ def chain_complex(self, subcomplex=None, augmented=False, EXAMPLES:: sage: circle = SimplicialComplex([[0,1], [1,2], [0, 2]]) - sage: circle.chain_complex() + sage: circle.chain_complex() # optional - sage.modules Chain complex with at most 2 nonzero terms over Integer Ring - sage: circle.chain_complex()._latex_() + sage: circle.chain_complex()._latex_() # optional - sage.modules '\\Bold{Z}^{3} \\xrightarrow{d_{1}} \\Bold{Z}^{3}' - sage: circle.chain_complex(base_ring=QQ, augmented=True) + sage: circle.chain_complex(base_ring=QQ, augmented=True) # optional - sage.modules Chain complex with at most 3 nonzero terms over Rational Field """ # initialize subcomplex @@ -2217,6 +2219,8 @@ def chain_complex(self, subcomplex=None, augmented=False, current = self._n_cells_sorted(n-1, subcomplex=subcomplex) differentials[n-1] = matrix(base_ring, 0, len(current)) # finally, return the chain complex + from sage.homology.chain_complex import ChainComplex + if cochain: return ChainComplex(data=differentials, degree=1, base_ring=base_ring, check=check) @@ -2307,12 +2311,13 @@ def _homology_(self, dim=None, base_ring=ZZ, subcomplex=None, sage: sphere = SimplicialComplex([[0,1,2,3]]) sage: sphere.remove_face([0,1,2,3]) sage: sphere - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)} - sage: sphere._homology_() + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)} + sage: sphere._homology_() # optional - sage.modules {0: 0, 1: 0, 2: Z} - sage: sphere._homology_(reduced=False) + sage: sphere._homology_(reduced=False) # optional - sage.modules {0: Z, 1: 0, 2: Z} - sage: sphere._homology_(base_ring=GF(2), reduced=False) + sage: sphere._homology_(base_ring=GF(2), reduced=False) # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 0 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} @@ -2320,35 +2325,36 @@ def _homology_(self, dim=None, base_ring=ZZ, subcomplex=None, We need an immutable complex to compute homology generators:: sage: sphere.set_immutable() - sage: sphere._homology_(generators=True) + sage: sphere._homology_(generators=True) # optional - sage.modules {0: [], 1: [], 2: [(Z, (0, 1, 2) - (0, 1, 3) + (0, 2, 3) - (1, 2, 3))]} Another way to get a two-sphere: take a two-point space and take its three-fold join with itself:: sage: S = SimplicialComplex([[0], [1]]) - sage: (S*S*S)._homology_(dim=2, cohomology=True) + sage: (S*S*S)._homology_(dim=2, cohomology=True) # optional - sage.modules Z The same computation, done without finding a contractible subcomplex:: - sage: (S*S*S)._homology_(dim=2, cohomology=True, enlarge=False) + sage: (S*S*S)._homology_(dim=2, cohomology=True, enlarge=False) # optional - sage.modules Z Relative homology:: sage: T = SimplicialComplex([[0,1,2]]) sage: U = SimplicialComplex([[0,1], [1,2], [0,2]]) - sage: T._homology_(subcomplex=U) + sage: T._homology_(subcomplex=U) # optional - sage.modules {0: 0, 1: 0, 2: Z} Generators:: - sage: simplicial_complexes.Torus().homology(generators=True) + sage: simplicial_complexes.Torus().homology(generators=True) # optional - sage.modules {0: [], 1: [(Z, (2, 4) - (2, 6) + (4, 6)), (Z, (1, 4) - (1, 6) + (4, 6))], - 2: [(Z, - (0, 1, 2) - (0, 1, 5) + (0, 2, 6) - (0, 3, 4) + (0, 3, 5) - (0, 4, 6) - (1, 2, 4) + (1, 3, 4) - (1, 3, 6) + (1, 5, 6) - (2, 3, 5) + (2, 3, 6) + (2, 4, 5) - (4, 5, 6))]} + 2: [(Z, (0, 1, 2) - (0, 1, 5) + (0, 2, 6) - (0, 3, 4) + (0, 3, 5) + - (0, 4, 6) - (1, 2, 4) + (1, 3, 4) - (1, 3, 6) + (1, 5, 6) + - (2, 3, 5) + (2, 3, 6) + (2, 4, 5) - (4, 5, 6))]} """ from sage.homology.homology_group import HomologyGroup @@ -2479,15 +2485,15 @@ def algebraic_topological_model(self, base_ring=None): EXAMPLES:: - sage: RP2 = simplicial_complexes.RealProjectivePlane() - sage: phi, M = RP2.algebraic_topological_model(GF(2)) - sage: M.homology() + sage: RP2 = simplicial_complexes.RealProjectivePlane() # optional - sage.rings.finite_rings + sage: phi, M = RP2.algebraic_topological_model(GF(2)) # optional - sage.rings.finite_rings + sage: M.homology() # optional - sage.modules sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: T = simplicial_complexes.Torus() sage: phi, M = T.algebraic_topological_model(QQ) - sage: M.homology() + sage: M.homology() # optional - sage.modules {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 2 over Rational Field, 2: Vector space of dimension 1 over Rational Field} @@ -2563,27 +2569,27 @@ def add_face(self, face): sage: T.homology() {0: 0, 1: Z x Z x Z} sage: T.add_face([1,2,3]) - sage: T.homology() + sage: T.homology() # optional - sage.modules {0: 0, 1: Z x Z, 2: 0} Check that the ``_faces`` cache is treated correctly (:trac:`20758`):: sage: T = SimplicialComplex([range(1,5)]).n_skeleton(1) - sage: _ = T.faces() # populate the _faces attribute - sage: _ = T.homology() # add more to _faces - sage: T.add_face((1,2,3)) - sage: all(Simplex((1,2,3)) in T._faces[L][2] for L in T._faces) + sage: _ = T.faces() # populate the _faces attribute + sage: _ = T.homology() # add more to _faces # optional - sage.modules + sage: T.add_face((1,2,3)) # optional - sage.modules + sage: all(Simplex((1,2,3)) in T._faces[L][2] for L in T._faces) # optional - sage.modules True Check that the ``__enlarged`` cache is treated correctly (:trac:`20758`):: sage: T = SimplicialComplex([range(1,5)]).n_skeleton(1) - sage: T.homology() # to populate the __enlarged attribute + sage: T.homology() # to populate the __enlarged attribute # optional - sage.modules {0: 0, 1: Z x Z x Z} - sage: T.add_face([1,2,3]) - sage: len(T._SimplicialComplex__enlarged) > 0 + sage: T.add_face([1,2,3]) # optional - sage.modules + sage: len(T._SimplicialComplex__enlarged) > 0 # optional - sage.modules True Check we've fixed the bug reported at :trac:`14578`:: @@ -2592,7 +2598,7 @@ def add_face(self, face): sage: t0.add_face(('a', 'b')) sage: t0.add_face(('c', 'd', 'e')) sage: t0.add_face(('e', 'f', 'c')) - sage: t0.homology() + sage: t0.homology() # optional - sage.modules {0: Z, 1: 0, 2: 0} Check that we've fixed the bug reported at :trac:`22880`:: @@ -2686,14 +2692,17 @@ def remove_face(self, face, check=False): Simplicial complex with vertex set (1, 2, 3, 4) and facets {(1, 2, 3, 4)} sage: Z.remove_face([1,2]) sage: Z - Simplicial complex with vertex set (1, 2, 3, 4) and facets {(1, 3, 4), (2, 3, 4)} + Simplicial complex with vertex set (1, 2, 3, 4) and + facets {(1, 3, 4), (2, 3, 4)} sage: S = SimplicialComplex([[0,1,2],[2,3]]) sage: S - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(2, 3), (0, 1, 2)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(2, 3), (0, 1, 2)} sage: S.remove_face([0,1,2]) sage: S - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1), (0, 2), (1, 2), (2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1), (0, 2), (1, 2), (2, 3)} TESTS: @@ -2701,14 +2710,14 @@ def remove_face(self, face, check=False): :trac:`20758`:: sage: T = SimplicialComplex([range(1,5)]).n_skeleton(1) - sage: _ = T.faces() # populate the _faces attribute - sage: _ = T.homology() # add more to _faces - sage: T.add_face((1,2,3)) - sage: T.remove_face((1,2,3)) - sage: len(T._faces) + sage: _ = T.faces() # populate the _faces attribute + sage: _ = T.homology() # add more to _faces # optional - sage.modules + sage: T.add_face((1,2,3)) # optional - sage.modules + sage: T.remove_face((1,2,3)) # optional - sage.modules + sage: len(T._faces) # optional - sage.modules 2 - sage: T.remove_face((1,2)) - sage: len(T._faces) + sage: T.remove_face((1,2)) # optional - sage.modules + sage: len(T._faces) # optional - sage.modules 1 Check that the face to be removed can be given with a @@ -2900,7 +2909,7 @@ def connected_sum(self, other, is_mutable=True): sage: P + P # the Klein bottle Simplicial complex with 9 vertices and 18 facets - sage: (P + P).homology()[1] + sage: (P + P).homology()[1] # optional - sage.modules Z x C2 """ if not (self.is_pure() and other.is_pure() and @@ -3010,23 +3019,23 @@ def is_cohen_macaulay(self, base_ring=QQ, ncpus=0): Spheres are Cohen-Macaulay:: sage: S = SimplicialComplex([[1,2],[2,3],[3,1]]) - sage: S.is_cohen_macaulay(ncpus=3) + sage: S.is_cohen_macaulay(ncpus=3) # optional - sage.modules True The following example is taken from Bruns, Herzog - Cohen-Macaulay rings, Figure 5.3:: sage: S = SimplicialComplex([[1,2,3],[1,4,5]]) - sage: S.is_cohen_macaulay(ncpus=3) + sage: S.is_cohen_macaulay(ncpus=3) # optional - sage.modules False The choice of base ring can matter. The real projective plane `\RR P^2` has `H_1(\RR P^2) = \ZZ/2`, hence is CM over `\QQ` but not over `\ZZ`. :: sage: X = simplicial_complexes.RealProjectivePlane() - sage: X.is_cohen_macaulay() + sage: X.is_cohen_macaulay() # optional - sage.modules True - sage: X.is_cohen_macaulay(ZZ) + sage: X.is_cohen_macaulay(ZZ) # optional - sage.modules False """ from sage.parallel.decorate import parallel @@ -3532,7 +3541,8 @@ def stanley_reisner_ring(self, base_ring=ZZ): sage: X = SimplicialComplex([[0,1,2], [0,2,3]]) sage: X.stanley_reisner_ring() - Quotient of Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring by the ideal (x1*x3) + Quotient of Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring + by the ideal (x1*x3) sage: Y = SimplicialComplex([[0,1,2,3,4]]); Y Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2, 3, 4)} sage: Y.add_face([0,1,2,3,4]) @@ -3563,7 +3573,8 @@ def alexander_dual(self, is_mutable=True): EXAMPLES:: sage: Y = SimplicialComplex([[i] for i in range(5)]); Y - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0,), (1,), (2,), (3,), (4,)} + Simplicial complex with vertex set (0, 1, 2, 3, 4) and + facets {(0,), (1,), (2,), (3,), (4,)} sage: Y.alexander_dual() Simplicial complex with vertex set (0, 1, 2, 3, 4) and 10 facets sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [3,0]]) @@ -3583,18 +3594,16 @@ def barycentric_subdivision(self): EXAMPLES:: sage: triangle = SimplicialComplex([[0,1], [1,2], [0, 2]]) - sage: hexagon = triangle.barycentric_subdivision() - sage: hexagon + sage: hexagon = triangle.barycentric_subdivision(); hexagon # optional - sage.combinat sage.graphs Simplicial complex with 6 vertices and 6 facets - sage: hexagon.homology(1) == triangle.homology(1) + sage: hexagon.homology(1) == triangle.homology(1) # optional - sage.combinat sage.graphs sage.modules True Barycentric subdivisions can get quite large, since each `n`-dimensional facet in the original complex produces `(n+1)!` facets in the subdivision:: - sage: S4 = simplicial_complexes.Sphere(4) - sage: S4 + sage: S4 = simplicial_complexes.Sphere(4); S4 Minimal triangulation of the 4-sphere sage: S4.barycentric_subdivision() Simplicial complex with 62 vertices and 720 facets @@ -3629,13 +3638,17 @@ def stellar_subdivision(self, simplex, inplace=False, is_mutable=True): sage: F2 = Simplex([1,3]) sage: F3 = Simplex([1,2,3]) sage: SC.stellar_subdivision(F1) - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 4), (0, 2, 4), (1, 3, 4), (2, 3, 4)} + Simplicial complex with vertex set (0, 1, 2, 3, 4) and + facets {(0, 1, 4), (0, 2, 4), (1, 3, 4), (2, 3, 4)} sage: SC.stellar_subdivision(F2) - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2), (1, 2, 4), (2, 3, 4)} + Simplicial complex with vertex set (0, 1, 2, 3, 4) and + facets {(0, 1, 2), (1, 2, 4), (2, 3, 4)} sage: SC.stellar_subdivision(F3) - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2), (1, 2, 4), (1, 3, 4), (2, 3, 4)} + Simplicial complex with vertex set (0, 1, 2, 3, 4) and + facets {(0, 1, 2), (1, 2, 4), (1, 3, 4), (2, 3, 4)} sage: SC.stellar_subdivision(F3, inplace=True);SC - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2), (1, 2, 4), (1, 3, 4), (2, 3, 4)} + Simplicial complex with vertex set (0, 1, 2, 3, 4) and + facets {(0, 1, 2), (1, 2, 4), (1, 3, 4), (2, 3, 4)} The simplex to subdivide should be a face of self:: @@ -3699,12 +3712,14 @@ def graph(self): EXAMPLES:: sage: S = SimplicialComplex([[0,1,2,3]]) - sage: G = S.graph(); G + sage: G = S.graph(); G # optional - sage.graphs Graph on 4 vertices - sage: G.edges(sort=True) + sage: G.edges(sort=True) # optional - sage.graphs [(0, 1, None), (0, 2, None), (0, 3, None), (1, 2, None), (1, 3, None), (2, 3, None)] """ if self._graph is None: + from sage.graphs.graph import Graph + edges = self.n_cells(1) vertices = [min(f) for f in self._facets if f.dimension() == 0] used_vertices = [] # vertices which are in an edge @@ -3745,7 +3760,7 @@ def delta_complex(self, sort_simplices=False): sage: Td = T.delta_complex() sage: Td Delta complex with 7 vertices and 43 simplices - sage: T.homology() == Td.homology() + sage: T.homology() == Td.homology() # optional - sage.modules True """ from .delta_complex import DeltaComplex @@ -3774,11 +3789,11 @@ def is_flag_complex(self): EXAMPLES:: - sage: h = Graph({0:[1,2,3,4],1:[2,3,4],2:[3]}) - sage: x = h.clique_complex() - sage: x - Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 4), (0, 1, 2, 3)} - sage: x.is_flag_complex() + sage: h = Graph({0: [1,2,3,4], 1: [2,3,4], 2: [3]}) # optional - sage.graphs + sage: x = h.clique_complex(); x # optional - sage.graphs + Simplicial complex with vertex set (0, 1, 2, 3, 4) + and facets {(0, 1, 4), (0, 1, 2, 3)} + sage: x.is_flag_complex() # optional - sage.graphs True sage: X = simplicial_complexes.ChessboardComplex(3,3) @@ -3800,12 +3815,15 @@ def n_skeleton(self, n): sage: X = SimplicialComplex([[0,1], [1,2,3], [0,2,3]]) sage: X.n_skeleton(1) - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)} sage: X.set_immutable() sage: X.n_skeleton(2) - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1), (0, 2, 3), (1, 2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1), (0, 2, 3), (1, 2, 3)} sage: X.n_skeleton(4) - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1), (0, 2, 3), (1, 2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1), (0, 2, 3), (1, 2, 3)} """ if n >= self.dimension(): return self @@ -3845,10 +3863,12 @@ def _contractible_subcomplex(self, verbose=False): sage: sphere = SimplicialComplex([[0,1,2,3]]) sage: sphere.remove_face([0,1,2,3]) sage: sphere - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)} + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)} sage: L = sphere._contractible_subcomplex(); L - Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (0, 1, 3), (0, 2, 3)} - sage: L.homology() + Simplicial complex with vertex set (0, 1, 2, 3) and + facets {(0, 1, 2), (0, 1, 3), (0, 2, 3)} + sage: L.homology() # optional - sage.modules {0: 0, 1: 0, 2: 0} """ facets = [sorted(self._facets, key=str)[0]] @@ -3884,14 +3904,14 @@ def _enlarge_subcomplex(self, subcomplex, verbose=False): Inside the torus, define a subcomplex consisting of a loop:: sage: S = SimplicialComplex([[0,1], [1,2], [0,2]], is_mutable=False) - sage: S.homology() + sage: S.homology() # optional - sage.modules {0: 0, 1: Z} sage: L = T._enlarge_subcomplex(S) sage: L Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 8 facets sage: sorted(L.facets()) [(0, 1), (0, 1, 5), (0, 2), (0, 2, 6), (0, 3, 4), (0, 3, 5), (0, 4, 6), (1, 2)] - sage: L.homology()[1] + sage: L.homology()[1] # optional - sage.modules Z """ # Make the subcomplex immutable if not @@ -3973,12 +3993,12 @@ def _cubical_(self): EXAMPLES:: sage: T = simplicial_complexes.Torus() - sage: T.homology() + sage: T.homology() # optional - sage.modules {0: 0, 1: Z x Z, 2: Z} sage: Tc = T._cubical_() sage: Tc Cubical complex with 42 vertices and 168 cubes - sage: Tc.homology() + sage: Tc.homology() # optional - sage.modules {0: 0, 1: Z x Z, 2: Z} """ from .cubical_complex import CubicalComplex @@ -4015,20 +4035,22 @@ def connected_component(self, simplex=None): EXAMPLES:: sage: S1 = simplicial_complexes.Sphere(1) - sage: S1 == S1.connected_component() + sage: S1 == S1.connected_component() # optional - sage.graphs True sage: X = S1.disjoint_union(S1) - sage: X == X.connected_component() + sage: X == X.connected_component() # optional - sage.graphs False - sage: X.connected_component(Simplex(['L0'])) == X.connected_component(Simplex(['R0'])) + sage: CL0 = X.connected_component(Simplex(['L0'])) # optional - sage.graphs + sage: CR0 = X.connected_component(Simplex(['R0'])) # optional - sage.graphs + sage: CL0 == CR0 # optional - sage.graphs False sage: S0 = simplicial_complexes.Sphere(0) sage: S0.vertices() (0, 1) - sage: S0.connected_component() + sage: S0.connected_component() # optional - sage.graphs Simplicial complex with vertex set (0,) and facets {(0,)} - sage: S0.connected_component(Simplex((1,))) + sage: S0.connected_component(Simplex((1,))) # optional - sage.graphs Simplicial complex with vertex set (1,) and facets {(1,)} sage: SimplicialComplex([[]]).connected_component() @@ -4075,7 +4097,7 @@ def fundamental_group(self, base_point=None, simplify=True): EXAMPLES:: sage: S1 = simplicial_complexes.Sphere(1) - sage: S1.fundamental_group() + sage: S1.fundamental_group() # optional - sage.graphs sage.groups Finitely presented group < e | > If we pass the argument ``simplify=False``, we get generators and @@ -4083,43 +4105,43 @@ def fundamental_group(self, base_point=None, simplify=True): cyclic group of order 2, for instance:: sage: RP2 = simplicial_complexes.RealProjectiveSpace(2) - sage: C2 = RP2.fundamental_group(simplify=False) - sage: C2 - Finitely presented group < e0, e1, e2, e3, e4, e5, e6, e7, e8, e9 | e0, e3, e4, e7, e9, e5*e2^-1*e0, e7*e2^-1*e1, e8*e3^-1*e1, e8*e6^-1*e4, e9*e6^-1*e5 > - sage: C2.simplified() + sage: C2 = RP2.fundamental_group(simplify=False); C2 # optional - sage.graphs sage.groups + Finitely presented group < e0, e1, e2, e3, e4, e5, e6, e7, e8, e9 | e0, e3, + e4, e7, e9, e5*e2^-1*e0, e7*e2^-1*e1, e8*e3^-1*e1, e8*e6^-1*e4, e9*e6^-1*e5 > + sage: C2.simplified() # optional - sage.graphs sage.groups Finitely presented group < e1 | e1^2 > This is the same answer given if the argument ``simplify`` is True (the default):: - sage: RP2.fundamental_group() + sage: RP2.fundamental_group() # optional - sage.graphs sage.groups Finitely presented group < e1 | e1^2 > You must specify a base point to compute the fundamental group of a non-connected complex:: - sage: K = S1.disjoint_union(RP2) - sage: K.fundamental_group() + sage: K = S1.disjoint_union(RP2) # optional - sage.graphs sage.groups + sage: K.fundamental_group() # optional - sage.graphs sage.groups Traceback (most recent call last): ... ValueError: this complex is not connected, so you must specify a base point - sage: K.fundamental_group(base_point='L0') + sage: K.fundamental_group(base_point='L0') # optional - sage.graphs sage.groups Finitely presented group < e | > - sage: K.fundamental_group(base_point='R0').order() + sage: K.fundamental_group(base_point='R0').order() # optional - sage.graphs sage.groups 2 Some other examples:: - sage: S1.wedge(S1).fundamental_group() + sage: S1.wedge(S1).fundamental_group() # optional - sage.graphs sage.groups Finitely presented group < e0, e1 | > - sage: simplicial_complexes.Torus().fundamental_group() + sage: simplicial_complexes.Torus().fundamental_group() # optional - sage.graphs sage.groups Finitely presented group < e1, e4 | e4^-1*e1^-1*e4*e1 > - sage: G = simplicial_complexes.MooreSpace(5).fundamental_group() - sage: G.ngens() + sage: G = simplicial_complexes.MooreSpace(5).fundamental_group() # optional - sage.graphs sage.groups + sage: G.ngens() # optional - sage.graphs sage.groups 1 - sage: x = G.gen(0) - sage: [(x**n).is_one() for n in range(1,6)] + sage: x = G.gen(0) # optional - sage.graphs sage.groups + sage: [(x**n).is_one() for n in range(1,6)] # optional - sage.graphs sage.groups [False, False, False, False, True] """ if not self.is_connected(): @@ -4188,18 +4210,18 @@ def is_isomorphic(self, other, certificate=False): sage: Z1 = SimplicialComplex([[0,1],[1,2],[2,3,4],[4,5]]) sage: Z2 = SimplicialComplex([['a','b'],['b','c'],['c','d','e'],['e','f']]) sage: Z3 = SimplicialComplex([[1,2,3]]) - sage: Z1.is_isomorphic(Z2) + sage: Z1.is_isomorphic(Z2) # optional - sage.graphs True - sage: Z1.is_isomorphic(Z2, certificate=True) + sage: Z1.is_isomorphic(Z2, certificate=True) # optional - sage.graphs (True, {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}) - sage: Z3.is_isomorphic(Z2) + sage: Z3.is_isomorphic(Z2) # optional - sage.graphs False We check that :trac:`20751` is fixed:: sage: C1 = SimplicialComplex([[1,2,3], [2,4], [3,5], [5,6]]) sage: C2 = SimplicialComplex([['a','b','c'], ['b','d'], ['c','e'], ['e','f']]) - sage: C1.is_isomorphic(C2, certificate=True) + sage: C1.is_isomorphic(C2, certificate=True) # optional - sage.graphs (True, {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f'}) """ # Check easy invariants agree @@ -4207,6 +4229,9 @@ def is_isomorphic(self, other, certificate=False): != sorted(x.dimension() for x in other._facets) or len(self.vertices()) != len(other.vertices())): return False + + from sage.graphs.graph import Graph + g1 = Graph() g2 = Graph() # With Python 3, "is_isomorphic" for graphs works best if the @@ -4252,27 +4277,28 @@ def automorphism_group(self): EXAMPLES:: sage: S = simplicial_complexes.Simplex(3) - sage: S.automorphism_group().is_isomorphic(SymmetricGroup(4)) + sage: S.automorphism_group().is_isomorphic(SymmetricGroup(4)) # optional - sage.graphs sage.groups True sage: P = simplicial_complexes.RealProjectivePlane() - sage: P.automorphism_group().is_isomorphic(AlternatingGroup(5)) + sage: P.automorphism_group().is_isomorphic(AlternatingGroup(5)) # optional - sage.graphs sage.groups True sage: Z = SimplicialComplex([['1','2'],['2','3','a']]) - sage: Z.automorphism_group().is_isomorphic(CyclicPermutationGroup(2)) + sage: Z.automorphism_group().is_isomorphic(CyclicPermutationGroup(2)) # optional - sage.graphs sage.groups True - sage: group = Z.automorphism_group() - sage: sorted(group.domain()) + sage: group = Z.automorphism_group() # optional - sage.graphs sage.groups + sage: sorted(group.domain()) # optional - sage.graphs sage.groups ['1', '2', '3', 'a'] Check that :trac:`17032` is fixed:: sage: s = SimplicialComplex([[(0,1),(2,3)]]) - sage: s.automorphism_group().cardinality() + sage: s.automorphism_group().cardinality() # optional - sage.graphs sage.groups 2 """ from sage.groups.perm_gps.permgroup import PermutationGroup + from sage.graphs.graph import Graph G = Graph() G.add_vertices(self.vertices()) @@ -4309,26 +4335,25 @@ def fixed_complex(self, G): sage: S4 = simplicial_complexes.Sphere(4) sage: S3 = simplicial_complexes.Sphere(3) - sage: fix = S4.fixed_complex([S4.automorphism_group()([(0,1)])]) - sage: fix + sage: fix = S4.fixed_complex([S4.automorphism_group()([(0,1)])]); fix # optional - sage.graphs sage.groups Simplicial complex with vertex set (0, 2, 3, 4, 5) and 5 facets - sage: fix.is_isomorphic(S3) + sage: fix.is_isomorphic(S3) # optional - sage.graphs sage.groups True Another simple example:: sage: T = SimplicialComplex([[1,2,3],[2,3,4]]) - sage: G = T.automorphism_group() - sage: T.fixed_complex([G([(1,4)])]) + sage: G = T.automorphism_group() # optional - sage.graphs sage.groups + sage: T.fixed_complex([G([(1,4)])]) # optional - sage.graphs sage.groups Simplicial complex with vertex set (2, 3) and facets {(2, 3)} A more sophisticated example:: sage: RP2 = simplicial_complexes.ProjectivePlane() sage: CP2 = simplicial_complexes.ComplexProjectivePlane() - sage: G = CP2.automorphism_group() - sage: H = G.subgroup([G([(2,3),(5,6),(8,9)])]) - sage: CP2.fixed_complex(H).is_isomorphic(RP2) + sage: G = CP2.automorphism_group() # optional - sage.graphs sage.groups + sage: H = G.subgroup([G([(2,3),(5,6),(8,9)])]) # optional - sage.graphs sage.groups + sage: CP2.fixed_complex(H).is_isomorphic(RP2) # optional - sage.graphs sage.groups True """ from sage.categories.groups import Groups @@ -4621,7 +4646,8 @@ def decone(self): sage: SimplicialComplex([[1,2,3]]).decone() Simplicial complex with vertex set () and facets {()} sage: SimplicialComplex([[1,2,3], [1,3,4], [1,5,6]]).decone() - Simplicial complex with vertex set (2, 3, 4, 5, 6) and facets {(2, 3), (3, 4), (5, 6)} + Simplicial complex with vertex set (2, 3, 4, 5, 6) + and facets {(2, 3), (3, 4), (5, 6)} sage: X = SimplicialComplex([[1,2,3], [1,3,4], [2,5,6]]) sage: X.decone() == X True @@ -4653,29 +4679,29 @@ def is_balanced(self, check_purity=False, certificate=False): A 1-dim simplicial complex is balanced iff it is bipartite:: - sage: X = SimplicialComplex([[1,2],[1,4],[3,4],[2,5]]) - sage: X.is_balanced() + sage: X = SimplicialComplex([[1,2], [1,4], [3,4], [2,5]]) + sage: X.is_balanced() # optional - sage.graphs True - sage: sorted(X.is_balanced(certificate=True)) + sage: sorted(X.is_balanced(certificate=True)) # optional - sage.graphs [[1, 3, 5], [2, 4]] - sage: X = SimplicialComplex([[1,2],[1,4],[3,4],[2,4]]) - sage: X.is_balanced() + sage: X = SimplicialComplex([[1,2], [1,4], [3,4], [2,4]]) + sage: X.is_balanced() # optional - sage.graphs False Any barycentric division is balanced:: - sage: X = SimplicialComplex([[1,2,3],[1,2,4],[2,3,4]]) - sage: X.is_balanced() + sage: X = SimplicialComplex([[1,2,3], [1,2,4], [2,3,4]]) + sage: X.is_balanced() # optional - sage.graphs False - sage: X.barycentric_subdivision().is_balanced() + sage: X.barycentric_subdivision().is_balanced() # optional - sage.graphs True A non-pure balanced complex:: - sage: X=SimplicialComplex([[1,2,3],[3,4]]) - sage: X.is_balanced(check_purity=True) + sage: X = SimplicialComplex([[1,2,3], [3,4]]) + sage: X.is_balanced(check_purity=True) # optional - sage.graphs False - sage: sorted(X.is_balanced(certificate=True)) + sage: sorted(X.is_balanced(certificate=True)) # optional - sage.graphs [[1, 4], [2], [3]] """ d = 1 + self.dimension() @@ -4730,7 +4756,7 @@ def is_partitionable(self, certificate=False, Simplices are trivially partitionable:: - sage: X = SimplicialComplex([ [1,2,3,4] ]) + sage: X = SimplicialComplex([[1,2,3,4]]) sage: X.is_partitionable() True sage: X.is_partitionable(certificate=True) @@ -4738,23 +4764,27 @@ def is_partitionable(self, certificate=False, Shellable complexes are partitionable:: - sage: X = SimplicialComplex([ [1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5] ]) + sage: X = SimplicialComplex([[1,3,5], [1,3,6], [1,4,5], [1,4,6], + ....: [2,3,5], [2,3,6], [2,4,5]]) sage: X.is_partitionable() True sage: P = X.is_partitionable(certificate=True) - sage: n_intervals_containing = lambda f: len([ RF for RF in P if RF[0].is_face(f) and f.is_face(RF[1]) ]) - sage: all( n_intervals_containing(f)==1 for k in X.faces().keys() for f in X.faces()[k] ) + sage: def n_intervals_containing(f): + ....: return len([RF for RF in P + ....: if RF[0].is_face(f) and f.is_face(RF[1])]) + sage: all(n_intervals_containing(f) == 1 + ....: for k in X.faces().keys() for f in X.faces()[k]) True A non-shellable, non-Cohen-Macaulay, partitionable example, constructed by Björner:: - sage: X = SimplicialComplex([ [1,2,3],[1,2,4],[1,3,4],[2,3,4],[1,5,6] ]) + sage: X = SimplicialComplex([[1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,5,6]]) sage: X.is_partitionable() True The bowtie complex is not partitionable:: - sage: X = SimplicialComplex([ [1,2,3],[1,4,5] ]) + sage: X = SimplicialComplex([[1,2,3], [1,4,5]]) sage: X.is_partitionable() False """ @@ -4785,9 +4815,9 @@ def intersection(self, other): EXAMPLES:: - sage: X = SimplicialComplex([[1,2,3],[1,2,4]]) - sage: Y = SimplicialComplex([[1,2,3],[1,4,5]]) - sage: Z = SimplicialComplex([[1,2,3],[1,4],[2,4]]) + sage: X = SimplicialComplex([[1,2,3], [1,2,4]]) + sage: Y = SimplicialComplex([[1,2,3], [1,4,5]]) + sage: Z = SimplicialComplex([[1,2,3], [1,4], [2,4]]) sage: sorted(X.intersection(Y).facets()) [(1, 2, 3), (1, 4)] sage: X.intersection(X) == X diff --git a/src/sage/topology/simplicial_complex_examples.py b/src/sage/topology/simplicial_complex_examples.py index a1403bcd43c..084d2687a8a 100644 --- a/src/sage/topology/simplicial_complex_examples.py +++ b/src/sage/topology/simplicial_complex_examples.py @@ -229,7 +229,7 @@ def __classcall__(self, maximal_faces=None, name=None, **kwds): Testing ``from_characteristic_function``:: - sage: UniqueSimplicialComplex(from_characteristic_function=(lambda x:sum(x)<=4, range(5))) + sage: UniqueSimplicialComplex(from_characteristic_function=(lambda x: sum(x) <= 4, range(5))) Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 4), (0, 1, 2), (0, 1, 3)} """ char_fcn = kwds.get('from_characteristic_function', None) @@ -469,7 +469,7 @@ def MooreSpace(q): INPUT: - - ``q`` -0 integer, at least 2 + - ``q`` -- integer, at least 2 This is a simplicial complex with simplices of dimension 0, 1, and 2, such that its reduced homology is isomorphic to @@ -572,14 +572,14 @@ def QuaternionicProjectivePlane(): EXAMPLES:: - sage: HP2 = simplicial_complexes.QuaternionicProjectivePlane() ; HP2 + sage: HP2 = simplicial_complexes.QuaternionicProjectivePlane(); HP2 # optional - sage.groups Simplicial complex with 15 vertices and 490 facets - sage: HP2.f_vector() + sage: HP2.f_vector() # optional - sage.groups [1, 15, 105, 455, 1365, 3003, 4515, 4230, 2205, 490] Checking its automorphism group:: - sage: HP2.automorphism_group().is_isomorphic(AlternatingGroup(5)) + sage: HP2.automorphism_group().is_isomorphic(AlternatingGroup(5)) # optional - sage.groups True """ from sage.groups.perm_gps.permgroup import PermutationGroup @@ -852,7 +852,7 @@ def K3Surface(): EXAMPLES:: - sage: K3=simplicial_complexes.K3Surface() ; K3 + sage: K3 = simplicial_complexes.K3Surface(); K3 Minimal triangulation of the K3 surface sage: K3.f_vector() [1, 16, 120, 560, 720, 288] @@ -975,7 +975,7 @@ def BarnetteSphere(): EXAMPLES:: - sage: BS = simplicial_complexes.BarnetteSphere() ; BS + sage: BS = simplicial_complexes.BarnetteSphere(); BS Barnette's triangulation of the 3-sphere sage: BS.f_vector() [1, 8, 27, 38, 19] @@ -992,7 +992,7 @@ def BarnetteSphere(): ....: [3, 4, 5, 8], [4, 5, 6, 8], [1, 2, 6, 8], ....: [1, 5, 6, 8], [1, 3, 5, 8], [2, 4, 6, 8], ....: [1, 3, 5, 7]]) - sage: BS.is_isomorphic(BS2) + sage: BS.is_isomorphic(BS2) # optional - sage.graphs True """ return UniqueSimplicialComplex([ @@ -1018,7 +1018,7 @@ def BrucknerGrunbaumSphere(): EXAMPLES:: - sage: BGS = simplicial_complexes.BrucknerGrunbaumSphere() ; BGS + sage: BGS = simplicial_complexes.BrucknerGrunbaumSphere(); BGS Bruckner and Grunbaum's triangulation of the 3-sphere sage: BGS.f_vector() [1, 8, 28, 40, 20] @@ -1116,8 +1116,7 @@ def MatchingComplex(n): EXAMPLES:: sage: M = simplicial_complexes.MatchingComplex(7) - sage: H = M.homology() - sage: H + sage: H = M.homology(); H {0: 0, 1: C3, 2: Z^20} sage: H[2].ngens() 20 @@ -1401,15 +1400,15 @@ def RandomTwoSphere(n): EXAMPLES:: - sage: G = simplicial_complexes.RandomTwoSphere(6); G + sage: G = simplicial_complexes.RandomTwoSphere(6); G # optional - sage.graphs Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and 8 facets - sage: G.homology() + sage: G.homology() # optional - sage.graphs {0: 0, 1: 0, 2: Z} - sage: G.is_pure() + sage: G.is_pure() # optional - sage.graphs True - sage: fg = G.flip_graph(); fg + sage: fg = G.flip_graph(); fg # optional - sage.graphs Graph on 8 vertices - sage: fg.is_planar() and fg.is_regular(3) + sage: fg.is_planar() and fg.is_regular(3) # optional - sage.graphs True """ from sage.graphs.generators.random import RandomTriangulation @@ -1448,14 +1447,14 @@ def ShiftedComplex(generators): EXAMPLES:: - sage: X = simplicial_complexes.ShiftedComplex([ Simplex([1, 6]), (2, 4), [8] ]) - sage: sorted(X.facets()) + sage: X = simplicial_complexes.ShiftedComplex([Simplex([1, 6]), (2, 4), [8]]) # optional - sage.combinat + sage: sorted(X.facets()) # optional - sage.combinat [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (7,), (8,)] - sage: X = simplicial_complexes.ShiftedComplex([ [2, 3, 5] ]) - sage: sorted(X.facets()) + sage: X = simplicial_complexes.ShiftedComplex([[2, 3, 5]]) # optional - sage.combinat + sage: sorted(X.facets()) # optional - sage.combinat [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (2, 3, 4), (2, 3, 5)] - sage: X = simplicial_complexes.ShiftedComplex([ [1, 3, 5], [2, 6] ]) - sage: sorted(X.facets()) + sage: X = simplicial_complexes.ShiftedComplex([[1, 3, 5], [2, 6]]) # optional - sage.combinat + sage: sorted(X.facets()) # optional - sage.combinat [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 6), (2, 6)] """ from sage.combinat.partition import Partitions @@ -1577,14 +1576,14 @@ def FareyMap(p): EXAMPLES:: - sage: S5 = simplicial_complexes.FareyMap(5); S5 + sage: S5 = simplicial_complexes.FareyMap(5); S5 # optional - sage.groups Simplicial complex with 12 vertices and 20 facets - sage: S5.automorphism_group().cardinality() + sage: S5.automorphism_group().cardinality() # optional - sage.groups 120 - sage: S7 = simplicial_complexes.FareyMap(7); S7 + sage: S7 = simplicial_complexes.FareyMap(7); S7 # optional - sage.groups Simplicial complex with 24 vertices and 56 facets - sage: S7.f_vector() + sage: S7.f_vector() # optional - sage.groups [1, 24, 84, 56] REFERENCES: @@ -1642,7 +1641,7 @@ def GenusSix(): EXAMPLES:: sage: S = simplicial_complexes.GenusSix() - sage: S.automorphism_group().cardinality() + sage: S.automorphism_group().cardinality() # optional - sage.groups 12 sage: S.betti() {0: 1, 1: 12, 2: 1} diff --git a/src/sage/topology/simplicial_complex_homset.py b/src/sage/topology/simplicial_complex_homset.py index 8f7b84d1cde..6b36184c7fc 100644 --- a/src/sage/topology/simplicial_complex_homset.py +++ b/src/sage/topology/simplicial_complex_homset.py @@ -110,8 +110,7 @@ def diagonal_morphism(self,rename_vertices=True): sage: S = simplicial_complexes.Sphere(2) sage: H = Hom(S,S.product(S, is_mutable=False)) - sage: d = H.diagonal_morphism() - sage: d + sage: d = H.diagonal_morphism(); d Simplicial complex morphism: From: Minimal triangulation of the 2-sphere To: Simplicial complex with 16 vertices and 96 facets @@ -121,13 +120,13 @@ def diagonal_morphism(self,rename_vertices=True): 3 |--> L3R3 sage: T = SimplicialComplex([[0], [1]], is_mutable=False) - sage: U = T.product(T,rename_vertices = False, is_mutable=False) - sage: G = Hom(T,U) - sage: e = G.diagonal_morphism(rename_vertices = False) - sage: e + sage: U = T.product(T, rename_vertices=False, is_mutable=False) + sage: G = Hom(T, U) + sage: e = G.diagonal_morphism(rename_vertices=False); e Simplicial complex morphism: From: Simplicial complex with vertex set (0, 1) and facets {(0,), (1,)} - To: Simplicial complex with 4 vertices and facets {((0, 0),), ((0, 1),), ((1, 0),), ((1, 1),)} + To: Simplicial complex with 4 vertices and + facets {((0, 0),), ((0, 1),), ((1, 0),), ((1, 1),)} Defn: 0 |--> (0, 0) 1 |--> (1, 1) """ @@ -150,15 +149,16 @@ def identity(self): EXAMPLES:: sage: S = simplicial_complexes.Sphere(2) - sage: H = Hom(S,S) + sage: H = Hom(S, S) sage: i = H.identity() sage: i.is_identity() True sage: T = SimplicialComplex([[0,1]], is_mutable=False) - sage: G = Hom(T,T) + sage: G = Hom(T, T) sage: G.identity() - Simplicial complex endomorphism of Simplicial complex with vertex set (0, 1) and facets {(0, 1)} + Simplicial complex endomorphism of + Simplicial complex with vertex set (0, 1) and facets {(0, 1)} Defn: 0 |--> 0 1 |--> 1 """ diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 321442fdc8f..8508ba44a01 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -41,10 +41,9 @@ sage: simplicial_sets.Torus() Torus - sage: simplicial_sets.RealProjectiveSpace(7) + sage: simplicial_sets.RealProjectiveSpace(7) # optional - sage.groups RP^7 - sage: S5 = simplicial_sets.Sphere(5) - sage: S5 + sage: S5 = simplicial_sets.Sphere(5); S5 S^5 sage: S5.nondegenerate_simplices() [v_0, sigma_5] @@ -817,14 +816,14 @@ def __deepcopy__(self, memo): copies of simplicial sets:: sage: from sage.topology.simplicial_set import SimplicialSet - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) - sage: dict(copy.copy(RP3._data)) == dict(RP3._data) + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.groups + sage: dict(copy.copy(RP3._data)) == dict(RP3._data) # optional - sage.groups True - sage: dict(copy.deepcopy(RP3._data)) == dict(RP3._data) + sage: dict(copy.deepcopy(RP3._data)) == dict(RP3._data) # optional - sage.groups False - sage: SimplicialSet(RP3) == RP3 + sage: SimplicialSet(RP3) == RP3 # optional - sage.groups False - sage: copy.copy(RP3) == RP3 + sage: copy.copy(RP3) == RP3 # optional - sage.groups False """ underlying = self.nondegenerate() @@ -1151,11 +1150,11 @@ def faces(self, simplex): sage: S2.faces(sigma.apply_degeneracies(0)) [sigma_2, sigma_2, s_1 s_0 v_0, s_1 s_0 v_0] - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: f2 = BC3.n_cells(1)[1]; f2 + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: f2 = BC3.n_cells(1)[1]; f2 # optional - sage.groups f^2 - sage: BC3.faces(f2) + sage: BC3.faces(f2) # optional - sage.groups (1, 1) TESTS:: @@ -1356,11 +1355,11 @@ def nondegenerate_simplices(self, max_dim=None): Test an infinite example:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.nondegenerate_simplices(2) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.nondegenerate_simplices(2) # optional - sage.groups [1, f, f^2, f * f, f * f^2, f^2 * f, f^2 * f^2] - sage: BC3.nondegenerate_simplices() + sage: BC3.nondegenerate_simplices() # optional - sage.groups Traceback (most recent call last): ... NotImplementedError: this simplicial set may be infinite, so specify max_dim @@ -1411,20 +1410,20 @@ def cells(self, subcomplex=None, max_dim=None): sage: S1.cells() {0: [v], 1: [e]} - sage: S0.cells(S0.subsimplicial_set([v, w])) + sage: S0.cells(S0.subsimplicial_set([v, w])) # optional - sage.graphs {0: [*]} sage: X = SimplicialSet({e: (v,w)}) - sage: X.cells(X.subsimplicial_set([v, w])) + sage: X.cells(X.subsimplicial_set([v, w])) # optional - sage.graphs {0: [*], 1: [e]} Test an infinite example:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.cells(max_dim=2) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.cells(max_dim=2) # optional - sage.groups {0: [1], 1: [f, f^2], 2: [f * f, f * f^2, f^2 * f, f^2 * f^2]} - sage: BC3.cells() + sage: BC3.cells() # optional - sage.groups Traceback (most recent call last): ... NotImplementedError: this simplicial set may be infinite, so specify max_dim @@ -1470,9 +1469,9 @@ def n_cells(self, n, subcomplex=None): [sigma_3] sage: simplicial_sets.Sphere(3).n_cells(2) [] - sage: C2 = groups.misc.MultiplicativeAbelian([2]) - sage: BC2 = C2.nerve() - sage: BC2.n_cells(3) + sage: C2 = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: BC2 = C2.nerve() # optional - sage.groups + sage: BC2.n_cells(3) # optional - sage.groups [f * f * f] """ cells = self.cells(subcomplex=subcomplex, max_dim=n) @@ -1530,9 +1529,9 @@ def all_n_simplices(self, n): An example involving an infinite simplicial set:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.all_n_simplices(2) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.all_n_simplices(2) # optional - sage.groups [f * f, f * f^2, f^2 * f, @@ -1576,9 +1575,10 @@ def identity(self): Simplicial set endomorphism of S^3 Defn: Identity map - sage: BC3 = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([3])) - sage: one = BC3.identity() - sage: [(sigma, one(sigma)) for sigma in BC3.n_cells(2)] + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: one = BC3.identity() # optional - sage.groups + sage: [(sigma, one(sigma)) for sigma in BC3.n_cells(2)] # optional - sage.groups [(f * f, f * f), (f * f^2, f * f^2), (f^2 * f, f^2 * f), @@ -1616,8 +1616,8 @@ def constant_map(self, codomain=None, point=None): To: S^0 Defn: Constant map at v_0 - sage: Sigma3 = groups.permutation.Symmetric(3) - sage: Sigma3.nerve().constant_map() + sage: Sigma3 = groups.permutation.Symmetric(3) # optional - sage.groups + sage: Sigma3.nerve().constant_map() # optional - sage.groups Simplicial set morphism: From: Nerve of Symmetric group of order 3! as a permutation group To: Point @@ -1656,8 +1656,8 @@ def graph(self): EXAMPLES:: sage: Delta3 = simplicial_sets.Simplex(3) - sage: G = Delta3.graph() - sage: G.edges(sort=True) + sage: G = Delta3.graph() # optional - sage.graphs + sage: G.edges(sort=True) # optional - sage.graphs [((0,), (1,), (0, 1)), ((0,), (2,), (0, 2)), ((0,), (3,), (0, 3)), @@ -1666,20 +1666,20 @@ def graph(self): ((2,), (3,), (2, 3))] sage: T = simplicial_sets.Torus() - sage: T.graph() + sage: T.graph() # optional - sage.graphs Looped multi-graph on 1 vertex - sage: len(T.graph().edges(sort=False)) + sage: len(T.graph().edges(sort=False)) # optional - sage.graphs 3 sage: CP3 = simplicial_sets.ComplexProjectiveSpace(3) - sage: G = CP3.graph() - sage: len(G.vertices(sort=False)) + sage: G = CP3.graph() # optional - sage.graphs + sage: len(G.vertices(sort=False)) # optional - sage.graphs 1 - sage: len(G.edges(sort=False)) + sage: len(G.edges(sort=False)) # optional - sage.graphs 0 - sage: Sigma3 = groups.permutation.Symmetric(3) - sage: Sigma3.nerve().is_connected() + sage: Sigma3 = groups.permutation.Symmetric(3) # optional - sage.groups + sage: Sigma3.nerve().is_connected() # optional - sage.graphs sage.groups True """ from sage.graphs.graph import Graph @@ -1699,14 +1699,14 @@ def is_connected(self): sage: T = simplicial_sets.Torus() sage: K = simplicial_sets.KleinBottle() - sage: X = T.disjoint_union(K) - sage: T.is_connected() + sage: X = T.disjoint_union(K) # optional - sage.graphs + sage: T.is_connected() # optional - sage.graphs True - sage: K.is_connected() + sage: K.is_connected() # optional - sage.graphs True - sage: X.is_connected() + sage: X.is_connected() # optional - sage.graphs False - sage: simplicial_sets.Sphere(0).is_connected() + sage: simplicial_sets.Sphere(0).is_connected() # optional - sage.graphs False """ return self.graph().is_connected() @@ -1740,8 +1740,7 @@ def subsimplicial_set(self, simplices): sage: f = AbstractSimplex(1, name='f') sage: X = SimplicialSet({e: (v, w), f: (w, v)}) - sage: Y = X.subsimplicial_set([e]) - sage: Y + sage: Y = X.subsimplicial_set([e]); Y Simplicial set with 3 non-degenerate simplices sage: Y.nondegenerate_simplices() [v, w, e] @@ -1757,13 +1756,12 @@ def subsimplicial_set(self, simplices): A subsimplicial set knows about its ambient space and the inclusion map into it:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) - sage: M = RP4.n_skeleton(2) - sage: M + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups + sage: M = RP4.n_skeleton(2); M # optional - sage.groups Simplicial set with 3 non-degenerate simplices - sage: M.ambient_space() + sage: M.ambient_space() # optional - sage.groups RP^4 - sage: M.inclusion_map() + sage: M.inclusion_map() # optional - sage.groups Simplicial set morphism: From: Simplicial set with 3 non-degenerate simplices To: RP^4 @@ -1771,11 +1769,12 @@ def subsimplicial_set(self, simplices): An infinite ambient simplicial set:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: BxB = B.product(B) - sage: BxB.n_cells(2)[5:] + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: BxB = B.product(B) # optional - sage.groups + sage: BxB.n_cells(2)[5:] # optional - sage.groups [(s_0 f, s_1 f), (s_1 f, f * f), (s_1 f, s_0 f), (s_1 s_0 1, f * f)] - sage: BxB.subsimplicial_set(BxB.n_cells(2)[5:]) + sage: BxB.subsimplicial_set(BxB.n_cells(2)[5:]) # optional - sage.groups Simplicial set with 8 non-degenerate simplices TESTS: @@ -1913,14 +1912,14 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, sage: simplicial_sets.Sphere(5).chain_complex() Chain complex with at most 3 nonzero terms over Integer Ring - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.chain_complex(range(4), base_ring=GF(3)) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.chain_complex(range(4), base_ring=GF(3)) # optional - sage.groups sage.rings.finite_rings Chain complex with at most 4 nonzero terms over Finite Field of size 3 TESTS:: - sage: BC3.chain_complex() + sage: BC3.chain_complex() # optional - sage.groups sage.rings.finite_rings Traceback (most recent call last): ... NotImplementedError: this simplicial set may be infinite, so specify dimensions when computing its chain complex @@ -1966,33 +1965,34 @@ def homology(self, dim=None, **kwds): EXAMPLES:: - sage: simplicial_sets.Sphere(5).homology() + sage: simplicial_sets.Sphere(5).homology() # optional - sage.modules {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z} - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.homology(range(4), base_ring=GF(3)) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.homology(range(4), base_ring=GF(3)) # optional - sage.groups sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 3, 1: Vector space of dimension 1 over Finite Field of size 3, 2: Vector space of dimension 1 over Finite Field of size 3, 3: Vector space of dimension 1 over Finite Field of size 3} - sage: BC2 = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: BK = BC2.product(BC2) - sage: BK.homology(range(4)) + sage: C2 = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: BC2 = simplicial_sets.ClassifyingSpace(C2) # optional - sage.groups + sage: BK = BC2.product(BC2) # optional - sage.groups + sage: BK.homology(range(4)) # optional - sage.groups sage.modules {0: 0, 1: C2 x C2, 2: C2, 3: C2 x C2 x C2} TESTS:: sage: S3 = simplicial_sets.Sphere(3) - sage: S3.homology(0) + sage: S3.homology(0) # optional - sage.modules 0 - sage: S3.homology((0,)) + sage: S3.homology((0,)) # optional - sage.modules {0: 0} - sage: S3.homology(0, reduced=False) + sage: S3.homology(0, reduced=False) # optional - sage.modules Z - sage: BC3.homology() + sage: BC3.homology() # optional - sage.groups sage.modules Traceback (most recent call last): ... NotImplementedError: this simplicial set may be infinite, so specify dimensions when computing homology @@ -2098,9 +2098,9 @@ def betti(self, dim=None, subcomplex=None): sage: simplicial_sets.Sphere(5).betti() {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1} - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) - sage: BC3.betti(range(4)) + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.groups + sage: BC3.betti(range(4)) # optional - sage.groups sage.modules {0: 1, 1: 0, 2: 0, 3: 0} """ dict = {} @@ -2140,11 +2140,11 @@ def n_chains(self, n, base_ring=ZZ, cochains=False): sage: C = S3.n_chains(3, cochains=True) sage: list(C.basis()) [\chi_sigma_3] - sage: Sigma3 = groups.permutation.Symmetric(3) - sage: BSigma3 = simplicial_sets.ClassifyingSpace(Sigma3) - sage: list(BSigma3.n_chains(1).basis()) + sage: Sigma3 = groups.permutation.Symmetric(3) # optional - sage.groups + sage: BSigma3 = simplicial_sets.ClassifyingSpace(Sigma3) # optional - sage.groups + sage: list(BSigma3.n_chains(1).basis()) # optional - sage.groups [(1,2), (1,2,3), (1,3), (1,3,2), (2,3)] - sage: list(BSigma3.n_chains(1, cochains=True).basis()) + sage: list(BSigma3.n_chains(1, cochains=True).basis()) # optional - sage.groups [\chi_(1,2), \chi_(1,2,3), \chi_(1,3), \chi_(1,3,2), \chi_(2,3)] """ if self.is_finite(): @@ -2192,29 +2192,29 @@ def quotient(self, subcomplex, vertex_name='*'): sage: e = AbstractSimplex(1, name='e') sage: f = AbstractSimplex(1, name='f') sage: X = SimplicialSet({e: (v, w), f: (v, w)}) - sage: Y = X.quotient([f]) - sage: Y.nondegenerate_simplices() + sage: Y = X.quotient([f]) # optional - sage.graphs + sage: Y.nondegenerate_simplices() # optional - sage.graphs [*, e] - sage: Y.homology(1) + sage: Y.homology(1) # optional - sage.graphs Z sage: E = SimplicialSet({e: (v, w)}) - sage: Z = E.quotient([v, w]) - sage: Z.nondegenerate_simplices() + sage: Z = E.quotient([v, w]) # optional - sage.graphs + sage: Z.nondegenerate_simplices() # optional - sage.graphs [*, e] - sage: Z.homology(1) + sage: Z.homology(1) # optional - sage.graphs Z - sage: F = E.quotient([v]) - sage: F.nondegenerate_simplices() + sage: F = E.quotient([v]) # optional - sage.graphs + sage: F.nondegenerate_simplices() # optional - sage.graphs [*, w, e] - sage: F.base_point() + sage: F.base_point() # optional - sage.graphs * sage: RP5 = simplicial_sets.RealProjectiveSpace(5) sage: RP2 = RP5.n_skeleton(2) - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.homology(base_ring=GF(2)) + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.graphs + sage: RP5_2.homology(base_ring=GF(2)) # optional - sage.graphs sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 0 over Finite Field of size 2, 2: Vector space of dimension 0 over Finite Field of size 2, @@ -2222,15 +2222,16 @@ def quotient(self, subcomplex, vertex_name='*'): 4: Vector space of dimension 1 over Finite Field of size 2, 5: Vector space of dimension 1 over Finite Field of size 2} - sage: RP5_2.ambient() + sage: RP5_2.ambient() # optional - sage.graphs RP^5 - sage: RP5_2.subcomplex() + sage: RP5_2.subcomplex() # optional - sage.graphs Simplicial set with 3 non-degenerate simplices - sage: RP5_2.quotient_map() + sage: RP5_2.quotient_map() # optional - sage.graphs Simplicial set morphism: From: RP^5 To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] + Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] + --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] Behavior of base points:: @@ -2240,7 +2241,7 @@ def quotient(self, subcomplex, vertex_name='*'): sage: L = K.subsimplicial_set([K.n_cells(1)[-1]]) sage: L.nondegenerate_simplices() [(2,), (3,), (2, 3)] - sage: K.quotient([K.n_cells(1)[-1]]).base_point() + sage: K.quotient([K.n_cells(1)[-1]]).base_point() # optional - sage.graphs * sage: K = K.set_base_point(K.n_cells(0)[0]) @@ -2249,15 +2250,14 @@ def quotient(self, subcomplex, vertex_name='*'): sage: L = K.subsimplicial_set([K.n_cells(1)[-1]]) sage: L.nondegenerate_simplices() [(2,), (3,), (2, 3)] - sage: K.quotient(L).base_point() + sage: K.quotient(L).base_point() # optional - sage.graphs (0,) TESTS:: - sage: pt = RP5.quotient(RP5.n_skeleton(5)) - sage: pt + sage: pt = RP5.quotient(RP5.n_skeleton(5)); pt # optional - sage.graphs sage.groups Quotient: (RP^5/RP^5) - sage: len(pt.nondegenerate_simplices()) + sage: len(pt.nondegenerate_simplices()) # optional - sage.graphs sage.groups 1 """ from .simplicial_set_constructions import SubSimplicialSet @@ -2303,37 +2303,37 @@ def disjoint_union(self, *others): sage: f = AbstractSimplex(1, name='f') sage: X = SimplicialSet({e: (v, v)}) sage: Y = SimplicialSet({f: (v, w)}) - sage: Z = X.disjoint_union(Y) + sage: Z = X.disjoint_union(Y) # optional - sage.graphs Since ``X`` and ``Y`` have simplices in common, Sage uses a copy of ``Y`` when constructing the disjoint union. Note the name conflict in the list of simplices: ``v`` appears twice:: - sage: Z = X.disjoint_union(Y) - sage: Z.nondegenerate_simplices() + sage: Z = X.disjoint_union(Y) # optional - sage.graphs + sage: Z.nondegenerate_simplices() # optional - sage.graphs [v, v, w, e, f] Factors and inclusion maps:: sage: T = simplicial_sets.Torus() sage: S2 = simplicial_sets.Sphere(2) - sage: A = T.disjoint_union(S2) - sage: A.factors() + sage: A = T.disjoint_union(S2) # optional - sage.graphs + sage: A.factors() # optional - sage.graphs (Torus, S^2) - sage: i = A.inclusion_map(0) - sage: i.domain() + sage: i = A.inclusion_map(0) # optional - sage.graphs + sage: i.domain() # optional - sage.graphs Torus - sage: i.codomain() + sage: i.codomain() # optional - sage.graphs Disjoint union: (Torus u S^2) Empty factors are ignored:: sage: from sage.topology.simplicial_set_examples import Empty sage: E = Empty() - sage: K = S2.disjoint_union(S2, E, E, S2) - sage: K == S2.disjoint_union(S2, S2) + sage: K = S2.disjoint_union(S2, E, E, S2) # optional - sage.graphs + sage: K == S2.disjoint_union(S2, S2) # optional - sage.graphs True - sage: K.factors() + sage: K.factors() # optional - sage.graphs (S^2, S^2, S^2) """ from .simplicial_set_constructions import DisjointUnionOfSimplicialSets, \ @@ -2364,35 +2364,40 @@ def coproduct(self, *others): sage: Y = S2.unset_base_point() sage: Z = K.unset_base_point() - sage: S2.coproduct(K).is_pointed() + sage: S2.coproduct(K).is_pointed() # optional - sage.graphs True - sage: S2.coproduct(K) + sage: S2.coproduct(K) # optional - sage.graphs Wedge: (S^2 v Klein bottle) - sage: D3.coproduct(Y, Z).is_pointed() + sage: D3.coproduct(Y, Z).is_pointed() # optional - sage.graphs False - sage: D3.coproduct(Y, Z) - Disjoint union: (3-simplex u Simplicial set with 2 non-degenerate simplices u Simplicial set with 6 non-degenerate simplices) + sage: D3.coproduct(Y, Z) # optional - sage.graphs + Disjoint union: (3-simplex u Simplicial set with 2 non-degenerate simplices + u Simplicial set with 6 non-degenerate simplices) The coproduct comes equipped with an inclusion map from each summand, as long as the summands are all finite:: - sage: S2.coproduct(K).inclusion_map(0) + sage: S2.coproduct(K).inclusion_map(0) # optional - sage.graphs Simplicial set morphism: From: S^2 To: Wedge: (S^2 v Klein bottle) Defn: [v_0, sigma_2] --> [*, sigma_2] - sage: D3.coproduct(Y, Z).inclusion_map(2) + sage: D3.coproduct(Y, Z).inclusion_map(2) # optional - sage.graphs Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices - To: Disjoint union: (3-simplex u Simplicial set with 2 non-degenerate simplices u Simplicial set with 6 non-degenerate simplices) - Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] --> [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + To: Disjoint union: (3-simplex + u Simplicial set with 2 non-degenerate simplices + u Simplicial set with 6 non-degenerate simplices) + Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + --> [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] TESTS:: - sage: D3.coproduct(S2, Z) + sage: D3.coproduct(S2, Z) # optional - sage.graphs Traceback (most recent call last): ... - ValueError: some, but not all, of the simplicial sets are pointed, so the categorical coproduct is not defined: the category is ambiguous + ValueError: some, but not all, of the simplicial sets are pointed, + so the categorical coproduct is not defined: the category is ambiguous """ if self.is_pointed() and all(X.is_pointed() for X in others): return self.wedge(*others) @@ -2441,7 +2446,7 @@ def product(self, *others): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) - sage: T.homology(reduced=False) + sage: T.homology(reduced=False) # optional - sage.modules {0: Z, 1: Z x Z, 2: Z} Since ``S1`` is pointed, so is ``T``:: @@ -2541,8 +2546,7 @@ def pushout(self, *maps): sage: K = simplicial_sets.Simplex(4) sage: L = K.n_skeleton(3) - sage: S4 = L.pushout(L.constant_map(), L.inclusion_map()) - sage: S4 + sage: S4 = L.pushout(L.constant_map(), L.inclusion_map()); S4 # optional - sage.graphs Pushout of maps: Simplicial set morphism: From: Simplicial set with 30 non-degenerate simplices @@ -2551,10 +2555,22 @@ def pushout(self, *maps): Simplicial set morphism: From: Simplicial set with 30 non-degenerate simplices To: 4-simplex - Defn: [(0,), (1,), (2,), (3,), (4,), (0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4), (1, 2, 3, 4)] --> [(0,), (1,), (2,), (3,), (4,), (0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4), (1, 2, 3, 4)] - sage: len(S4.nondegenerate_simplices()) + Defn: [(0,), (1,), (2,), (3,), (4,), + (0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), + (2, 3), (2, 4), (3, 4), + (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), + (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), + (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4), + (1, 2, 3, 4)] + --> [(0,), (1,), (2,), (3,), (4,), + (0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), + (2, 3), (2, 4), (3, 4), + (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), + (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), + (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4), (1, 2, 3, 4)] + sage: len(S4.nondegenerate_simplices()) # optional - sage.graphs 2 - sage: S4.homology(4) + sage: S4.homology(4) # optional - sage.graphs sage.modules Z The associated maps:: @@ -2562,40 +2578,41 @@ def pushout(self, *maps): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) sage: K = T.factor(0, as_subset=True) - sage: W = S1.wedge(T) # wedge, constructed as a pushout - sage: W.defining_map(1) + sage: W = S1.wedge(T) # wedge, constructed as a pushout # optional - sage.graphs + sage: W.defining_map(1) # optional - sage.graphs Simplicial set morphism: From: Point To: S^1 x S^1 Defn: Constant map at (v_0, v_0) - sage: W.structure_map(0) + sage: W.structure_map(0) # optional - sage.graphs Simplicial set morphism: From: S^1 To: Wedge: (S^1 v S^1 x S^1) Defn: [v_0, sigma_1] --> [*, sigma_1] - sage: f = S1.Hom(T)({S1.n_cells(0)[0]:K.n_cells(0)[0], S1.n_cells(1)[0]:K.n_cells(1)[0]}) + sage: f = S1.Hom(T)({S1.n_cells(0)[0]: K.n_cells(0)[0], # optional - sage.graphs sage.modules + ....: S1.n_cells(1)[0]: K.n_cells(1)[0]}) The maps `f: S^1 \to T` and `1: T \to T` induce a map `S^1 \vee T \to T`:: - sage: g = W.universal_property(f, Hom(T,T).identity()) - sage: g.domain() == W + sage: g = W.universal_property(f, Hom(T,T).identity()) # optional - sage.graphs sage.modules + sage: g.domain() == W # optional - sage.graphs sage.modules True - sage: g.codomain() == T + sage: g.codomain() == T # optional - sage.graphs sage.modules True TESTS:: sage: K = simplicial_sets.Simplex(5) - sage: K.pushout() + sage: K.pushout() # optional - sage.graphs Empty simplicial set sage: S0 = simplicial_sets.Sphere(0) sage: pt_map = S0.base_point_map() - sage: pt_map.domain().pushout(pt_map) == S0 + sage: pt_map.domain().pushout(pt_map) == S0 # optional - sage.graphs True - sage: K.pushout(K.constant_map(), pt_map) + sage: K.pushout(K.constant_map(), pt_map) # optional - sage.graphs Traceback (most recent call last): ... ValueError: the domains of the maps must be equal @@ -2682,14 +2699,15 @@ def pullback(self, *maps): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) sage: K = T.factor(0, as_subset=True) - sage: f = S1.Hom(T)({S1.n_cells(0)[0]:K.n_cells(0)[0], S1.n_cells(1)[0]:K.n_cells(1)[0]}) - sage: D = S1.cone() # the cone C(S^1) - sage: g = D.map_from_base() # map from S^1 to C(S^1) - sage: P = T.product(D) - sage: h = P.universal_property(f, g) - sage: h.domain() == S1 + sage: f = S1.Hom(T)({S1.n_cells(0)[0]: K.n_cells(0)[0], + ....: S1.n_cells(1)[0]: K.n_cells(1)[0]}) + sage: D = S1.cone() # the cone C(S^1) # optional - sage.graphs + sage: g = D.map_from_base() # map from S^1 to C(S^1) # optional - sage.graphs + sage: P = T.product(D) # optional - sage.graphs + sage: h = P.universal_property(f, g) # optional - sage.graphs + sage: h.domain() == S1 # optional - sage.graphs True - sage: h.codomain() == P + sage: h.codomain() == P # optional - sage.graphs True TESTS:: @@ -2740,25 +2758,25 @@ def wedge(self, *others): sage: f = AbstractSimplex(1, name='f') sage: X = SimplicialSet({e: (v, v)}, base_point=v) sage: Y = SimplicialSet({f: (w, w)}, base_point=w) - sage: W = X.wedge(Y) - sage: W.nondegenerate_simplices() + sage: W = X.wedge(Y) # optional - sage.graphs + sage: W.nondegenerate_simplices() # optional - sage.graphs [*, e, f] - sage: W.homology() + sage: W.homology() # optional - sage.graphs {0: 0, 1: Z x Z} sage: S2 = simplicial_sets.Sphere(2) - sage: X.wedge(S2).homology(reduced=False) + sage: X.wedge(S2).homology(reduced=False) # optional - sage.graphs {0: Z, 1: Z, 2: Z} - sage: X.wedge(X).nondegenerate_simplices() + sage: X.wedge(X).nondegenerate_simplices() # optional - sage.graphs [*, e, e] sage: S3 = simplicial_sets.Sphere(3) - sage: W = S2.wedge(S3, S2) - sage: W.inclusion_map(2) + sage: W = S2.wedge(S3, S2) # optional - sage.graphs + sage: W.inclusion_map(2) # optional - sage.graphs Simplicial set morphism: From: S^2 To: Wedge: (S^2 v S^3 v S^2) Defn: [v_0, sigma_2] --> [*, sigma_2] - sage: W.projection_map(1) + sage: W.projection_map(1) # optional - sage.graphs Simplicial set morphism: From: Wedge: (S^2 v S^3 v S^2) To: Quotient: (Wedge: (S^2 v S^3 v S^2)/Simplicial set with 3 non-degenerate simplices) @@ -2770,15 +2788,15 @@ def wedge(self, *others): sage: S2.f_vector() [1, 0, 1] - sage: W.projection_map(2).codomain().f_vector() + sage: W.projection_map(2).codomain().f_vector() # optional - sage.graphs [1, 0, 1] - sage: (W.projection_map(2) * W.inclusion_map(2)).is_bijective() + sage: (W.projection_map(2) * W.inclusion_map(2)).is_bijective() # optional - sage.graphs True TESTS:: sage: Z = SimplicialSet({e: (v,w)}) - sage: X.wedge(Z) + sage: X.wedge(Z) # optional - sage.graphs Traceback (most recent call last): ... ValueError: the simplicial sets must be pointed @@ -2813,18 +2831,18 @@ def cone(self): sage: v = AbstractSimplex(0, name='v') sage: e = AbstractSimplex(1, name='e') sage: X = SimplicialSet({e: (v, v)}) - sage: CX = X.cone() # unreduced cone, since X not pointed - sage: CX.nondegenerate_simplices() + sage: CX = X.cone() # unreduced cone, since X not pointed # optional - sage.graphs + sage: CX.nondegenerate_simplices() # optional - sage.graphs [*, v, (v,*), e, (e,*)] - sage: CX.base_point() + sage: CX.base_point() # optional - sage.graphs * `X` as a subset of the cone, and also the map from `X`, in the unreduced case:: - sage: CX.base_as_subset() + sage: CX.base_as_subset() # optional - sage.graphs Simplicial set with 2 non-degenerate simplices - sage: CX.map_from_base() + sage: CX.map_from_base() # optional - sage.graphs Simplicial set morphism: From: Simplicial set with 2 non-degenerate simplices To: Cone of Simplicial set with 2 non-degenerate simplices @@ -2833,10 +2851,10 @@ def cone(self): In the reduced case, only the map from `X` is available:: sage: X = X.set_base_point(v) - sage: CX = X.cone() # reduced cone - sage: CX.nondegenerate_simplices() + sage: CX = X.cone() # reduced cone # optional - sage.graphs + sage: CX.nondegenerate_simplices() # optional - sage.graphs [*, e, (e,*)] - sage: CX.map_from_base() + sage: CX.map_from_base() # optional - sage.graphs Simplicial set morphism: From: Simplicial set with 2 non-degenerate simplices To: Reduced cone of Simplicial set with 2 non-degenerate simplices @@ -2871,25 +2889,25 @@ def suspension(self, n=1): EXAMPLES:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) - sage: S1 = simplicial_sets.Sphere(1) - sage: SigmaRP4 = RP4.suspension() - sage: S1_smash_RP4 = S1.smash_product(RP4) - sage: SigmaRP4.homology() == S1_smash_RP4.homology() + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups + sage: S1 = simplicial_sets.Sphere(1) # optional - sage.groups + sage: SigmaRP4 = RP4.suspension() # optional - sage.graphs sage.groups + sage: S1_smash_RP4 = S1.smash_product(RP4) # optional - sage.graphs sage.groups + sage: SigmaRP4.homology() == S1_smash_RP4.homology() # optional - sage.graphs sage.groups True The version of the suspension obtained by the smash product is typically less efficient than the reduced suspension produced here:: - sage: SigmaRP4.f_vector() + sage: SigmaRP4.f_vector() # optional - sage.graphs sage.groups [1, 0, 1, 1, 1, 1] - sage: S1_smash_RP4.f_vector() + sage: S1_smash_RP4.f_vector() # optional - sage.graphs sage.groups [1, 1, 4, 6, 8, 5] TESTS:: - sage: RP4.suspension(-3) + sage: RP4.suspension(-3) # optional - sage.graphs sage.groups Traceback (most recent call last): ... ValueError: n must be non-negative @@ -2946,22 +2964,22 @@ def reduce(self): sage: K = simplicial_sets.Simplex(2) sage: K.is_reduced() False - sage: X = K.reduce() - sage: X.is_reduced() + sage: X = K.reduce() # optional - sage.graphs + sage: X.is_reduced() # optional - sage.graphs True ``X`` is reduced, so calling ``reduce`` on it again returns ``X`` itself:: - sage: X is X.reduce() + sage: X is X.reduce() # optional - sage.graphs True - sage: K is K.reduce() + sage: K is K.reduce() # optional - sage.graphs False Raise an error for disconnected simplicial sets:: sage: S0 = simplicial_sets.Sphere(0) - sage: S0.reduce() + sage: S0.reduce() # optional - sage.graphs Traceback (most recent call last): ... ValueError: this simplicial set is not connected @@ -3219,7 +3237,7 @@ def __init__(self, data, base_point=None, name=None, check=True, sage: skip = ["_test_pickling", "_test_elements"] sage: TestSuite(S1).run(skip=skip) sage: TestSuite(simplicial_sets.Sphere(5)).run(skip=skip) - sage: TestSuite(simplicial_sets.RealProjectiveSpace(6)).run(skip=skip) + sage: TestSuite(simplicial_sets.RealProjectiveSpace(6)).run(skip=skip) # optional - sage.groups """ def face(sigma, i): """ @@ -3556,7 +3574,7 @@ def euler_characteristic(self): EXAMPLES:: - sage: simplicial_sets.RealProjectiveSpace(4).euler_characteristic() + sage: simplicial_sets.RealProjectiveSpace(4).euler_characteristic() # optional - sage.groups 1 sage: simplicial_sets.Sphere(6).euler_characteristic() 2 @@ -3609,16 +3627,16 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, sage: degen = v.apply_degeneracies(1, 0) # s_1 s_0 applied to v sage: sigma = AbstractSimplex(3) sage: S3 = SimplicialSet({sigma: (degen, degen, degen, degen)}) # the 3-sphere - sage: S3.chain_complex().homology() + sage: S3.chain_complex().homology() # optional - sage.modules {0: Z, 3: Z} - sage: S3.chain_complex(augmented=True).homology() + sage: S3.chain_complex(augmented=True).homology() # optional - sage.modules {-1: 0, 0: 0, 3: Z} - sage: S3.chain_complex(dimensions=range(3), base_ring=QQ).homology() + sage: S3.chain_complex(dimensions=range(3), base_ring=QQ).homology() # optional - sage.modules {0: Vector space of dimension 1 over Rational Field} - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP5.chain_complex(subcomplex=RP2).homology() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP5.chain_complex(subcomplex=RP2).homology() # optional - sage.groups sage.modules {0: Z, 3: C2, 4: 0, 5: Z} TESTS: @@ -3627,12 +3645,13 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, simplicial sets, and compare homology calculations:: sage: T = simplicial_complexes.Torus() - sage: T.homology() == SimplicialSet(T).homology() + sage: T.homology() == SimplicialSet(T).homology() # optional - sage.modules True - sage: RP2 = delta_complexes.RealProjectivePlane() - sage: RP2.homology() == SimplicialSet(RP2).homology() + sage: RP2 = delta_complexes.RealProjectivePlane() # optional - sage.groups sage.modules + sage: RP2.homology() == SimplicialSet(RP2).homology() # optional - sage.groups sage.modules True - sage: RP2.cohomology(base_ring=GF(2)) == SimplicialSet(RP2).cohomology(base_ring=GF(2)) + sage: cohoRP2 = RP2.cohomology(base_ring=GF(2)) # optional - sage.groups sage.modules sage.rings.finite_rings + sage: cohoRP2 == SimplicialSet(RP2).cohomology(base_ring=GF(2)) # optional - sage.groups sage.modules sage.rings.finite_rings True """ from sage.homology.chain_complex import ChainComplex @@ -3772,15 +3791,15 @@ def algebraic_topological_model(self, base_ring=None): EXAMPLES:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) - sage: phi, M = RP2.algebraic_topological_model(GF(2)) - sage: M.homology() + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups + sage: phi, M = RP2.algebraic_topological_model(GF(2)) # optional - sage.groups sage.rings.finite_rings + sage: M.homology() # optional - sage.groups sage.modules sage.rings.finite_rings {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: T = simplicial_sets.Torus() sage: phi, M = T.algebraic_topological_model(QQ) - sage: M.homology() + sage: M.homology() # optional - sage.modules {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 2 over Rational Field, 2: Vector space of dimension 1 over Rational Field} @@ -4028,28 +4047,29 @@ def shrink_simplicial_complex(K): sage: from sage.topology.simplicial_set import shrink_simplicial_complex sage: K = simplicial_complexes.Simplex(3) - sage: X = shrink_simplicial_complex(K) - sage: X.f_vector() + sage: X = shrink_simplicial_complex(K) # optional - sage.graphs + sage: X.f_vector() # optional - sage.graphs [1] sage: Y = simplicial_complexes.Sphere(2) - sage: S2 = shrink_simplicial_complex(Y) - sage: S2 - Quotient: (Simplicial set with 14 non-degenerate simplices/Simplicial set with 13 non-degenerate simplices) - sage: S2.f_vector() + sage: S2 = shrink_simplicial_complex(Y); S2 # optional - sage.graphs + Quotient: (Simplicial set with + 14 non-degenerate simplices/Simplicial set with + 13 non-degenerate simplices) + sage: S2.f_vector() # optional - sage.graphs [1, 0, 1] - sage: S2.homology() + sage: S2.homology() # optional - sage.graphs sage.modules {0: 0, 1: 0, 2: Z} sage: Z = simplicial_complexes.SurfaceOfGenus(3) sage: Z.f_vector() [1, 15, 57, 38] - sage: Z.homology() + sage: Z.homology() # optional - sage.modules {0: 0, 1: Z^6, 2: Z} - sage: M = shrink_simplicial_complex(Z) - sage: M.f_vector() # random + sage: M = shrink_simplicial_complex(Z) # optional - sage.graphs + sage: M.f_vector() # random # optional - sage.graphs [1, 32, 27] - sage: M.homology() + sage: M.homology() # optional - sage.graphs sage.modules {0: 0, 1: Z^6, 2: Z} """ L = K._contractible_subcomplex() diff --git a/src/sage/topology/simplicial_set_catalog.py b/src/sage/topology/simplicial_set_catalog.py index d20df19e4a1..94208f14dac 100644 --- a/src/sage/topology/simplicial_set_catalog.py +++ b/src/sage/topology/simplicial_set_catalog.py @@ -34,14 +34,14 @@ EXAMPLES:: - sage: RP10 = simplicial_sets.RealProjectiveSpace(8) - sage: RP10.homology() + sage: RP10 = simplicial_sets.RealProjectiveSpace(8) # optional - sage.groups + sage: RP10.homology() # optional - sage.groups sage.modules {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: C2, 6: 0, 7: C2, 8: 0} sage: eta = simplicial_sets.HopfMap() sage: S3 = eta.domain() sage: S2 = eta.codomain() - sage: S3.wedge(S2).homology() + sage: S3.wedge(S2).homology() # optional - sage.graphs sage.modules {0: 0, 1: 0, 2: Z, 3: Z} """ diff --git a/src/sage/topology/simplicial_set_constructions.py b/src/sage/topology/simplicial_set_constructions.py index e5a14632098..a4cc87ef3ac 100644 --- a/src/sage/topology/simplicial_set_constructions.py +++ b/src/sage/topology/simplicial_set_constructions.py @@ -15,14 +15,14 @@ sage: K = simplicial_sets.Simplex(1) sage: endpoints = K.n_skeleton(0) - sage: circle = K.quotient(endpoints) + sage: circle = K.quotient(endpoints) # optional - sage.graphs The mapping cone of a morphism of simplicial sets is constructed as a pushout:: sage: eta = simplicial_sets.HopfMap() - sage: CP2 = eta.mapping_cone() - sage: type(CP2) + sage: CP2 = eta.mapping_cone() # optional - sage.graphs + sage: type(CP2) # optional - sage.graphs See the main documentation for simplicial sets, as well as for the @@ -34,7 +34,7 @@ for example, if ``K`` is a simplicial set, calling ``K.suspension()`` twice returns the same result both times:: - sage: CP2.suspension() is CP2.suspension() + sage: CP2.suspension() is CP2.suspension() # optional - sage.graphs True So on one hand, a command like ``simplicial_sets.Sphere(2)`` @@ -48,7 +48,7 @@ sage: S2 = simplicial_sets.Sphere(2) sage: S2.product(S2) == S2.product(S2) True - sage: S2.disjoint_union(CP2, S2) == S2.disjoint_union(CP2, S2) + sage: S2.disjoint_union(CP2, S2) == S2.disjoint_union(CP2, S2) # optional - sage.graphs True AUTHORS: @@ -143,14 +143,14 @@ def __init__(self, data, ambient=None): sage: S3 = simplicial_sets.Sphere(3) sage: K = simplicial_sets.KleinBottle() - sage: X = S3.disjoint_union(K) - sage: Y = X.structure_map(0).image() # the S3 summand - sage: Y.inclusion_map() + sage: X = S3.disjoint_union(K) # optional - sage.graphs + sage: Y = X.structure_map(0).image() # the S3 summand # optional - sage.graphs + sage: Y.inclusion_map() # optional - sage.graphs Simplicial set morphism: From: Simplicial set with 2 non-degenerate simplices To: Disjoint union: (S^3 u Klein bottle) Defn: [v_0, sigma_3] --> [v_0, sigma_3] - sage: Y.ambient_space() + sage: Y.ambient_space() # optional - sage.graphs Disjoint union: (S^3 u Klein bottle) TESTS:: @@ -191,9 +191,9 @@ def inclusion_map(self): EXAMPLES:: - sage: RP6 = simplicial_sets.RealProjectiveSpace(6) - sage: K = RP6.n_skeleton(2) - sage: K.inclusion_map() + sage: RP6 = simplicial_sets.RealProjectiveSpace(6) # optional - sage.groups + sage: K = RP6.n_skeleton(2) # optional - sage.groups + sage: K.inclusion_map() # optional - sage.groups Simplicial set morphism: From: Simplicial set with 3 non-degenerate simplices To: RP^6 @@ -202,7 +202,7 @@ def inclusion_map(self): `RP^6` itself is constructed as a subsimplicial set of `RP^\infty`:: - sage: latex(RP6.inclusion_map()) + sage: latex(RP6.inclusion_map()) # optional - sage.groups RP^{6} \to RP^{\infty} """ return self._inclusion @@ -217,7 +217,7 @@ def ambient_space(self): sage: eight = T.wedge_as_subset() sage: eight Simplicial set with 3 non-degenerate simplices - sage: eight.fundamental_group() + sage: eight.fundamental_group() # optional - sage.groups Finitely presented group < e0, e1 | > sage: eight.ambient_space() Torus @@ -267,10 +267,10 @@ def __init__(self, maps=None): base point map gives a simplicial set isomorphic to the original subcomplex:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: K = RP5.quotient(RP5.n_skeleton(2)) - sage: X = K.pullback(K.quotient_map(), K.base_point_map()) - sage: X.homology() == RP5.n_skeleton(2).homology() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: K = RP5.quotient(RP5.n_skeleton(2)) # optional - sage.groups + sage: X = K.pullback(K.quotient_map(), K.base_point_map()) # optional - sage.groups + sage: X.homology() == RP5.n_skeleton(2).homology() # optional - sage.groups sage.modules True Pullbacks of identity maps:: @@ -278,7 +278,7 @@ def __init__(self, maps=None): sage: S2 = simplicial_sets.Sphere(2) sage: one = S2.Hom(S2).identity() sage: P = S2.pullback(one, one) - sage: P.homology() + sage: P.homology() # optional - sage.modules {0: 0, 1: 0, 2: Z} The pullback is constructed in terms of the product -- of @@ -319,17 +319,18 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: one = Hom(B,B).identity() - sage: c = Hom(B,B).constant_map() - sage: P = B.pullback(one, c) - sage: P.n_skeleton(2) + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: one = Hom(B,B).identity() # optional - sage.groups + sage: c = Hom(B,B).constant_map() # optional - sage.groups + sage: P = B.pullback(one, c) # optional - sage.groups + sage: P.n_skeleton(2) # optional - sage.groups Pullback of maps: Simplicial set endomorphism of Simplicial set with 3 non-degenerate simplices Defn: Identity map Simplicial set endomorphism of Simplicial set with 3 non-degenerate simplices Defn: Constant map at 1 - sage: P.n_skeleton(3).homology() + sage: P.n_skeleton(3).homology() # optional - sage.groups sage.modules {0: 0, 1: C2, 2: 0, 3: Z} """ if self.is_finite(): @@ -362,15 +363,15 @@ def defining_map(self, i): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: K = RP5.quotient(RP5.n_skeleton(2)) - sage: Y = K.pullback(K.quotient_map(), K.base_point_map()) - sage: Y.defining_map(1) + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: K = RP5.quotient(RP5.n_skeleton(2)) # optional - sage.groups + sage: Y = K.pullback(K.quotient_map(), K.base_point_map()) # optional - sage.groups + sage: Y.defining_map(1) # optional - sage.groups Simplicial set morphism: From: Point To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) Defn: Constant map at * - sage: Y.defining_map(0).domain() + sage: Y.defining_map(0).domain() # optional - sage.groups RP^5 """ return self._maps[i] @@ -444,10 +445,11 @@ def __init__(self, maps=None): sage: S2.pullback(eta, c).is_finite() True - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: one = Hom(B,B).identity() - sage: c = Hom(B,B).constant_map() - sage: B.pullback(one, c).is_finite() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: one = Hom(B,B).identity() # optional - sage.groups + sage: c = Hom(B,B).constant_map() # optional - sage.groups + sage: B.pullback(one, c).is_finite() # optional - sage.groups False TESTS:: @@ -614,28 +616,29 @@ def structure_map(self, i): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: K = RP5.quotient(RP5.n_skeleton(2)) - sage: Y = K.pullback(K.quotient_map(), K.base_point_map()) - sage: Y.structure_map(0) + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: K = RP5.quotient(RP5.n_skeleton(2)) # optional - sage.groups + sage: Y = K.pullback(K.quotient_map(), K.base_point_map()) # optional - sage.groups + sage: Y.structure_map(0) # optional - sage.groups Simplicial set morphism: From: Pullback of maps: Simplicial set morphism: From: RP^5 To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] + Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] + --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] Simplicial set morphism: From: Point To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) Defn: Constant map at * To: RP^5 Defn: [(1, *), (f, s_0 *), (f * f, s_1 s_0 *)] --> [1, f, f * f] - sage: Y.structure_map(1).codomain() + sage: Y.structure_map(1).codomain() # optional - sage.groups Point - These maps are also accessible via ``projection_map``:: + These maps are also accessible via :meth:`projection_map`:: - sage: Y.projection_map(1).codomain() + sage: Y.projection_map(1).codomain() # optional - sage.groups Point """ if len(self._maps) == 1: @@ -667,7 +670,8 @@ def universal_property(self, *maps): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) sage: K = T.factor(0, as_subset=True) - sage: f = S1.Hom(T)({S1.n_cells(0)[0]:K.n_cells(0)[0], S1.n_cells(1)[0]:K.n_cells(1)[0]}) + sage: f = S1.Hom(T)({S1.n_cells(0)[0]: K.n_cells(0)[0], + ....: S1.n_cells(1)[0]: K.n_cells(1)[0]}) sage: P = S1.product(T) sage: P.universal_property(S1.Hom(S1).identity(), f) Simplicial set morphism: @@ -716,11 +720,11 @@ def factors(self): EXAMPLES:: - sage: S2 = simplicial_sets.Sphere(2) - sage: S3 = simplicial_sets.Sphere(3) - sage: S2.wedge(S3).factors() == (S2, S3) + sage: S2 = simplicial_sets.Sphere(2) # optional - sage.graphs + sage: S3 = simplicial_sets.Sphere(3) # optional - sage.graphs + sage: S2.wedge(S3).factors() == (S2, S3) # optional - sage.graphs True - sage: S2.product(S3).factors()[0] + sage: S2.product(S3).factors()[0] # optional - sage.graphs S^2 """ return self._factors @@ -737,14 +741,15 @@ def factor(self, i): sage: S2 = simplicial_sets.Sphere(2) sage: S3 = simplicial_sets.Sphere(3) - sage: K = S2.disjoint_union(S3) - sage: K.factor(0) + sage: K = S2.disjoint_union(S3) # optional - sage.graphs + sage: K.factor(0) # optional - sage.graphs S^2 - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: X = B.wedge(S3, B) - sage: X.factor(1) + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: X = B.wedge(S3, B) # optional - sage.groups + sage: X.factor(1) # optional - sage.groups S^3 - sage: X.factor(2) + sage: X.factor(2) # optional - sage.groups Classifying space of Multiplicative Abelian group isomorphic to C2 """ return self.factors()[i] @@ -815,7 +820,7 @@ def __init__(self, factors=None): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) - sage: T.homology(reduced=False) + sage: T.homology(reduced=False) # optional - sage.modules {0: Z, 1: Z x Z, 2: Z} Since ``S1`` is pointed, so is ``T``:: @@ -832,7 +837,7 @@ def __init__(self, factors=None): sage: S2 = simplicial_sets.Sphere(2) sage: S3 = simplicial_sets.Sphere(3) sage: Z = S2.product(S3) - sage: Z.homology() + sage: Z.homology() # optional - sage.modules {0: 0, 1: 0, 2: Z, 3: Z, 4: 0, 5: Z} Products involving infinite simplicial sets:: @@ -844,12 +849,12 @@ def __init__(self, factors=None): RP^oo x RP^oo sage: X.n_cells(1) [(f, f), (f, s_0 1), (s_0 1, f)] - sage: X.homology(range(3), base_ring=GF(2)) + sage: X.homology(range(3), base_ring=GF(2)) # optional - sage.modules {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 2 over Finite Field of size 2, 2: Vector space of dimension 3 over Finite Field of size 2} sage: Y = B.product(S2) - sage: Y.homology(range(5), base_ring=GF(2)) + sage: Y.homology(range(5), base_ring=GF(2)) # optional - sage.modules {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 2 over Finite Field of size 2, @@ -881,9 +886,11 @@ def n_skeleton(self, n): sage: S3 = simplicial_sets.Sphere(3) sage: S2.product(S3).n_skeleton(2) Simplicial set with 2 non-degenerate simplices - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: X = B.product(B) - sage: X.n_skeleton(2) + + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: X = B.product(B) # optional - sage.groups + sage: X.n_skeleton(2) # optional - sage.groups Simplicial set with 13 non-degenerate simplices """ n_skel = SimplicialSet_finite.n_skeleton @@ -929,7 +936,7 @@ def factor(self, i, as_subset=False): sage: K.factor(0, as_subset=True) Simplicial set with 2 non-degenerate simplices - sage: K.factor(0, as_subset=True).homology() + sage: K.factor(0, as_subset=True).homology() # optional - sage.groups {0: 0, 1: 0, 2: Z} sage: K.factor(0) is S2 @@ -961,10 +968,11 @@ def _repr_(self): sage: S2 = simplicial_sets.Sphere(2) sage: K = simplicial_sets.KleinBottle() - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: S2.product(S2) + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: S2.product(S2) # optional - sage.groups S^2 x S^2 - sage: S2.product(K, B) + sage: S2.product(K, B) # optional - sage.groups S^2 x Klein bottle x Classifying space of Multiplicative Abelian group isomorphic to C2 """ return ' x '.join(str(X) for X in self._factors) @@ -978,8 +986,8 @@ def _latex_(self): sage: S2 = simplicial_sets.Sphere(2) sage: latex(S2.product(S2)) S^{2} \times S^{2} - sage: RPoo = simplicial_sets.RealProjectiveSpace(Infinity) - sage: latex(S2.product(RPoo, S2)) + sage: RPoo = simplicial_sets.RealProjectiveSpace(Infinity) # optional - sage.groups + sage: latex(S2.product(RPoo, S2)) # optional - sage.groups S^{2} \times RP^{\infty} \times S^{2} """ return ' \\times '.join(latex(X) for X in self._factors) @@ -1008,7 +1016,7 @@ def __init__(self, factors=None): sage: e = AbstractSimplex(1) sage: X = SimplicialSet({e: (v, v)}) sage: W = X.product(X, X) - sage: W.homology() + sage: W.homology() # optional - sage.groups {0: 0, 1: Z x Z x Z, 2: Z x Z x Z, 3: Z} sage: W.is_pointed() False @@ -1069,7 +1077,7 @@ def wedge_as_subset(self): sage: W = P.wedge_as_subset() sage: W.nondegenerate_simplices() [(v, w), (e, s_0 w), (s_0 v, f)] - sage: W.homology() + sage: W.homology() # optional - sage.groups {0: 0, 1: Z x Z} """ basept_factors = [sset.base_point() for sset in self.factors()] @@ -1101,7 +1109,7 @@ def fat_wedge_as_subset(self): sage: S1 = simplicial_sets.Sphere(1) sage: X = S1.product(S1, S1) sage: W = X.fat_wedge_as_subset() - sage: W.homology() + sage: W.homology() # optional - sage.groups {0: 0, 1: Z x Z x Z, 2: Z x Z x Z} """ basept_factors = [sset.base_point() for sset in self.factors()] @@ -1186,17 +1194,17 @@ def __init__(self, maps=None, vertex_name=None): sage: f1_data = {a:v, b:v, e2:v.apply_degeneracies(0)} sage: f0 = X.Hom(Y0)(f0_data) sage: f1 = X.Hom(Y1)(f1_data) - sage: P = X.pushout(f0, f1) - sage: P.nondegenerate_simplices() + sage: P = X.pushout(f0, f1) # optional - sage.graphs + sage: P.nondegenerate_simplices() # optional - sage.graphs [a, c, e_0, e_1] There are defining maps `f_i: X \to Y_i` and structure maps `\bar{f}_i: Y_i \to P`; the latter are only implemented in Sage when each `Y_i` is finite. :: - sage: P.defining_map(0) == f0 + sage: P.defining_map(0) == f0 # optional - sage.graphs True - sage: P.structure_map(1) + sage: P.structure_map(1) # optional - sage.graphs Simplicial set morphism: From: 0-simplex To: Pushout of maps: @@ -1209,9 +1217,9 @@ def __init__(self, maps=None, vertex_name=None): To: 0-simplex Defn: Constant map at (0,) Defn: Constant map at a - sage: P.structure_map(0).domain() == Y0 + sage: P.structure_map(0).domain() == Y0 # optional - sage.graphs True - sage: P.structure_map(0).codomain() == P + sage: P.structure_map(0).codomain() == P # optional - sage.graphs True An inefficient way of constructing a suspension for an @@ -1222,29 +1230,31 @@ def __init__(self, maps=None, vertex_name=None): sage: T = T.unset_base_point() sage: CT = T.cone() sage: inc = CT.base_as_subset().inclusion_map() - sage: P = T.pushout(inc, inc) - sage: P.homology() + sage: P = T.pushout(inc, inc) # optional - sage.graphs + sage: P.homology() # optional - sage.graphs sage.modules {0: 0, 1: 0, 2: Z x Z, 3: Z} - sage: len(P.nondegenerate_simplices()) + sage: len(P.nondegenerate_simplices()) # optional - sage.graphs 20 It is more efficient to construct the suspension as the quotient `CX/X`:: - sage: len(CT.quotient(CT.base_as_subset()).nondegenerate_simplices()) + sage: len(CT.quotient(CT.base_as_subset()).nondegenerate_simplices()) # optional - sage.graphs 8 It is more efficient still if the original simplicial set has a base point:: sage: T = simplicial_sets.Torus() - sage: len(T.suspension().nondegenerate_simplices()) + sage: len(T.suspension().nondegenerate_simplices()) # optional - sage.graphs 6 sage: S1 = simplicial_sets.Sphere(1) sage: pt = simplicial_sets.Point() - sage: bouquet = pt.pushout(S1.base_point_map(), S1.base_point_map(), S1.base_point_map()) - sage: bouquet.homology(1) + sage: bouquet = pt.pushout(S1.base_point_map(), # optional - sage.graphs + ....: S1.base_point_map(), + ....: S1.base_point_map()) + sage: bouquet.homology(1) # optional - sage.graphs sage.modules Z x Z x Z """ # Import this here to prevent circular imports. @@ -1278,10 +1288,11 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: K = B.n_skeleton(3) - sage: Q = K.pushout(K.inclusion_map(), K.constant_map()) - sage: Q.n_skeleton(5).homology() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: K = B.n_skeleton(3) # optional - sage.groups + sage: Q = K.pushout(K.inclusion_map(), K.constant_map()) # optional - sage.groups + sage: Q.n_skeleton(5).homology() # optional - sage.groups sage.modules {0: 0, 1: 0, 2: 0, 3: 0, 4: Z, 5: Z} Of course, computing the `n`-skeleton and then taking homology @@ -1289,7 +1300,7 @@ def n_skeleton(self, n): dimension `n`, since the latter computation will use the `(n+1)`-skeleton:: - sage: Q.homology(range(6)) + sage: Q.homology(range(6)) # optional - sage.groups sage.modules {0: 0, 1: 0, 2: 0, 3: 0, 4: Z, 5: C2} """ if self.is_finite(): @@ -1327,15 +1338,15 @@ def defining_map(self, i): sage: S1 = simplicial_sets.Sphere(1) sage: T = simplicial_sets.Torus() - sage: X = S1.wedge(T) # a pushout - sage: X.defining_map(0) + sage: X = S1.wedge(T) # a pushout # optional - sage.graphs + sage: X.defining_map(0) # optional - sage.graphs Simplicial set morphism: From: Point To: S^1 Defn: Constant map at v_0 - sage: X.defining_map(1).domain() + sage: X.defining_map(1).domain() # optional - sage.graphs Point - sage: X.defining_map(1).codomain() + sage: X.defining_map(1).codomain() # optional - sage.graphs Torus """ return self._maps[i] @@ -1349,7 +1360,7 @@ def _repr_(self): sage: S2 = simplicial_sets.Sphere(2) sage: S3 = simplicial_sets.Sphere(3) sage: pt = simplicial_sets.Point() - sage: pt.pushout(S2.base_point_map(), S3.base_point_map()) + sage: pt.pushout(S2.base_point_map(), S3.base_point_map()) # optional - sage.graphs Pushout of maps: Simplicial set morphism: From: Point @@ -1387,7 +1398,7 @@ def __classcall_private__(cls, maps=None, vertex_name=None): sage: from sage.topology.simplicial_set_constructions import PushoutOfSimplicialSets_finite sage: S2 = simplicial_sets.Sphere(2) sage: one = S2.Hom(S2).identity() - sage: PushoutOfSimplicialSets_finite([one, one]) == PushoutOfSimplicialSets_finite((one, one)) + sage: PushoutOfSimplicialSets_finite([one, one]) == PushoutOfSimplicialSets_finite((one, one)) # optional - sage.graphs True """ if maps: @@ -1411,9 +1422,9 @@ def __init__(self, maps=None, vertex_name=None): sage: from sage.topology.simplicial_set_constructions import PushoutOfSimplicialSets_finite sage: T = simplicial_sets.Torus() sage: S2 = simplicial_sets.Sphere(2) - sage: PushoutOfSimplicialSets_finite([T.base_point_map(), S2.base_point_map()]).n_cells(0)[0] + sage: PushoutOfSimplicialSets_finite([T.base_point_map(), S2.base_point_map()]).n_cells(0)[0] # optional - sage.graphs * - sage: PushoutOfSimplicialSets_finite([T.base_point_map(), S2.base_point_map()], vertex_name='v').n_cells(0)[0] + sage: PushoutOfSimplicialSets_finite([T.base_point_map(), S2.base_point_map()], vertex_name='v').n_cells(0)[0] # optional - sage.graphs v """ from sage.graphs.graph import Graph @@ -1584,15 +1595,15 @@ def structure_map(self, i): sage: S1 = simplicial_sets.Sphere(1) sage: T = simplicial_sets.Torus() - sage: X = S1.disjoint_union(T) # a pushout - sage: X.structure_map(0) + sage: X = S1.disjoint_union(T) # a pushout # optional - sage.graphs + sage: X.structure_map(0) # optional - sage.graphs Simplicial set morphism: From: S^1 To: Disjoint union: (S^1 u Torus) Defn: [v_0, sigma_1] --> [v_0, sigma_1] - sage: X.structure_map(1).domain() + sage: X.structure_map(1).domain() # optional - sage.graphs Torus - sage: X.structure_map(1).codomain() + sage: X.structure_map(1).codomain() # optional - sage.graphs Disjoint union: (S^1 u Torus) """ return self._structure[i] @@ -1625,12 +1636,14 @@ def universal_property(self, *maps): sage: Y_1 = SimplicialSet({evx: (x, v)}) sage: f_0 = Hom(X, Y_0)({v:v, w:w, x:x, evw:evw, evx:evx}) - sage: f_1 = Hom(X, Y_1)({v:v, w:v, x:x, evw:v.apply_degeneracies(0), evx:evx}) - sage: P = X.pushout(f_0, f_1) + sage: f_1 = Hom(X, Y_1)({v:v, w:v, x:x, + ....: evw:v.apply_degeneracies(0), evx:evx}) + sage: P = X.pushout(f_0, f_1) # optional - sage.graphs sage: one = Hom(Y_1, Y_1).identity() - sage: g = Hom(Y_0, Y_1)({v:v, w:v, x:x, evw:v.apply_degeneracies(0), evx:evx, ewx:evx}) - sage: P.universal_property(g, one) + sage: g = Hom(Y_0, Y_1)({v:v, w:v, x:x, + ....: evw:v.apply_degeneracies(0), evx:evx, ewx:evx}) + sage: P.universal_property(g, one) # optional - sage.graphs Simplicial set morphism: From: Pushout of maps: Simplicial set morphism: @@ -1683,16 +1696,16 @@ def __init__(self, inclusion, vertex_name='*'): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2 + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP5_2 = RP5.quotient(RP2); RP5_2 # optional - sage.graphs sage.groups Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - sage: RP5_2.quotient_map() + sage: RP5_2.quotient_map() # optional - sage.graphs sage.groups Simplicial set morphism: From: RP^5 To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] + Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] + --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] """ subcomplex = inclusion.domain() PushoutOfSimplicialSets.__init__(self, [inclusion, @@ -1712,16 +1725,17 @@ def ambient(self): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.ambient() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.graphs sage.groups + sage: RP5_2.ambient() # optional - sage.graphs sage.groups RP^5 - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: K = B.n_skeleton(3) - sage: Q = B.quotient(K) - sage: Q.ambient() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: K = B.n_skeleton(3) # optional - sage.groups + sage: Q = B.quotient(K) # optional - sage.graphs sage.groups + sage: Q.ambient() # optional - sage.graphs sage.groups Classifying space of Multiplicative Abelian group isomorphic to C2 """ return self._maps[0].codomain() @@ -1734,16 +1748,17 @@ def subcomplex(self): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.subcomplex() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.graphs sage.groups + sage: RP5_2.subcomplex() # optional - sage.graphs sage.groups Simplicial set with 3 non-degenerate simplices - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: K = B.n_skeleton(3) - sage: Q = B.quotient(K) - sage: Q.subcomplex() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: K = B.n_skeleton(3) # optional - sage.groups + sage: Q = B.quotient(K) # optional - sage.graphs sage.groups + sage: Q.subcomplex() # optional - sage.graphs sage.groups Simplicial set with 4 non-degenerate simplices """ return self._maps[0].domain() @@ -1764,12 +1779,15 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: K = B.n_skeleton(3) - sage: Q = B.quotient(K) - sage: Q.n_skeleton(6) - Quotient: (Simplicial set with 7 non-degenerate simplices/Simplicial set with 4 non-degenerate simplices) - sage: Q.n_skeleton(6).homology() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: K = B.n_skeleton(3) # optional - sage.groups + sage: Q = B.quotient(K) # optional - sage.graphs sage.groups + sage: Q.n_skeleton(6) # optional - sage.graphs sage.groups + Quotient: (Simplicial set with 7 + non-degenerate simplices/Simplicial set with 4 + non-degenerate simplices) + sage: Q.n_skeleton(6).homology() # optional - sage.graphs sage.groups sage.modules {0: 0, 1: 0, 2: 0, 3: 0, 4: Z, 5: C2, 6: 0} """ if self.is_finite(): @@ -1797,7 +1815,7 @@ def _repr_(self): EXAMPLES:: sage: T = simplicial_sets.Torus() - sage: T.quotient(T.n_skeleton(1)) + sage: T.quotient(T.n_skeleton(1)) # optional - sage.graphs Quotient: (Torus/Simplicial set with 4 non-degenerate simplices) """ return 'Quotient: ({}/{})'.format(self.ambient(), self.subcomplex()) @@ -1808,10 +1826,10 @@ def _latex_(self): EXAMPLES:: - sage: RPoo = simplicial_sets.RealProjectiveSpace(Infinity) - sage: RP3 = RPoo.n_skeleton(3) - sage: RP3.rename_latex('RP^{3}') - sage: latex(RPoo.quotient(RP3)) + sage: RPoo = simplicial_sets.RealProjectiveSpace(Infinity) # optional - sage.groups + sage: RP3 = RPoo.n_skeleton(3) # optional - sage.groups + sage: RP3.rename_latex('RP^{3}') # optional - sage.groups + sage: latex(RPoo.quotient(RP3)) # optional - sage.graphs sage.groups RP^{\infty} / RP^{3} """ return '{} / {}'.format(latex(self.ambient()), latex(self.subcomplex())) @@ -1833,16 +1851,16 @@ def __init__(self, inclusion, vertex_name='*'): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2 + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP5_2 = RP5.quotient(RP2); RP5_2 # optional - sage.graphs sage.groups Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - sage: RP5_2.quotient_map() + sage: RP5_2.quotient_map() # optional - sage.graphs sage.groups Simplicial set morphism: From: RP^5 To: Quotient: (RP^5/Simplicial set with 3 non-degenerate simplices) - Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] + Defn: [1, f, f * f, f * f * f, f * f * f * f, f * f * f * f * f] + --> [*, s_0 *, s_1 s_0 *, f * f * f, f * f * f * f, f * f * f * f * f] """ subcomplex = inclusion.domain() PushoutOfSimplicialSets_finite.__init__(self, [inclusion, @@ -1861,16 +1879,16 @@ def quotient_map(self): EXAMPLES:: sage: K = simplicial_sets.Simplex(1) - sage: S1 = K.quotient(K.n_skeleton(0)) - sage: q = S1.quotient_map() - sage: q + sage: S1 = K.quotient(K.n_skeleton(0)) # optional - sage.graphs + sage: q = S1.quotient_map() # optional - sage.graphs + sage: q # optional - sage.graphs Simplicial set morphism: From: 1-simplex To: Quotient: (1-simplex/Simplicial set with 2 non-degenerate simplices) Defn: [(0,), (1,), (0, 1)] --> [*, *, (0, 1)] - sage: q.domain() == K + sage: q.domain() == K # optional - sage.graphs True - sage: q.codomain() == S1 + sage: q.codomain() == S1 # optional - sage.graphs True """ return self.structure_map(0) @@ -1885,7 +1903,7 @@ def __classcall__(cls, factors=None): sage: from sage.topology.simplicial_set_constructions import SmashProductOfSimplicialSets_finite as Smash sage: S2 = simplicial_sets.Sphere(2) - sage: Smash([S2, S2]) == Smash((S2, S2)) + sage: Smash([S2, S2]) == Smash((S2, S2)) # optional - sage.graphs True """ if factors: @@ -1913,7 +1931,7 @@ def __init__(self, factors=None): sage: T = simplicial_sets.Torus() sage: S2 = simplicial_sets.Sphere(2) - sage: T.smash_product(S2).homology() == T.suspension(2).homology() + sage: T.smash_product(S2).homology() == T.suspension(2).homology() # optional - sage.graphs sage.modules True """ if any(not space.is_pointed() for space in factors): @@ -1929,9 +1947,9 @@ def _repr_(self): EXAMPLES:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) - sage: S1 = simplicial_sets.Sphere(1) - sage: S1.smash_product(RP4, S1) + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups + sage: S1 = simplicial_sets.Sphere(1) # optional - sage.groups + sage: S1.smash_product(RP4, S1) # optional - sage.graphs sage.groups Smash product: (S^1 ^ RP^4 ^ S^1) """ s = 'Smash product: (' @@ -1945,9 +1963,9 @@ def _latex_(self): EXAMPLES:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) - sage: S1 = simplicial_sets.Sphere(1) - sage: latex(S1.smash_product(RP4, S1)) + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups + sage: S1 = simplicial_sets.Sphere(1) # optional - sage.groups + sage: latex(S1.smash_product(RP4, S1)) # optional - sage.graphs sage.groups S^{1} \wedge RP^{4} \wedge S^{1} """ return ' \\wedge '.join(latex(X) for X in self._factors) @@ -1961,7 +1979,7 @@ def __classcall__(cls, factors=None): sage: from sage.topology.simplicial_set_constructions import WedgeOfSimplicialSets sage: S2 = simplicial_sets.Sphere(2) - sage: WedgeOfSimplicialSets([S2, S2]) == WedgeOfSimplicialSets((S2, S2)) + sage: WedgeOfSimplicialSets([S2, S2]) == WedgeOfSimplicialSets((S2, S2)) # optional - sage.graphs True """ if factors: @@ -1991,26 +2009,27 @@ def __init__(self, factors=None): sage: CP2 = simplicial_sets.ComplexProjectiveSpace(2) sage: K = simplicial_sets.KleinBottle() - sage: W = CP2.wedge(K) - sage: W.homology() + sage: W = CP2.wedge(K) # optional - sage.graphs + sage: W.homology() # optional - sage.graphs sage.modules {0: 0, 1: Z x C2, 2: Z, 3: 0, 4: Z} - sage: W.inclusion_map(1) + sage: W.inclusion_map(1) # optional - sage.graphs Simplicial set morphism: From: Klein bottle To: Wedge: (CP^2 v Klein bottle) - Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] --> [*, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + --> [*, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] - sage: W.projection_map(0).domain() + sage: W.projection_map(0).domain() # optional - sage.graphs Wedge: (CP^2 v Klein bottle) - sage: W.projection_map(0).codomain() # copy of CP^2 + sage: W.projection_map(0).codomain() # copy of CP^2 # optional - sage.graphs Quotient: (Wedge: (CP^2 v Klein bottle)/Simplicial set with 6 non-degenerate simplices) - sage: W.projection_map(0).codomain().homology() + sage: W.projection_map(0).codomain().homology() # optional - sage.graphs sage.modules {0: 0, 1: 0, 2: Z, 3: 0, 4: Z} An error occurs if any of the factors is not pointed:: - sage: CP2.wedge(simplicial_sets.Simplex(1)) + sage: CP2.wedge(simplicial_sets.Simplex(1)) # optional - sage.graphs Traceback (most recent call last): ... ValueError: the simplicial sets must be pointed @@ -2036,7 +2055,7 @@ def _repr_(self): EXAMPLES:: sage: K = simplicial_sets.KleinBottle() - sage: K.wedge(K, K) + sage: K.wedge(K, K) # optional - sage.graphs Wedge: (Klein bottle v Klein bottle v Klein bottle) """ s = 'Wedge: (' @@ -2050,9 +2069,9 @@ def _latex_(self): EXAMPLES:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) - sage: S1 = simplicial_sets.Sphere(1) - sage: latex(S1.wedge(RP4, S1)) + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups + sage: S1 = simplicial_sets.Sphere(1) # optional - sage.groups + sage: latex(S1.wedge(RP4, S1)) # optional - sage.graphs sage.groups S^{1} \vee RP^{4} \vee S^{1} """ return ' \\vee '.join(latex(X) for X in self._factors) @@ -2078,7 +2097,7 @@ def __init__(self, factors=None): sage: from sage.topology.simplicial_set_constructions import WedgeOfSimplicialSets_finite sage: K = simplicial_sets.Simplex(3) - sage: WedgeOfSimplicialSets_finite((K,K)) + sage: WedgeOfSimplicialSets_finite((K,K)) # optional - sage.graphs Traceback (most recent call last): ... ValueError: the simplicial sets must be pointed @@ -2102,15 +2121,15 @@ def inclusion_map(self, i): sage: S1 = simplicial_sets.Sphere(1) sage: S2 = simplicial_sets.Sphere(2) - sage: W = S1.wedge(S2, S1) - sage: W.inclusion_map(1) + sage: W = S1.wedge(S2, S1) # optional - sage.graphs + sage: W.inclusion_map(1) # optional - sage.graphs Simplicial set morphism: From: S^2 To: Wedge: (S^1 v S^2 v S^1) Defn: [v_0, sigma_2] --> [*, sigma_2] - sage: W.inclusion_map(0).domain() + sage: W.inclusion_map(0).domain() # optional - sage.graphs S^1 - sage: W.inclusion_map(2).domain() + sage: W.inclusion_map(2).domain() # optional - sage.graphs S^1 """ return self.structure_map(i) @@ -2123,15 +2142,16 @@ def projection_map(self, i): sage: S1 = simplicial_sets.Sphere(1) sage: S2 = simplicial_sets.Sphere(2) - sage: W = S1.wedge(S2, S1) - sage: W.projection_map(1) + sage: W = S1.wedge(S2, S1) # optional - sage.graphs + sage: W.projection_map(1) # optional - sage.graphs Simplicial set morphism: From: Wedge: (S^1 v S^2 v S^1) - To: Quotient: (Wedge: (S^1 v S^2 v S^1)/Simplicial set with 3 non-degenerate simplices) + To: Quotient: (Wedge: (S^1 v S^2 v S^1)/Simplicial set with + 3 non-degenerate simplices) Defn: [*, sigma_1, sigma_1, sigma_2] --> [*, s_0 *, s_0 *, sigma_2] - sage: W.projection_map(1).image().homology(1) + sage: W.projection_map(1).image().homology(1) # optional - sage.graphs sage.modules 0 - sage: W.projection_map(1).image().homology(2) + sage: W.projection_map(1).image().homology(2) # optional - sage.graphs sage.modules Z """ m = len(self._factors) @@ -2180,15 +2200,16 @@ def __init__(self, factors=None): sage: CP2 = simplicial_sets.ComplexProjectiveSpace(2) sage: K = simplicial_sets.KleinBottle() - sage: W = CP2.disjoint_union(K) - sage: W.homology() + sage: W = CP2.disjoint_union(K) # optional - sage.graphs + sage: W.homology() # optional - sage.graphs sage.modules {0: Z, 1: Z x C2, 2: Z, 3: 0, 4: Z} - sage: W.inclusion_map(1) + sage: W.inclusion_map(1) # optional - sage.graphs Simplicial set morphism: From: Klein bottle To: Disjoint union: (CP^2 u Klein bottle) - Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] --> [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + Defn: [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] + --> [Delta_{0,0}, Delta_{1,0}, Delta_{1,1}, Delta_{1,2}, Delta_{2,0}, Delta_{2,1}] """ PushoutOfSimplicialSets.__init__(self, [space._map_from_empty_set() for space in factors]) @@ -2212,10 +2233,11 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: T = simplicial_sets.Torus() - sage: X = B.disjoint_union(T) - sage: X.n_skeleton(3).homology() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: T = simplicial_sets.Torus() # optional - sage.groups + sage: X = B.disjoint_union(T) # optional - sage.groups + sage: X.n_skeleton(3).homology() # optional - sage.groups sage.modules {0: Z, 1: Z x Z x C2, 2: Z, 3: Z} """ if self.is_finite(): @@ -2241,8 +2263,8 @@ def _repr_(self): EXAMPLES:: sage: T = simplicial_sets.Torus() - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) - sage: T.disjoint_union(T, RP3) + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.groups + sage: T.disjoint_union(T, RP3) # optional - sage.groups Disjoint union: (Torus u Torus u RP^3) """ s = 'Disjoint union: (' @@ -2256,9 +2278,9 @@ def _latex_(self): EXAMPLES:: - sage: RP4 = simplicial_sets.RealProjectiveSpace(4) + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) # optional - sage.groups sage: S1 = simplicial_sets.Sphere(1) - sage: latex(S1.disjoint_union(RP4, S1)) + sage: latex(S1.disjoint_union(RP4, S1)) # optional - sage.graphs sage.groups S^{1} \amalg RP^{4} \amalg S^{1} """ return ' \\amalg '.join(latex(X) for X in self._factors) @@ -2287,9 +2309,9 @@ def __init__(self, factors=None): sage: from sage.topology.simplicial_set_constructions import DisjointUnionOfSimplicialSets_finite sage: from sage.topology.simplicial_set_examples import Empty sage: S = simplicial_sets.Sphere(4) - sage: DisjointUnionOfSimplicialSets_finite((S,S,S)) + sage: DisjointUnionOfSimplicialSets_finite((S,S,S)) # optional - sage.graphs Disjoint union: (S^4 u S^4 u S^4) - sage: DisjointUnionOfSimplicialSets_finite([Empty(), Empty()]) == Empty() + sage: DisjointUnionOfSimplicialSets_finite([Empty(), Empty()]) == Empty() # optional - sage.graphs True """ if not factors: @@ -2307,15 +2329,15 @@ def inclusion_map(self, i): sage: S1 = simplicial_sets.Sphere(1) sage: S2 = simplicial_sets.Sphere(2) - sage: W = S1.disjoint_union(S2, S1) - sage: W.inclusion_map(1) + sage: W = S1.disjoint_union(S2, S1) # optional - sage.graphs + sage: W.inclusion_map(1) # optional - sage.graphs Simplicial set morphism: From: S^2 To: Disjoint union: (S^1 u S^2 u S^1) Defn: [v_0, sigma_2] --> [v_0, sigma_2] - sage: W.inclusion_map(0).domain() + sage: W.inclusion_map(0).domain() # optional - sage.graphs S^1 - sage: W.inclusion_map(2).domain() + sage: W.inclusion_map(2).domain() # optional - sage.graphs S^1 """ return self.structure_map(i) @@ -2373,10 +2395,11 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: X = B.disjoint_union(B) - sage: CX = B.cone() - sage: CX.n_skeleton(3).homology() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: X = B.disjoint_union(B) # optional - sage.graphs sage.groups + sage: CX = B.cone() # optional - sage.graphs sage.groups + sage: CX.n_skeleton(3).homology() # optional - sage.graphs sage.groups sage.modules {0: 0, 1: 0, 2: 0, 3: Z} """ if self.is_finite(): @@ -2397,7 +2420,7 @@ def _repr_(self): EXAMPLES:: - sage: simplicial_sets.Simplex(3).cone() + sage: simplicial_sets.Simplex(3).cone() # optional - sage.graphs Cone of 3-simplex """ return 'Cone of {}'.format(self._base) @@ -2408,7 +2431,7 @@ def _latex_(self): EXAMPLES:: - sage: latex(simplicial_sets.Simplex(3).cone()) + sage: latex(simplicial_sets.Simplex(3).cone()) # optional - sage.graphs C \Delta^{3} """ return 'C {}'.format(latex(self._base)) @@ -2479,11 +2502,11 @@ def base_as_subset(self): EXAMPLES:: - sage: X = simplicial_sets.RealProjectiveSpace(4).unset_base_point() - sage: Y = X.cone() - sage: Y.base_as_subset() + sage: X = simplicial_sets.RealProjectiveSpace(4).unset_base_point() # optional - sage.groups + sage: Y = X.cone() # optional - sage.graphs sage.groups + sage: Y.base_as_subset() # optional - sage.graphs sage.groups Simplicial set with 5 non-degenerate simplices - sage: Y.base_as_subset() == X + sage: Y.base_as_subset() == X # optional - sage.graphs sage.groups True """ X = self._base @@ -2496,12 +2519,13 @@ def map_from_base(self): EXAMPLES:: sage: X = simplicial_sets.Simplex(2).n_skeleton(1) - sage: Y = X.cone() - sage: Y.map_from_base() + sage: Y = X.cone() # optional - sage.graphs + sage: Y.map_from_base() # optional - sage.graphs Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices To: Cone of Simplicial set with 6 non-degenerate simplices - Defn: [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)] --> [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)] + Defn: [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)] + --> [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)] """ return self.base_as_subset().inclusion_map() @@ -2531,8 +2555,8 @@ def __init__(self, base): sage: e = AbstractSimplex(1, name='e') sage: X = SimplicialSet({e: (v, v)}) sage: X = X.set_base_point(v) - sage: CX = X.cone() # indirect doctest - sage: CX.nondegenerate_simplices() + sage: CX = X.cone() # indirect doctest # optional - sage.graphs + sage: CX.nondegenerate_simplices() # optional - sage.graphs [*, e, (e,*)] """ C = ConeOfSimplicialSet(base) @@ -2563,8 +2587,9 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: B.cone().n_skeleton(3).homology() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: B.cone().n_skeleton(3).homology() # optional - sage.graphs sage.groups sage.modules {0: 0, 1: 0, 2: 0, 3: Z} """ if self.is_finite(): @@ -2585,7 +2610,7 @@ def _repr_(self): EXAMPLES:: sage: X = simplicial_sets.Sphere(4) - sage: X.cone() + sage: X.cone() # optional - sage.graphs Reduced cone of S^4 """ return 'Reduced cone of {}'.format(self._base) @@ -2596,7 +2621,7 @@ def _latex_(self): EXAMPLES:: - sage: latex(simplicial_sets.Sphere(4).cone()) + sage: latex(simplicial_sets.Sphere(4).cone()) # optional - sage.graphs C S^{4} """ return 'C {}'.format(latex(self._base)) @@ -2628,8 +2653,8 @@ def __init__(self, base): sage: e = AbstractSimplex(1, name='e') sage: X = SimplicialSet({e: (v, v)}) sage: X = X.set_base_point(v) - sage: CX = X.cone() # indirect doctest - sage: CX.nondegenerate_simplices() + sage: CX = X.cone() # indirect doctest # optional - sage.graphs + sage: CX.nondegenerate_simplices() # optional - sage.graphs [*, e, (e,*)] """ C = ConeOfSimplicialSet_finite(base) @@ -2657,8 +2682,8 @@ def map_from_base(self): EXAMPLES:: sage: S3 = simplicial_sets.Sphere(3) - sage: CS3 = S3.cone() - sage: CS3.map_from_base() + sage: CS3 = S3.cone() # optional - sage.graphs + sage: CS3.map_from_base() # optional - sage.graphs Simplicial set morphism: From: S^3 To: Reduced cone of S^3 @@ -2692,18 +2717,19 @@ def __init__(self, base): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: B.suspension() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: B.suspension() # optional - sage.graphs sage.groups Sigma(Classifying space of Multiplicative Abelian group isomorphic to C2) - sage: B.suspension().n_skeleton(3).homology() + sage: B.suspension().n_skeleton(3).homology() # optional - sage.graphs sage.groups sage.modules {0: 0, 1: 0, 2: C2, 3: 0} If ``X`` is finite, the suspension comes with a quotient map from the cone:: sage: S3 = simplicial_sets.Sphere(3) - sage: S4 = S3.suspension() - sage: S4.quotient_map() + sage: S4 = S3.suspension() # optional - sage.graphs + sage: S4.quotient_map() # optional - sage.graphs Simplicial set morphism: From: Reduced cone of S^3 To: Sigma(S^3) @@ -2711,11 +2737,11 @@ def __init__(self, base): TESTS:: - sage: S3.suspension() == S3.suspension() + sage: S3.suspension() == S3.suspension() # optional - sage.graphs True - sage: S3.suspension() == simplicial_sets.Sphere(3).suspension() + sage: S3.suspension() == simplicial_sets.Sphere(3).suspension() # optional - sage.graphs False - sage: B.suspension() == B.suspension() + sage: B.suspension() == B.suspension() # optional - sage.graphs sage.groups True """ Cat = SimplicialSets() @@ -2748,9 +2774,10 @@ def n_skeleton(self, n): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: SigmaB = B.suspension() - sage: SigmaB.n_skeleton(4).homology(base_ring=GF(2)) + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: SigmaB = B.suspension() # optional - sage.graphs sage.groups + sage: SigmaB.n_skeleton(4).homology(base_ring=GF(2)) # optional - sage.graphs sage.groups sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 0 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2, @@ -2783,10 +2810,10 @@ def __repr_or_latex__(self, output_type=None): EXAMPLES:: sage: T = simplicial_sets.Torus() - sage: K = T.suspension(10) - sage: K.__repr_or_latex__() + sage: K = T.suspension(10) # optional - sage.graphs + sage: K.__repr_or_latex__() # optional - sage.graphs 'Sigma^10(Torus)' - sage: K.__repr_or_latex__('latex') + sage: K.__repr_or_latex__('latex') # optional - sage.graphs '\\Sigma^{10}(S^{1} \\times S^{1})' """ latex_output = (output_type == 'latex') @@ -2824,12 +2851,12 @@ def _repr_(self): EXAMPLES:: sage: S2 = simplicial_sets.Sphere(2) - sage: S2.suspension(3) + sage: S2.suspension(3) # optional - sage.graphs Sigma^3(S^2) sage: K = simplicial_sets.Simplex(2) - sage: K.suspension(3) + sage: K.suspension(3) # optional - sage.graphs S^3(2-simplex) - sage: K.suspension() + sage: K.suspension() # optional - sage.graphs S(2-simplex) """ return self.__repr_or_latex__() @@ -2844,12 +2871,12 @@ def _latex_(self): EXAMPLES:: sage: S2 = simplicial_sets.Sphere(2) - sage: latex(S2.suspension(3)) + sage: latex(S2.suspension(3)) # optional - sage.graphs \Sigma^{3}(S^{2}) sage: K = simplicial_sets.Simplex(2) - sage: latex(K.suspension(3)) + sage: latex(K.suspension(3)) # optional - sage.graphs S^{3}(\Delta^{2}) - sage: latex(K.suspension()) + sage: latex(K.suspension()) # optional - sage.graphs S(\Delta^{2}) """ return self.__repr_or_latex__('latex') @@ -2873,10 +2900,10 @@ def __init__(self, base): EXAMPLES:: sage: X = simplicial_sets.Sphere(3) - sage: X.suspension(2) + sage: X.suspension(2) # optional - sage.graphs Sigma^2(S^3) sage: Y = X.unset_base_point() - sage: Y.suspension(2) + sage: Y.suspension(2) # optional - sage.graphs S^2(Simplicial set with 2 non-degenerate simplices) """ self._base = base diff --git a/src/sage/topology/simplicial_set_examples.py b/src/sage/topology/simplicial_set_examples.py index 30bfa0fbaab..94925d7248a 100644 --- a/src/sage/topology/simplicial_set_examples.py +++ b/src/sage/topology/simplicial_set_examples.py @@ -31,7 +31,6 @@ import re import os -from pyparsing import OneOrMore, nestedExpr from sage.env import SAGE_ENV from sage.misc.cachefunc import cached_method, cached_function @@ -108,11 +107,11 @@ def __eq__(self, other): EXAMPLES:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: C3.nerve() == C3.nerve() + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: C3.nerve() == C3.nerve() # optional - sage.groups False - sage: BC3 = C3.nerve() - sage: BC3 == BC3 + sage: BC3 = C3.nerve() # optional - sage.groups + sage: BC3 == BC3 # optional - sage.groups True """ return (isinstance(other, Nerve) @@ -125,11 +124,11 @@ def __ne__(self, other): EXAMPLES:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) - sage: G3 = groups.permutation.Cyclic(3) - sage: C3.nerve() != G3.nerve() + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups + sage: G3 = groups.permutation.Cyclic(3) # optional - sage.groups + sage: C3.nerve() != G3.nerve() # optional - sage.groups True - sage: C3.nerve() != C3.nerve() + sage: C3.nerve() != C3.nerve() # optional - sage.groups True """ return not self == other @@ -141,17 +140,17 @@ def __hash__(self): EXAMPLES:: - sage: G3 = groups.permutation.Cyclic(3) - sage: hash(G3.nerve()) # random + sage: G3 = groups.permutation.Cyclic(3) # optional - sage.groups + sage: hash(G3.nerve()) # random # optional - sage.groups 17 Different instances yield different base points, hence different hashes:: - sage: X = G3.nerve() - sage: Y = G3.nerve() - sage: X.base_point() != Y.base_point() + sage: X = G3.nerve() # optional - sage.groups + sage: Y = G3.nerve() # optional - sage.groups + sage: X.base_point() != Y.base_point() # optional - sage.groups True - sage: hash(X) != hash(Y) + sage: hash(X) != hash(Y) # optional - sage.groups True """ return hash(self._monoid) ^ hash(self.base_point()) @@ -169,13 +168,13 @@ def n_skeleton(self, n): EXAMPLES:: - sage: K4 = groups.misc.MultiplicativeAbelian([2,2]) - sage: BK4 = simplicial_sets.ClassifyingSpace(K4) - sage: BK4.n_skeleton(3) + sage: K4 = groups.misc.MultiplicativeAbelian([2,2]) # optional - sage.groups + sage: BK4 = simplicial_sets.ClassifyingSpace(K4) # optional - sage.groups + sage: BK4.n_skeleton(3) # optional - sage.groups Simplicial set with 40 non-degenerate simplices - sage: BK4.n_cells(1) == BK4.n_skeleton(3).n_cells(1) + sage: BK4.n_cells(1) == BK4.n_skeleton(3).n_cells(1) # optional - sage.groups True - sage: BK4.n_cells(3) == BK4.n_skeleton(1).n_cells(3) + sage: BK4.n_cells(3) == BK4.n_skeleton(1).n_cells(3) # optional - sage.groups False """ from .simplicial_set_constructions import SubSimplicialSet @@ -314,17 +313,16 @@ def ClassifyingSpace(group): EXAMPLES:: - sage: C2 = groups.misc.MultiplicativeAbelian([2]) - sage: BC2 = simplicial_sets.ClassifyingSpace(C2) - sage: H = BC2.homology(range(9), base_ring=GF(2)) - sage: [H[i].dimension() for i in range(9)] + sage: C2 = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: BC2 = simplicial_sets.ClassifyingSpace(C2) # optional - sage.groups + sage: H = BC2.homology(range(9), base_ring=GF(2)) # optional - sage.groups sage.modules sage.rings.finite_rings + sage: [H[i].dimension() for i in range(9)] # optional - sage.groups sage.modules sage.rings.finite_rings [0, 1, 1, 1, 1, 1, 1, 1, 1] - sage: Klein4 = groups.misc.MultiplicativeAbelian([2, 2]) - sage: BK = simplicial_sets.ClassifyingSpace(Klein4) - sage: BK + sage: Klein4 = groups.misc.MultiplicativeAbelian([2, 2]) # optional - sage.groups + sage: BK = simplicial_sets.ClassifyingSpace(Klein4); BK # optional - sage.groups Classifying space of Multiplicative Abelian group isomorphic to C2 x C2 - sage: BK.homology(range(5), base_ring=GF(2)) # long time (1 second) + sage: BK.homology(range(5), base_ring=GF(2)) # long time (1 second) # optional - sage.groups sage.modules sage.rings.finite_rings {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 2 over Finite Field of size 2, 2: Vector space of dimension 3 over Finite Field of size 2, @@ -346,18 +344,18 @@ def RealProjectiveSpace(n): EXAMPLES:: - sage: simplicial_sets.RealProjectiveSpace(7) + sage: simplicial_sets.RealProjectiveSpace(7) # optional - sage.groups RP^7 - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP5.homology() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP5.homology() # optional - sage.groups {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: Z} - sage: RP5 + sage: RP5 # optional - sage.groups RP^5 - sage: latex(RP5) + sage: latex(RP5) # optional - sage.groups RP^{5} - sage: BC2 = simplicial_sets.RealProjectiveSpace(Infinity) - sage: latex(BC2) + sage: BC2 = simplicial_sets.RealProjectiveSpace(Infinity) # optional - sage.groups + sage: latex(BC2) # optional - sage.groups RP^{\infty} """ if n == Infinity: @@ -385,7 +383,7 @@ def KleinBottle(): sage: K = simplicial_sets.KleinBottle() sage: K.f_vector() [1, 3, 2] - sage: K.homology(reduced=False) + sage: K.homology(reduced=False) # optional - sage.modules {0: Z, 1: Z x C2, 2: 0} sage: K Klein bottle @@ -410,7 +408,7 @@ def Torus(): sage: T = simplicial_sets.Torus() sage: T.f_vector() [1, 3, 2] - sage: T.homology(reduced=False) + sage: T.homology(reduced=False) # optional - sage.modules {0: Z, 1: Z x Z, 2: Z} """ S1 = Sphere(1) @@ -536,23 +534,23 @@ def ComplexProjectiveSpace(n): sage: simplicial_sets.ComplexProjectiveSpace(2).homology(reduced=False) {0: Z, 1: 0, 2: Z, 3: 0, 4: Z} - sage: CP3 = simplicial_sets.ComplexProjectiveSpace(3) - sage: CP3 + sage: CP3 = simplicial_sets.ComplexProjectiveSpace(3) # optional - pyparsing + sage: CP3 # optional - pyparsing CP^3 - sage: latex(CP3) + sage: latex(CP3) # optional - pyparsing CP^{3} - sage: CP3.f_vector() + sage: CP3.f_vector() # optional - pyparsing [1, 0, 3, 10, 25, 30, 15] - sage: K = CP3.suspension() # long time (1 second) - sage: R = K.cohomology_ring(GF(2)) # long time - sage: R.gens() # long time + sage: K = CP3.suspension() # long time (1 second) # optional - pyparsing + sage: R = K.cohomology_ring(GF(2)) # long time # optional - pyparsing + sage: R.gens() # long time # optional - pyparsing (h^{0,0}, h^{3,0}, h^{5,0}, h^{7,0}) - sage: x = R.gens()[1] # long time - sage: x.Sq(2) # long time + sage: x = R.gens()[1] # long time # optional - pyparsing + sage: x.Sq(2) # long time # optional - pyparsing h^{5,0} - sage: simplicial_sets.ComplexProjectiveSpace(4).f_vector() + sage: simplicial_sets.ComplexProjectiveSpace(4).f_vector() # optional - pyparsing [1, 0, 4, 22, 97, 255, 390, 315, 105] sage: simplicial_sets.ComplexProjectiveSpace(5) @@ -646,10 +644,12 @@ def simplicial_data_from_kenzo_output(filename): sage: from sage.topology.simplicial_set_examples import simplicial_data_from_kenzo_output sage: from sage.topology.simplicial_set import SimplicialSet sage: sphere = os.path.join(SAGE_ENV['SAGE_EXTCODE'], 'kenzo', 'S4.txt') - sage: S4 = SimplicialSet(simplicial_data_from_kenzo_output(sphere)) - sage: S4.homology(reduced=False) + sage: S4 = SimplicialSet(simplicial_data_from_kenzo_output(sphere)) # optional - pyparsing + sage: S4.homology(reduced=False) # optional - pyparsing {0: Z, 1: 0, 2: 0, 3: 0, 4: Z} """ + from pyparsing import OneOrMore, nestedExpr + with open(filename, 'r') as f: data = f.read() dim = 0 @@ -732,14 +732,14 @@ def HopfMap(): Using the Hopf map to attach a cell:: - sage: X = g.mapping_cone() - sage: CP2 = simplicial_sets.ComplexProjectiveSpace(2) - sage: X.homology() == CP2.homology() + sage: X = g.mapping_cone() # optional - sage.graphs + sage: CP2 = simplicial_sets.ComplexProjectiveSpace(2) # optional - sage.graphs + sage: X.homology() == CP2.homology() # optional - sage.graphs True - sage: X.f_vector() + sage: X.f_vector() # optional - sage.graphs [1, 0, 5, 9, 6] - sage: CP2.f_vector() + sage: CP2.f_vector() # optional - sage.graphs [1, 0, 2, 3, 3] """ # The 2-sphere and its simplices. @@ -811,19 +811,17 @@ def PresentationComplex(G): EXAMPLES:: - sage: G = SymmetricGroup(2).as_finitely_presented_group() - sage: G + sage: G = SymmetricGroup(2).as_finitely_presented_group(); G # optional - sage.groups Finitely presented group < a | a^2 > - sage: S = simplicial_sets.PresentationComplex(G) - sage: S + sage: S = simplicial_sets.PresentationComplex(G); S # optional - sage.groups Simplicial set with 5 non-degenerate simplices - sage: S.face_data() + sage: S.face_data() # optional - sage.groups {Delta^0: None, a: (Delta^0, Delta^0), a^-1: (Delta^0, Delta^0), Ta: (a, s_0 Delta^0, a^-1), a^2: (a, s_0 Delta^0, a)} - sage: S.fundamental_group() + sage: S.fundamental_group() # optional - sage.groups Finitely presented group < e0 | e0^2 > """ O = AbstractSimplex(0) diff --git a/src/sage/topology/simplicial_set_morphism.py b/src/sage/topology/simplicial_set_morphism.py index 263679c9254..4569c1e440f 100644 --- a/src/sage/topology/simplicial_set_morphism.py +++ b/src/sage/topology/simplicial_set_morphism.py @@ -101,8 +101,8 @@ def diagonal_morphism(self): EXAMPLES:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) - sage: Hom(RP2, RP2.product(RP2)).diagonal_morphism() + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups + sage: Hom(RP2, RP2.product(RP2)).diagonal_morphism() # optional - sage.groups Simplicial set morphism: From: RP^2 To: RP^2 x RP^2 @@ -619,9 +619,9 @@ def __call__(self, x): sage: one(e) == e True - sage: B = AbelianGroup([2]).nerve() - sage: c = B.constant_map() - sage: c(B.n_cells(2)[0]) + sage: B = AbelianGroup([2]).nerve() # optional - sage.groups + sage: c = B.constant_map() # optional - sage.groups + sage: c(B.n_cells(2)[0]) # optional - sage.groups s_1 s_0 * """ if x not in self.domain(): @@ -666,7 +666,7 @@ def _composition_(self, right, homset): Defn: [v_0, sigma_1] --> [(v_0, v_0), (sigma_1, s_0 v_0)] sage: (g*f).image() Simplicial set with 2 non-degenerate simplices - sage: f.image().homology() + sage: f.image().homology() # optional - sage.modules {0: 0, 1: Z} """ if self.is_identity(): @@ -688,21 +688,22 @@ def image(self): sage: S1 = simplicial_sets.Sphere(1) sage: T = S1.product(S1) sage: K = T.factor(0, as_subset=True) - sage: f = S1.Hom(T)({S1.n_cells(0)[0]:K.n_cells(0)[0], S1.n_cells(1)[0]:K.n_cells(1)[0]}) - sage: f + sage: f = S1.Hom(T)({S1.n_cells(0)[0]: K.n_cells(0)[0], + ....: S1.n_cells(1)[0]: K.n_cells(1)[0]}); f Simplicial set morphism: From: S^1 To: S^1 x S^1 Defn: [v_0, sigma_1] --> [(v_0, v_0), (sigma_1, s_0 v_0)] sage: f.image() Simplicial set with 2 non-degenerate simplices - sage: f.image().homology() + sage: f.image().homology() # optional - sage.modules {0: 0, 1: Z} - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: B.constant_map().image() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: B.constant_map().image() # optional - sage.groups Point - sage: Hom(B,B).identity().image() == B + sage: Hom(B,B).identity().image() == B # optional - sage.groups True """ if self._is_identity: @@ -745,16 +746,17 @@ def is_identity(self): sage: (f*g).induced_homology_morphism().to_matrix(1) [0] - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP5.n_skeleton(2).inclusion_map().is_identity() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP5.n_skeleton(2).inclusion_map().is_identity() # optional - sage.groups False - sage: RP5.n_skeleton(5).inclusion_map().is_identity() + sage: RP5.n_skeleton(5).inclusion_map().is_identity() # optional - sage.groups True - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: Hom(B,B).identity().is_identity() + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: Hom(B,B).identity().is_identity() # optional - sage.groups True - sage: Hom(B,B).constant_map().is_identity() + sage: Hom(B,B).constant_map().is_identity() # optional - sage.groups False """ ans = (self._is_identity or @@ -770,18 +772,18 @@ def is_surjective(self): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP2.inclusion_map().is_surjective() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP2.inclusion_map().is_surjective() # optional - sage.groups False - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.quotient_map().is_surjective() + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.groups + sage: RP5_2.quotient_map().is_surjective() # optional - sage.groups True - sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) - sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) - sage: f.is_surjective() + sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) # optional - sage.groups + sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) # optional - sage.groups + sage: f.is_surjective() # optional - sage.groups True """ return self._is_identity or self.image() == self.codomain() @@ -792,18 +794,18 @@ def is_injective(self): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP2.inclusion_map().is_injective() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP2.inclusion_map().is_injective() # optional - sage.groups True - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.quotient_map().is_injective() + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.groups + sage: RP5_2.quotient_map().is_injective() # optional - sage.groups False - sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) - sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) - sage: f.is_injective() + sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) # optional - sage.groups + sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) # optional - sage.groups + sage: f.is_injective() # optional - sage.groups True """ if self._is_identity: @@ -822,18 +824,18 @@ def is_bijective(self): EXAMPLES:: - sage: RP5 = simplicial_sets.RealProjectiveSpace(5) - sage: RP2 = RP5.n_skeleton(2) - sage: RP2.inclusion_map().is_bijective() + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) # optional - sage.groups + sage: RP2 = RP5.n_skeleton(2) # optional - sage.groups + sage: RP2.inclusion_map().is_bijective() # optional - sage.groups False - sage: RP5_2 = RP5.quotient(RP2) - sage: RP5_2.quotient_map().is_bijective() + sage: RP5_2 = RP5.quotient(RP2) # optional - sage.groups + sage: RP5_2.quotient_map().is_bijective() # optional - sage.groups False - sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) - sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) - sage: f.is_bijective() + sage: K = RP5_2.pullback(RP5_2.quotient_map(), RP5_2.base_point_map()) # optional - sage.groups + sage: f = K.universal_property(RP2.inclusion_map(), RP2.constant_map()) # optional - sage.groups + sage: f.is_bijective() # optional - sage.groups True """ return self.is_injective() and self.is_surjective() @@ -915,8 +917,7 @@ def pushout(self, *others): sage: K = simplicial_sets.KleinBottle() sage: init_T = T._map_from_empty_set() sage: init_K = K._map_from_empty_set() - sage: D = init_T.pushout(init_K) # the disjoint union as a pushout - sage: D + sage: D = init_T.pushout(init_K); D # the disjoint union as a pushout # optional - sage.graphs Pushout of maps: Simplicial set morphism: From: Empty simplicial set @@ -951,8 +952,7 @@ def pullback(self, *others): sage: K = simplicial_sets.KleinBottle() sage: term_T = T.constant_map() sage: term_K = K.constant_map() - sage: P = term_T.pullback(term_K) # the product as a pullback - sage: P + sage: P = term_T.pullback(term_K); P # the product as a pullback Pullback of maps: Simplicial set morphism: From: Torus @@ -1057,8 +1057,7 @@ def coequalizer(self, other): sage: f = K.inclusion_map() sage: v,w = K.n_cells(0) sage: g = Hom(K,L)({v:pt, w:pt, e:pt.apply_degeneracies(0)}) - sage: P = f.coequalizer(g) - sage: P + sage: P = f.coequalizer(g); P # optional - sage.graphs Pushout of maps: Simplicial set morphism: From: Disjoint union: (Simplicial set with 3 non-degenerate simplices u 2-simplex) @@ -1096,7 +1095,8 @@ def mapping_cone(self): sage: L = K.set_base_point(K.n_cells(0)[0]) sage: u,v,w = L.n_cells(0) sage: e,f,g = L.n_cells(1) - sage: h = L.Hom(S1)({u:v_0, v:v_0, w:v_0, e:sigma_1, f:v_0.apply_degeneracies(0), g:sigma_1}) + sage: h = L.Hom(S1)({u:v_0, v:v_0, w:v_0, e:sigma_1, + ....: f:v_0.apply_degeneracies(0), g:sigma_1}) sage: h Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices @@ -1106,8 +1106,8 @@ def mapping_cone(self): [1|0] [-+-] [0|2] - sage: X = h.mapping_cone() - sage: X.homology() == simplicial_sets.RealProjectiveSpace(2).homology() + sage: X = h.mapping_cone() # optional - sage.graphs + sage: X.homology() == simplicial_sets.RealProjectiveSpace(2).homology() # optional - sage.graphs sage.modules True """ dom = self.domain() @@ -1154,10 +1154,10 @@ def coproduct(self, *others): sage: S1 = simplicial_sets.Sphere(1) sage: f = Hom(S1,S1).identity() - sage: f.coproduct(f).is_bijective() + sage: f.coproduct(f).is_bijective() # optional - sage.graphs True sage: g = S1.constant_map(S1) - sage: g.coproduct(g).is_bijective() + sage: g.coproduct(g).is_bijective() # optional - sage.graphs False """ codomain = self.codomain().coproduct(*[g.codomain() for g in others]) @@ -1177,8 +1177,9 @@ def suspension(self, n=1): EXAMPLES:: sage: eta = simplicial_sets.HopfMap() - sage: susp_eta = eta.suspension() - sage: susp_eta.mapping_cone().homology() == eta.mapping_cone().suspension().homology() + sage: mc_susp_eta = eta.suspension().mapping_cone() # optional - sage.graphs + sage: susp_mc_eta = eta.mapping_cone().suspension() # optional - sage.graphs + sage: mc_susp_eta.homology() == susp_mc_eta.homology() # optional - sage.graphs sage.modules True This uses reduced suspensions if the original morphism is @@ -1188,19 +1189,19 @@ def suspension(self, n=1): sage: L = simplicial_sets.Simplex(1) sage: L.constant_map().is_pointed() False - sage: f = L.constant_map().suspension() - sage: f.is_constant() + sage: f = L.constant_map().suspension() # optional - sage.graphs + sage: f.is_constant() # optional - sage.graphs False sage: K = simplicial_sets.Sphere(3) sage: K.constant_map().is_pointed() True - sage: g = K.constant_map().suspension() - sage: g.is_constant() + sage: g = K.constant_map().suspension() # optional - sage.graphs + sage: g.is_constant() # optional - sage.graphs True - sage: h = K.identity().suspension() - sage: h.is_identity() + sage: h = K.identity().suspension() # optional - sage.graphs + sage: h.is_identity() # optional - sage.graphs True """ domain = self.domain() @@ -1248,13 +1249,14 @@ def n_skeleton(self, n, domain=None, codomain=None): EXAMPLES:: - sage: B = simplicial_sets.ClassifyingSpace(groups.misc.MultiplicativeAbelian([2])) - sage: one = Hom(B,B).identity() - sage: one.n_skeleton(3) + sage: G = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups + sage: B = simplicial_sets.ClassifyingSpace(G) # optional - sage.groups + sage: one = Hom(B,B).identity() # optional - sage.groups + sage: one.n_skeleton(3) # optional - sage.groups Simplicial set endomorphism of Simplicial set with 4 non-degenerate simplices Defn: Identity map - sage: c = Hom(B,B).constant_map() - sage: c.n_skeleton(3) + sage: c = Hom(B,B).constant_map() # optional - sage.groups + sage: c.n_skeleton(3) # optional - sage.groups Simplicial set endomorphism of Simplicial set with 4 non-degenerate simplices Defn: Constant map at 1 @@ -1383,13 +1385,13 @@ def induced_homology_morphism(self, base_ring=None, cohomology=False): sage: Y = SimplicialSet({e: (v, v)}) sage: H = Hom(X, Y) sage: f = H({v: v, w: v, e: e, f: e}) - sage: g = f.induced_homology_morphism() - sage: g.to_matrix() + sage: g = f.induced_homology_morphism() # optional - sage.modules + sage: g.to_matrix() # optional - sage.modules [1|0] [-+-] [0|2] - sage: g3 = f.induced_homology_morphism(base_ring=GF(3), cohomology=True) - sage: g3.to_matrix() + sage: g3 = f.induced_homology_morphism(base_ring=GF(3), cohomology=True) # optional - sage.modules sage.rings.finite_rings + sage: g3.to_matrix() # optional - sage.modules sage.rings.finite_rings [1|0] [-+-] [0|2]