### Navigation

- index
- modules |
- next |
- previous |
- Cell complexes and their homology »

# Finite simplicial complexes

AUTHORS:

- John H. Palmieri (2009-04)
- D. Benjamin Antieau (2009-06): added is_connected, generated_subcomplex, remove_facet, and is_flag_complex methods; cached the output of the graph() method.
- Travis Scrimshaw (2012-08-17): Made `SimplicialComplex` have an immutable option, and added `__hash__()` function which checks to make sure it is immutable. Made `SimplicialComplex.remove_face()` into a mutator. Deprecated the `vertex_set` parameter.
- Christian Stump (2011-06): implementation of is_cohen_macaulay
- Travis Scrimshaw (2013-02-16): Allowed `SimplicialComplex` to make mutable copies.
- Simon King (2014-05-02): Let simplicial complexes be objects of the category of simplicial complexes.

This module implements the basic structure of finite simplicial complexes. Given a set \(V\) of “vertices”, a simplicial complex on \(V\) is a collection \(K\) of subsets of \(V\) satisfying the condition that if \(S\) is one of the subsets in \(K\), then so is every subset of \(S\). The subsets \(S\) are called the ‘simplices’ of \(K\).

A simplicial complex \(K\) can be viewed as a purely combinatorial object, as described above, but it also gives rise to a topological space \(|K|\) (its geometric realization) as follows: first, the points of \(V\) should be in general position in euclidean space. Next, if \(\{v\}\) is in \(K\), then the vertex \(v\) is in \(|K|\). If \(\{v, w\}\) is in \(K\), then the line segment from \(v\) to \(w\) is in \(|K|\). If \(\{u, v, w\}\) is in \(K\), then the triangle with vertices \(u\), \(v\), and \(w\) is in \(|K|\). In general, \(|K|\) is the union of the convex hulls of simplices of \(K\). Frequently, one abuses notation and uses \(K\) to denote both the simplicial complex and the associated topological space.

For any simplicial complex \(K\) and any commutative ring \(R\) there is an associated chain complex, with differential of degree \(-1\). The \(n^{th}\) term is the free \(R\)-module with basis given by the \(n\)-simplices of \(K\). The differential is determined by its value on any simplex: on the \(n\)-simplex with vertices \((v_0, v_1, ..., v_n)\), the differential is the alternating sum with \(i^{th}\) summand \((-1)^i\) multiplied by the \((n-1)\)-simplex obtained by omitting vertex \(v_i\).

In the implementation here, the vertex set must be finite. To define a simplicial complex, specify its vertex set: this should be a list, tuple, or set, or it can be a non-negative integer \(n\), in which case the vertex set is \((0, ..., n)\). Also specify the facets: the maximal faces.

Note

The elements of the vertex set are not automatically contained in the simplicial complex: each one is only included if and only if it is a vertex of at least one of the specified facets.

Note

This class derives from `GenericCellComplex`, and so inherits its methods. Some of those methods are not listed here; see the `Generic Cell Complex` page instead.

EXAMPLES:

    sage: SimplicialComplex([[1], [3, 7]])
    Simplicial complex with vertex set (1, 3, 7) and facets {(3, 7), (1,)}
    sage: SimplicialComplex()   # the empty simplicial complex
    Simplicial complex with vertex set () and facets {()}
    sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [3,0]])
    sage: X
    Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2), (2, 3), (0, 3), (0, 1)}
    sage: X.stanley_reisner_ring()
    Quotient of Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring by the ideal (x1*x3, x0*x2)
    sage: X.is_pure()
    True

Sage can perform a number of operations on simplicial complexes, such as the join and the product, and it can also compute homology:

    sage: S = SimplicialComplex([[0,1], [1,2], [0,2]]) # circle
    sage: T = S.product(S)  # torus
    sage: T
    Simplicial complex with 9 vertices and 18 facets
    sage: T.homology()   # this computes reduced homology
    {0: 0, 1: Z x Z, 2: Z}
    sage: T.euler_characteristic()
    0

Sage knows about some basic combinatorial data associated to a simplicial complex:

    sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [0,3]])
    sage: X.f_vector()
    [1, 4, 4]
    sage: X.face_poset()
    Finite poset containing 8 elements
    sage: X.stanley_reisner_ring()
    Quotient of Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring by the ideal (x1*x3, x0*x2)

