Finite simplicial complexes¶
AUTHORS:
 John H. Palmieri (200904)
 D. Benjamin Antieau (200906): added is_connected, generated_subcomplex, remove_facet, and is_flag_complex methods; cached the output of the graph() method.
 Travis Scrimshaw (20120817): Made
SimplicialComplex
have an immutable option, and added__hash__()
function which checks to make sure it is immutable. MadeSimplicialComplex.remove_face()
into a mutator. Deprecated thevertex_set
parameter.  Christian Stump (201106): implementation of is_cohen_macaulay
 Travis Scrimshaw (20130216): Allowed
SimplicialComplex
to make mutable copies.  Simon King (20140502): 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 \((n1)\)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 nonnegative 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, list, other iterable) – set of vertices Returns: simplex with those vertices X
may be a nonnegative 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'

alexander_whitney
(dim)¶ Subdivide this simplex into a pair of simplices.
If this simplex has vertices \(v_0\), \(v_1\), ..., \(v_n\), then subdivide it into simplices \((v_0, v_1, ..., v_{dim})\) and \((v_{dim}, v_{dim + 1}, ..., v_n)\).
INPUT:
dim
– integer between 0 and one more than the dimension of this simplex
OUTPUT:
 a list containing just the triple
(1, left, right)
, whereleft
andright
are the two simplices described above.
This method allows one to construct a coproduct from the \(p+q\)chains to the tensor product of the \(p\)chains and the \(q\)chains. The number 1 (a Sage integer) is the coefficient of
left tensor right
in this coproduct. (The corresponding formula is more complicated for the cubes that make up a cubical complex, and the output format is intended to be consistent for both cubes and simplices.)Calling this method
alexander_whitney
is an abuse of notation, since the actual AlexanderWhitney map goes from \(C(X \times Y) \to C(X) \otimes C(Y)\), where \(C()\) denotes the chain complex of singular chains, but this subdivision of simplices is at the heart of it.EXAMPLES:
sage: s = Simplex((0,1,3,4)) sage: s.alexander_whitney(0) [(1, (0,), (0, 1, 3, 4))] sage: s.alexander_whitney(2) [(1, (0, 1, 3), (3, 4))]

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 righthand factor)
 rename_vertices (boolean; optional, default
True
) – If this isTrue
, the vertices in the join will be renamed by this formula: vertex “v” in the lefthand factor –> vertex “Lv” in the join, vertex “w” in the righthand 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 isFalse
, then the vertices in the product are the set of ordered pairs \((v,w)\) where \(v\) is a vertex in the lefthand factor (self
) and \(w\) is a vertex in the righthand factor (other
). If this isTrue
, 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 StanleyReisner ring of the complex: vertex names like (0,1) are not suitable for that, while vertex names like “L0R1” are.
Algorithm: see Hatcher, p. 277278 [Hat2002] (who in turn refers to EilenbergSteenrod, p. 68): given
S = Simplex(m)
andT = 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 lefthand factor and \(w\) is a vertex in the righthand factor.
Note
This produces a list of simplices – not a
Simplex
, not aSimplicialComplex
.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()) <... '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, category=None)¶ Bases:
sage.structure.parent.Parent
,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 toFalse
to make this immutable  category (category; optional, default finite simplicial complexes) – the category of the simplicial complex
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 setfrom_characteristic_function=(f,X)
whereX
is the set of points andf
a boolean monotone hereditary function that accepts a list of elements fromX
as input (seesubsets_with_hereditary_property()
for more information).If
maximality_check
isTrue
, 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 beTrue
; various methods for this class may fail if faces which are claimed to be maximal are in fact not.If
sort_facets
isTrue
, 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
isTrue
, 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 StanleyReisner 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 builtin 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, l.ground_set())) Simplicial complex with 21 vertices and 168 facets
Warning
Simplicial complexes are not proper parents as they do not possess element classes. In particular, parents are assumed to be hashable (and hence immutable) by the coercion framework. However this is close enough to being a parent with elements being the faces of
self
that we currently allow this abuse.
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)}

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 mutableEXAMPLES:
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)}

