Simplicial sets#

AUTHORS:

  • John H. Palmieri (2016-07)

This module implements simplicial sets.

A simplicial set \(X\) is a collection of sets \(X_n\) indexed by the non-negative integers; the set \(X_n\) is called the set of \(n\)-simplices. These sets are connected by maps

\[\begin{split}d_i: X_n \to X_{n-1}, \ \ 0 \leq i \leq n \ \ \text{(face maps)} \\ s_j: X_n \to X_{n+1}, \ \ 0 \leq j \leq n \ \ \text{(degeneracy maps)}\end{split}\]

satisfying the simplicial identities:

\[\begin{split}d_i d_j &= d_{j-1} d_i \ \ \text{if } i<j \\ d_i s_j &= s_{j-1} d_i \ \ \text{if } i<j \\ d_j s_j &= 1 = d_{j+1} s_j \\ d_i s_j &= s_{j} d_{i-1} \ \ \text{if } i>j+1 \\ s_i s_j &= s_{j+1} s_{i} \ \ \text{if } i<j+1\end{split}\]

See Wikipedia article Simplicial_set, Peter May’s seminal book [May1967], or Greg Friedman’s “Illustrated introduction” arXiv 0809.4221 for more information.

Several simplicial sets are predefined, and users can construct others either by hand (using SimplicialSet_finite) or from existing ones using pushouts, pullbacks, etc.

EXAMPLES:

Some of the predefined simplicial sets:

sage: simplicial_sets.Torus()
Torus
sage: simplicial_sets.RealProjectiveSpace(7)                                        # needs sage.groups
RP^7
sage: S5 = simplicial_sets.Sphere(5); S5
S^5
sage: S5.nondegenerate_simplices()
[v_0, sigma_5]

One class of infinite simplicial sets is available: classifying spaces of groups, or more generally, nerves of finite monoids:

sage: Sigma4 = groups.permutation.Symmetric(4)                                      # needs sage.groups
sage: Sigma4.nerve()                                                                # needs sage.groups
Nerve of Symmetric group of order 4! as a permutation group

The same simplicial set (albeit with a different name) can also be constructed as

sage: simplicial_sets.ClassifyingSpace(Sigma4)                                      # needs sage.groups
Classifying space of Symmetric group of order 4! as a permutation group

Type simplicial_sets. and hit the Tab key to get a full list of the predefined simplicial sets.

You can construct new simplicial sets from old by taking quotients, subsimplicial sets, disjoint unions, wedges (if they are pointed), smash products (if they are pointed and finite), products, pushouts, pullbacks, cones, and suspensions, most of which also have maps associated with them. Wedges, for example:

sage: T = simplicial_sets.Torus()
sage: S3 = simplicial_sets.Sphere(3)
sage: T.is_pointed() and S3.is_pointed()
True
sage: T.wedge(S3)
Wedge: (Torus v S^3)
sage: T.disjoint_union(S3) == T.coproduct(S3)
False

sage: W = T.wedge(S3)
sage: W.inclusion_map(0).domain()
Torus
sage: W.projection_map(1).codomain()
Quotient: (Wedge: (Torus v S^3)/Simplicial set with 6 non-degenerate simplices)

If the \(1\)-sphere were not already available via simplicial_sets.Sphere(1), you could construct it as follows:

sage: pt = simplicial_sets.Simplex(0)
sage: edge = pt.cone()
sage: S1 = edge.quotient(edge.n_skeleton(0))
sage: S1
Quotient: (Cone of 0-simplex/Simplicial set with 2 non-degenerate simplices)

At this point, S1 is pointed: every quotient is automatically given a base point, namely the image of the subcomplex. So its suspension is the reduced suspension, and therefore is small:

sage: S5 = S1.suspension(4)
sage: S5
Sigma^4(Quotient: (Cone of 0-simplex/Simplicial set with 2 non-degenerate simplices))
sage: S5.f_vector()
[1, 0, 0, 0, 0, 1]

If we forget about the base point in S1, we would get the unreduced suspension instead:

sage: Z1 = S1.unset_base_point()
sage: Z1.suspension(4).f_vector()
[2, 2, 2, 2, 1, 1]

The cone on a pointed simplicial set is the reduced cone. The \(n\)-simplex in Sage is not pointed, but the simplicial set Point is.

sage: simplicial_sets.Simplex(0).cone().f_vector()
[2, 1]
sage: simplicial_sets.Point().cone().f_vector()
[1]

For most simplicial sets (the Point is the main exception), each time it is constructed, it gives a distinct copy, and two distinct simplicial sets are never equal:

sage: T = simplicial_sets.Torus()
sage: T == simplicial_sets.Torus()
False
sage: T == T
True
sage: simplicial_sets.Torus() == simplicial_sets.Torus()
False
sage: simplicial_sets.Point() == simplicial_sets.Point()
True

You can construct subsimplicial sets by specifying a list of simplices, and then you can define the quotient simplicial set:

sage: X = simplicial_sets.Simplex(2)
sage: e,f,g = X.n_cells(1)
sage: Y = X.subsimplicial_set([e,f,g])
sage: Z = X.quotient(Y)

Or equivalently:

sage: Y = X.n_skeleton(1)
sage: Z = X.quotient(Y)
sage: Z
Quotient: (2-simplex/Simplicial set with 6 non-degenerate simplices)

Note that subsimplicial sets and quotients come equipped with inclusion and quotient morphisms:

sage: inc = Y.inclusion_map()
sage: inc.domain() == Y and inc.codomain() == X
True
sage: quo = Z.quotient_map()
sage: quo.domain()
2-simplex
sage: quo.codomain() == Z
True

You can compute homology groups and the fundamental group of any simplicial set:

sage: S1 = simplicial_sets.Sphere(1)
sage: eight = S1.wedge(S1)
sage: eight.fundamental_group()                                                     # needs sage.groups
Finitely presented group < e0, e1 | >

sage: # needs sage.groups
sage: Sigma3 = groups.permutation.Symmetric(3)
sage: BSigma3 = Sigma3.nerve()
sage: pi = BSigma3.fundamental_group(); pi
Finitely presented group < e1, e2 | e2^2, e1^3, (e2*e1)^2 >
sage: pi.order()
6
sage: pi.is_abelian()
False

sage: RP6 = simplicial_sets.RealProjectiveSpace(6)                                  # needs sage.groups
sage: RP6.homology(reduced=False, base_ring=GF(2))                                  # needs sage.groups sage.modules
{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,
 3: Vector space of dimension 1 over Finite Field of size 2,
 4: Vector space of dimension 1 over Finite Field of size 2,
 5: Vector space of dimension 1 over Finite Field of size 2,
 6: Vector space of dimension 1 over Finite Field of size 2}
sage: RP6.homology(reduced=False, base_ring=QQ)                                     # needs sage.groups sage.modules
{0: Vector space of dimension 1 over Rational Field,
 1: Vector space of dimension 0 over Rational Field,
 2: Vector space of dimension 0 over Rational Field,
 3: Vector space of dimension 0 over Rational Field,
 4: Vector space of dimension 0 over Rational Field,
 5: Vector space of dimension 0 over Rational Field,
 6: Vector space of dimension 0 over Rational Field}

When infinite simplicial sets are involved, most computations are done by taking an \(n\)-skeleton for an appropriate \(n\), either implicitly or explicitly:

sage: # needs sage.groups
sage: G = groups.misc.MultiplicativeAbelian([3])
sage: B3 = simplicial_sets.ClassifyingSpace(G)
sage: B3.disjoint_union(B3).n_skeleton(3)
Disjoint union: (Simplicial set with 15 non-degenerate simplices
                  u Simplicial set with 15 non-degenerate simplices)
sage: S1 = simplicial_sets.Sphere(1)
sage: B3.product(S1).homology(range(4))                                             # needs sage.modules
{0: 0, 1: Z x C3, 2: C3, 3: C3}

Without the range argument, this would raise an error, since B3 is infinite:

sage: B3.product(S1).homology()                                                     # needs sage.groups sage.modules
Traceback (most recent call last):
...
NotImplementedError: this simplicial set may be infinite,
so specify dimensions when computing homology

It should be easy to construct many simplicial sets from the predefined ones using pushouts, pullbacks, etc., but they can also be constructed “by hand”: first define some simplices, then define a simplicial set by specifying their faces:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: f = AbstractSimplex(1, name='f')
sage: X = SimplicialSet({e: (v,w), f: (w,w)})

