# Morphisms of simplicial complexes¶

AUTHORS:

• Benjamin Antieau <d.ben.antieau@gmail.com> (2009.06)

• Travis Scrimshaw (2012-08-18): Made all simplicial complexes immutable to work with the homset cache.

This module implements morphisms of simplicial complexes. The input is given by a dictionary on the vertex set of a simplicial complex. The initialization checks that faces are sent to faces.

There is also the capability to create the fiber product of two morphisms with the same codomain.

EXAMPLES:

sage: S = SimplicialComplex([[0,2],[1,5],[3,4]], is_mutable=False)
sage: H = Hom(S,S.product(S, is_mutable=False))
sage: H.diagonal_morphism()
Simplicial complex morphism:
From: Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 2), (1, 5), (3, 4)}
To: Simplicial complex with 36 vertices and 18 facets
Defn: [0, 1, 2, 3, 4, 5] --> ['L0R0', 'L1R1', 'L2R2', 'L3R3', 'L4R4', 'L5R5']

sage: S = SimplicialComplex([[0,2],[1,5],[3,4]], is_mutable=False)
sage: T = SimplicialComplex([[0,2],[1,3]], is_mutable=False)
sage: f = {0:0,1:1,2:2,3:1,4:3,5:3}
sage: H = Hom(S,T)
sage: x = H(f)
sage: x.image()
Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2), (1, 3)}
sage: x.is_surjective()
True
sage: x.is_injective()
False
sage: x.is_identity()
False

sage: S = simplicial_complexes.Sphere(2)
sage: H = Hom(S,S)
sage: i = H.identity()
sage: i.image()
Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)}
sage: i.is_surjective()
True
sage: i.is_injective()
True
sage: i.is_identity()
True

sage: S = simplicial_complexes.Sphere(2)
sage: H = Hom(S,S)
sage: i = H.identity()
sage: j = i.fiber_product(i)
sage: j
Simplicial complex morphism:
From: Simplicial complex with 4 vertices and 4 facets
To:   Minimal triangulation of the 2-sphere
Defn: L0R0 |--> 0
L1R1 |--> 1
L2R2 |--> 2
L3R3 |--> 3
sage: S = simplicial_complexes.Sphere(2)
sage: T = S.product(SimplicialComplex([[0,1]]), rename_vertices = False, is_mutable=False)
sage: H = Hom(T,S)
sage: T
Simplicial complex with 8 vertices and 12 facets
sage: sorted(T.vertices())
[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)]
sage: f = {(0, 0): 0, (0, 1): 0, (1, 0): 1, (1, 1): 1, (2, 0): 2, (2, 1): 2, (3, 0): 3, (3, 1): 3}
sage: x = H(f)
sage: U = simplicial_complexes.Sphere(1)
sage: G = Hom(U,S)
sage: U
Minimal triangulation of the 1-sphere
sage: g = {0:0,1:1,2:2}
sage: y = G(g)
sage: z = y.fiber_product(x)
sage: z                                     # this is the mapping path space
Simplicial complex morphism:
From: Simplicial complex with 6 vertices and ... facets
To:   Minimal triangulation of the 2-sphere
Defn: ['L0R(0, 0)', 'L0R(0, 1)', 'L1R(1, 0)', 'L1R(1, 1)', 'L2R(2, 0)', 'L2R(2, 1)'] --> [0, 0, 1, 1, 2, 2]

class sage.homology.simplicial_complex_morphism.SimplicialComplexMorphism(f, X, Y)

An element of this class is a morphism of simplicial complexes.

associated_chain_complex_morphism(base_ring=Integer Ring, augmented=False, cochain=False)

Return the associated chain complex morphism of self.

EXAMPLES:

sage: S = simplicial_complexes.Sphere(1)
sage: T = simplicial_complexes.Sphere(2)
sage: H = Hom(S,T)
sage: f = {0:0,1:1,2:2}
sage: x = H(f)
sage: x
Simplicial complex morphism:
From: Minimal triangulation of the 1-sphere
To:   Minimal triangulation of the 2-sphere
Defn: 0 |--> 0
1 |--> 1
2 |--> 2
sage: a = x.associated_chain_complex_morphism()
sage: a
Chain complex morphism:
From: Chain complex with at most 2 nonzero terms over Integer Ring
To:   Chain complex with at most 3 nonzero terms over Integer Ring
sage: a._matrix_dictionary
{0: [1 0 0]
[0 1 0]
[0 0 1]
[0 0 0], 1: [1 0 0]
[0 1 0]
[0 0 0]
[0 0 1]
[0 0 0]
[0 0 0], 2: []}
sage: x.associated_chain_complex_morphism(augmented=True)
Chain complex morphism:
From: Chain complex with at most 3 nonzero terms over Integer Ring
To:   Chain complex with at most 4 nonzero terms over Integer Ring
sage: x.associated_chain_complex_morphism(cochain=True)
Chain complex morphism:
From: Chain complex with at most 3 nonzero terms over Integer Ring
To:   Chain complex with at most 2 nonzero terms over Integer Ring
sage: x.associated_chain_complex_morphism(augmented=True,cochain=True)
Chain complex morphism:
From: Chain complex with at most 4 nonzero terms over Integer Ring
To:   Chain complex with at most 3 nonzero terms over Integer Ring
sage: x.associated_chain_complex_morphism(base_ring=GF(11))
Chain complex morphism:
From: Chain complex with at most 2 nonzero terms over Finite Field of size 11
To:   Chain complex with at most 3 nonzero terms over Finite Field of size 11


Some simplicial maps which reverse the orientation of a few simplices:

sage: g = {0:1, 1:2, 2:0}
sage: H(g).associated_chain_complex_morphism()._matrix_dictionary
{0: [0 0 1]
[1 0 0]
[0 1 0]
[0 0 0], 1: [ 0 -1  0]
[ 0  0 -1]
[ 0  0  0]
[ 1  0  0]
[ 0  0  0]
[ 0  0  0], 2: []}
sage: X = SimplicialComplex([[0, 1]], is_mutable=False)
sage: Hom(X,X)({0:1, 1:0}).associated_chain_complex_morphism()._matrix_dictionary
{0: [0 1]
[1 0], 1: [-1]}