alexander_whitney
(simplex, dim_left)¶ Subdivide this simplex into a pair of simplices.
If this simplex has vertices \(v_0\), \(v_1\), ..., \(v_n\), then subdivide it into simplices \((v_0, v_1, ..., v_{dim})\) and \((v_{dim}, v_{dim + 1}, ..., v_n)\).
See
Simplex.alexander_whitney()
for more details. This method just calls that one.INPUT:
simplex
– a simplex in this complexdim
– integer between 0 and one more than the dimension of this simplex
OUTPUT: a list containing just the triple
(1, left, right)
, whereleft
andright
are the two simplices described above.EXAMPLES:
sage: s = Simplex((0,1,3,4)) sage: X = SimplicialComplex([s]) sage: X.alexander_whitney(s, 0) [(1, (0,), (0, 1, 3, 4))] sage: X.alexander_whitney(s, 2) [(1, (0, 1, 3), (3, 4))]

algebraic_topological_model
(base_ring=None)¶ Algebraic topological model for this simplicial complex with coefficients in
base_ring
.The term “algebraic topological model” is defined by Pilarczyk and Réal [PR2015].
INPUT:
base_ring
 coefficient ring (optional, defaultQQ
). Must be a field.
Denote by \(C\) the chain complex associated to this simplicial complex. 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\) viaphi.pi()
andphi.iota()
. Then one can recover \(C\) and \(M\) from, for example,phi.pi().domain()
andphi.pi().codomain()
, respectively.EXAMPLES:
sage: RP2 = simplicial_complexes.RealProjectivePlane() sage: phi, M = RP2.algebraic_topological_model(GF(2)) sage: M.homology() {0: Vector space of dimension 1 over Finite Field of size 2, 1: Vector space of dimension 1 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2} sage: T = simplicial_complexes.Torus() sage: phi, M = T.algebraic_topological_model(QQ) sage: M.homology() {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}

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 Minimal triangulation of the 4sphere 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
(subcomplex=None, augmented=False, verbose=False, check=False, dimensions=None, base_ring=Integer Ring, cochain=False)¶ 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
) – IfTrue
, return the augmented chain complex (that is, include a class in dimension \(1\) corresponding to the empty cell). This is ignored ifdimensions
is specified.  cochain (boolean; optional, default
False
) – IfTrue
, return the cochain complex (that is, the dual of the chain complex).  verbose (boolean; optional, default
False
) – IfTrue
, print some messages as the chain complex is computed.  check (boolean; optional, default
False
) – IfTrue
, 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\).The rows and columns of the boundary matrices are indexed by the lists given by the
n_cells()
method, which by default are sorted.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
 dimensions – if

cone
(is_mutable=True)¶ The cone on this simplicial complex.
Parameters: is_mutable (boolean; optional, default True
) – Determines if the output is mutableThe 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 onepoint 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
. Ifsimplex
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
andother
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 nonmanifolds, 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 lefthand factor are renamed by prepending an “L”, and similarly the remaining vertices in the righthand 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 Minimal triangulation of the real projective plane 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
) – ifTrue
, sort the list of simplices in each dimensionEXAMPLES:
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 righthand 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 lefthand factor –> vertex “Lv” in the disjoint union, vertex “w” in the righthand 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}

f_triangle
()¶ Compute the \(f\)triangle of
self
.The \(f\)triangle is given by \(f_{i,j}\) being the number of faces \(F\) of size \(j\) such that \(i = \max_{G \subseteq F} G\).
EXAMPLES:
sage: X = SimplicialComplex([[1,2,3], [3,4,5], [1,4], [1,5], [2,4], [2,5]]) sage: X.f_triangle() ## this complex is not pure [[0], [0, 0], [0, 0, 4], [1, 5, 6, 2]]
A complex is pure if and only if the last row is nonzero:
sage: X = SimplicialComplex([[1,2,3], [3,4,5], [1,4,5]]) sage: X.f_triangle() [[0], [0, 0], [0, 0, 0], [1, 5, 8, 3]]