Now \(e\) is an edge from \(v\) to \(w\) and \(f\) is an edge starting and ending at \(w\). Therefore the first homology group of \(X\) should be a copy of the integers:

sage: X.homology(1)                                                                 # needs sage.modules
Z
sage.topology.simplicial_set.AbstractSimplex(dim, degeneracies=(), underlying=None, name=None, latex_name=None)#

An abstract simplex, a building block of a simplicial set.

In a simplicial set, a simplex either is non-degenerate or is obtained by applying degeneracy maps to a non-degenerate simplex.

INPUT:

  • dim – a non-negative integer, the dimension of the underlying non-degenerate simplex.

  • degeneracies (optional, default None) – a list or tuple of non-negative integers, the degeneracies to be applied.

  • underlying (optional) – a non-degenerate simplex to which the degeneracies are being applied.

  • name (optional) – string, a name for this simplex.

  • latex_name (optional) – string, a name for this simplex to use in the LaTeX representation.

So to define a simplex formed by applying the degeneracy maps \(s_2 s_1\) to a 1-simplex, call AbstractSimplex(1, (2, 1)).

Specify underlying if you need to keep explicit track of the underlying non-degenerate simplex, for example when computing faces of another simplex. This is mainly for use by the method AbstractSimplex_class.apply_degeneracies().

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: AbstractSimplex(3, (3, 1))
s_3 s_1 Delta^3
sage: AbstractSimplex(3, None)
Delta^3
sage: AbstractSimplex(3)
Delta^3

Simplices may be named (or renamed), affecting how they are printed:

sage: AbstractSimplex(0)
Delta^0
sage: v = AbstractSimplex(0, name='v')
sage: v
v
sage: v.rename('w_0')
sage: v
w_0
sage: latex(v)
w_0
sage: latex(AbstractSimplex(0, latex_name='\\sigma'))
\sigma

The simplicial identities are used to put the degeneracies in standard decreasing form:

sage: x = AbstractSimplex(0, (0, 0, 0))
sage: x
s_2 s_1 s_0 Delta^0
sage: x.degeneracies()
[2, 1, 0]

Use of the underlying argument:

sage: v = AbstractSimplex(0, name='v')
sage: e = AbstractSimplex(0, (0,), underlying=v)
sage: e
s_0 v
sage: e.nondegenerate() is v
True

sage: e.dimension()
1
sage: e.is_degenerate()
True

Distinct non-degenerate simplices are never equal:

sage: AbstractSimplex(0, None) == AbstractSimplex(0, None)
False
sage: AbstractSimplex(0, (2,1,0)) == AbstractSimplex(0, (2,1,0))
False

sage: e = AbstractSimplex(0, ((0,)))
sage: f = AbstractSimplex(0, ((0,)))
sage: e == f
False
sage: e.nondegenerate() == f.nondegenerate()
False

This means that if, when defining a simplicial set, you specify the faces of a 2-simplex as:

(e, e, e)

then the faces are the same degenerate vertex, but if you specify the faces as:

(AbstractSimplex(0, ((0,))), AbstractSimplex(0, ((0,))), AbstractSimplex(0, ((0,))))

then the faces are three different degenerate vertices.

View a command like AbstractSimplex(0, (2,1,0)) as first constructing AbstractSimplex(0) and then applying degeneracies to it, and you always get distinct simplices from different calls to AbstractSimplex(0). On the other hand, if you apply degeneracies to the same non-degenerate simplex, the resulting simplices are equal:

sage: v = AbstractSimplex(0)
sage: v.apply_degeneracies(1, 0) == v.apply_degeneracies(1, 0)
True
sage: AbstractSimplex(1, (0,), underlying=v) == AbstractSimplex(1, (0,), underlying=v)
True
class sage.topology.simplicial_set.AbstractSimplex_class(dim, degeneracies=(), underlying=None, name=None, latex_name=None)#

Bases: SageObject

A simplex of dimension dim.

INPUT:

  • dim – integer, the dimension

  • degeneracies (optional) – iterable, the indices of the degeneracy maps

  • underlying (optional) – a non-degenerate simplex

  • name (optional) – string

  • latex_name (optional) – string

Users should not call this directly, but instead use AbstractSimplex(). See that function for more documentation.

apply_degeneracies(*args)#

Apply the degeneracies given by the arguments args to this simplex.

INPUT:

  • args – integers

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: v = AbstractSimplex(0)
sage: e = v.apply_degeneracies(0)
sage: e.nondegenerate() == v
True
sage: f = e.apply_degeneracies(0)
sage: f
s_1 s_0 Delta^0
sage: f.degeneracies()
[1, 0]
sage: f.nondegenerate() == v
True
sage: v.apply_degeneracies(1, 0)
s_1 s_0 Delta^0
degeneracies()#

Return the list of indices for the degeneracy maps for this simplex.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: AbstractSimplex(4, (0,0,0)).degeneracies()
[2, 1, 0]
sage: AbstractSimplex(4, None).degeneracies()
[]
dimension()#

The dimension of this simplex.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: AbstractSimplex(3, (2,1)).dimension()
5
sage: AbstractSimplex(3, None).dimension()
3
sage: AbstractSimplex(7).dimension()
7
is_degenerate()#

True if this simplex is degenerate.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: AbstractSimplex(3, (2,1)).is_degenerate()
True
sage: AbstractSimplex(3, None).is_degenerate()
False
is_nondegenerate()#

True if this simplex is non-degenerate.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: AbstractSimplex(3, (2,1)).is_nondegenerate()
False
sage: AbstractSimplex(3, None).is_nondegenerate()
True
sage: AbstractSimplex(5).is_nondegenerate()
True
nondegenerate()#

The non-degenerate simplex underlying this one.

Therefore return itself if this simplex is non-degenerate.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: v = AbstractSimplex(0, name='v')
sage: sigma = v.apply_degeneracies(1, 0)
sage: sigma.nondegenerate()
v
sage: tau = AbstractSimplex(1, (3,2,1))
sage: x = tau.nondegenerate(); x
Delta^1
sage: x == tau.nondegenerate()
True

sage: AbstractSimplex(1, None)
Delta^1
sage: AbstractSimplex(1, None) == x
False
sage: AbstractSimplex(1, None) == tau.nondegenerate()
False
class sage.topology.simplicial_set.NonDegenerateSimplex(dim, name=None, latex_name=None)#

Bases: AbstractSimplex_class, WithEqualityById

A nondegenerate simplex.

INPUT:

  • dim – non-negative integer, the dimension

  • name (optional) – string, a name for this simplex.

  • latex_name (optional) – string, a name for this simplex to use in the LaTeX representation.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex
sage: v = AbstractSimplex(0, name='v')
sage: v
v
sage: type(v)
<class 'sage.topology.simplicial_set.NonDegenerateSimplex'>

Distinct non-degenerate simplices should never be equal, even if they have the same starting data.

sage: v == AbstractSimplex(0, name='v')
False
sage: AbstractSimplex(3) == AbstractSimplex(3)
False

sage: from sage.topology.simplicial_set import NonDegenerateSimplex
sage: x = NonDegenerateSimplex(0, name='x')
sage: x == NonDegenerateSimplex(0, name='x')
False
sage.topology.simplicial_set.SimplicialSet#

alias of SimplicialSet_finite

class sage.topology.simplicial_set.SimplicialSet_arbitrary#

Bases: Parent

A simplicial set.

A simplicial set \(X\) is a collection of sets \(X_n\), the n-simplices, indexed by the non-negative integers, together with maps

\[\begin{split}d_i: X_n \to X_{n-1}, \ \ 0 \leq i \leq n \ \ \text{(face maps)} \\ s_j: X_n \to X_{n+1}, \ \ 0 \leq j \leq n \ \ \text{(degeneracy maps)}\end{split}\]

satisfying the simplicial identities:

\[\begin{split}d_i d_j &= d_{j-1} d_i \ \ \text{if } i<j \\ d_i s_j &= s_{j-1} d_i \ \ \text{if } i<j \\ d_j s_j &= 1 = d_{j+1} s_j \\ d_i s_j &= s_{j} d_{i-1} \ \ \text{if } i>j+1 \\ s_i s_j &= s_{j+1} s_{i} \ \ \text{if } i<j+1\end{split}\]

This class is not fully implemented and is not intended to be called directly by users. It is intended instead to be used by other classes which inherit from this one. See SimplicialSet_finite and Nerve for two examples. In particular, any such class must implement a method n_skeleton – without this, most computations will be impossible. It must also implement an __init__ method which should also set the category, so that methods defined at the category level, like is_pointed and is_finite, work correctly.