Mutability (see trac ticket #12587):

    sage: S = SimplicialComplex([[1,4], [2,4]])
    sage: S.add_face([1,3])
    sage: S.remove_face([1,3]); S
    Simplicial complex with vertex set (1, 2, 3, 4) and facets {(2, 4), (1, 4), (3,)}
    sage: hash(S)
    Traceback (most recent call last):
    ...
    ValueError: This simplicial complex must be immutable. Call set_immutable().
    sage: S = SimplicialComplex([[1,4], [2,4]])
    sage: S.set_immutable()
    sage: S.add_face([1,3])
    Traceback (most recent call last):
    ...
    ValueError: This simplicial complex is not mutable
    sage: S.remove_face([1,3])
    Traceback (most recent call last):
    ...
    ValueError: This simplicial complex is not mutable
    sage: hash(S) == hash(S)
    True

    sage: S2 = SimplicialComplex([[1,4], [2,4]], is_mutable=False)
    sage: hash(S2) == hash(S)
    True

We can also make mutable copies of an immutable simplicial complex (see trac ticket #14142):

    sage: S = SimplicialComplex([[1,4], [2,4]])
    sage: S.set_immutable()
    sage: T = copy(S)
    sage: T.is_mutable()
    True
    sage: S == T
    True

class `sage.homology.simplicial_complex.``Simplex`(X)

  Bases: `sage.structure.sage_object.SageObject`

  Define a simplex.

  Topologically, a simplex is the convex hull of a collection of vertices in general position. Combinatorially, it is defined just by specifying a set of vertices. It is represented in Sage by the tuple of the vertices.

  Parameters: | X (integer or list, tuple, or other iterable) – set of vertices
  Returns: | simplex with those vertices

  `X` may be a non-negative integer \(n\), in which case the simplicial complex will have \(n+1\) vertices \((0, 1, ..., n)\), or it may be anything which may be converted to a tuple, in which case the vertices will be that tuple. In the second case, each vertex must be hashable, so it should be a number, a string, or a tuple, for instance, but not a list.

  Warning

  The vertices should be distinct, and no error checking is done to make sure this is the case.

  EXAMPLES:

      sage: Simplex(4)
      (0, 1, 2, 3, 4)
      sage: Simplex([3, 4, 1])
      (3, 4, 1)
      sage: X = Simplex((3, 'a', 'vertex')); X
      (3, 'a', 'vertex')
      sage: X == loads(dumps(X))
      True

  Vertices may be tuples but not lists:

      sage: Simplex([(1,2), (3,4)])
      ((1, 2), (3, 4))
      sage: Simplex([[1,2], [3,4]])
      Traceback (most recent call last):
      ...
      TypeError: unhashable type: 'list'

  `dimension`()

    The dimension of this simplex.

    The dimension of a simplex is the number of vertices minus 1.

    EXAMPLES:

        sage: Simplex(5).dimension() == 5
        True
        sage: Simplex(5).face(1).dimension()
        4

  `face`(n)

    The \(n\)-th face of this simplex.

    Parameters: | n (integer) – an integer between 0 and the dimension of this simplex
    Returns: | the simplex obtained by removing the \(n\)-th vertex from this simplex

    EXAMPLES:

        sage: S = Simplex(4)
        sage: S.face(0)
        (1, 2, 3, 4)
        sage: S.face(3)
        (0, 1, 2, 4)

  `faces`()

    The list of faces (of codimension 1) of this simplex.

    EXAMPLES:

        sage: S = Simplex(4)
        sage: S.faces()
        [(1, 2, 3, 4), (0, 2, 3, 4), (0, 1, 3, 4), (0, 1, 2, 4), (0, 1, 2, 3)]
        sage: len(Simplex(10).faces())
        11

  `is_empty`()

    Return `True` iff this simplex is the empty simplex.

    EXAMPLES:

        sage: [Simplex(n).is_empty() for n in range(-1,4)]
        [True, False, False, False, False]

  `is_face`(other)

    Return `True` iff this simplex is a face of other.

    EXAMPLES:

        sage: Simplex(3).is_face(Simplex(5))
        True
        sage: Simplex(5).is_face(Simplex(2))
        False
        sage: Simplex(['a', 'b', 'c']).is_face(Simplex(8))
        False

  `join`(right, rename_vertices=True)

    The join of this simplex with another one.

    The join of two simplices \([v_0, ..., v_k]\) and \([w_0, ..., w_n]\) is the simplex \([v_0, ..., v_k, w_0, ..., w_n]\).

    Parameters: | right – the other simplex (the right-hand factor) rename_vertices (boolean; optional, default `True`) – If this is `True`, the vertices in the join will be renamed by this formula: vertex “v” in the left-hand factor –> vertex “Lv” in the join, vertex “w” in the right-hand factor –> vertex “Rw” in the join. If this is false, this tries to construct the join without renaming the vertices; this may cause problems if the two factors have any vertices with names in common.

    EXAMPLES:

        sage: Simplex(2).join(Simplex(3))
        ('L0', 'L1', 'L2', 'R0', 'R1', 'R2', 'R3')
        sage: Simplex(['a', 'b']).join(Simplex(['x', 'y', 'z']))
        ('La', 'Lb', 'Rx', 'Ry', 'Rz')
        sage: Simplex(['a', 'b']).join(Simplex(['x', 'y', 'z']), rename_vertices=False)
        ('a', 'b', 'x', 'y', 'z')

  `product`(other, rename_vertices=True)

    The product of this simplex with another one, as a list of simplices.

    Parameters: | other – the other simplex rename_vertices (boolean; optional, default `True`) – If this is `False`, then the vertices in the product are the set of ordered pairs \((v,w)\) where \(v\) is a vertex in the left-hand factor (`self`) and \(w\) is a vertex in the right-hand factor (`other`). If this is `True`, then the vertices are renamed as “LvRw” (e.g., the vertex (1,2) would become “L1R2”). This is useful if you want to define the Stanley-Reisner ring of the complex: vertex names like (0,1) are not suitable for that, while vertex names like “L0R1” are.

    Algorithm: see Hatcher, p. 277-278 [Hat] (who in turn refers to Eilenberg-Steenrod, p. 68): given `S = Simplex(m)` and `T = Simplex(n)`, then \(S \times T\) can be triangulated as follows: for each path \(f\) from \((0,0)\) to \((m,n)\) along the integer grid in the plane, going up or right at each lattice point, associate an \((m+n)\)-simplex with vertices \(v_0\), \(v_1\), ..., where \(v_k\) is the \(k^{th}\) vertex in the path \(f\).

    Note that there are \(m+n\) choose \(n\) such paths. Note also that each vertex in the product is a pair of vertices \((v,w)\) where \(v\) is a vertex in the left-hand factor and \(w\) is a vertex in the right-hand factor.

    Note

    This produces a list of simplices – not a `Simplex`, not a `SimplicialComplex`.

    EXAMPLES:

        sage: len(Simplex(2).product(Simplex(2)))
        6
        sage: Simplex(1).product(Simplex(1))
        [('L0R0', 'L0R1', 'L1R1'), ('L0R0', 'L1R0', 'L1R1')]
        sage: Simplex(1).product(Simplex(1), rename_vertices=False)
        [((0, 0), (0, 1), (1, 1)), ((0, 0), (1, 0), (1, 1))]

  `set`()

    The frozenset attached to this simplex.

    EXAMPLES:

        sage: Simplex(3).set()
        frozenset({0, 1, 2, 3})

  `tuple`()

    The tuple attached to this simplex.

    EXAMPLES:

        sage: Simplex(3).tuple()
        (0, 1, 2, 3)

    Although simplices are printed as if they were tuples, they are not the same type:

        sage: type(Simplex(3).tuple())
        <type 'tuple'>
        sage: type(Simplex(3))
        <class 'sage.homology.simplicial_complex.Simplex'>

class `sage.homology.simplicial_complex.``SimplicialComplex`(maximal_faces=None, from_characteristic_function=None, maximality_check=True, sort_facets=True, name_check=False, is_mutable=True, is_immutable=False)

  Bases: `sage.structure.category_object.CategoryObject`, `sage.homology.cell_complex.GenericCellComplex`

  Define a simplicial complex.

  Parameters: | maximal_faces – set of maximal faces from_characteristic_function – see below maximality_check (boolean; optional, default `True`) – see below sort_facets (boolean; optional, default `True`) – see below name_check (boolean; optional, default `False`) – see below is_mutable (boolean; optional, default `True`) – Set to `False` to make this immutable
  Returns: | a simplicial complex

  `maximal_faces` should be a list or tuple or set (indeed, anything which may be converted to a set) whose elements are lists (or tuples, etc.) of vertices. Maximal faces are also known as ‘facets’.

  Alternatively, the maximal faces can be defined from a monotome boolean function on the subsets of a set \(X\). While defining `maximal_faces=None`, you can thus set `from_characteristic_function=(f,X)` where `X` is the set of points and `f` a boolean monotone hereditary function that accepts a list of elements from `X` as input (see `subsets_with_hereditary_property()` for more information).

  If `maximality_check` is `True`, check that each maximal face is, in fact, maximal. In this case, when producing the internal representation of the simplicial complex, omit those that are not. It is highly recommended that this be `True`; various methods for this class may fail if faces which are claimed to be maximal are in fact not.

  If `sort_facets` is `True`, sort the vertices in each facet. If the vertices in different facets are not ordered compatibly (e.g., if you have facets `(1, 3, 5)` and `(5, 3, 8)`), then homology calculations may have unpredictable results.

  If `name_check` is `True`, check the names of the vertices to see if they can be easily converted to generators of a polynomial ring – use this if you plan to use the Stanley-Reisner ring for the simplicial complex.

  EXAMPLES:

      sage: SimplicialComplex([[1,2], [1,4]])
      Simplicial complex with vertex set (1, 2, 4) and facets {(1, 2), (1, 4)}
      sage: SimplicialComplex([[0,2], [0,3], [0]])
      Simplicial complex with vertex set (0, 2, 3) and facets {(0, 2), (0, 3)}
      sage: SimplicialComplex([[0,2], [0,3], [0]], maximality_check=False)
      Simplicial complex with vertex set (0, 2, 3) and facets {(0, 2), (0, 3), (0,)}
      sage: S = SimplicialComplex((('a', 'b'), ['a', 'c'], ('b', 'c')))
      sage: S
      Simplicial complex with vertex set ('a', 'b', 'c') and facets {('b', 'c'), ('a', 'c'), ('a', 'b')}

  Finally, if there is only one argument and it is a simplicial complex, return that complex. If it is an object with a built-in conversion to simplicial complexes (via a `_simplicial_` method), then the resulting simplicial complex is returned:

      sage: S = SimplicialComplex([[0,2], [0,3], [0,6]])
      sage: SimplicialComplex(S) == S
      True
      sage: Tc = cubical_complexes.Torus(); Tc
      Cubical complex with 16 vertices and 64 cubes
      sage: Ts = SimplicialComplex(Tc); Ts
      Simplicial complex with 16 vertices and 32 facets
      sage: Ts.homology()
      {0: 0, 1: Z x Z, 2: Z}

  From a characteristic monotone boolean function, e.g. the simplicial complex of all subsets \(S\subseteq \{0,1,2,3,4\}\) such that \(sum(S)\leq 4\):

      sage: SimplicialComplex(from_characteristic_function=(lambda x:sum(x)<=4,range(5)))
      Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 4), (0, 1, 2), (0, 1, 3)}

  or e.g. the simplicial complex of all 168 hyperovals of the projective plane of order 4:

      sage: l=designs.ProjectiveGeometryDesign(2,1,GF(4,name='a'))
      sage: f = lambda S: not any(len(set(S).intersection(x))>2 for x in l)
      sage: SimplicialComplex(from_characteristic_function=(f, range(21)))
      Simplicial complex with 21 vertices and 168 facets

  TESTS:

  Check that we can make mutable copies (see trac ticket #14142):

      sage: S = SimplicialComplex([[0,2], [0,3]], is_mutable=False)
      sage: S.is_mutable()
      False
      sage: C = copy(S)
      sage: C.is_mutable()
      True
      sage: SimplicialComplex(S, is_mutable=True).is_mutable()
      True
      sage: SimplicialComplex(S, is_immutable=False).is_mutable()
      True

  `add_face`(face)

    Add a face to this simplicial complex

    Parameters: | face – a subset of the vertex set

    This changes the simplicial complex, adding a new face and all of its subfaces.

    EXAMPLES:

        sage: X = SimplicialComplex([[0,1], [0,2]])
        sage: X.add_face([0,1,2,]); X
        Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}
        sage: Y = SimplicialComplex(); Y
        Simplicial complex with vertex set () and facets {()}
        sage: Y.add_face([0,1])
        sage: Y.add_face([1,2,3])
        sage: Y
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2, 3), (0, 1)}

    If you add a face which is already present, there is no effect:

        sage: Y.add_face([1,3]); Y
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2, 3), (0, 1)}

    Check that the bug reported at trac ticket #14354 has been fixed:

        sage: T = SimplicialComplex([range(1,5)]).n_skeleton(1)
        sage: T.homology()
        {0: 0, 1: Z x Z x Z}
        sage: T.add_face([1,2,3])
        sage: T.homology()
        {0: 0, 1: Z x Z, 2: 0}

    Check we’ve fixed the bug reported at trac ticket #14578:

        sage: t0 = SimplicialComplex()
        sage: t0.add_face(('a', 'b'))
        sage: t0.add_face(('c', 'd', 'e'))
        sage: t0.add_face(('e', 'f', 'c'))
        sage: t0.homology()
        {0: Z, 1: 0, 2: 0}

  `alexander_dual`(is_mutable=True)

    The Alexander dual of this simplicial complex: according to the Macaulay2 documentation, this is the simplicial complex whose faces are the complements of its nonfaces.

    Thus find the minimal nonfaces and take their complements to find the facets in the Alexander dual.

    Parameters: | is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    EXAMPLES:

        sage: Y = SimplicialComplex([[i] for i in range(5)]); Y
        Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(4,), (2,), (3,), (0,), (1,)}
        sage: Y.alexander_dual()
        Simplicial complex with vertex set (0, 1, 2, 3, 4) and 10 facets
        sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [3,0]])
        sage: X.alexander_dual()
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (0, 2)}

  `automorphism_group`()

    Return the automorphism group of the simplicial complex.

    This is done by creating a bipartite graph, whose vertices are vertices and facets of the simplicial complex, and computing its automorphism group.

    Warning

    Since trac ticket #14319 the domain of the automorphism group is equal to the graph’s vertex set, and the `translation` argument has become useless.

    EXAMPLES:

        sage: S = simplicial_complexes.Simplex(3)
        sage: S.automorphism_group().is_isomorphic(SymmetricGroup(4))
        True

        sage: P = simplicial_complexes.RealProjectivePlane()
        sage: P.automorphism_group().is_isomorphic(AlternatingGroup(5))
        True

        sage: Z = SimplicialComplex([['1','2'],['2','3','a']])
        sage: Z.automorphism_group().is_isomorphic(CyclicPermutationGroup(2))
        True
        sage: group = Z.automorphism_group()
        sage: group.domain()
        {'1', '2', '3', 'a'}

    Check that trac ticket #17032 is fixed:

        sage: s = SimplicialComplex([[(0,1),(2,3)]])
        sage: s.automorphism_group().cardinality()
        2

  `barycentric_subdivision`()

    The barycentric subdivision of this simplicial complex.

    See http://en.wikipedia.org/wiki/Barycentric_subdivision for a definition.

    EXAMPLES:

        sage: triangle = SimplicialComplex([[0,1], [1,2], [0, 2]])
        sage: hexagon = triangle.barycentric_subdivision()
        sage: hexagon
        Simplicial complex with 6 vertices and 6 facets
        sage: hexagon.homology(1) == triangle.homology(1)
        True

    Barycentric subdivisions can get quite large, since each \(n\)-dimensional facet in the original complex produces \((n+1)!\) facets in the subdivision:

        sage: S4 = simplicial_complexes.Sphere(4)
        sage: S4
        Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and 6 facets
        sage: S4.barycentric_subdivision()
        Simplicial complex with 62 vertices and 720 facets

  `cells`(subcomplex=None)

    The faces of this simplicial complex, in the form of a dictionary of sets keyed by dimension. If the optional argument `subcomplex` is present, then return only the faces which are not in the subcomplex.

    Parameters: | subcomplex (optional, default `None`) – a subcomplex of this simplicial complex. Return faces which are not in this subcomplex.

    EXAMPLES:

        sage: Y = SimplicialComplex([[1,2], [1,4]])
        sage: Y.faces()
        {-1: {()}, 0: {(1,), (2,), (4,)}, 1: {(1, 2), (1, 4)}}
        sage: L = SimplicialComplex([[1,2]])
        sage: Y.faces(subcomplex=L)
        {-1: set(), 0: {(4,)}, 1: {(1, 4)}}

  `chain_complex`(**kwds)

    The chain complex associated to this simplicial complex.

    Parameters: | 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 subcomplex (optional, default empty) – a subcomplex of this simplicial complex. Compute the chain complex relative to this subcomplex. augmented (boolean; optional, default `False`) – If `True`, return the augmented chain complex (that is, include a class in dimension \(-1\) corresponding to the empty cell). This is ignored if `dimensions` is specified. cochain (boolean; optional, default `False`) – If `True`, return the cochain complex (that is, the dual of the chain complex). verbose (boolean; optional, default `False`) – If `True`, print some messages as the chain complex is computed. check_diffs (boolean; 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 subcomplex is nonempty, then the argument `augmented` has no effect: the chain complex relative to a nonempty subcomplex is zero in dimension \(-1\).

    EXAMPLES:

        sage: circle = SimplicialComplex([[0,1], [1,2], [0, 2]])
        sage: circle.chain_complex()
        Chain complex with at most 2 nonzero terms over Integer Ring
        sage: circle.chain_complex()._latex_()
        '\Bold{Z}^{3} \xrightarrow{d_{1}} \Bold{Z}^{3}'
        sage: circle.chain_complex(base_ring=QQ, augmented=True)
        Chain complex with at most 3 nonzero terms over Rational Field

  `cone`(is_mutable=True)

    The cone on this simplicial complex.

    Parameters: | is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    The cone is the simplicial complex formed by adding a new vertex \(C\) and simplices of the form \([C, v_0, ..., v_k]\) for every simplex \([v_0, ..., v_k]\) in the original simplicial complex. That is, the cone is the join of the original complex with a one-point simplicial complex.

    EXAMPLES:

        sage: S = SimplicialComplex([[0], [1]])
        sage: S.cone()
        Simplicial complex with vertex set ('L0', 'L1', 'R0') and facets {('L0', 'R0'), ('L1', 'R0')}

  `connected_component`(simplex=None)

    Return the connected component of this simplicial complex containing `simplex`. If `simplex` is omitted, then return the connected component containing the zeroth vertex in the vertex list. (If the simplicial complex is empty, raise an error.)

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S1 == S1.connected_component()
        True
        sage: X = S1.disjoint_union(S1)
        sage: X == X.connected_component()
        False
        sage: v0 = X.vertices()[0]
        sage: v1 = X.vertices()[-1]
        sage: X.connected_component(Simplex([v0])) == X.connected_component(Simplex([v1]))
        False

        sage: S0 = simplicial_complexes.Sphere(0)
        sage: S0.vertices()
        (0, 1)
        sage: S0.connected_component()
        Simplicial complex with vertex set (0,) and facets {(0,)}
        sage: S0.connected_component(Simplex((1,)))
        Simplicial complex with vertex set (1,) and facets {(1,)}

        sage: SimplicialComplex([[]]).connected_component()
        Traceback (most recent call last):
        ...
        ValueError: the empty simplicial complex has no connected components.

  `connected_sum`(other, is_mutable=True)

    The connected sum of this simplicial complex with another one.

    Parameters: | other – another simplicial complex is_mutable (boolean; optional, default `True`) – Determines if the output is mutable
    Returns: | the connected sum `self # other`

    Warning

    This does not check that `self` and `other` are manifolds, only that their facets all have the same dimension. Since a (more or less) random facet is chosen from each complex and then glued together, this method may return random results if applied to non-manifolds, depending on which facet is chosen.

    Algorithm: a facet is chosen from each surface, and removed. The vertices of these two facets are relabeled to `(0,1,...,dim)`. Of the remaining vertices, the ones from the left-hand factor are renamed by prepending an “L”, and similarly the remaining vertices in the right-hand factor are renamed by prepending an “R”.

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S1.connected_sum(S1.connected_sum(S1)).homology()
        {0: 0, 1: Z}
        sage: P = simplicial_complexes.RealProjectivePlane(); P
        Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and 10 facets
        sage: P.connected_sum(P)    # the Klein bottle
        Simplicial complex with 9 vertices and 18 facets

    The notation ‘+’ may be used for connected sum, also:

        sage: P + P    # the Klein bottle
        Simplicial complex with 9 vertices and 18 facets
        sage: (P + P).homology()[1]
        Z x C2

  `delta_complex`(sort_simplices=False)

    Returns `self` as a \(\Delta\)-complex. The \(\Delta\)-complex is essentially identical to the simplicial complex: it has same simplices with the same boundaries.

    Parameters: | sort_simplices (boolean; optional, default `False`) – if `True`, sort the list of simplices in each dimension

    EXAMPLES:

        sage: T = simplicial_complexes.Torus()
        sage: Td = T.delta_complex()
        sage: Td
        Delta complex with 7 vertices and 43 simplices
        sage: T.homology() == Td.homology()
        True

  `disjoint_union`(right, rename_vertices=True, is_mutable=True)

    The disjoint union of this simplicial complex with another one.

    Parameters: | right – the other simplicial complex (the right-hand factor) rename_vertices (boolean; optional, default True) – If this is True, the vertices in the disjoint union will be renamed by the formula: vertex “v” in the left-hand factor –> vertex “Lv” in the disjoint union, vertex “w” in the right-hand factor –> vertex “Rw” in the disjoint union. If this is false, this tries to construct the disjoint union without renaming the vertices; this will cause problems if the two factors have any vertices with names in common.

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S2 = simplicial_complexes.Sphere(2)
        sage: S1.disjoint_union(S2).homology()
        {0: Z, 1: Z, 2: Z}

  `face_iterator`(increasing=True)

    An iterator for the faces in this simplicial complex.

    INPUTS:

    - `increasing` – (optional, default `True`) if `True`, return faces in increasing order of dimension, thus starting with the empty face. Otherwise it returns faces in decreasing order of dimension.

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: [f for f in S1.face_iterator()]
        [(), (2,), (0,), (1,), (1, 2), (0, 2), (0, 1)]

  `faces`(subcomplex=None)

    The faces of this simplicial complex, in the form of a dictionary of sets keyed by dimension. If the optional argument `subcomplex` is present, then return only the faces which are not in the subcomplex.

    Parameters: | subcomplex (optional, default `None`) – a subcomplex of this simplicial complex. Return faces which are not in this subcomplex.

    EXAMPLES:

        sage: Y = SimplicialComplex([[1,2], [1,4]])
        sage: Y.faces()
        {-1: {()}, 0: {(1,), (2,), (4,)}, 1: {(1, 2), (1, 4)}}
        sage: L = SimplicialComplex([[1,2]])
        sage: Y.faces(subcomplex=L)
        {-1: set(), 0: {(4,)}, 1: {(1, 4)}}

  `facets`()

    The maximal faces (a.k.a. facets) of this simplicial complex.

    This just returns the set of facets used in defining the simplicial complex, so if the simplicial complex was defined with no maximality checking, none is done here, either.

    EXAMPLES:

        sage: Y = SimplicialComplex([[0,2], [1,4]])
        sage: Y.maximal_faces()
        {(1, 4), (0, 2)}

    `facets` is a synonym for `maximal_faces`:

        sage: S = SimplicialComplex([[0,1], [0,1,2]])
        sage: S.facets()
        {(0, 1, 2)}

  `fixed_complex`(G)

    Return the fixed simplicial complex \(Fix(G)\) for a subgroup \(G\).

    INPUT:

    - `G` – a subgroup of the automorphism group of the simplicial complex or a list of elements of the automorphism group

    OUTPUT:

    - a simplicial complex \(Fix(G)\)

    Vertices in \(Fix(G)\) are the orbits of \(G\) (acting on vertices of `self`) that form a simplex in `self`. More generally, simplices in \(Fix(G)\) correspond to simplices in `self` that are union of such orbits.

    A basic example:

        sage: S4 = simplicial_complexes.Sphere(4)
        sage: S3 = simplicial_complexes.Sphere(3)
        sage: fix = S4.fixed_complex([S4.automorphism_group()([(0,1)])])
        sage: fix
        Simplicial complex with vertex set (0, 2, 3, 4, 5) and 5 facets
        sage: fix.is_isomorphic(S3)
        True

    Another simple example:

        sage: T = SimplicialComplex([[1,2,3],[2,3,4]])
        sage: G = T.automorphism_group()
        sage: T.fixed_complex([G([(1,4)])])
        Simplicial complex with vertex set (2, 3) and facets {(2, 3)}

    A more sophisticated example:

        sage: RP2 = simplicial_complexes.ProjectivePlane()
        sage: CP2 = simplicial_complexes.ComplexProjectivePlane()
        sage: G = CP2.automorphism_group()
        sage: H = G.subgroup([G([(2,3),(5,6),(8,9)])])
        sage: CP2.fixed_complex(H).is_isomorphic(RP2)
        True

  `flip_graph`()

    If `self` is pure, then it returns the the flip graph of `self`, otherwise, it returns `None`.

    The flip graph of a pure simplicial complex is the (undirected) graph with vertices being the facets, such that two facets are joined by an edge if they meet in a codimension \(1\) face.

    The flip graph is used to detect if `self` is a pseudomanifold.

    EXAMPLES:

        sage: S0 = simplicial_complexes.Sphere(0)
        sage: G = S0.flip_graph()
        sage: G.vertices(); G.edges(labels=False)
        [(0,), (1,)]
        [((0,), (1,))]

        sage: G = (S0.wedge(S0)).flip_graph()
        sage: G.vertices(); G.edges(labels=False)
        [(0,), ('L1',), ('R1',)]
        [((0,), ('L1',)), ((0,), ('R1',)), (('L1',), ('R1',))]

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S2 = simplicial_complexes.Sphere(2)
        sage: G = (S1.wedge(S1)).flip_graph()
        sage: G.vertices(); G.edges(labels=False)
        [(0, 'L1'), (0, 'L2'), (0, 'R1'), (0, 'R2'), ('L1', 'L2'), ('R1', 'R2')]
        [((0, 'L1'), (0, 'L2')),
         ((0, 'L1'), (0, 'R1')),
         ((0, 'L1'), (0, 'R2')),
         ((0, 'L1'), ('L1', 'L2')),
         ((0, 'L2'), (0, 'R1')),
         ((0, 'L2'), (0, 'R2')),
         ((0, 'L2'), ('L1', 'L2')),
         ((0, 'R1'), (0, 'R2')),
         ((0, 'R1'), ('R1', 'R2')),
         ((0, 'R2'), ('R1', 'R2'))]

        sage: (S1.wedge(S2)).flip_graph() is None
        True

        sage: G = S2.flip_graph()
        sage: G.vertices(); G.edges(labels=False)
        [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
        [((0, 1, 2), (0, 1, 3)),
         ((0, 1, 2), (0, 2, 3)),
         ((0, 1, 2), (1, 2, 3)),
         ((0, 1, 3), (0, 2, 3)),
         ((0, 1, 3), (1, 2, 3)),
         ((0, 2, 3), (1, 2, 3))]

        sage: T = simplicial_complexes.Torus()
        sage: G = T.suspension(4).flip_graph()
        sage: len(G.vertices()); len(G.edges(labels=False))
        46
        161

  `fundamental_group`(base_point=None, simplify=True)

    Return the fundamental group of this simplicial complex.

    INPUT:

    - `base_point` (optional, default None) – if this complex is not path-connected, then specify a vertex; the fundamental group is computed with that vertex as a base point. If the complex is path-connected, then you may specify a vertex or leave this as its default setting of `None`. (If this complex is path-connected, then this argument is ignored.)
    - `simplify` (bool, optional True) – if False, then return a presentation of the group in terms of generators and relations. If True, the default, simplify as much as GAP is able to.

    Algorithm: we compute the edge-path group – see Wikipedia article Fundamental_group. Choose a spanning tree for the 1-skeleton, and then the group’s generators are given by the edges in the 1-skeleton; there are two types of relations: \(e=1\) if \(e\) is in the spanning tree, and for every 2-simplex, if its edges are \(e_0\), \(e_1\), and \(e_2\), then we impose the relation \(e_0 e_1^{-1} e_2 = 1\).

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S1.fundamental_group()
        Finitely presented group < e |  >

    If we pass the argument `simplify=False`, we get generators and relations in a form which is not usually very helpful. Here is the cyclic group of order 2, for instance:

        sage: RP2 = simplicial_complexes.RealProjectiveSpace(2)
        sage: C2 = RP2.fundamental_group(simplify=False)
        sage: C2
        Finitely presented group < e0, e1, e2, e3, e4, e5, e6, e7, e8, e9 | e6, e5, e3, e9, e4*e7^-1*e6, e9*e7^-1*e0, e0*e1^-1*e2, e5*e1^-1*e8, e4*e3^-1*e8, e2 >
        sage: C2.simplified()
        Finitely presented group < e0 | e0^2 >

    This is the same answer given if the argument `simplify` is True (the default):

        sage: RP2.fundamental_group()
        Finitely presented group < e0 | e0^2 >

    You must specify a base point to compute the fundamental group of a non-connected complex:

        sage: K = S1.disjoint_union(RP2)
        sage: K.fundamental_group()
        Traceback (most recent call last):
        ...
        ValueError: this complex is not connected, so you must specify a base point.
        sage: v0 = list(K.vertices())[0]
        sage: K.fundamental_group(base_point=v0)
        Finitely presented group < e |  >
        sage: v1 = list(K.vertices())[-1]
        sage: K.fundamental_group(base_point=v1)
        Finitely presented group < e0 | e0^2 >

    Some other examples:

        sage: S1.wedge(S1).fundamental_group()
        Finitely presented group < e0, e1 | >
        sage: simplicial_complexes.Torus().fundamental_group()
        Finitely presented group < e0, e3 | e0*e3^-1*e0^-1*e3 >
        sage: simplicial_complexes.MooreSpace(5).fundamental_group()
        Finitely presented group < e1 | e1^5 >

  `g_vector`()

    The \(g\)-vector of this simplicial complex.

    If the \(h\)-vector of the complex is \((h_0, h_1, ..., h_d, h_{d+1})\) – see `h_vector()` – then its \(g\)-vector \((g_0, g_1, ..., g_{[(d+1)/2]})\) is defined by \(g_0 = 1\) and \(g_i = h_i - h_{i-1}\) for \(i > 0\).

    EXAMPLES:

        sage: S3 = simplicial_complexes.Sphere(3).barycentric_subdivision()
        sage: S3.f_vector()
        [1, 30, 150, 240, 120]
        sage: S3.h_vector()
        [1, 26, 66, 26, 1]
        sage: S3.g_vector()
        [1, 25, 40]

  `generated_subcomplex`(sub_vertex_set, is_mutable=True)

    Returns the largest sub-simplicial complex of `self` containing exactly `sub_vertex_set` as vertices.

    Parameters: | sub_vertex_set – The sub-vertex set. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    EXAMPLES:

        sage: S = simplicial_complexes.Sphere(2)
        sage: S
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
        sage: S.generated_subcomplex([0,1,2])
        Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}

  `graph`()

    The 1-skeleton of this simplicial complex, as a graph.

    Warning

    This may give the wrong answer if the simplicial complex was constructed with `maximality_check` set to `False`.

    EXAMPLES:

        sage: S = SimplicialComplex([[0,1,2,3]])
        sage: G = S.graph(); G
        Graph on 4 vertices
        sage: G.edges()
        [(0, 1, None), (0, 2, None), (0, 3, None), (1, 2, None), (1, 3, None), (2, 3, None)]

  `h_vector`()

    The \(h\)-vector of this simplicial complex.

    If the complex has dimension \(d\) and \((f_{-1}, f_0, f_1, ..., f_d)\) is its \(f\)-vector (with \(f_{-1} = 1\), representing the empy simplex), then the \(h\)-vector \((h_0, h_1, ..., h_d, h_{d+1})\) is defined by

    \[\sum_{i=0}^{d+1} h_i x^{d+1-i} = \sum_{i=0}^{d+1} f_{i-1} (x-1)^{d+1-i}.\]

    Alternatively,

    \[h_j = \sum_{i=-1}^{j-1} (-1)^{j-i-1} \binom{d-i}{j-i-1} f_i.\]

    EXAMPLES:

    The \(f\)- and \(h\)-vectors of the boundary of an octahedron are computed in Wikipedia’s page on simplicial complexes, http://en.wikipedia.org/wiki/Simplicial_complex:

        sage: square = SimplicialComplex([[0,1], [1,2], [2,3], [0,3]])
        sage: S0 = SimplicialComplex([[0], [1]])
        sage: octa = square.join(S0) # boundary of an octahedron
        sage: octa.f_vector()
        [1, 6, 12, 8]
        sage: octa.h_vector()
        [1, 3, 3, 1]

  `is_cohen_macaulay`(ncpus=0)

    Returns True if `self` is Cohen-Macaulay, i.e., if \(\tilde{H}_i(\operatorname{lk}_\Delta(F);\ZZ) = 0\) for all \(F \in \Delta\) and \(i < \operatorname{dim}\operatorname{lk}_\Delta(F)\). Here, \(\Delta\) is `self`, and \(\operatorname{lk}\) denotes the link operator on `self`.

    INPUT:

    - `ncpus` – (default: 0) number of cpus used for the computation. If this is 0, determine the number of cpus automatically based on the hardware being used.

    For finite simplicial complexes, this is equivalent to the statement that the Stanley-Reisner ring of `self` is Cohen-Macaulay.

    EXAMPLES:

    Spheres are Cohen-Macaulay:

        sage: S = SimplicialComplex([[1,2],[2,3],[3,1]])
        sage: S.is_cohen_macaulay(ncpus=3)
        True

    The following example is taken from Bruns, Herzog - Cohen-Macaulay rings, Figure 5.3:

        sage: S = SimplicialComplex([[1,2,3],[1,4,5]])
        sage: S.is_cohen_macaulay(ncpus=3)
        ...
        False

  `is_connected`()

    Returns `True` if and only if `self` is connected.

    Warning

    This may give the wrong answer if the simplicial complex was constructed with `maximality_check` set to `False`.

    EXAMPLES:

        sage: V = SimplicialComplex([[0,1,2],[3]])
        sage: V
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (3,)}
        sage: V.is_connected()
        False

        sage: X = SimplicialComplex([[0,1,2]])
        sage: X.is_connected()
        True

        sage: U = simplicial_complexes.ChessboardComplex(3,3)
        sage: U.is_connected()
        True

        sage: W = simplicial_complexes.Sphere(3)
        sage: W.is_connected()
        True

        sage: S = SimplicialComplex([[0,1],[2,3]])
        sage: S.is_connected()
        False

  `is_flag_complex`()

    Returns `True` if and only if `self` is a flag complex.

    A flag complex is a simplicial complex that is the largest simplicial complex on its 1-skeleton. Thus a flag complex is the clique complex of its graph.

    EXAMPLES:

        sage: h = Graph({0:[1,2,3,4],1:[2,3,4],2:[3]})
        sage: x = h.clique_complex()
        sage: x
        Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 4), (0, 1, 2, 3)}
        sage: x.is_flag_complex()
        True

        sage: X = simplicial_complexes.ChessboardComplex(3,3)
        sage: X.is_flag_complex()
        True

  `is_immutable`()

    Return `True` if immutable.

    EXAMPLES:

        sage: S = SimplicialComplex([[1,4], [2,4]])
        sage: S.is_immutable()
        False
        sage: S.set_immutable()
        sage: S.is_immutable()
        True

  `is_isomorphic`(other, certify=False)

    Check whether two simplicial complexes are isomorphic.

    INPUT:

    - `certify` – if `True`, then output is `(a,b)`, where `a` is a boolean and `b` is either a map or `None`.

    This is done by creating two graphs and checking whether they are isomorphic.

    EXAMPLES:

        sage: Z1 = SimplicialComplex([[0,1],[1,2],[2,3,4],[4,5]])
        sage: Z2 = SimplicialComplex([['a','b'],['b','c'],['c','d','e'],['e','f']])
        sage: Z3 = SimplicialComplex([[1,2,3]])
        sage: Z1.is_isomorphic(Z2)
        True
        sage: Z1.is_isomorphic(Z2, certify=True)
        (True, {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'})
        sage: Z3.is_isomorphic(Z2)
        False

  `is_mutable`()

    Return `True` if mutable.

    EXAMPLES:

        sage: S = SimplicialComplex([[1,4], [2,4]])
        sage: S.is_mutable()
        True
        sage: S.set_immutable()
        sage: S.is_mutable()
        False
        sage: S2 = SimplicialComplex([[1,4], [2,4]], is_mutable=False)
        sage: S2.is_mutable()
        False
        sage: S3 = SimplicialComplex([[1,4], [2,4]], is_mutable=False)
        sage: S3.is_mutable()
        False

  `is_pseudomanifold`()

    Return True if self is a pseudomanifold.

    A pseudomanifold is a simplicial complex with the following properties:

    - it is pure of some dimension \(d\) (all of its facets are \(d\)-dimensional)

    - every \((d-1)\)-dimensional simplex is the face of exactly two facets

    - for every two facets \(S\) and \(T\), there is a sequence of facets

      \[S = f_0, f_1, ..., f_n = T\]

      such that for each \(i\), \(f_i\) and \(f_{i-1}\) intersect in a \((d-1)\)-simplex.

    By convention, \(S^0\) is the only 0-dimensional pseudomanifold.

    EXAMPLES:

        sage: S0 = simplicial_complexes.Sphere(0)
        sage: S0.is_pseudomanifold()
        True
        sage: (S0.wedge(S0)).is_pseudomanifold()
        False
        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S2 = simplicial_complexes.Sphere(2)
        sage: (S1.wedge(S1)).is_pseudomanifold()
        False
        sage: (S1.wedge(S2)).is_pseudomanifold()
        False
        sage: S2.is_pseudomanifold()
        True
        sage: T = simplicial_complexes.Torus()
        sage: T.suspension(4).is_pseudomanifold()
        True

  `is_pure`()

    Return `True` iff this simplicial complex is pure.

    A simplicial complex is pure if and only if all of its maximal faces have the same dimension.

    Warning

    This may give the wrong answer if the simplicial complex was constructed with `maximality_check` set to `False`.

    EXAMPLES:

        sage: U = SimplicialComplex([[1,2], [1, 3, 4]])
        sage: U.is_pure()
        False
        sage: X = SimplicialComplex([[0,1], [0,2], [1,2]])
        sage: X.is_pure()
        True

    Demonstration of the warning:

        sage: S = SimplicialComplex([[0,1], [0]], maximality_check=False)
        sage: S.is_pure()
        False

  `join`(right, rename_vertices=True, is_mutable=True)

    The join of this simplicial complex with another one.

    The join of two simplicial complexes \(S\) and \(T\) is the simplicial complex \(S*T\) with simplices of the form \([v_0, ..., v_k, w_0, ..., w_n]\) for all simplices \([v_0, ..., v_k]\) in \(S\) and \([w_0, ..., w_n]\) in \(T\).

    Parameters: | right – the other simplicial complex (the right-hand factor) rename_vertices (boolean; optional, default `True`) – If this is True, the vertices in the join will be renamed by the formula: vertex “v” in the left-hand factor –> vertex “Lv” in the join, vertex “w” in the right-hand factor –> vertex “Rw” in the join. If this is false, this tries to construct the join without renaming the vertices; this will cause problems if the two factors have any vertices with names in common. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    EXAMPLES:

        sage: S = SimplicialComplex([[0], [1]])
        sage: T = SimplicialComplex([[2], [3]])
        sage: S.join(T)
        Simplicial complex with vertex set ('L0', 'L1', 'R2', 'R3') and 4 facets
        sage: S.join(T, rename_vertices=False)
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (1, 2), (0, 2), (0, 3)}

    The notation ‘*’ may be used, as well:

        sage: S * S
        Simplicial complex with vertex set ('L0', 'L1', 'R0', 'R1') and 4 facets
        sage: S * S * S * S * S * S * S * S
        Simplicial complex with 16 vertices and 256 facets

  `link`(simplex, is_mutable=True)

    The link of a simplex in this simplicial complex.

    The link of a simplex \(F\) is the simplicial complex formed by all simplices \(G\) which are disjoint from \(F\) but for which \(F \cup G\) is a simplex.

    Parameters: | simplex – a simplex in this simplicial complex. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    EXAMPLES:

        sage: X = SimplicialComplex([[0,1,2], [1,2,3]])
        sage: X.link(Simplex([0]))
        Simplicial complex with vertex set (1, 2) and facets {(1, 2)}
        sage: X.link([1,2])
        Simplicial complex with vertex set (0, 3) and facets {(3,), (0,)}
        sage: Y = SimplicialComplex([[0,1,2,3]])
        sage: Y.link([1])
        Simplicial complex with vertex set (0, 2, 3) and facets {(0, 2, 3)}

  `maximal_faces`()

    The maximal faces (a.k.a. facets) of this simplicial complex.

    This just returns the set of facets used in defining the simplicial complex, so if the simplicial complex was defined with no maximality checking, none is done here, either.

    EXAMPLES:

        sage: Y = SimplicialComplex([[0,2], [1,4]])
        sage: Y.maximal_faces()
        {(1, 4), (0, 2)}

    `facets` is a synonym for `maximal_faces`:

        sage: S = SimplicialComplex([[0,1], [0,1,2]])
        sage: S.facets()
        {(0, 1, 2)}

  `minimal_nonfaces`()

    Set consisting of the minimal subsets of the vertex set of this simplicial complex which do not form faces.

    Algorithm: first take the complement (within the vertex set) of each facet, obtaining a set \((f_1, f_2, ...)\) of simplices. Now form the set of all simplices of the form \((v_1, v_2, ...)\) where vertex \(v_i\) is in face \(f_i\). This set will contain the minimal nonfaces and may contain some non-minimal nonfaces also, so loop through the set to find the minimal ones. (The last two steps are taken care of by the `_transpose_simplices` routine.)

    This is used in computing the `Stanley-Reisner ring` and the `Alexander dual`.

    EXAMPLES:

        sage: X = SimplicialComplex([[1,3],[1,2]])
        sage: X.minimal_nonfaces()
        {(2, 3)}
        sage: Y = SimplicialComplex([[0,1], [1,2], [2,3], [3,0]])
        sage: Y.minimal_nonfaces()
        {(1, 3), (0, 2)}

  `n_faces`(n, subcomplex=None)

    The set of simplices of dimension `n` of this simplicial complex. If the optional argument `subcomplex` is present, then return the `n`-dimensional faces which are not in the subcomplex.

    Parameters: | n – non-negative integer subcomplex (optional, default `None`) – a subcomplex of this simplicial complex. Return `n`-dimensional faces which are not in this subcomplex.

    EXAMPLES:

        sage: S = Set(range(1,5))
        sage: Z = SimplicialComplex(S.subsets())
        sage: Z
        Simplicial complex with vertex set (1, 2, 3, 4) and facets {(1, 2, 3, 4)}
        sage: Z.n_faces(2)
        {(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)}
        sage: K = SimplicialComplex([[1,2,3], [2,3,4]])
        sage: Z.n_faces(2, subcomplex=K)
        {(1, 2, 4), (1, 3, 4)}

  `n_skeleton`(n)

    The \(n\)-skeleton of this simplicial complex.

    The \(n\)-skeleton of a simplicial complex is obtained by discarding all of the simplices in dimensions larger than \(n\).

    Parameters: | n – non-negative integer

    EXAMPLES:

        sage: X = SimplicialComplex([[0,1], [1,2,3], [0,2,3]])
        sage: X.n_skeleton(1)
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(2, 3), (0, 2), (1, 3), (1, 2), (0, 3), (0, 1)}
        sage: X.set_immutable()
        sage: X.n_skeleton(2)
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (1, 2, 3), (0, 1)}

  `product`(right, rename_vertices=True, is_mutable=True)

    The product of this simplicial complex with another one.

    Parameters: | right – the other simplicial complex (the right-hand factor) rename_vertices (boolean; optional, default `True`) – If this is False, then the vertices in the product are the set of ordered pairs \((v,w)\) where \(v\) is a vertex in `self` and \(w\) is a vertex in `right`. If this is `True`, then the vertices are renamed as “LvRw” (e.g., the vertex (1,2) would become “L1R2”). This is useful if you want to define the Stanley-Reisner ring of the complex: vertex names like (0,1) are not suitable for that, while vertex names like “L0R1” are. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    The vertices in the product will be the set of ordered pairs \((v,w)\) where \(v\) is a vertex in self and \(w\) is a vertex in right.

    Warning

    If `X` and `Y` are simplicial complexes, then `X*Y` returns their join, not their product.

    EXAMPLES:

        sage: S = SimplicialComplex([[0,1], [1,2], [0,2]]) # circle
        sage: K = SimplicialComplex([[0,1]])   # edge
        sage: S.product(K).vertices()  # cylinder
        ('L0R0', 'L0R1', 'L1R0', 'L1R1', 'L2R0', 'L2R1')
        sage: S.product(K, rename_vertices=False).vertices()
        ((0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1))
        sage: T = S.product(S)  # torus
        sage: T
        Simplicial complex with 9 vertices and 18 facets
        sage: T.homology()
        {0: 0, 1: Z x Z, 2: Z}

    These can get large pretty quickly:

        sage: T = simplicial_complexes.Torus(); T
        Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 14 facets
        sage: K = simplicial_complexes.KleinBottle(); K
        Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6, 7) and 16 facets
        sage: T.product(K)      # long time: 5 or 6 seconds
        Simplicial complex with 56 vertices and 1344 facets

  `remove_face`(face)

    Remove a face from this simplicial complex and return the resulting simplicial complex.

    Parameters: | face – a face of the simplicial complex

    This changes the simplicial complex.

    ALGORITHM:

    The facets of the new simplicial complex are the facets of the original complex not containing `face`, together with those of `link(face)*boundary(face)`.

    EXAMPLES:

        sage: S = range(1,5)
        sage: Z = SimplicialComplex([S]); Z
        Simplicial complex with vertex set (1, 2, 3, 4) and facets {(1, 2, 3, 4)}
        sage: Z.remove_face([1,2])
        sage: Z
        Simplicial complex with vertex set (1, 2, 3, 4) and facets {(1, 3, 4), (2, 3, 4)}

        sage: S = SimplicialComplex([[0,1,2],[2,3]])
        sage: S
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (2, 3)}
        sage: S.remove_face([0,1,2])
        sage: S
        Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2), (2, 3), (0, 2), (0, 1)}

  `set_immutable`()

    Make this simplicial complex immutable.

    EXAMPLES:

        sage: S = SimplicialComplex([[1,4], [2,4]])
        sage: S.is_mutable()
        True
        sage: S.set_immutable()
        sage: S.is_mutable()
        False

  `stanley_reisner_ring`(base_ring=Integer Ring)

    The Stanley-Reisner ring of this simplicial complex.

    Parameters: | base_ring (optional, default `ZZ`) – a commutative ring
    Returns: | a quotient of a polynomial algebra with coefficients in `base_ring`, with one generator for each vertex in the simplicial complex, by the ideal generated by the products of those vertices which do not form faces in it.

    Thus the ideal is generated by the products corresponding to the minimal nonfaces of the simplicial complex.

    Warning

    This may be quite slow!

    Also, this may behave badly if the vertices have the ‘wrong’ names. To avoid this, define the simplicial complex at the start with the flag `name_check` set to `True`.

    More precisely, this is a quotient of a polynomial ring with one generator for each vertex. If the name of a vertex is a non-negative integer, then the corresponding polynomial generator is named `'x'` followed by that integer (e.g., `'x2'`, `'x3'`, `'x5'`, ...). Otherwise, the polynomial generators are given the same names as the vertices. Thus if the vertex set is `(2, 'x2')`, there will be problems.

    EXAMPLES:

        sage: X = SimplicialComplex([[0,1], [1,2], [2,3], [0,3]])
        sage: X.stanley_reisner_ring()
        Quotient of Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring by the ideal (x1*x3, x0*x2)
        sage: Y = SimplicialComplex([[0,1,2,3,4]]); Y
        Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2, 3, 4)}
        sage: Y.add_face([0,1,2,3,4])
        sage: Y.stanley_reisner_ring(base_ring=QQ)
        Multivariate Polynomial Ring in x0, x1, x2, x3, x4 over Rational Field

  `suspension`(n=1, is_mutable=True)

    The suspension of this simplicial complex.

    Parameters: | n (optional, default 1) – positive integer – suspend this many times. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    The suspension is the simplicial complex formed by adding two new vertices \(S_0\) and \(S_1\) and simplices of the form \([S_0, v_0, ..., v_k]\) and \([S_1, v_0, ..., v_k]\) for every simplex \([v_0, ..., v_k]\) in the original simplicial complex. That is, the suspension is the join of the original complex with a two-point simplicial complex.

    If the simplicial complex \(M\) happens to be a pseudomanifold (see `is_pseudomanifold()`), then this instead constructs Datta’s one-point suspension (see p. 434 in the cited article): choose a vertex \(u\) in \(M\) and choose a new vertex \(w\) to add. Denote the join of simplices by “\(*\)”. The facets in the one-point suspension are of the two forms

    - \(u * \alpha\) where \(\alpha\) is a facet of \(M\) not containing \(u\)
    - \(w * \beta\) where \(\beta\) is any facet of \(M\).

    REFERENCES:

    - Basudeb Datta, “Minimal triangulations of manifolds”, J. Indian Inst. Sci. 87 (2007), no. 4, 429-449.

    EXAMPLES:

        sage: S0 = SimplicialComplex([[0], [1]])
        sage: S0.suspension() == simplicial_complexes.Sphere(1)
        True
        sage: S3 = S0.suspension(3)  # the 3-sphere
        sage: S3.homology()
        {0: 0, 1: 0, 2: 0, 3: Z}

    For pseudomanifolds, the complex constructed here will be smaller than that obtained by taking the join with the 0-sphere: the join adds two vertices, while this construction only adds one.

        sage: T = simplicial_complexes.Torus()
        sage: T.join(S0).vertices()      # 9 vertices
        ('L0', 'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'R0', 'R1')
        sage: T.suspension().vertices()  # 8 vertices
        (0, 1, 2, 3, 4, 5, 6, 7)

  `vertices`()

    The vertex set of this simplicial complex.

    EXAMPLES:

        sage: S = SimplicialComplex([[i] for i in range(16)] + [[0,1], [1,2]])
        sage: S
        Simplicial complex with 16 vertices and 15 facets
        sage: S.vertices()
        (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)

    Note that this actually returns a simplex:

        sage: type(S.vertices())
        <class 'sage.homology.simplicial_complex.Simplex'>

  `wedge`(right, rename_vertices=True, is_mutable=True)

    The wedge (one-point union) of this simplicial complex with another one.

    Parameters: | right – the other simplicial complex (the right-hand factor) rename_vertices (boolean; optional, default `True`) – If this is `True`, the vertices in the wedge will be renamed by the formula: first vertex in each are glued together and called “0”. Otherwise, each vertex “v” in the left-hand factor –> vertex “Lv” in the wedge, vertex “w” in the right-hand factor –> vertex “Rw” in the wedge. If this is `False`, this tries to construct the wedge without renaming the vertices; this will cause problems if the two factors have any vertices with names in common. is_mutable (boolean; optional, default `True`) – Determines if the output is mutable

    Note

    This operation is not well-defined if `self` or `other` is not path-connected.

    EXAMPLES:

        sage: S1 = simplicial_complexes.Sphere(1)
        sage: S2 = simplicial_complexes.Sphere(2)
        sage: S1.wedge(S2).homology()
        {0: 0, 1: Z, 2: Z}

`sage.homology.simplicial_complex.``lattice_paths`(t1, t2, length=None)

  Given lists (or tuples or ...) `t1` and `t2`, think of them as labelings for vertices: `t1` labeling points on the x-axis, `t2` labeling points on the y-axis, both increasing. Return the list of rectilinear paths along the grid defined by these points in the plane, starting from `(t1[0], t2[0])`, ending at `(t1[last], t2[last])`, and at each grid point, going either right or up. See the examples.

  Parameters: | t1 (tuple, list, other iterable) – labeling for vertices t2 (tuple, list, other iterable) – labeling for vertices length (integer or `None`; optional, default `None`) – if not `None`, then an integer, the length of the desired path.
  Returns: | list of lists of vertices making up the paths as described above
  Return type: | list of lists

  This is used when triangulating the product of simplices. The optional argument `length` is used for \(\Delta\)-complexes, to specify all simplices in a product: in the triangulation of a product of two simplices, there is a \(d\)-simplex for every path of length \(d+1\) in the lattice. The path must start at the bottom left and end at the upper right, and it must use at least one point in each row and in each column, so if `length` is too small, there will be no paths.

  EXAMPLES:

      sage: from sage.homology.simplicial_complex import lattice_paths
      sage: lattice_paths([0,1,2], [0,1,2])
      [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)],
       [(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)],
       [(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)],
       [(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)],
       [(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)],
       [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]]
      sage: lattice_paths(('a', 'b', 'c'), (0, 3, 5))
      [[('a', 0), ('a', 3), ('a', 5), ('b', 5), ('c', 5)],
       [('a', 0), ('a', 3), ('b', 3), ('b', 5), ('c', 5)],
       [('a', 0), ('b', 0), ('b', 3), ('b', 5), ('c', 5)],
       [('a', 0), ('a', 3), ('b', 3), ('c', 3), ('c', 5)],
       [('a', 0), ('b', 0), ('b', 3), ('c', 3), ('c', 5)],
       [('a', 0), ('b', 0), ('c', 0), ('c', 3), ('c', 5)]]
      sage: lattice_paths(range(3), range(3), length=2)
      []
      sage: lattice_paths(range(3), range(3), length=3)
      [[(0, 0), (1, 1), (2, 2)]]
      sage: lattice_paths(range(3), range(3), length=4)
      [[(0, 0), (1, 1), (1, 2), (2, 2)],
       [(0, 0), (0, 1), (1, 2), (2, 2)],
       [(0, 0), (1, 1), (2, 1), (2, 2)],
       [(0, 0), (1, 0), (2, 1), (2, 2)],
       [(0, 0), (0, 1), (1, 1), (2, 2)],
       [(0, 0), (1, 0), (1, 1), (2, 2)]]

`sage.homology.simplicial_complex.``rename_vertex`(n, keep, left=True)

  Rename a vertex: the vertices from the list `keep` get relabeled 0, 1, 2, ..., in order. Any other vertex (e.g. 4) gets renamed to by prepending an ‘L’ or an ‘R’ (thus to either ‘L4’ or ‘R4’), depending on whether the argument left is `True` or `False`.

  Parameters: | n – a ‘vertex’: either an integer or a string keep – a list of three vertices left (boolean; optional, default `True`) – if `True`, rename for use in left factor

  This is used by the `connected_sum()` method for simplicial complexes.

  EXAMPLES:

      sage: from sage.homology.simplicial_complex import rename_vertex
      sage: rename_vertex(6, [5, 6, 7])
      1
      sage: rename_vertex(3, [5, 6, 7, 8, 9])
      'L3'
      sage: rename_vertex(3, [5, 6, 7], left=False)
      'R3'

### Navigation

- index
- modules |
- next |
- previous |
- Cell complexes and their homology »