face
(simplex, i)¶ The \(i\)th face of
simplex
in this simplicial complexINPUT:
simplex
– a simplex in this simplicial complexi
– integer
EXAMPLES:
sage: S = SimplicialComplex([[0,1,4], [0,1,2]]) sage: S.face(Simplex((0,2)), 0) (2,) sage: S.face(Simplex((0,3)), 0) Traceback (most recent call last): ... ValueError: this simplex is not in this simplicial complex

face_iterator
(increasing=True)¶ An iterator for the faces in this simplicial complex.
INPUT:
increasing
– (optional, defaultTrue
) ifTrue
, 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 formaximal_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 inself
. More generally, simplices in \(Fix(G)\) correspond to simplices inself
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 flip graph ofself
, otherwise, it returnsNone
.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 pathconnected, then specify a vertex; the fundamental group is computed with that vertex as a base point. If the complex is pathconnected, then you may specify a vertex or leave this as its default setting ofNone
. (If this complex is pathconnected, 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 edgepath group – see Wikipedia article Fundamental_group. Choose a spanning tree for the 1skeleton, and then the group’s generators are given by the edges in the 1skeleton; there are two types of relations: \(e=1\) if \(e\) is in the spanning tree, and for every 2simplex, 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  e0, e3, e4, e7, e9, e5*e2^1*e0, e7*e2^1*e1, e8*e3^1*e1, e8*e6^1*e4, e9*e6^1*e5 > sage: C2.simplified() Finitely presented group < e1  e1^2 >
This is the same answer given if the argument
simplify
is True (the default):sage: RP2.fundamental_group() Finitely presented group < e1  e1^2 >
You must specify a base point to compute the fundamental group of a nonconnected 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 < e1  e1^2 >
Some other examples:
sage: S1.wedge(S1).fundamental_group() Finitely presented group < e0, e1  > sage: simplicial_complexes.Torus().fundamental_group() Finitely presented group < e1, e4  e4^1*e1^1*e4*e1 > sage: simplicial_complexes.MooreSpace(5).fundamental_group() Finitely presented group < e0  e0^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_{i1}\) 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 subsimplicial complex of
self
containing exactlysub_vertex_set
as vertices.Parameters:  sub_vertex_set – The subvertex set.
 is_mutable (boolean; optional, default
True
) – Determines if the output is mutable
EXAMPLES:
sage: S = simplicial_complexes.Sphere(2) sage: S Minimal triangulation of the 2sphere sage: S.generated_subcomplex([0,1,2]) Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}

graph
()¶ The 1skeleton of this simplicial complex, as a graph.
Warning
This may give the wrong answer if the simplicial complex was constructed with
maximality_check
set toFalse
.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_triangle
()¶ Compute the \(h\)triangle of
self
.The \(h\)triangle of a simplicial complex \(\Delta\) is given by
\[h_{i,j} = \sum_{k=0}^j (1)^{jk} \binom{ik}{jk} f_{i,k},\]where \(f_{i,k}\) is the \(f\)triangle of \(\Delta\).
EXAMPLES:
sage: X = SimplicialComplex([[1,2,3], [3,4,5], [1,4], [1,5], [2,4], [2,5]]) sage: X.h_triangle() [[0], [0, 0], [0, 0, 4], [1, 2, 1, 0]]

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 empty 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+1i} = \sum_{i=0}^{d+1} f_{i1} (x1)^{d+1i}.\]Alternatively,
\[h_j = \sum_{i=1}^{j1} (1)^{ji1} \binom{di}{ji1} 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
(base_ring=Rational Field, ncpus=0)¶ Return
True
ifself
is CohenMacaulay.A simplicial complex \(\Delta\) is CohenMacaulay over \(R\) iff \(\tilde{H}_i(\mathrm{lk}_\Delta(F);R) = 0\) for all \(F \in \Delta\) and \(i < \dim\mathrm{lk}_\Delta(F)\). Here, \(\Delta\) is
self
and \(R\) isbase_ring
, and \(\mathrm{lk}\) denotes the link operator onself
.INPUT:
base_ring
– (default:QQ
) the base ring.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 StanleyReisner ring of
self
is CohenMacaulay.EXAMPLES:
Spheres are CohenMacaulay:
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  CohenMacaulay rings, Figure 5.3:
sage: S = SimplicialComplex([[1,2,3],[1,4,5]]) sage: S.is_cohen_macaulay(ncpus=3) ... False
The choice of base ring can matter. The real projective plane \(\RR P^2\) has \(H_1(\RR P^2) = \ZZ/2\), hence is CM over \(\QQ\) but not over \(\ZZ\).
sage: X = simplicial_complexes.RealProjectivePlane() sage: X.is_cohen_macaulay() True sage: X.is_cohen_macaulay(ZZ) False

is_flag_complex
()¶ Returns
True
if and only ifself
is a flag complex.A flag complex is a simplicial complex that is the largest simplicial complex on its 1skeleton. 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, certificate=False)¶ Check whether two simplicial complexes are isomorphic.
INPUT:
certificate
– ifTrue
, then output is(a, b)
, wherea
is a boolean andb
is either a map orNone
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, certificate=True) (True, {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}) sage: Z3.is_isomorphic(Z2) False
We check that trac ticket #20751 is fixed:
sage: C1 = SimplicialComplex([[1,2,3], [1,2,4], [1,3,4]]) sage: C2 = SimplicialComplex([['j','k','l'], ['j','l','m'], ['j','k','m']]) sage: C1.is_isomorphic(C2, certificate=True) (True, {1: 'j', 2: 'k', 3: 'l', 4: 'm'})

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 \((d1)\)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_{i1}\) intersect in a \((d1)\)simplex.
By convention, \(S^0\) is the only 0dimensional 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 toFalse
.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