Note that the method subsimplicial_set() calls n_skeleton(), so to avoid circularity, the n_skeleton() method should call simplicial_set_constructions.SubSimplicialSet directly, not subsimplicial_set().

alexander_whitney(simplex, dim_left)#

Return the ‘subdivision’ of simplex in this simplicial set into a pair of simplices.

The left factor should have dimension dim_left, so the right factor should have dimension dim - dim_left, if dim is the dimension of the starting simplex. The results are obtained by applying iterated face maps to simplex. Writing \(d\) for dim and \(j\) for dim_left: apply \(d_{j+1} d_{j+2} ... d_{d}\) to get the left factor, \(d_0 ... d_0\) to get the right factor.

INPUT:

  • dim_left – integer, the dimension of the left-hand factor

OUTPUT: a list containing the triple (c, left, right), where left and right are the two simplices described above. If either left or right is degenerate, c is 0; otherwise, c is 1. This is so that, when used to compute cup products, it is easy to ignore terms which have degenerate factors.

EXAMPLES:

sage: S2 = simplicial_sets.Sphere(2)
sage: sigma = S2.n_cells(2)[0]
sage: S2.alexander_whitney(sigma, 0)
[(1, v_0, sigma_2)]
sage: S2.alexander_whitney(sigma, 1)
[(0, s_0 v_0, s_0 v_0)]
all_n_simplices(n)#

Return a list of all simplices, non-degenerate and degenerate, in dimension n.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: degen = v.apply_degeneracies(0)
sage: tau = AbstractSimplex(2, name='tau')
sage: Y = SimplicialSet({tau: (degen, degen, degen), w: None})

Y is the disjoint union of a 2-sphere, with vertex v and non-degenerate 2-simplex tau, and a point w.

sage: Y.all_n_simplices(0)
[v, w]
sage: Y.all_n_simplices(1)
[s_0 v, s_0 w]
sage: Y.all_n_simplices(2)
[tau, s_1 s_0 v, s_1 s_0 w]

An example involving an infinite simplicial set:

sage: C3 = groups.misc.MultiplicativeAbelian([3])                           # needs sage.groups
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)                            # needs sage.groups
sage: BC3.all_n_simplices(2)                                                # needs sage.groups
[f * f,
 f * f^2,
 f^2 * f,
 f^2 * f^2, s_0 f, s_0 f^2, s_1 f, s_1 f^2, s_1 s_0 1]
betti(dim=None, subcomplex=None)#

The Betti numbers of this simplicial complex as a dictionary (or a single Betti number, if only one dimension is given): the ith Betti number is the rank of the ith homology group.

INPUT:

  • dim (optional, default None – If None, then return the homology in every dimension. If dim is an integer or list, return the homology in the given dimensions. (Actually, if dim is a list, return the homology in the range from min(dim) to max(dim).)

  • subcomplex (optional, default None) – a subcomplex

    of this cell complex. Compute the Betti numbers of the homology relative to this subcomplex.

Note

If this simplicial set is not finite, you must specify dimensions in which to compute Betti numbers via the argument dim.

EXAMPLES:

Build the two-sphere as a three-fold join of a two-point space with itself:

sage: simplicial_sets.Sphere(5).betti()                                     # needs sage.modules
{0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1}

sage: C3 = groups.misc.MultiplicativeAbelian([3])                           # needs sage.groups
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)                            # needs sage.groups
sage: BC3.betti(range(4))                                                   # needs sage.groups sage.modules
{0: 1, 1: 0, 2: 0, 3: 0}
cartesian_product(*others)#

Return the product of this simplicial set with others.

INPUT:

  • others – one or several simplicial sets

If \(X\) and \(Y\) are simplicial sets, then their product \(X \times Y\) is defined to be the simplicial set with \(n\)-simplices \(X_n \times Y_n\). See simplicial_set_constructions.ProductOfSimplicialSets for more information.

If a simplicial set is constructed as a product, the factors are recorded and are accessible via the method simplicial_set_constructions.Factors.factors(). If each factor is finite, then you can also construct the projection maps onto each factor, the wedge as a subcomplex, and the fat wedge as a subcomplex.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: X = SimplicialSet({e: (v, w)})
sage: square = X.product(X)

square is now the standard triangulation of the square: 4 vertices, 5 edges (the four on the border and the diagonal), 2 triangles:

sage: square.f_vector()
[4, 5, 2]

sage: S1 = simplicial_sets.Sphere(1)
sage: T = S1.product(S1)
sage: T.homology(reduced=False)                                             # needs sage.modules
{0: Z, 1: Z x Z, 2: Z}

Since S1 is pointed, so is T:

sage: S1.is_pointed()
True
sage: S1.base_point()
v_0
sage: T.is_pointed()
True
sage: T.base_point()
(v_0, v_0)

sage: S2 = simplicial_sets.Sphere(2)
sage: S3 = simplicial_sets.Sphere(3)
sage: S2xS3 = S2.product(S3)
sage: S2xS3.homology(reduced=False)                                         # needs sage.modules
{0: Z, 1: 0, 2: Z, 3: Z, 4: 0, 5: Z}

sage: S2xS3.factors() == (S2, S3)
True
sage: S2xS3.factors() == (S3, S2)
False

sage: # needs sage.groups
sage: G = groups.misc.MultiplicativeAbelian([2])
sage: B = simplicial_sets.ClassifyingSpace(G)
sage: B.rename('RP^oo')
sage: X = B.product(B, S2); X
RP^oo x RP^oo x S^2
sage: X.factor(1)
RP^oo
sage: X.factors()
(RP^oo, RP^oo, S^2)

Projection maps and wedges:

sage: S2xS3.projection_map(0)
Simplicial set morphism:
  From: S^2 x S^3
  To:   S^2
  Defn: ...
sage: S2xS3.wedge_as_subset().homology()                                    # needs sage.modules
{0: 0, 1: 0, 2: Z, 3: Z}

In the case of pointed simplicial sets, there is an inclusion of each factor into the product. These are not automatically defined in Sage, but they are easy to construct using identity maps and constant maps and the universal property of the product:

sage: one = S2.identity()
sage: const = S2.constant_map(codomain=S3)
sage: S2xS3.universal_property(one, const)
Simplicial set morphism:
  From: S^2
  To:   S^2 x S^3
  Defn: [v_0, sigma_2] --> [(v_0, v_0), (sigma_2, s_1 s_0 v_0)]
cells(subcomplex=None, max_dim=None)#

Return a dictionary of all non-degenerate simplices.

INPUT:

  • subcomplex (optional) – a subsimplicial set of this simplicial set. If subcomplex is specified, then return the simplices in the quotient by the subcomplex.

  • max_dim – optional, default None. If specified, return the non-degenerate simplices of this dimension or smaller. This argument is required if this simplicial set is infinite.

Each key is a dimension, and the corresponding value is the list of simplices in that dimension.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0)
sage: w = AbstractSimplex(0)
sage: S0 = SimplicialSet({v: None, w: None})
sage: S0.cells()
{0: [Delta^0, Delta^0]}

sage: v.rename('v')
sage: w.rename('w')
sage: S0.cells()
{0: [v, w]}

sage: e = AbstractSimplex(1, name='e')
sage: S1 = SimplicialSet({e: (v, v)})
sage: S1.cells()
{0: [v], 1: [e]}

sage: S0.cells(S0.subsimplicial_set([v, w]))
{0: [*]}

sage: X = SimplicialSet({e: (v,w)})
sage: X.cells(X.subsimplicial_set([v, w]))
{0: [*], 1: [e]}

Test an infinite example:

sage: # needs sage.groups
sage: C3 = groups.misc.MultiplicativeAbelian([3])
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)
sage: BC3.cells(max_dim=2)
{0: [1], 1: [f, f^2], 2: [f * f, f * f^2, f^2 * f, f^2 * f^2]}
sage: BC3.cells()
Traceback (most recent call last):
...
NotImplementedError: this simplicial set may be infinite, so specify max_dim
chain_complex(dimensions=None, base_ring=Integer Ring, augmented=False, cochain=False, verbose=False, subcomplex=None, check=False)#

Return the normalized chain complex.

