def Sphere(self,n): """ A minimal triangulation of the n-dimensional sphere. INPUT: - ``n`` - positive integer EXAMPLES:: sage: simplicial_complexes.Sphere(2) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} sage: simplicial_complexes.Sphere(5).homology() {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z} sage: [simplicial_complexes.Sphere(n).euler_characteristic() for n in range(6)] [2, 0, 2, 0, 2, 0] sage: [simplicial_complexes.Sphere(n).f_vector() for n in range(6)] [[1, 2], [1, 3, 3], [1, 4, 6, 4], [1, 5, 10, 10, 5], [1, 6, 15, 20, 15, 6], [1, 7, 21, 35, 35, 21, 7]] """ S = Simplex(n+1) facets = S.faces() S = SimplicialComplex(n+1, facets) return S
def Sphere(self, n): """ A minimal triangulation of the n-dimensional sphere. INPUT: - ``n`` - positive integer EXAMPLES:: sage: simplicial_complexes.Sphere(2) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} sage: simplicial_complexes.Sphere(5).homology() {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z} sage: [simplicial_complexes.Sphere(n).euler_characteristic() for n in range(6)] [2, 0, 2, 0, 2, 0] sage: [simplicial_complexes.Sphere(n).f_vector() for n in range(6)] [[1, 2], [1, 3, 3], [1, 4, 6, 4], [1, 5, 10, 10, 5], [1, 6, 15, 20, 15, 6], [1, 7, 21, 35, 35, 21, 7]] """ S = Simplex(n + 1) facets = S.faces() S = SimplicialComplex(n + 1, facets) return S
def __call__(self, x, orientation=False): """ Input is a simplex of the domain. Output is the image simplex. If the optional argument ``orientation`` is ``True``, then this returns a pair ``(image simplex, oriented)`` where ``oriented`` is 1 or `-1` depending on whether the map preserves or reverses the orientation of the image simplex. EXAMPLES:: sage: S = simplicial_complexes.Sphere(2) sage: T = simplicial_complexes.Sphere(3) sage: S Minimal triangulation of the 2-sphere sage: T Minimal triangulation of the 3-sphere sage: f = {0:0,1:1,2:2,3:3} sage: H = Hom(S,T) sage: x = H(f) sage: from sage.homology.simplicial_complex import Simplex sage: x(Simplex([0,2,3])) (0, 2, 3) An orientation-reversing example:: sage: X = SimplicialComplex([[0,1]], is_mutable=False) sage: g = Hom(X,X)({0:1, 1:0}) sage: g(Simplex([0,1])) (0, 1) sage: g(Simplex([0,1]), orientation=True) ((0, 1), -1) """ dim = self.domain().dimension() if not isinstance(x, Simplex) or x.dimension( ) > dim or x not in self.domain().faces()[x.dimension()]: raise ValueError("x must be a simplex of the source of f") tup = x.tuple() fx = [] for j in tup: fx.append(self._vertex_dictionary[j]) if orientation: if len(set(fx)) == len(tup): oriented = Permutation(convert_perm(fx)).signature() else: oriented = 1 return (Simplex(set(fx)), oriented) else: return Simplex(set(fx))
def fiber_product(self, other, rename_vertices=True): """ Fiber product of ``self`` and ``other``. Both morphisms should have the same codomain. The method returns a morphism of simplicial complexes, which is the morphism from the space of the fiber product to the codomain. EXAMPLES:: sage: S = SimplicialComplex([[0,1],[1,2]], is_mutable=False) sage: T = SimplicialComplex([[0,2],[1]], is_mutable=False) sage: U = SimplicialComplex([[0,1],[2]], is_mutable=False) sage: H = Hom(S,U) sage: G = Hom(T,U) sage: f = {0:0,1:1,2:0} sage: g = {0:0,1:1,2:1} sage: x = H(f) sage: y = G(g) sage: z = x.fiber_product(y) sage: z Simplicial complex morphism: From: Simplicial complex with 4 vertices and facets {...} To: Simplicial complex with vertex set (0, 1, 2) and facets {(2,), (0, 1)} Defn: L0R0 |--> 0 L1R1 |--> 1 L1R2 |--> 1 L2R0 |--> 0 """ if self.codomain() != other.codomain(): raise ValueError("self and other must have the same codomain.") X = self.domain().product(other.domain(), rename_vertices=rename_vertices) v = [] f = dict() eff1 = self.domain().vertices() eff2 = other.domain().vertices() for i in eff1: for j in eff2: if self(Simplex([i])) == other(Simplex([j])): if rename_vertices: v.append("L" + str(i) + "R" + str(j)) f["L" + str(i) + "R" + str(j)] = self._vertex_dictionary[i] else: v.append((i, j)) f[(i, j)] = self._vertex_dictionary[i] return SimplicialComplexMorphism(f, X.generated_subcomplex(v), self.codomain())
def __init__(self, f, X, Y): """ Input is a dictionary ``f``, the domain ``X``, and the codomain ``Y``. One can define the dictionary on the vertices of `X`. EXAMPLES:: sage: S = SimplicialComplex([[0,1],[2],[3,4],[5]], is_mutable=False) sage: H = Hom(S,S) sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} sage: g = {0:0,1:1,2:0,3:3,4:4,5:0} sage: x = H(f) sage: y = H(g) sage: x == y False sage: x.image() Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(2,), (5,), (0, 1), (3, 4)} sage: y.image() Simplicial complex with vertex set (0, 1, 3, 4) and facets {(0, 1), (3, 4)} sage: x.image() == y.image() False """ if not isinstance(X, SimplicialComplex) or not isinstance( Y, SimplicialComplex): raise ValueError("X and Y must be SimplicialComplexes") if not set(f.keys()) == set(X.vertices()): raise ValueError( "f must be a dictionary from the vertex set of X to single values in the vertex set of Y" ) dim = X.dimension() Y_faces = Y.faces() for k in range(dim + 1): for i in X.faces()[k]: tup = i.tuple() fi = [] for j in tup: fi.append(f[j]) v = Simplex(set(fi)) if v not in Y_faces[v.dimension()]: raise ValueError( "f must be a dictionary from the vertices of X to the vertices of Y" ) self._vertex_dictionary = f Morphism.__init__(self, Hom(X, Y, SimplicialComplexes()))
def __init__(self,f,X,Y): """ Input is a dictionary ``f``, the domain ``X``, and the codomain ``Y``. One can define the dictionary on the vertices of `X`. EXAMPLES:: sage: S = SimplicialComplex([[0,1],[2],[3,4],[5]], is_mutable=False) sage: H = Hom(S,S) sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} sage: g = {0:0,1:1,2:0,3:3,4:4,5:0} sage: x = H(f) sage: y = H(g) sage: x == y False sage: x.image() Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (5,), (2,), (0, 1)} sage: y.image() Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)} sage: x.image() == y.image() False """ if not isinstance(X,SimplicialComplex) or not isinstance(Y,SimplicialComplex): raise ValueError("X and Y must be SimplicialComplexes") if not set(f.keys()) == set(X._vertex_set): raise ValueError("f must be a dictionary from the vertex set of X to single values in the vertex set of Y") dim = X.dimension() Y_faces = Y.faces() for k in range(dim+1): for i in X.faces()[k]: tup = i.tuple() fi = [] for j in tup: fi.append(f[j]) v = Simplex(set(fi)) if not v in Y_faces[v.dimension()]: raise ValueError("f must be a dictionary from the vertices of X to the vertices of Y") self._vertex_dictionary = f Morphism.__init__(self, Hom(X,Y,SimplicialComplexes()))
def Simplex(self, n): """ An `n`-dimensional simplex, as a simplicial complex. INPUT: - ``n`` - a non-negative integer OUTPUT: the simplicial complex consisting of the `n`-simplex on vertices `(0, 1, ..., n)` and all of its faces. EXAMPLES:: sage: simplicial_complexes.Simplex(3) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2, 3)} sage: simplicial_complexes.Simplex(5).euler_characteristic() 1 """ S = Simplex(n) return SimplicialComplex(n, list(S))
def is_contiguous_to(self, other): r""" Return ``True`` if ``self`` is contiguous to ``other``. Two morphisms `f_0, f_1: K \to L` are *contiguous* if for any simplex `\sigma \in K`, the union `f_0(\sigma) \cup f_1(\sigma)` is a simplex in `L`. This is not a transitive relation, but it induces an equivalence relation on simplicial maps: `f` is equivalent to `g` if there is a finite sequence `f_0 = f`, `f_1`, ..., `f_n = g` such that `f_i` and `f_{i+1}` are contiguous for each `i`. This is related to maps being homotopic: if they are contiguous, then they induce homotopic maps on the geometric realizations. Given two homotopic maps on the geometric realizations, then after barycentrically subdividing `n` times for some `n`, the maps have simplicial approximations which are in the same contiguity class. (This last fact is only true if the domain is a *finite* simplicial complex, by the way.) See Section 3.5 of Spanier [Spa1966]_ for details. ALGORITHM: It is enough to check when `\sigma` ranges over the facets. INPUT: - ``other`` -- a simplicial complex morphism with the same domain and codomain as ``self`` EXAMPLES:: sage: K = simplicial_complexes.Simplex(1) sage: L = simplicial_complexes.Sphere(1) sage: H = Hom(K, L) sage: f = H({0: 0, 1: 1}) sage: g = H({0: 0, 1: 0}) sage: f.is_contiguous_to(f) True sage: f.is_contiguous_to(g) True sage: h = H({0: 1, 1: 2}) sage: f.is_contiguous_to(h) False TESTS:: sage: one = Hom(K,K).identity() sage: one.is_contiguous_to(f) False sage: one.is_contiguous_to(3) # nonsensical input False """ if not isinstance(other, SimplicialComplexMorphism): return False if self.codomain() != other.codomain() or self.domain() != other.domain(): return False domain = self.domain() codomain = self.codomain() return all(Simplex(self(sigma).set().union(other(sigma))) in codomain for sigma in domain.facets())