is_shellable
(certificate=False)¶ Return if
self
is shellable.A simplicial complex is shellable if there exists a shelling order.
Note
 This method can check all orderings of the facets by brute force, hence can be very slow.
 This is shellability in the general (nonpure) sense of Bjorner and Wachs [BW1996]. This method does not check purity.
See also
INPUT:
certificate
– (default:False
) ifTrue
then returns the shelling order (if it exists)
EXAMPLES:
sage: X = SimplicialComplex([[1,2,5], [2,3,5], [3,4,5], [1,4,5]]) sage: X.is_shellable() True sage: order = X.is_shellable(True); order ((2, 3, 5), (1, 2, 5), (1, 4, 5), (3, 4, 5)) sage: X.is_shelling_order(order) True sage: X = SimplicialComplex([[1,2,3], [3,4,5]]) sage: X.is_shellable() False
Examples from Figure 1 in [BW1996]:
sage: X = SimplicialComplex([[1,2,3], [3,4], [4,5], [5,6], [4,6]]) sage: X.is_shellable() True sage: X = SimplicialComplex([[1,2,3], [3,4], [4,5,6]]) sage: X.is_shellable() False
REFERENCES:

is_shelling_order
(shelling_order, certificate=False)¶ Return if the order of the facets given by
shelling_order
is a shelling order forself
.A sequence of facets \((F_i)_{i=1}^N\) of a simplicial complex of dimension \(d\) is a shelling order if for all \(i = 2, 3, 4, \ldots\), the complex
\[X_i = \left( \bigcup_{j=1}^{i1} F_j \right) \cap F_i\]is pure and of dimension \(\dim F_i  1\).
INPUT:
shelling_order
– an ordering of the facets ofself
certificate
– (default:False
) ifTrue
then returns the index of the first facet that violate the condition
See also
EXAMPLES:
sage: facets = [[1,2,5],[2,3,5],[3,4,5],[1,4,5]] sage: X = SimplicialComplex(facets) sage: X.is_shelling_order(facets) True sage: b = [[1,2,5], [3,4,5], [2,3,5], [1,4,5]] sage: X.is_shelling_order(b) False sage: X.is_shelling_order(b, True) (False, 1)
A nonpure example:
sage: facets = [[1,2,3], [3,4], [4,5], [5,6], [4,6]] sage: X = SimplicialComplex(facets) sage: X.is_shelling_order(facets) True
REFERENCES:

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 righthand 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 lefthand factor –> vertex “Lv” in the join, vertex “w” in the righthand 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 formaximal_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: Proceeds through the faces of the complex increasing the dimension, starting from dimension 0, and add the faces that are not contained in the complex and that are not already contained in a previously seen minimal nonface.
This is used in computing the
StanleyReisner ring
and theAlexander 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_cells
(n, subcomplex=None, sort=None)¶ List of cells of dimension
n
of this cell complex.If the optional argument
subcomplex
is present, then return then
dimensional faces which are not in the subcomplex. Sort the list if the argumentsort
isTrue
. Ifsort
isNone
(the default), then sort depending on the value of thesort_facets
parameter (from the initialization of the simplicial complex).Note
This list is sorted to provide reliable indexing for the rows and columns of the matrices of differentials in the associated chain complex.
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_cells(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_cells(2, subcomplex=K) [(1, 2, 4), (1, 3, 4)] sage: S = SimplicialComplex([[complex(i), complex(1)]], sort_facets=False) sage: S.n_cells(0) [(1j,), ((1+0j),)]

n_faces
(n, subcomplex=None)¶ The set of simplices of dimension
n
of this simplicial complex. If the optional argumentsubcomplex
is present, then return then
dimensional faces which are not in the subcomplex.Parameters:  n – nonnegative integer
 subcomplex (optional, default
None
) – a subcomplex of this simplicial complex. Returnn
dimensional faces which are not in this subcomplex.
Note
This method is not used elsewhere in Sage. The current usage: if order doesn’t matter, for example to test membership, use
faces()
. If the order of the cells matters, usen_cells()
.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 – nonnegative 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)} sage: X.n_skeleton(4) 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 righthand 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 inself
and \(w\) is a vertex inright
. If this isTrue
, 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 StanleyReisner 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
andY
are simplicial complexes, thenX*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 Minimal triangulation of the torus sage: K = simplicial_complexes.KleinBottle(); K Minimal triangulation of the Klein bottle 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 oflink(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)}