INPUT:

  • dimensions – if None, compute the chain complex in all dimensions. If a list or tuple of integers, compute the chain complex in those dimensions, setting the chain groups in all other dimensions to zero.

  • base_ring (optional, default ZZ) – commutative ring

  • augmented (optional, default False) – if True, return the augmented chain complex (that is, include a class in dimension \(-1\) corresponding to the empty cell).

  • cochain (optional, default False) – if True, return the cochain complex (that is, the dual of the chain complex).

  • verbose (optional, default False) – ignored.

  • subcomplex (optional, default None) – if present, compute the chain complex relative to this subcomplex.

  • check (optional, default False) – If True, make sure that the chain complex is actually a chain complex: the differentials are composable and their product is zero.

Note

If this simplicial set is not finite, you must specify dimensions in which to compute its chain complex via the argument dimensions.

EXAMPLES:

sage: simplicial_sets.Sphere(5).chain_complex()                             # needs sage.modules
Chain complex with at most 3 nonzero terms over Integer Ring

sage: C3 = groups.misc.MultiplicativeAbelian([3])                           # needs sage.groups
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)                            # needs sage.groups
sage: BC3.chain_complex(range(4), base_ring=GF(3))                          # needs sage.groups sage.modules
Chain complex with at most 4 nonzero terms over Finite Field of size 3
cohomology(dim=None, **kwds)#

Return the cohomology of this simplicial set.

INPUT:

  • dim (optional, default None – If None, then return the homology in every dimension. If dim is an integer or list, return the homology in the given dimensions. (Actually, if dim is a list, return the homology in the range from min(dim) to max(dim).)

  • base_ring (optional, default ZZ) – commutative ring, must be ZZ or a field.

Other arguments are also allowed, the same as for the homology() method – see cell_complex.GenericCellComplex.homology() for complete documentation – except that homology() accepts a cohomology key word, while this function does not: cohomology is automatically true here. Indeed, this function just calls homology() with argument cohomology=True.

Note

If this simplicial set is not finite, you must specify dimensions in which to compute homology via the argument dim.

EXAMPLES:

sage: simplicial_sets.KleinBottle().homology(1)                             # needs sage.modules
Z x C2
sage: simplicial_sets.KleinBottle().cohomology(1)                           # needs sage.modules
Z
sage: simplicial_sets.KleinBottle().cohomology(2)                           # needs sage.modules
C2
cone()#

Return the (reduced) cone on this simplicial set.

If this simplicial set \(X\) is not pointed, construct the ordinary cone: add a point \(v\) (which will become the base point) and for each simplex \(\sigma\) in \(X\), add both \(\sigma\) and a simplex made up of \(v\) and \(\sigma\) (topologically, form the join of \(v\) and \(\sigma\)).

If this simplicial set is pointed, then construct the reduced cone: take the quotient of the unreduced cone by the 1-simplex connecting the old base point to the new one.

In either case, as long as the simplicial set is finite, it comes equipped in Sage with a map from it into the cone.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
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()
[*, v, (v,*), e, (e,*)]
sage: CX.base_point()
*

\(X\) as a subset of the cone, and also the map from \(X\), in the unreduced case:

sage: CX.base_as_subset()
Simplicial set with 2 non-degenerate simplices
sage: CX.map_from_base()
Simplicial set morphism:
From: Simplicial set with 2 non-degenerate simplices
  To:   Cone of Simplicial set with 2 non-degenerate simplices
  Defn: [v, e] --> [v, e]

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()
[*, e, (e,*)]
sage: CX.map_from_base()
Simplicial set morphism:
  From: Simplicial set with 2 non-degenerate simplices
  To:   Reduced cone of Simplicial set with 2 non-degenerate simplices
  Defn: [v, e] --> [*, e]
constant_map(codomain=None, point=None)#

Return a constant map with this simplicial set as its domain.

INPUT:

  • codomain – optional, default None. If None, the codomain is the standard one-point space constructed by Point(). Otherwise, either the codomain must be a pointed simplicial set, in which case the map is constant at the base point, or point must be specified.

  • point – optional, default None. If specified, it must be a 0-simplex in the codomain, and it will be the target of the constant map.

EXAMPLES:

sage: S4 = simplicial_sets.Sphere(4)
sage: S4.constant_map()
Simplicial set morphism:
  From: S^4
  To:   Point
  Defn: Constant map at *
sage: S0 = simplicial_sets.Sphere(0)
sage: S4.constant_map(codomain=S0)
Simplicial set morphism:
  From: S^4
  To:   S^0
  Defn: Constant map at v_0

sage: Sigma3 = groups.permutation.Symmetric(3)                              # needs sage.groups
sage: Sigma3.nerve().constant_map()                                         # needs sage.groups
Simplicial set morphism:
  From: Nerve of Symmetric group of order 3! as a permutation group
  To:   Point
  Defn: Constant map at *
coproduct(*others)#

Return the coproduct of this simplicial set with others.

INPUT:

  • others – one or several simplicial sets

If these simplicial sets are pointed, return their wedge sum; if they are not, return their disjoint union. If some are pointed and some are not, raise an error: it is not clear in which category to work.

EXAMPLES:

sage: S2 = simplicial_sets.Sphere(2)
sage: K = simplicial_sets.KleinBottle()
sage: D3 = simplicial_sets.Simplex(3)
sage: Y = S2.unset_base_point()
sage: Z = K.unset_base_point()

sage: S2.coproduct(K).is_pointed()
True
sage: S2.coproduct(K)
Wedge: (S^2 v Klein bottle)
sage: D3.coproduct(Y, Z).is_pointed()
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)

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)
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)
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}]
disjoint_union(*others)#

Return the disjoint union of this simplicial set with others.

INPUT:

  • others – one or several simplicial sets

As long as the factors are all finite, the inclusion map from each factor is available. Any factors which are empty are ignored completely: they do not appear in the list of factors, etc.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: f = AbstractSimplex(1, name='f')
sage: X = SimplicialSet({e: (v, v)})
sage: Y = SimplicialSet({f: (v, w)})
sage: Z = X.disjoint_union(Y)

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()
[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()
(Torus, S^2)
sage: i = A.inclusion_map(0)
sage: i.domain()
Torus
sage: i.codomain()
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)
True
sage: K.factors()
(S^2, S^2, S^2)
face(simplex, i)#

Return the \(i\)-th face of simplex in this simplicial set.

INPUT:

  • simplex – a simplex in this simplicial set

  • i – integer

EXAMPLES:

sage: S2 = simplicial_sets.Sphere(2)
sage: sigma = S2.n_cells(2)[0]
sage: v_0 = S2.n_cells(0)[0]
sage: S2.face(sigma, 0)
s_0 v_0
sage: S2.face(sigma, 0) == v_0.apply_degeneracies(0)
True
sage: S2.face(S2.face(sigma, 0), 0) == v_0
True
faces(simplex)#

Return the list of faces of simplex in this simplicial set.

INPUT:

  • simplex – a simplex in this simplicial set, either degenerate or not

EXAMPLES:

sage: S2 = simplicial_sets.Sphere(2)
sage: sigma = S2.n_cells(2)[0]
sage: S2.faces(sigma)
(s_0 v_0, s_0 v_0, s_0 v_0)
sage: S2.faces(sigma.apply_degeneracies(0))
[sigma_2, sigma_2, s_1 s_0 v_0, s_1 s_0 v_0]

sage: # needs sage.groups
sage: C3 = groups.misc.MultiplicativeAbelian([3])
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)
sage: f2 = BC3.n_cells(1)[1]; f2
f^2
sage: BC3.faces(f2)
(1, 1)
graph()#

Return the 1-skeleton of this simplicial set, as a graph.

EXAMPLES:

sage: Delta3 = simplicial_sets.Simplex(3)
sage: G = Delta3.graph()
sage: G.edges(sort=True)
[((0,), (1,), (0, 1)),
 ((0,), (2,), (0, 2)),
 ((0,), (3,), (0, 3)),
 ((1,), (2,), (1, 2)),
 ((1,), (3,), (1, 3)),
 ((2,), (3,), (2, 3))]

sage: T = simplicial_sets.Torus()
sage: T.graph()
Looped multi-graph on 1 vertex
sage: len(T.graph().edges(sort=False))
3

sage: # needs pyparsing
sage: CP3 = simplicial_sets.ComplexProjectiveSpace(3)
sage: G = CP3.graph()
sage: len(G.vertices(sort=False))
1
sage: len(G.edges(sort=False))
0