fiber_product(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

image()

Computes the image simplicial complex of $$f$$.

EXAMPLES:

sage: S = SimplicialComplex([[0,1],[2,3]], is_mutable=False)
sage: T = SimplicialComplex([[0,1]], is_mutable=False)
sage: f = {0:0,1:1,2:0,3:1}
sage: H = Hom(S,T)
sage: x = H(f)
sage: x.image()
Simplicial complex with vertex set (0, 1) and facets {(0, 1)}

sage: S = SimplicialComplex(is_mutable=False)
sage: H = Hom(S,S)
sage: i = H.identity()
sage: i.image()
Simplicial complex with vertex set () and facets {()}
sage: i.is_surjective()
True
sage: S = SimplicialComplex([[0,1]], is_mutable=False)
sage: T = SimplicialComplex([[0,1], [0,2]], is_mutable=False)
sage: f = {0:0,1:1}
sage: g = {0:0,1:1}
sage: k = {0:0,1:2}
sage: H = Hom(S,T)
sage: x = H(f)
sage: y = H(g)
sage: z = H(k)
sage: x == y
True
sage: x == z
False
sage: x.image()
Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
sage: y.image()
Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
sage: z.image()
Simplicial complex with vertex set (0, 2) and facets {(0, 2)}

induced_homology_morphism(base_ring=None, cohomology=False)

The map in (co)homology induced by this map

INPUT:

• base_ring – must be a field (optional, default QQ)

• cohomology – boolean (optional, default False). If True, the map induced in cohomology rather than homology.

EXAMPLES:

sage: S = simplicial_complexes.Sphere(1)
sage: T = S.product(S, is_mutable=False)
sage: H = Hom(S,T)
sage: diag = H.diagonal_morphism()
sage: h = diag.induced_homology_morphism(QQ)
sage: h
From: Homology module of Minimal triangulation of the 1-sphere over Rational Field
To:   Homology module of Simplicial complex with 9 vertices and 18 facets over Rational Field
Defn: induced by:
Simplicial complex morphism:
From: Minimal triangulation of the 1-sphere
To:   Simplicial complex with 9 vertices and 18 facets
Defn: 0 |--> L0R0
1 |--> L1R1
2 |--> L2R2


We can view the matrix form for the homomorphism:

sage: h.to_matrix(0) # in degree 0
[1]
sage: h.to_matrix(1) # in degree 1
[1]
[1]
sage: h.to_matrix()  # the entire homomorphism
[1|0]
[-+-]
[0|1]
[0|1]
[-+-]
[0|0]


The map on cohomology should be dual to the map on homology:

sage: coh = diag.induced_homology_morphism(QQ, cohomology=True)
sage: coh.to_matrix(1)
[1 1]
sage: h.to_matrix() == coh.to_matrix().transpose()
True


We can evaluate the map on (co)homology classes:

sage: x,y = list(T.cohomology_ring(QQ).basis(1))
sage: coh(x)
h^{1,0}
sage: coh(2*x+3*y)
5*h^{1,0}


Note that the complexes must be immutable for this to work. Many, but not all, complexes are immutable when constructed:

sage: S.is_immutable()
True
sage: S.barycentric_subdivision().is_immutable()
False
sage: S2 = S.suspension()
sage: S2.is_immutable()
False
sage: h = Hom(S,S2)({0: 0, 1:1, 2:2}).induced_homology_morphism()
Traceback (most recent call last):
...
ValueError: the domain and codomain complexes must be immutable
sage: S2.set_immutable(); S2.is_immutable()
True
sage: h = Hom(S,S2)({0: 0, 1:1, 2:2}).induced_homology_morphism()

is_contiguous_to(other)

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

is_identity()

If self is an identity morphism, returns True. Otherwise, False.

EXAMPLES:

sage: T = simplicial_complexes.Sphere(1)
sage: G = Hom(T,T)
sage: T
Minimal triangulation of the 1-sphere
sage: j = G({0:0,1:1,2:2})
sage: j.is_identity()
True

sage: S = simplicial_complexes.Sphere(2)
sage: T = simplicial_complexes.Sphere(3)
sage: H = Hom(S,T)
sage: f = {0:0,1:1,2:2,3:3}
sage: x = H(f)
sage: x
Simplicial complex morphism:
From: Minimal triangulation of the 2-sphere
To:   Minimal triangulation of the 3-sphere
Defn: 0 |--> 0
1 |--> 1
2 |--> 2
3 |--> 3
sage: x.is_identity()
False

is_injective()

Return True if and only if self is injective.

EXAMPLES:

sage: S = simplicial_complexes.Sphere(1)
sage: T = simplicial_complexes.Sphere(2)
sage: U = simplicial_complexes.Sphere(3)
sage: H = Hom(T,S)
sage: G = Hom(T,U)
sage: f = {0:0,1:1,2:0,3:1}
sage: x = H(f)
sage: g = {0:0,1:1,2:2,3:3}
sage: y = G(g)
sage: x.is_injective()
False
sage: y.is_injective()
True

is_surjective()

Return True if and only if self is surjective.

EXAMPLES:

sage: S = SimplicialComplex([(0,1,2)], is_mutable=False)
sage: S
Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}
sage: T = SimplicialComplex([(0,1)], is_mutable=False)
sage: T
Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
sage: H = Hom(S,T)
sage: x = H({0:0,1:1,2:1})
sage: x.is_surjective()
True

sage: S = SimplicialComplex([[0,1],[2,3]], is_mutable=False)
sage: T = SimplicialComplex([[0,1]], is_mutable=False)
sage: f = {0:0,1:1,2:0,3:1}
sage: H = Hom(S,T)
sage: x = H(f)
sage: x.is_surjective()
True

mapping_torus()

The mapping torus of a simplicial complex endomorphism

The mapping torus is the simplicial complex formed by taking the product of the domain of self with a $$4$$ point interval $$[I_0, I_1, I_2, I_3]$$ and identifying vertices of the form $$(I_0, v)$$ with $$(I_3, w)$$ where $$w$$ is the image of $$v$$ under the given morphism.

EXAMPLES:

sage: C = simplicial_complexes.Sphere(1)            # Circle
sage: T = Hom(C,C).identity().mapping_torus() ; T   # Torus
Simplicial complex with 9 vertices and 18 facets
sage: T.homology() == simplicial_complexes.Torus().homology()
True

sage: f = Hom(C,C)({0:0,1:2,2:1})
sage: K = f.mapping_torus() ; K  # Klein Bottle
Simplicial complex with 9 vertices and 18 facets
sage: K.homology() == simplicial_complexes.KleinBottle().homology()
True

sage.homology.simplicial_complex_morphism.is_SimplicialComplexMorphism(x)

Return True if and only if x is a morphism of simplicial complexes.

EXAMPLES:

sage: from sage.homology.simplicial_complex_morphism import is_SimplicialComplexMorphism
sage: S = SimplicialComplex([[0,1],[3,4]], is_mutable=False)
sage: H = Hom(S,S)
sage: f = {0:0,1:1,3:3,4:4}
sage: x = H(f)
sage: is_SimplicialComplexMorphism(x)
True