restriction_sets
(order)¶ Return the restriction sets of the facets according to
order
.A restriction set of a shelling order is the sequence of smallest new faces that are created during the shelling order.
See also
EXAMPLES:
sage: facets = [[1,2,5], [2,3,5], [3,4,5], [1,4,5]] sage: X = SimplicialComplex(facets) sage: X.restriction_sets(facets) [(), (3,), (4,), (1, 4)] sage: b = [[1,2,5], [3,4,5], [2,3,5], [1,4,5]] sage: X.restriction_sets(b) Traceback (most recent call last): ... ValueError: not a shelling order

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 StanleyReisner ring of this simplicial complex.
Parameters: base_ring (optional, default ZZ
) – a commutative ringReturns: 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 toTrue
.More precisely, this is a quotient of a polynomial ring with one generator for each vertex. If the name of a vertex is a nonnegative 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

star
(simplex, is_mutable=True)¶ Return the star of a simplex in this simplicial complex.
The star of
simplex
is the simplicial complex formed by all simplices which containsimplex
.INPUT:
simplex
– a simplex in this simplicial complexis_mutable
– (default:True
) boolean; determines if the output is mutable
EXAMPLES:
sage: X = SimplicialComplex([[0,1,2], [1,2,3]]) sage: X.star(Simplex([0])) Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)} sage: X.star(Simplex([1])) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (1, 2, 3)} sage: X.star(Simplex([1,2])) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (1, 2, 3)} sage: X.star(Simplex([])) Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (1, 2, 3)}

stellar_subdivision
(simplex, inplace=False, is_mutable=True)¶ Return the stellar subdivision of a simplex in this simplicial complex.
The stellar subdivision of a face is obtained by adding a new vertex to the simplicial complex
self
joined to the star of the face and then deleting the facesimplex
to the result.INPUT:
simplex
– a simplex face ofself
inplace
– (default:False
) boolean; determines if the operation is done onself
or on a copyis_mutable
– (default:True
) boolean; determines if the output is mutable
OUTPUT:
 A simplicial complex obtained by the stellar subdivision of the face