sage: Sigma3 = groups.permutation.Symmetric(3)                              # needs sage.groups
sage: Sigma3.nerve().is_connected()                                         # needs sage.groups
True
homology(dim=None, **kwds)#

Return the (reduced) homology of this simplicial set.

INPUT:

  • dim (optional, default None – If None, then return the homology in every dimension. If dim is an integer or list, return the homology in the given dimensions. (Actually, if dim is a list, return the homology in the range from min(dim) to max(dim).)

  • base_ring (optional, default ZZ) – commutative ring, must be ZZ or a field.

Other arguments are also allowed: see the documentation for cell_complex.GenericCellComplex.homology().

Note

If this simplicial set is not finite, you must specify dimensions in which to compute homology via the argument dim.

EXAMPLES:

sage: simplicial_sets.Sphere(5).homology()                                  # needs sage.modules
{0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z}

sage: C3 = groups.misc.MultiplicativeAbelian([3])                           # needs sage.groups
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)                            # needs sage.groups
sage: BC3.homology(range(4), base_ring=GF(3))                               # needs sage.groups sage.modules
{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: # needs sage.groups
sage: C2 = groups.misc.MultiplicativeAbelian([2])
sage: BC2 = simplicial_sets.ClassifyingSpace(C2)
sage: BK = BC2.product(BC2)
sage: BK.homology(range(4))                                                 # needs sage.modules
{0: 0, 1: C2 x C2, 2: C2, 3: C2 x C2 x C2}
identity()#

Return the identity map on this simplicial set.

EXAMPLES:

sage: S3 = simplicial_sets.Sphere(3)
sage: S3.identity()
Simplicial set endomorphism of S^3
  Defn: Identity map

sage: # needs sage.groups
sage: C3 = groups.misc.MultiplicativeAbelian([3])
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)
sage: one = BC3.identity()
sage: [(sigma, one(sigma)) for sigma in BC3.n_cells(2)]
[(f * f, f * f),
 (f * f^2, f * f^2),
 (f^2 * f, f^2 * f),
 (f^2 * f^2, f^2 * f^2)]
is_connected()#

Return True if this simplicial set is connected.

EXAMPLES:

sage: T = simplicial_sets.Torus()
sage: K = simplicial_sets.KleinBottle()
sage: X = T.disjoint_union(K)
sage: T.is_connected()
True
sage: K.is_connected()
True
sage: X.is_connected()
False
sage: simplicial_sets.Sphere(0).is_connected()
False
is_reduced()#

Return True if this simplicial set has only one vertex.

EXAMPLES:

sage: simplicial_sets.Sphere(0).is_reduced()
False
sage: simplicial_sets.Sphere(3).is_reduced()
True
join(*others)#

The join of this simplicial set with others.

Not implemented. See https://ncatlab.org/nlab/show/join+of+simplicial+sets for a few descriptions, for anyone interested in implementing this. See also P. J. Ehlers and Tim Porter, Joins for (Augmented) Simplicial Sets, Jour. Pure Applied Algebra, 145 (2000) 37-44 arXiv 9904039.

  • others – one or several simplicial sets

EXAMPLES:

sage: K = simplicial_sets.Simplex(2)
sage: K.join(K)
Traceback (most recent call last):
...
NotImplementedError: joins are not implemented for simplicial sets
n_cells(n, subcomplex=None)#

Return the list of cells of dimension n of this cell complex. If the optional argument subcomplex is present, then return the n-dimensional faces in the quotient by this subcomplex.

INPUT:

  • n – the dimension

  • subcomplex (optional, default None) – a subcomplex of this cell complex. Return the cells which are in the quotient by this subcomplex.

EXAMPLES:

sage: simplicial_sets.Sphere(3).n_cells(3)
[sigma_3]
sage: simplicial_sets.Sphere(3).n_cells(2)
[]
sage: C2 = groups.misc.MultiplicativeAbelian([2])                           # needs sage.groups
sage: BC2 = C2.nerve()                                                      # needs sage.groups
sage: BC2.n_cells(3)                                                        # needs sage.groups
[f * f * f]
n_chains(n, base_ring=Integer Ring, cochains=False)#

Return the free module of (normalized) chains in degree n over base_ring.

This is the free module on the nondegenerate simplices in the given dimension.

INPUT:

  • n – integer

  • base_ring – ring (optional, default \(\ZZ\))

  • cochains – boolean (optional, default False); if True, return cochains instead

The only difference between chains and cochains is notation: the generator corresponding to the dual of a simplex sigma is written as "\chi_sigma" in the group of cochains.

EXAMPLES:

sage: S3 = simplicial_sets.Sphere(3)
sage: C = S3.n_chains(3, cochains=True)                                     # needs sage.modules
sage: list(C.basis())                                                       # needs sage.modules
[\chi_sigma_3]

sage: # needs sage.groups
sage: Sigma3 = groups.permutation.Symmetric(3)
sage: BSigma3 = simplicial_sets.ClassifyingSpace(Sigma3)
sage: list(BSigma3.n_chains(1).basis())                                     # needs sage.modules
[(1,2), (1,2,3), (1,3), (1,3,2), (2,3)]
sage: list(BSigma3.n_chains(1, cochains=True).basis())                      # needs sage.modules
[\chi_(1,2), \chi_(1,2,3), \chi_(1,3), \chi_(1,3,2), \chi_(2,3)]
nondegenerate_simplices(max_dim=None)#

Return the sorted list of non-degenerate simplices in this simplicial set.

INPUT:

  • max_dim – optional, default None. If specified, return the non-degenerate simplices of this dimension or smaller. This argument is required if this simplicial set is infinite.

The sorting is in increasing order of dimension, and within each dimension, by the name (if present) of each simplex.

Note

The sorting is done when the simplicial set is constructed, so changing the name of a simplex after construction will not affect the ordering.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0)
sage: w = AbstractSimplex(0)
sage: S0 = SimplicialSet({v: None, w: None})
sage: S0.nondegenerate_simplices()
[Delta^0, Delta^0]

Name the vertices and reconstruct the simplicial set: they should be ordered alphabetically:

sage: v.rename('v')
sage: w.rename('w')
sage: S0 = SimplicialSet({v: None, w: None})
sage: S0.nondegenerate_simplices()
[v, w]

Rename but do not reconstruct the set; the ordering does not take the new names into account:

sage: v.rename('z')
sage: S0.nondegenerate_simplices() # old ordering is used
[z, w]

sage: X0 = SimplicialSet({v: None, w: None})
sage: X0.nondegenerate_simplices() # new ordering is used
[w, z]

Test an infinite example:

sage: # needs sage.groups
sage: C3 = groups.misc.MultiplicativeAbelian([3])
sage: BC3 = simplicial_sets.ClassifyingSpace(C3)
sage: BC3.nondegenerate_simplices(2)
[1, f, f^2, f * f, f * f^2, f^2 * f, f^2 * f^2]
sage: BC3.nondegenerate_simplices()
Traceback (most recent call last):
...
NotImplementedError: this simplicial set may be infinite, so specify max_dim
product(*others)#

Return the product of this simplicial set with others.

INPUT:

  • others – one or several simplicial sets

If \(X\) and \(Y\) are simplicial sets, then their product \(X \times Y\) is defined to be the simplicial set with \(n\)-simplices \(X_n \times Y_n\). See simplicial_set_constructions.ProductOfSimplicialSets for more information.

If a simplicial set is constructed as a product, the factors are recorded and are accessible via the method simplicial_set_constructions.Factors.factors(). If each factor is finite, then you can also construct the projection maps onto each factor, the wedge as a subcomplex, and the fat wedge as a subcomplex.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: X = SimplicialSet({e: (v, w)})
sage: square = X.product(X)

square is now the standard triangulation of the square: 4 vertices, 5 edges (the four on the border and the diagonal), 2 triangles:

sage: square.f_vector()
[4, 5, 2]

sage: S1 = simplicial_sets.Sphere(1)
sage: T = S1.product(S1)
sage: T.homology(reduced=False)                                             # needs sage.modules
{0: Z, 1: Z x Z, 2: Z}

Since S1 is pointed, so is T:

sage: S1.is_pointed()
True
sage: S1.base_point()
v_0
sage: T.is_pointed()
True
sage: T.base_point()
(v_0, v_0)

sage: S2 = simplicial_sets.Sphere(2)
sage: S3 = simplicial_sets.Sphere(3)
sage: S2xS3 = S2.product(S3)
sage: S2xS3.homology(reduced=False)                                         # needs sage.modules
{0: Z, 1: 0, 2: Z, 3: Z, 4: 0, 5: Z}

sage: S2xS3.factors() == (S2, S3)
True
sage: S2xS3.factors() == (S3, S2)
False

sage: # needs sage.groups
sage: G = groups.misc.MultiplicativeAbelian([2])
sage: B = simplicial_sets.ClassifyingSpace(G)
sage: B.rename('RP^oo')
sage: X = B.product(B, S2); X
RP^oo x RP^oo x S^2
sage: X.factor(1)
RP^oo
sage: X.factors()
(RP^oo, RP^oo, S^2)

Projection maps and wedges:

sage: S2xS3.projection_map(0)
Simplicial set morphism:
  From: S^2 x S^3
  To:   S^2
  Defn: ...
sage: S2xS3.wedge_as_subset().homology()                                    # needs sage.modules
{0: 0, 1: 0, 2: Z, 3: Z}

In the case of pointed simplicial sets, there is an inclusion of each factor into the product. These are not automatically defined in Sage, but they are easy to construct using identity maps and constant maps and the universal property of the product:

sage: one = S2.identity()
sage: const = S2.constant_map(codomain=S3)
sage: S2xS3.universal_property(one, const)
Simplicial set morphism:
  From: S^2
  To:   S^2 x S^3
  Defn: [v_0, sigma_2] --> [(v_0, v_0), (sigma_2, s_1 s_0 v_0)]
pullback(*maps)#

Return the pullback obtained from given maps.

INPUT:

  • maps – several maps of simplicial sets, each of which has this simplicial set as its codomain

If only a single map \(f: X \to Y\) is given, then return \(X\). If more than one map is given, say \(f_i: X_i \to Y\) for \(0 \leq i \leq m\), then return the pullback defined by those maps. If no maps are given, return the one-point simplicial set.

In addition to the defining maps \(f_i\) used to construct the pullback \(P\), there are also maps \(\bar{f}_i: P \to X_i\), which we refer to as structure maps or projection maps. The pullback also has a universal property: given maps \(g_i: Z \to X_i\) such that \(f_i g_i = f_j g_j\) for all \(i\), \(j\), then there is a unique map \(g: Z \to P\) making the appropriate diagram commute: that is, \(\bar{f}_i g = g_i\) for all \(i\). For example, given maps \(f: X \to Y\) and \(g: X \to Z\), there is an induced map \(g: X \to Y \times Z\).

In Sage, a pullback is equipped with its defining maps, and as long as the simplicial sets involved are finite, you can also access the structure maps and the universal property.

EXAMPLES:

Construct a product as a pullback:

sage: S2 = simplicial_sets.Sphere(2)
sage: pt = simplicial_sets.Point()
sage: P = pt.pullback(S2.constant_map(), S2.constant_map())
sage: P.homology(2)                                                         # needs sage.modules
Z x Z

If the pullback is defined via maps \(f_i: X_i \to Y\), then there are structure maps \(\bar{f}_i: Y_i \to P\). The structure maps are only available in Sage when all of the maps involved have finite domains.

sage: S2 = simplicial_sets.Sphere(2)
sage: one = S2.Hom(S2).identity()
sage: P = S2.pullback(one, one)
sage: P.homology()                                                          # needs sage.modules
{0: 0, 1: 0, 2: Z}

sage: P.defining_map(0) == one
True
sage: P.structure_map(1)
Simplicial set morphism:
  From: Pullback of maps:
  Simplicial set endomorphism of S^2
    Defn: Identity map
  Simplicial set endomorphism of S^2
    Defn: Identity map
  To:   S^2
  Defn: [(v_0, v_0), (sigma_2, sigma_2)] --> [v_0, sigma_2]
sage: P.structure_map(0).domain() == P
True
sage: P.structure_map(0).codomain() == S2
True

The universal property:

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
True
sage: h.codomain() == P
True
pushout(*maps)#

Return the pushout obtained from given maps.

INPUT:

  • maps – several maps of simplicial sets, each of which has this simplicial set as its domain

If only a single map \(f: X \to Y\) is given, then return \(Y\). If more than one map is given, say \(f_i: X \to Y_i\) for \(0 \leq i \leq m\), then return the pushout defined by those maps. If no maps are given, return the empty simplicial set.

In addition to the defining maps \(f_i\) used to construct the pushout \(P\), there are also maps \(\bar{f}_i: Y_i \to P\), which we refer to as structure maps. The pushout also has a universal property: given maps \(g_i: Y_i \to Z\) such that \(g_i f_i = g_j f_j\) for all \(i\), \(j\), then there is a unique map \(g: P \to Z\) making the appropriate diagram commute: that is, \(g \bar{f}_i = g_i\) for all \(i\).

In Sage, a pushout is equipped with its defining maps, and as long as the simplicial sets involved are finite, you can also access the structure maps and the universal property.

EXAMPLES:

Construct the 4-sphere as a quotient of a 4-simplex:

sage: K = simplicial_sets.Simplex(4)
sage: L = K.n_skeleton(3)
sage: S4 = L.pushout(L.constant_map(), L.inclusion_map()); S4
Pushout of maps:
  Simplicial set morphism:
    From: Simplicial set with 30 non-degenerate simplices
    To:   Point
    Defn: Constant map at *
  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())
2
sage: S4.homology(4)                                                        # needs sage.modules
Z

The associated 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)
Simplicial set morphism:
  From: Point
  To:   S^1 x S^1
  Defn: Constant map at (v_0, v_0)
sage: W.structure_map(0)
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]})

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
True
sage: g.codomain() == T
True
quotient(subcomplex, vertex_name='*')#

Return the quotient of this simplicial set by subcomplex.

That is, subcomplex is replaced by a vertex.

INPUT:

  • subcomplex – subsimplicial set of this simplicial set, or a list, tuple, or set of simplices defining a subsimplicial set.

  • vertex_name (optional) – string, name to be given to the new vertex. By default, use '*'.

In Sage, from a quotient simplicial set, you can recover the ambient space, the subcomplex, and (if the ambient space is finite) the quotient map.

Base points: if the original simplicial set has a base point not contained in subcomplex and if the original simplicial set is finite, then use its image as the base point for the quotient. In all other cases, * is the base point.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
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()
[*, e]
sage: Y.homology(1)                                                         # needs sage.modules
Z

sage: E = SimplicialSet({e: (v, w)})
sage: Z = E.quotient([v, w])
sage: Z.nondegenerate_simplices()
[*, e]
sage: Z.homology(1)                                                         # needs sage.modules
Z

sage: F = E.quotient([v])
sage: F.nondegenerate_simplices()
[*, w, e]
sage: F.base_point()
*

sage: # needs sage.groups
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))                                       # needs sage.modules
{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,
 3: Vector space of dimension 1 over Finite Field of size 2,
 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()
RP^5
sage: RP5_2.subcomplex()
Simplicial set with 3 non-degenerate simplices
sage: RP5_2.quotient_map()
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]

Behavior of base points:

sage: K = simplicial_sets.Simplex(3)
sage: K.is_pointed()
False
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 = K.set_base_point(K.n_cells(0)[0])
sage: K.base_point()
(0,)
sage: L = K.subsimplicial_set([K.n_cells(1)[-1]])
sage: L.nondegenerate_simplices()
[(2,), (3,), (2, 3)]
sage: K.quotient(L).base_point()
(0,)
reduce()#

Reduce this simplicial set.

That is, take the quotient by a spanning tree of the 1-skeleton, so that the resulting simplicial set has only one vertex. This only makes sense if the simplicial set is connected, so raise an error if not. If already reduced, return itself.

EXAMPLES:

sage: K = simplicial_sets.Simplex(2)
sage: K.is_reduced()
False
sage: X = K.reduce()
sage: X.is_reduced()
True

X is reduced, so calling reduce on it again returns X itself:

sage: X is X.reduce()
True
sage: K is K.reduce()
False

Raise an error for disconnected simplicial sets:

sage: S0 = simplicial_sets.Sphere(0)
sage: S0.reduce()
Traceback (most recent call last):
...
ValueError: this simplicial set is not connected
rename_latex(s)#

Rename or set the LaTeX name for this simplicial set.

INPUT:

  • s – string, the LaTeX representation. Or s can be None, in which case the LaTeX name is unset.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0)
sage: X = SimplicialSet({v: None}, latex_name='*')
sage: latex(X)
*
sage: X.rename_latex('x_0')
sage: latex(X)
x_0
subsimplicial_set(simplices)#