simplex
EXAMPLES:
sage: SC = SimplicialComplex([[0,1,2],[1,2,3]]) sage: F1 = Simplex([1,2]) sage: F2 = Simplex([1,3]) sage: F3 = Simplex([1,2,3]) sage: SC.stellar_subdivision(F1) Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 4), (1, 3, 4), (2, 3, 4), (0, 2, 4)} sage: SC.stellar_subdivision(F2) Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 1, 2), (2, 3, 4), (1, 2, 4)} sage: SC.stellar_subdivision(F3) Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(1, 3, 4), (0, 1, 2), (2, 3, 4), (1, 2, 4)} sage: SC.stellar_subdivision(F3, inplace=True);SC Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(1, 3, 4), (0, 1, 2), (2, 3, 4), (1, 2, 4)}
The simplex to subdivide should be a face of self:
sage: SC = SimplicialComplex([[0,1,2],[1,2,3]]) sage: F4 = Simplex([3,4]) sage: SC.stellar_subdivision(F4) Traceback (most recent call last): ... ValueError: the face to subdivide is not a face of self
One can not modify an immutable simplicial complex:
sage: SC = SimplicialComplex([[0,1,2],[1,2,3]], is_mutable=False) sage: SC.stellar_subdivision(F1, inplace=True) Traceback (most recent call last): ... ValueError: this simplicial complex is not mutable

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 twopoint simplicial complex.
If the simplicial complex \(M\) happens to be a pseudomanifold (see
is_pseudomanifold()
), then this instead constructs Datta’s onepoint suspension (see [Dat2007], p. 434): choose a vertex \(u\) in \(M\) and choose a new vertex \(w\) to add. Denote the join of simplices by “\(*\)”. The facets in the onepoint 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\).
EXAMPLES:
sage: S0 = SimplicialComplex([[0], [1]]) sage: S0.suspension() == simplicial_complexes.Sphere(1) True sage: S3 = S0.suspension(3) # the 3sphere 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 0sphere: 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, as a tuple, 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)

wedge
(right, rename_vertices=True, is_mutable=True)¶ The wedge (onepoint union) of this simplicial complex with another one.
Parameters:  right – the other simplicial complex (the righthand factor)
 rename_vertices (boolean; optional, default
True
) – If this isTrue
, 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 lefthand factor –> vertex “Lv” in the wedge, vertex “w” in the righthand factor –> vertex “Rw” in the wedge. If this isFalse
, 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 welldefined if
self
orother
is not pathconnected.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.
facets_for_K3
()¶ Returns the facets for a minimal triangulation of the K3 surface.
This is a pure simplicial complex of dimension 4 with 16 vertices and 288 facets. The facets are obtained by constructing a few facets and a permutation group \(G\), and then computing the \(G\)orbit of those facets.
See Casella and Kühnel in [CK2001] and Spreer and Kühnel [SK2011]; the construction here uses the labeling from Spreer and Kühnel.
EXAMPLES:
sage: from sage.homology.simplicial_complex import facets_for_K3 sage: A = facets_for_K3() # long time (a few seconds) sage: SimplicialComplex(A) == simplicial_complexes.K3Surface() # long time True

sage.homology.simplicial_complex.
facets_for_RP4
()¶ Return the list of facets for a minimal triangulation of 4dimensional real projective space.
We use vertices numbered 1 through 16, define two facets, and define a certain subgroup \(G\) of the symmetric group \(S_{16}\). Then the set of all facets is the \(G\)orbit of the two given facets.
See the description in Example 3.12 in Datta [Dat2007].
EXAMPLES:
sage: from sage.homology.simplicial_complex import facets_for_RP4 sage: A = facets_for_RP4() # long time (1 or 2 seconds) sage: SimplicialComplex(A) == simplicial_complexes.RealProjectiveSpace(4) # long time True

sage.homology.simplicial_complex.
lattice_paths
(t1, t2, length=None)¶ Given lists (or tuples or ...)
t1
andt2
, think of them as labelings for vertices:t1
labeling points on the xaxis,t2
labeling points on the yaxis, 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 (list, other iterable) – labeling for vertices
 t2 (list, other iterable) – labeling for vertices
 length (integer or
None
; optional, defaultNone
) – if notNone
, 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 iflength
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 isTrue
orFalse
.Parameters:  n – a ‘vertex’: either an integer or a string
 keep – a list of three vertices
 left (boolean; optional, default
True
) – ifTrue
, 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'