Return the sub-simplicial set of this simplicial set determined by simplices, a set of nondegenerate simplices.

INPUT:

  • simplices – set, list, or tuple of nondegenerate simplices in this simplicial set, or a simplicial complex – see below.

Each sub-simplicial set comes equipped with an inclusion map to its ambient space, and you can easily recover its ambient space.

If simplices is a simplicial complex, then the original simplicial set should itself have been converted from a simplicial complex, and simplices should be a subcomplex of that.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: f = AbstractSimplex(1, name='f')

sage: X = SimplicialSet({e: (v, w), f: (w, v)})
sage: Y = X.subsimplicial_set([e]); Y
Simplicial set with 3 non-degenerate simplices
sage: Y.nondegenerate_simplices()
[v, w, e]

sage: S3 = simplicial_complexes.Sphere(3)
sage: K = SimplicialSet(S3)
sage: tau = K.n_cells(3)[0]
sage: tau.dimension()
3
sage: K.subsimplicial_set([tau])
Simplicial set with 15 non-degenerate simplices

A subsimplicial set knows about its ambient space and the inclusion map into it:

sage: # needs sage.groups
sage: RP4 = simplicial_sets.RealProjectiveSpace(4)
sage: M = RP4.n_skeleton(2); M
Simplicial set with 3 non-degenerate simplices
sage: M.ambient_space()
RP^4
sage: M.inclusion_map()
Simplicial set morphism:
  From: Simplicial set with 3 non-degenerate simplices
  To:   RP^4
  Defn: [1, f, f * f] --> [1, f, f * f]

An infinite ambient simplicial set:

sage: # needs sage.groups
sage: G = groups.misc.MultiplicativeAbelian([2])
sage: B = simplicial_sets.ClassifyingSpace(G)
sage: BxB = B.product(B)
sage: BxB.n_cells(2)[5:]
[(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:])
Simplicial set with 8 non-degenerate simplices
suspension(n=1)#

Return the (reduced) \(n\)-th suspension of this simplicial set.

INPUT:

  • n (optional, default 1) – integer, suspend this many times.

If this simplicial set \(X\) is not pointed, return the suspension: the quotient \(CX/X\), where \(CX\) is the (ordinary, unreduced) cone on \(X\). If \(X\) is pointed, then use the reduced cone instead, and so return the reduced suspension.

EXAMPLES:

sage: # needs sage.groups
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()
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()                                                   # needs sage.groups
[1, 0, 1, 1, 1, 1]
sage: S1_smash_RP4.f_vector()                                               # needs sage.groups
[1, 1, 4, 6, 8, 5]
wedge(*others)#

Return the wedge sum of this pointed simplicial set with others.

  • others – one or several simplicial sets

This constructs the quotient of the disjoint union in which the base points of all of the simplicial sets have been identified. This is the coproduct in the category of pointed simplicial sets.

This raises an error if any of the factors is not pointed.

From the wedge, you can access the factors, and if the simplicial sets involved are all finite, you can also access the inclusion map of each factor into the wedge, as well as the projection map onto each factor.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: e = AbstractSimplex(1, name='e')
sage: w = AbstractSimplex(0, name='w')
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()
[*, e, f]
sage: W.homology()                                                          # needs sage.modules
{0: 0, 1: Z x Z}
sage: S2 = simplicial_sets.Sphere(2)
sage: X.wedge(S2).homology(reduced=False)                                   # needs sage.modules
{0: Z, 1: Z, 2: Z}
sage: X.wedge(X).nondegenerate_simplices()
[*, e, e]

sage: S3 = simplicial_sets.Sphere(3)
sage: W = S2.wedge(S3, S2)
sage: W.inclusion_map(2)
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)
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)
  Defn: [*, sigma_2, sigma_2, sigma_3] --> [*, s_1 s_0 *, s_1 s_0 *, sigma_3]

Note that the codomain of the projection map is not identical to the original S2, but is instead a quotient of the wedge which is isomorphic to S2:

sage: S2.f_vector()
[1, 0, 1]
sage: W.projection_map(2).codomain().f_vector()
[1, 0, 1]
sage: (W.projection_map(2) * W.inclusion_map(2)).is_bijective()
True
class sage.topology.simplicial_set.SimplicialSet_finite(data, base_point=None, name=None, check=True, category=None, latex_name=None)#

Bases: SimplicialSet_arbitrary, GenericCellComplex

A finite simplicial set.

A simplicial set \(X\) is a collection of sets \(X_n\), the n-simplices, indexed by the non-negative integers, together with face maps \(d_i\) and degeneracy maps \(s_j\). A simplex is degenerate if it is in the image of some \(s_j\), and a simplicial set is finite if there are only finitely many non-degenerate simplices.

INPUT:

  • data – the data defining the simplicial set. See below for details.

  • base_point (optional, default None) – 0-simplex in this simplicial set, its base point

  • name (optional, default None) – string, the name of the simplicial set

  • check (optional, default True) – boolean. If True, check the simplicial identity on the face maps when defining the simplicial set.

  • category (optional, default None) – the category in which to define this simplicial set. The default is either finite simplicial sets or finite pointed simplicial sets, depending on whether a base point is defined.

  • latex_name (optional, default None) – string, the LaTeX representation of the simplicial set.

data should have one of the following forms: it could be a simplicial complex or \(\Delta\)-complex, in case it is converted to a simplicial set. Alternatively, it could be a dictionary. The keys are the nondegenerate simplices of the simplicial set, and the value corresponding to a simplex \(\sigma\) is a tuple listing the faces of \(\sigma\). The 0-dimensional simplices may be omitted from data if they (or their degeneracies) are faces of other simplices; otherwise they must be included with value None.

See simplicial_set and the methods for simplicial sets for more information and examples.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: u = AbstractSimplex(0, name='u')
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: f = AbstractSimplex(1, name='f')

In the following simplicial set, u is an isolated vertex:

sage: X = SimplicialSet({e: (v,w), f: (w,w), u: None})
sage: X
Simplicial set with 5 non-degenerate simplices
sage: X.rename('X')
sage: X
X
sage: X = SimplicialSet({e: (v,w), f: (w,w), u: None}, name='Y')
sage: X
Y
algebraic_topological_model(base_ring=None)#

Return the algebraic topological model for this simplicial set with coefficients in base_ring.

The term “algebraic topological model” is defined by Pilarczyk and Réal [PR2015].

INPUT:

  • base_ring - coefficient ring (optional, default QQ). Must be a field.

Denote by \(C\) the chain complex associated to this simplicial set. The algebraic topological model is a chain complex \(M\) with zero differential, with the same homology as \(C\), along with chain maps \(\pi: C \to M\) and \(\iota: M \to C\) satisfying \(\iota \pi = 1_M\) and \(\pi \iota\) chain homotopic to \(1_C\). The chain homotopy \(\phi\) must satisfy

  • \(\phi \phi = 0\),

  • \(\pi \phi = 0\),

  • \(\phi \iota = 0\).

Such a chain homotopy is called a chain contraction.

OUTPUT: a pair consisting of

  • chain contraction phi associated to \(C\), \(M\), \(\pi\), and \(\iota\)

  • the chain complex \(M\)

Note that from the chain contraction phi, one can recover the chain maps \(\pi\) and \(\iota\) via phi.pi() and phi.iota(). Then one can recover \(C\) and \(M\) from, for example, phi.pi().domain() and phi.pi().codomain(), respectively.

EXAMPLES:

sage: RP2 = simplicial_sets.RealProjectiveSpace(2)                          # needs sage.groups
sage: phi, M = RP2.algebraic_topological_model(GF(2))                       # needs sage.groups
sage: M.homology()                                                          # needs sage.groups sage.modules
{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)                            # needs sage.modules
sage: M.homology()                                                          # needs 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}
chain_complex(dimensions=None, base_ring=Integer Ring, augmented=False, cochain=False, verbose=False, subcomplex=None, check=False)#

Return the normalized chain complex.

INPUT:

  • dimensions – if None, compute the chain complex in all dimensions. If a list or tuple of integers, compute the chain complex in those dimensions, setting the chain groups in all other dimensions to zero.

  • base_ring (optional, default ZZ) – commutative ring

  • augmented (optional, default False) – if True, return the augmented chain complex (that is, include a class in dimension \(-1\) corresponding to the empty cell).

  • cochain (optional, default False) – if True, return the cochain complex (that is, the dual of the chain complex).

  • verbose (optional, default False) – ignored.

  • subcomplex (optional, default None) – if present, compute the chain complex relative to this subcomplex.

  • check (optional, default False) – If True, make sure that the chain complex is actually a chain complex: the differentials are composable and their product is zero.

The normalized chain complex of a simplicial set is isomorphic to the chain complex obtained by modding out by degenerate simplices, and the latter is what is actually constructed here.

EXAMPLES:

sage: # needs sage.modules
sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0)
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()
{0: Z, 3: Z}
sage: S3.chain_complex(augmented=True).homology()
{-1: 0, 0: 0, 3: Z}
sage: S3.chain_complex(dimensions=range(3), base_ring=QQ).homology()
{0: Vector space of dimension 1 over Rational Field}

sage: RP5 = simplicial_sets.RealProjectiveSpace(5)                          # needs sage.groups
sage: RP2 = RP5.n_skeleton(2)                                               # needs sage.groups
sage: RP5.chain_complex(subcomplex=RP2).homology()                          # needs sage.groups sage.modules
{0: Z, 3: C2, 4: 0, 5: Z}
euler_characteristic()#

Return the Euler characteristic of this simplicial set: the alternating sum over \(n \geq 0\) of the number of nondegenerate \(n\)-simplices.

EXAMPLES:

sage: simplicial_sets.RealProjectiveSpace(4).euler_characteristic()         # needs sage.groups
1
sage: simplicial_sets.Sphere(6).euler_characteristic()
2
sage: simplicial_sets.KleinBottle().euler_characteristic()
0
f_vector()#

Return the list of the number of non-degenerate simplices in each dimension.

Unlike for some other cell complexes in Sage, this does not include the empty simplex in dimension \(-1\); thus its \(i\)-th entry is the number of \(i\)-dimensional simplices.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0)
sage: w = AbstractSimplex(0)
sage: S0 = SimplicialSet({v: None, w: None})
sage: S0.f_vector()
[2]

sage: e = AbstractSimplex(1)
sage: S1 = SimplicialSet({e: (v, v)})
sage: S1.f_vector()
[1, 1]
sage: simplicial_sets.Sphere(3).f_vector()
[1, 0, 0, 1]
face_data()#

Return the face-map data – a dictionary – defining this simplicial set.

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: e = AbstractSimplex(1, name='e')
sage: X = SimplicialSet({e: (v, w)})
sage: X.face_data()[e]
(v, w)

sage: Y = SimplicialSet({v: None, w: None})
sage: v in Y.face_data()
True
sage: Y.face_data()[v] is None
True
n_skeleton(n)#

Return the \(n\)-skeleton of this simplicial set.

That is, the subsimplicial set generated by all nondegenerate simplices of dimension at most \(n\).

INPUT:

  • n – the dimension

EXAMPLES:

sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
sage: v = AbstractSimplex(0, name='v')
sage: w = AbstractSimplex(0, name='w')
sage: degen = v.apply_degeneracies(0)
sage: tau = AbstractSimplex(2, name='tau')
sage: Y = SimplicialSet({tau: (degen, degen, degen), w: None})

Y is the disjoint union of a 2-sphere, with vertex v and non-degenerate 2-simplex tau, and a point w.

sage: Y.nondegenerate_simplices()
[v, w, tau]
sage: Y.n_skeleton(1).nondegenerate_simplices()
[v, w]
sage: Y.n_skeleton(2).nondegenerate_simplices()
[v, w, tau]
sage.topology.simplicial_set.all_degeneracies(n, l=1)#

Return list of all composites of degeneracies (written in “admissible” form, i.e., as a strictly decreasing sequence) of length \(l\) on an \(n\)-simplex.

INPUT:

  • n, l – integers

On an \(n\)-simplex, one may apply the degeneracies \(s_i\) for \(0 \leq i \leq n\). Then on the resulting \(n+1\)-simplex, one may apply \(s_i\) for \(0 \leq i \leq n+1\), and so on. But one also has to take into account the simplicial identity

\[s_i s_j = s_{j+1} s_i \ \ \text{if } i \leq j.\]

There are \(\binom{l+n}{n}\) such composites: each non-degenerate \(n\)-simplex leads to \(\binom{l+n}{n}\) degenerate \(l+n\) simplices.

EXAMPLES:

sage: from sage.topology.simplicial_set import all_degeneracies
sage: all_degeneracies(0, 3)
{(2, 1, 0)}
sage: all_degeneracies(1, 1)
{(0,), (1,)}
sage: all_degeneracies(1, 3)
{(2, 1, 0), (3, 1, 0), (3, 2, 0), (3, 2, 1)}
sage.topology.simplicial_set.face_degeneracies(m, I)#

Return the result of applying the face map \(d_m\) to the iterated degeneracy \(s_I = s_{i_1} s_{i_2} ... s_{i_n}\).

INPUT:

  • m – integer

  • I – tuple (i_1, i_2, ..., i_n) of integers. We assume that this sequence is strictly decreasing.

Using the simplicial identities (see simplicial_set), we can rewrite

\[d_m s_{i_1} s_{i_2} ... s_{i_n}\]

in one of the forms

\[s_{j_1} s_{j_2} ... s_{j_n} d_t, \quad s_{j_1} s_{j_2} ... s_{j_{n-1}}.\]

OUTPUT: the pair (J, t) or (J, None). J is returned as a list.

EXAMPLES:

sage: from sage.topology.simplicial_set import face_degeneracies
sage: face_degeneracies(0, (1, 0))
([0], None)
sage: face_degeneracies(1, (1, 0))
([0], None)
sage: face_degeneracies(2, (1, 0))
([0], None)
sage: face_degeneracies(3, (1, 0))
([1, 0], 1)
sage: face_degeneracies(3, ())
([], 3)
sage.topology.simplicial_set.shrink_simplicial_complex(K)#

Convert the simplicial complex K to a “small” simplicial set.

First convert K naively, then mod out by a large contractible subcomplex, as found by simplicial_complex.SimplicialComplex._contractible_subcomplex(). This will produce a simplicial set no larger than, and sometimes much smaller than, the initial simplicial complex.

EXAMPLES:

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()
[1]

sage: Y = simplicial_complexes.Sphere(2)
sage: S2 = shrink_simplicial_complex(Y); S2
Quotient: (Simplicial set with
           14 non-degenerate simplices/Simplicial set with
                                       13 non-degenerate simplices)
sage: S2.f_vector()
[1, 0, 1]
sage: S2.homology()                                                             # needs 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()                                                              # needs sage.modules
{0: 0, 1: Z^6, 2: Z}
sage: M = shrink_simplicial_complex(Z)
sage: M.f_vector()  # random
[1, 32, 27]
sage: M.homology()                                                              # needs sage.modules
{0: 0, 1: Z^6, 2: Z}
sage.topology.simplicial_set.standardize_degeneracies(*L)#

Return list of indices of degeneracy maps in standard (decreasing) order.

INPUT:

  • L – list of integers, representing a composition of degeneracies in a simplicial set.

OUTPUT:

an equivalent list of degeneracies, standardized to be written in decreasing order, using the simplicial identity

\[s_i s_j = s_{j+1} s_i \ \ \text{if } i \leq j.\]

For example, \(s_0 s_2 = s_3 s_0\) and \(s_0 s_0 = s_1 s_0\).

EXAMPLES:

sage: from sage.topology.simplicial_set import standardize_degeneracies
sage: standardize_degeneracies(0, 0)
(1, 0)
sage: standardize_degeneracies(0, 0, 0, 0)
(3, 2, 1, 0)
sage: standardize_degeneracies(1, 2)
(3, 1)
sage.topology.simplicial_set.standardize_face_maps(*L)#

Return list of indices of face maps in standard (non-increasing) order.

INPUT:

  • L – list of integers, representing a composition of face maps in a simplicial set.

OUTPUT:

an equivalent list of face maps, standardized to be written in non-increasing order, using the simplicial identity

\[d_i d_j = d_{j-1} d_i \ \ \text{if } i<j.\]

For example, \(d_0 d_2 = d_1 d_0\) and \(d_0 d_1 = d_0 d_0\).

EXAMPLES:

sage: from sage.topology.simplicial_set import standardize_face_maps
sage: standardize_face_maps(0, 1)
(0, 0)
sage: standardize_face_maps(0, 2)
(1, 0)
sage: standardize_face_maps(1, 3, 5)
(3, 2, 1)